Improve cstore code generation on 64-bit sparc.
authorDavid S. Miller <davem@davemloft.net>
Wed, 10 Apr 2013 19:41:57 +0000 (19:41 +0000)
committerDavid S. Miller <davem@gcc.gnu.org>
Wed, 10 Apr 2013 19:41:57 +0000 (12:41 -0700)
One major suboptimal area of the sparc back end is cstore generation
on 64-bit.

Due to the way arguments and return values of functions must be
promoted, the ideal mode for cstore's result would be DImode.

But this hasn't been done because of a fundamental limitation
of the cstore patterns.  They require a fixed mode be used for
the boolean result value.

I've decided to work around this by building a target hook which
specifies the type to use for conditional store results, and then I
use a special predicate for operans 0 in the cstore expanders so
that they still match even when we use DImode.

The default version of the target hook just does what it does now,
so no other target should be impacted by this at all.

Regstrapped on 32-bit sparc-linux-gnu and I've run the testsuite
with "-m64" to validate the 64-bit side.

gcc/

* target.def (cstore_mode): New hook.
* target.h: Include insn-codes.h
* targhooks.c: Likewise.
(default_cstore_mode): New function.
* targhooks.h: Declare it.
* doc/tm.texi.in: New hook slot for TARGET_CSTORE_MODE.
* doc/tm.texi: Rebuild.
* expmed.c (emit_cstore): Obtain cstore boolean result mode using
target hook, rather than inspecting the insn_data.
* config/sparc/sparc.c (sparc_cstore_mode): New function.
(TARGET_CSTORE_MODE): Redefine.
(emit_scc_insn): When TARGET_ARCH64, emit new 64-bit boolean
result patterns.
* config/sparc/predicates.md (cstore_result_operand): New special
predicate.
* config/sparc/sparc.md (cstoresi4, cstoredi4, cstore<F:mode>4):
Use it for operand 0.
(*seqsi_special): Rewrite using 'P' mode iterator on operand 0.
(*snesi_special): Likewise.
(*snesi_zero): Likewise.
(*seqsi_zero): Likewise.
(*sltu_insn): Likewise.
(*sgeu_insn): Likewise.
(*seqdi_special): Make operand 0 and comparison operation be of
DImode.
(*snedi_special): Likewise.
(*snedi_special_vis3): Likewise.
(*neg_snesi_zero): Rename to *neg_snesisi_zero.
(*neg_snesi_sign_extend): Rename to *neg_snesidi_zero.
(*snesi_zero_extend): Delete, covered by 'P' mode iterator.
(*neg_seqsi_zero): Rename to *neg_seqsisi_zero.
(*neg_seqsi_sign_extend): Rename to *neg_seqsidi_zero.
(*seqsi_zero_extend): Delete, covered by 'P' mode iterator.
(*sltu_extend_sp64): Likewise.
(*neg_sltu_insn): Rename to *neg_sltusi_insn.
(*neg_sltu_extend_sp64): Rename to *neg_sltudi_insn.
(*sgeu_extend_sp64): Delete, covered by 'P' mode iterator.
(*neg_sgeu_insn): Rename to *neg_sgeusi_insn.
(*neg_sgeu_extend_sp64): Rename to *neg_sgeudi_insn.

gcc/testsuite/

* gcc.target/sparc/setcc-4.c: New test.
* gcc.target/sparc/setcc-5.c: New test.

From-SVN: r197679

14 files changed:
gcc/ChangeLog
gcc/config/sparc/predicates.md
gcc/config/sparc/sparc.c
gcc/config/sparc/sparc.md
gcc/doc/tm.texi
gcc/doc/tm.texi.in
gcc/expmed.c
gcc/target.def
gcc/target.h
gcc/targhooks.c
gcc/targhooks.h
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/sparc/setcc-4.c [new file with mode: 0644]
gcc/testsuite/gcc.target/sparc/setcc-5.c [new file with mode: 0644]

index 3c281b4c8768f799e9768fb3e36f8335547b39ef..1c36f919af51cbf4b0cbade4a4e46584f6f675c6 100644 (file)
@@ -1,3 +1,45 @@
+2013-04-10  David S. Miller  <davem@davemloft.net>
+
+       * target.def (cstore_mode): New hook.
+       * target.h: Include insn-codes.h
+       * targhooks.c: Likewise.
+       (default_cstore_mode): New function.
+       * targhooks.h: Declare it.
+       * doc/tm.texi.in: New hook slot for TARGET_CSTORE_MODE.
+       * doc/tm.texi: Rebuild.
+       * expmed.c (emit_cstore): Obtain cstore boolean result mode using
+       target hook, rather than inspecting the insn_data.
+       * config/sparc/sparc.c (sparc_cstore_mode): New function.
+       (TARGET_CSTORE_MODE): Redefine.
+       (emit_scc_insn): When TARGET_ARCH64, emit new 64-bit boolean
+       result patterns.
+       * config/sparc/predicates.md (cstore_result_operand): New special
+       predicate.
+       * config/sparc/sparc.md (cstoresi4, cstoredi4, cstore<F:mode>4):
+       Use it for operand 0.
+       (*seqsi_special): Rewrite using 'P' mode iterator on operand 0.
+       (*snesi_special): Likewise.
+       (*snesi_zero): Likewise.
+       (*seqsi_zero): Likewise.
+       (*sltu_insn): Likewise.
+       (*sgeu_insn): Likewise.
+       (*seqdi_special): Make operand 0 and comparison operation be of
+       DImode.
+       (*snedi_special): Likewise.
+       (*snedi_special_vis3): Likewise.
+       (*neg_snesi_zero): Rename to *neg_snesisi_zero.
+       (*neg_snesi_sign_extend): Rename to *neg_snesidi_zero.
+       (*snesi_zero_extend): Delete, covered by 'P' mode iterator.
+       (*neg_seqsi_zero): Rename to *neg_seqsisi_zero.
+       (*neg_seqsi_sign_extend): Rename to *neg_seqsidi_zero.
+       (*seqsi_zero_extend): Delete, covered by 'P' mode iterator.
+       (*sltu_extend_sp64): Likewise.
+       (*neg_sltu_insn): Rename to *neg_sltusi_insn.
+       (*neg_sltu_extend_sp64): Rename to *neg_sltudi_insn.
+       (*sgeu_extend_sp64): Delete, covered by 'P' mode iterator.
+       (*neg_sgeu_insn): Rename to *neg_sgeusi_insn.
+       (*neg_sgeu_extend_sp64): Rename to *neg_sgeudi_insn.
+
 2013-04-10  Yufeng Zhang  <yufeng.zhang@arm.com>
 
        * config/aarch64/aarch64.c (aarch64_print_extension): New function.
index b8524e5a0643d2feb9ac2ee09c3b8f0d4b66a38e..073bce2adec3a29742a3a4b2695dd303677f373d 100644 (file)
   (ior (match_test "register_operand (op, SImode)")
        (match_test "TARGET_ARCH64 && register_operand (op, DImode)")))
 
+;; Return true if OP is an integer register of the appropriate mode
+;; for a cstore result.
+(define_special_predicate "cstore_result_operand"
+  (match_test "register_operand (op, TARGET_ARCH64 ? DImode : SImode)"))
+
 ;; Return true if OP is a floating point condition code register.
 (define_predicate "fcc_register_operand"
   (match_code "reg")
index 3e98325bd3baa48ddc503409a40a68bbf4f7609e..4a73c73147521fa432e87ae9c7aadfc425cbb1ba 100644 (file)
@@ -597,6 +597,7 @@ static void sparc_print_operand_address (FILE *, rtx);
 static reg_class_t sparc_secondary_reload (bool, rtx, reg_class_t,
                                           enum machine_mode,
                                           secondary_reload_info *);
+static enum machine_mode sparc_cstore_mode (enum insn_code icode);
 \f
 #ifdef SUBTARGET_ATTRIBUTE_TABLE
 /* Table of valid machine attributes.  */
@@ -802,6 +803,9 @@ char sparc_hard_reg_printed[8];
 #undef TARGET_ATOMIC_TEST_AND_SET_TRUEVAL
 #define TARGET_ATOMIC_TEST_AND_SET_TRUEVAL 0xff
 
+#undef TARGET_CSTORE_MODE
+#define TARGET_CSTORE_MODE sparc_cstore_mode
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 static void
@@ -2572,7 +2576,11 @@ emit_scc_insn (rtx operands[])
     {
       if (GET_MODE (x) == SImode)
         {
-          rtx pat = gen_seqsi_special (operands[0], x, y);
+         rtx pat;
+         if (TARGET_ARCH64)
+           pat = gen_seqsidi_special (operands[0], x, y);
+         else
+           pat = gen_seqsisi_special (operands[0], x, y);
           emit_insn (pat);
           return true;
         }
@@ -2588,7 +2596,11 @@ emit_scc_insn (rtx operands[])
     {
       if (GET_MODE (x) == SImode)
         {
-          rtx pat = gen_snesi_special (operands[0], x, y);
+          rtx pat;
+         if (TARGET_ARCH64)
+           pat = gen_snesidi_special (operands[0], x, y);
+         else
+           pat = gen_snesisi_special (operands[0], x, y);
           emit_insn (pat);
           return true;
         }
@@ -2631,7 +2643,7 @@ emit_scc_insn (rtx operands[])
       || (!TARGET_VIS3 && code == GEU))
     {
       emit_insn (gen_rtx_SET (VOIDmode, operands[0],
-                             gen_rtx_fmt_ee (code, SImode,
+                             gen_rtx_fmt_ee (code, GET_MODE (operands[0]),
                                              gen_compare_reg_1 (code, x, y),
                                              const0_rtx)));
       return true;
@@ -12104,4 +12116,9 @@ sparc_modes_tieable_p (enum machine_mode mode1, enum machine_mode mode2)
   return true;
 }
 
+static enum machine_mode sparc_cstore_mode (enum insn_code icode ATTRIBUTE_UNUSED)
+{
+  return (TARGET_ARCH64 ? DImode : SImode);
+}
+
 #include "gt-sparc.h"
index 832032b40b4913e562d210394a71882c5522abae..292cb2052717e6642e2d6136062e860d086108f8 100644 (file)
 \f
 ;; Next come the scc insns.
 
+;; Note that the boolean result (operand 0) takes on DImode
+;; (not SImode) when TARGET_ARCH64.
+
 (define_expand "cstoresi4"
   [(use (match_operator 1 "comparison_operator"
          [(match_operand:SI 2 "compare_operand" "")
           (match_operand:SI 3 "arith_operand" "")]))
-   (clobber (match_operand:SI 0 "register_operand"))]
+   (clobber (match_operand:SI 0 "cstore_result_operand"))]
   ""
 {
   if (GET_CODE (operands[2]) == ZERO_EXTRACT && operands[3] != const0_rtx)
   [(use (match_operator 1 "comparison_operator"
          [(match_operand:DI 2 "compare_operand" "")
           (match_operand:DI 3 "arith_operand" "")]))
-   (clobber (match_operand:SI 0 "register_operand"))]
+   (clobber (match_operand:SI 0 "cstore_result_operand"))]
   "TARGET_ARCH64"
 {
   if (GET_CODE (operands[2]) == ZERO_EXTRACT && operands[3] != const0_rtx)
   [(use (match_operator 1 "comparison_operator"
          [(match_operand:F 2 "register_operand" "")
           (match_operand:F 3 "register_operand" "")]))
-   (clobber (match_operand:SI 0 "register_operand"))]
+   (clobber (match_operand:SI 0 "cstore_result_operand"))]
   "TARGET_FPU"
   { if (emit_scc_insn (operands)) DONE; else FAIL; })
 
 ;; Seq_special[_xxx] and sne_special[_xxx] clobber the CC reg, because they
 ;; generate addcc/subcc instructions.
 
-(define_expand "seqsi_special"
+(define_expand "seqsi<P:mode>_special"
   [(set (match_dup 3)
        (xor:SI (match_operand:SI 1 "register_operand" "")
                (match_operand:SI 2 "register_operand" "")))
-   (parallel [(set (match_operand:SI 0 "register_operand" "")
-                  (eq:SI (match_dup 3) (const_int 0)))
+   (parallel [(set (match_operand:P 0 "register_operand" "")
+                  (eq:P (match_dup 3) (const_int 0)))
              (clobber (reg:CC CC_REG))])]
   ""
   { operands[3] = gen_reg_rtx (SImode); })
   [(set (match_dup 3)
        (xor:DI (match_operand:DI 1 "register_operand" "")
                (match_operand:DI 2 "register_operand" "")))
-   (set (match_operand:SI 0 "register_operand" "")
-       (eq:SI (match_dup 3) (const_int 0)))]
+   (set (match_operand:DI 0 "register_operand" "")
+       (eq:DI (match_dup 3) (const_int 0)))]
   "TARGET_ARCH64"
   { operands[3] = gen_reg_rtx (DImode); })
 
-(define_expand "snesi_special"
+(define_expand "snesi<P:mode>_special"
   [(set (match_dup 3)
        (xor:SI (match_operand:SI 1 "register_operand" "")
                (match_operand:SI 2 "register_operand" "")))
-   (parallel [(set (match_operand:SI 0 "register_operand" "")
-                  (ne:SI (match_dup 3) (const_int 0)))
+   (parallel [(set (match_operand:P 0 "register_operand" "")
+                  (ne:P (match_dup 3) (const_int 0)))
              (clobber (reg:CC CC_REG))])]
   ""
   { operands[3] = gen_reg_rtx (SImode); })
   [(set (match_dup 3)
        (xor:DI (match_operand:DI 1 "register_operand" "")
                (match_operand:DI 2 "register_operand" "")))
-   (set (match_operand:SI 0 "register_operand" "")
-       (ne:SI (match_dup 3) (const_int 0)))]
+   (set (match_operand:DI 0 "register_operand" "")
+       (ne:DI (match_dup 3) (const_int 0)))]
   "TARGET_ARCH64 && ! TARGET_VIS3"
   { operands[3] = gen_reg_rtx (DImode); })
 
   [(set (match_dup 3)
        (xor:DI (match_operand:DI 1 "register_operand" "")
                (match_operand:DI 2 "register_operand" "")))
-   (parallel [(set (match_operand:SI 0 "register_operand" "")
-                  (ne:SI (match_dup 3) (const_int 0)))
+   (parallel [(set (match_operand:DI 0 "register_operand" "")
+                  (ne:DI (match_dup 3) (const_int 0)))
              (clobber (reg:CCX CC_REG))])]
   "TARGET_ARCH64 && TARGET_VIS3"
   { operands[3] = gen_reg_rtx (DImode); })
 ;; them to always use the splits below so the results can be
 ;; scheduled.
 
-(define_insn_and_split "*snesi_zero"
-  [(set (match_operand:SI 0 "register_operand" "=r")
-       (ne:SI (match_operand:SI 1 "register_operand" "r")
+(define_insn_and_split "*snesi<P:mode>_zero"
+  [(set (match_operand:P 0 "register_operand" "=r")
+       (ne:P (match_operand:SI 1 "register_operand" "r")
               (const_int 0)))
    (clobber (reg:CC CC_REG))]
   ""
   ""
   [(set (reg:CC_NOOV CC_REG) (compare:CC_NOOV (neg:SI (match_dup 1))
                                           (const_int 0)))
-   (set (match_dup 0) (ltu:SI (reg:CC CC_REG) (const_int 0)))]
+   (set (match_dup 0) (ltu:P (reg:CC CC_REG) (const_int 0)))]
   ""
   [(set_attr "length" "2")])
 
-(define_insn_and_split "*neg_snesi_zero"
+(define_insn_and_split "*neg_snesisi_zero"
   [(set (match_operand:SI 0 "register_operand" "=r")
        (neg:SI (ne:SI (match_operand:SI 1 "register_operand" "r")
                       (const_int 0))))
   ""
   [(set_attr "length" "2")])
 
-(define_insn_and_split "*snesi_zero_extend"
+(define_insn_and_split "*neg_snesidi_zero"
   [(set (match_operand:DI 0 "register_operand" "=r")
-        (ne:DI (match_operand:SI 1 "register_operand" "r")
-               (const_int 0)))
+       (neg:DI (ne:DI (match_operand:SI 1 "register_operand" "r")
+                      (const_int 0))))
    (clobber (reg:CC CC_REG))]
   "TARGET_ARCH64"
   "#"
-  "&& 1"
-  [(set (reg:CC_NOOV CC_REG) (compare:CC_NOOV (minus:SI (const_int 0)
-                                                     (match_dup 1))
-                                           (const_int 0)))
-   (set (match_dup 0) (zero_extend:DI (plus:SI (plus:SI (const_int 0)
-                                                        (const_int 0))
-                                               (ltu:SI (reg:CC_NOOV CC_REG)
-                                                       (const_int 0)))))]
   ""
-  [(set_attr "length" "2")])
-
-(define_insn_and_split "*neg_snesi_sign_extend"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-        (neg:DI (ne:DI (match_operand:SI 1 "register_operand" "r")
-                      (const_int 0))))
-   (clobber (reg:CC CC_REG))]
-  "TARGET_ARCH64"
-  "#"
-  "&& 1"
-  [(set (reg:CC_NOOV CC_REG) (compare:CC_NOOV (minus:SI (const_int 0)
-                                                     (match_dup 1))
-                                           (const_int 0)))
+  [(set (reg:CC_NOOV CC_REG) (compare:CC_NOOV (neg:SI (match_dup 1))
+                                          (const_int 0)))
    (set (match_dup 0) (sign_extend:DI (neg:SI (ltu:SI (reg:CC CC_REG)
                                                       (const_int 0)))))]
   ""
   ""
   [(set_attr "length" "2")])
 
-(define_insn_and_split "*seqsi_zero"
-  [(set (match_operand:SI 0 "register_operand" "=r")
-       (eq:SI (match_operand:SI 1 "register_operand" "r")
+(define_insn_and_split "*seqsi<P:mode>_zero"
+  [(set (match_operand:P 0 "register_operand" "=r")
+       (eq:P (match_operand:SI 1 "register_operand" "r")
               (const_int 0)))
    (clobber (reg:CC CC_REG))]
   ""
   ""
   [(set (reg:CC_NOOV CC_REG) (compare:CC_NOOV (neg:SI (match_dup 1))
                                           (const_int 0)))
-   (set (match_dup 0) (geu:SI (reg:CC CC_REG) (const_int 0)))]
+   (set (match_dup 0) (geu:P (reg:CC CC_REG) (const_int 0)))]
   ""
   [(set_attr "length" "2")])
 
-(define_insn_and_split "*neg_seqsi_zero"
+(define_insn_and_split "*neg_seqsisi_zero"
   [(set (match_operand:SI 0 "register_operand" "=r")
        (neg:SI (eq:SI (match_operand:SI 1 "register_operand" "r")
                       (const_int 0))))
   ""
   [(set_attr "length" "2")])
 
-(define_insn_and_split "*seqsi_zero_extend"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-        (eq:DI (match_operand:SI 1 "register_operand" "r")
-               (const_int 0)))
-   (clobber (reg:CC CC_REG))]
-  "TARGET_ARCH64"
-  "#"
-  "&& 1"
-  [(set (reg:CC_NOOV CC_REG) (compare:CC_NOOV (minus:SI (const_int 0)
-                                                     (match_dup 1))
-                                           (const_int 0)))
-   (set (match_dup 0) (zero_extend:DI (minus:SI (minus:SI (const_int 0)
-                                                          (const_int -1))
-                                                (ltu:SI (reg:CC_NOOV CC_REG)
-                                                        (const_int 0)))))]
-  ""
-  [(set_attr "length" "2")])
-
-(define_insn_and_split "*neg_seqsi_sign_extend"
+(define_insn_and_split "*neg_seqsidi_zero"
   [(set (match_operand:DI 0 "register_operand" "=r")
        (neg:DI (eq:DI (match_operand:SI 1 "register_operand" "r")
                       (const_int 0))))
 ;; ??? The addx/subx insns use the 32 bit carry flag so there are no DImode
 ;; versions for v9.
 
-(define_insn "*sltu_insn"
-  [(set (match_operand:SI 0 "register_operand" "=r")
-       (ltu:SI (reg:CC CC_REG) (const_int 0)))]
+(define_insn "*sltu<P:mode>_insn"
+  [(set (match_operand:P 0 "register_operand" "=r")
+       (ltu:P (reg:CC CC_REG) (const_int 0)))]
   ""
   "addx\t%%g0, 0, %0"
   [(set_attr "type" "ialuX")])
   "addxc\t%%g0, %%g0, %0"
   [(set_attr "type" "ialuX")])
 
-(define_insn "*sltu_extend_sp64"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-       (ltu:DI (reg:CC CC_REG) (const_int 0)))]
-  "TARGET_ARCH64"
-  "addx\t%%g0, 0, %0"
-  [(set_attr "type" "ialuX")])
-
-(define_insn "*neg_sltu_insn"
+(define_insn "*neg_sltusi_insn"
   [(set (match_operand:SI 0 "register_operand" "=r")
        (neg:SI (ltu:SI (reg:CC CC_REG) (const_int 0))))]
   ""
   "subx\t%%g0, 0, %0"
   [(set_attr "type" "ialuX")])
 
-(define_insn "*neg_sltu_extend_sp64"
+(define_insn "*neg_sltudi_insn"
   [(set (match_operand:DI 0 "register_operand" "=r")
        (sign_extend:DI (neg:SI (ltu:SI (reg:CC CC_REG) (const_int 0)))))]
   "TARGET_ARCH64"
   "subx\t%%g0, 0, %0"
   [(set_attr "type" "ialuX")])
 
-;; ??? Combine should canonicalize these next two to the same pattern.
 (define_insn "*neg_sltu_minus_x"
   [(set (match_operand:SI 0 "register_operand" "=r")
        (minus:SI (neg:SI (ltu:SI (reg:CC CC_REG) (const_int 0)))
   "subx\t%%g0, %1, %0"
   [(set_attr "type" "ialuX")])
 
-(define_insn "*sgeu_insn"
-  [(set (match_operand:SI 0 "register_operand" "=r")
-       (geu:SI (reg:CC CC_REG) (const_int 0)))]
+(define_insn "*sgeu<P:mode>_insn"
+  [(set (match_operand:P 0 "register_operand" "=r")
+       (geu:P (reg:CC CC_REG) (const_int 0)))]
   ""
   "subx\t%%g0, -1, %0"
   [(set_attr "type" "ialuX")])
 
-(define_insn "*sgeu_extend_sp64"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-       (geu:DI (reg:CC CC_REG) (const_int 0)))]
-  "TARGET_ARCH64"
-  "subx\t%%g0, -1, %0"
-  [(set_attr "type" "ialuX")])
-
-(define_insn "*neg_sgeu_insn"
+(define_insn "*neg_sgeusi_insn"
   [(set (match_operand:SI 0 "register_operand" "=r")
        (neg:SI (geu:SI (reg:CC CC_REG) (const_int 0))))]
   ""
   "addx\t%%g0, -1, %0"
   [(set_attr "type" "ialuX")])
 
-(define_insn "*neg_sgeu_extend_sp64"
+(define_insn "*neg_sgeudi_insn"
   [(set (match_operand:DI 0 "register_operand" "=r")
        (sign_extend:DI (neg:SI (geu:SI (reg:CC CC_REG) (const_int 0)))))]
   "TARGET_ARCH64"
index 6395b4b9e71b981dca079a69d1448a26f8f996b9..f6c59f9e3a01931f739ce75b12643dca037041a1 100644 (file)
@@ -2905,6 +2905,10 @@ A target hook which returns true if an address with the same structure  can have
 This hook defines a class of registers which could be used for spilling  pseudos of the given mode and class, or @code{NO_REGS} if only memory  should be used.  Not defining this hook is equivalent to returning  @code{NO_REGS} for all inputs.
 @end deftypefn
 
+@deftypefn {Target Hook} {enum machine_mode} TARGET_CSTORE_MODE (enum insn_code @var{icode})
+This hook defines the machine mode to use for the boolean result of  conditional store patterns.  The ICODE argument is the instruction code  for the cstore being performed.  Not definiting this hook is the same  as accepting the mode encoded into operand 0 of the cstore expander  patterns.
+@end deftypefn
+
 @node Old Constraints
 @section Obsolete Macros for Defining Constraints
 @cindex defining constraints, obsolete method
index 91a756c592e9cf3c31102387791366896969c2ef..2d4b98af0848f16f7229e1e689229ee5433a8810 100644 (file)
@@ -2873,6 +2873,8 @@ as below:
 
 @hook TARGET_SPILL_CLASS
 
+@hook TARGET_CSTORE_MODE
+
 @node Old Constraints
 @section Obsolete Macros for Defining Constraints
 @cindex defining constraints, obsolete method
index d66c6e667fbeaaff3bca7c3d353850d9cc1f8e2e..3c3a179701fbc2832d19ce994d3806be909d8823 100644 (file)
@@ -5081,7 +5081,7 @@ emit_cstore (rtx target, enum insn_code icode, enum rtx_code code,
 {
   struct expand_operand ops[4];
   rtx op0, last, comparison, subtarget;
-  enum machine_mode result_mode = insn_data[(int) icode].operand[0].mode;
+  enum machine_mode result_mode = targetm.cstore_mode (icode);
 
   last = get_last_insn ();
   x = prepare_operand (icode, x, 2, mode, compare_mode, unsignedp);
index 3ad587093f180e3a940faf2bfacedd8fc16431ff..db742732e340799edfd1cfdca8b56148c35f3271 100644 (file)
@@ -2457,6 +2457,16 @@ DEFHOOK
  reg_class_t, (reg_class_t, enum machine_mode),
  NULL)
 
+DEFHOOK
+(cstore_mode,
+ "This hook defines the machine mode to use for the boolean result of\
+  conditional store patterns.  The ICODE argument is the instruction code\
+  for the cstore being performed.  Not definiting this hook is the same\
+  as accepting the mode encoded into operand 0 of the cstore expander\
+  patterns.",
+  enum machine_mode, (enum insn_code icode),
+  default_cstore_mode)
+
 /* True if a structure, union or array with MODE containing FIELD should
    be accessed using BLKmode.  */
 DEFHOOK
index c868118eb5cdf36b87b876c8e839b6100f0562e4..405e2928b7372d2d0951556a644c0567c7f31a73 100644 (file)
@@ -49,6 +49,7 @@
 #define GCC_TARGET_H
 
 #include "insn-modes.h"
+#include "insn-codes.h"
 
 #ifdef ENABLE_CHECKING
 
index 85436ac7393dc682c4b7a1bd2120b149ebb08ef4..80b4aa6bafd9ae1590c119f0ca777e432a6842f2 100644 (file)
@@ -70,6 +70,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "opts.h"
 #include "tree-flow.h"
 #include "tree-ssa-alias.h"
+#include "insn-codes.h"
 
 
 bool
@@ -1537,6 +1538,14 @@ default_pch_valid_p (const void *data_p, size_t len)
   return NULL;
 }
 
+/* Default version of cstore_mode.  */
+
+enum machine_mode
+default_cstore_mode (enum insn_code icode)
+{
+  return insn_data[(int) icode].operand[0].mode;
+}
+
 /* Default version of member_type_forces_blk.  */
 
 bool
index 0837c09c324a7f1794227f0a9f7618e6024d0091..ce10ebc947b73f5637970399158ffa92c23d8c5f 100644 (file)
@@ -195,4 +195,5 @@ extern const char *default_pch_valid_p (const void *, size_t);
 
 extern void default_asm_output_ident_directive (const char*);
 
+extern enum machine_mode default_cstore_mode (enum insn_code);
 extern bool default_member_type_forces_blk (const_tree, enum machine_mode);
index 8bc42b41d951027c2012ea5e5c72a00d1c82bae5..ef84fe1a495c64322daea4fcf68957cc900dd5be 100644 (file)
@@ -1,3 +1,8 @@
+2013-04-10  David S. Miller  <davem@davemloft.net>
+
+       * gcc.target/sparc/setcc-4.c: New test.
+       * gcc.target/sparc/setcc-5.c: New test.
+
 2013-04-10  Richard Biener  <rguenther@suse.de>
 
        * g++.dg/pr55604.C: Use -fdump-rtl-ira.
diff --git a/gcc/testsuite/gcc.target/sparc/setcc-4.c b/gcc/testsuite/gcc.target/sparc/setcc-4.c
new file mode 100644 (file)
index 0000000..ffa4ee0
--- /dev/null
@@ -0,0 +1,44 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-options "-O1 -mno-vis3" } */
+
+long neq (long a, long b)
+{
+  return a != b;
+}
+
+long eq (long a, long b)
+{
+  return a == b;
+}
+
+long lt (unsigned long a, unsigned long b)
+{
+  return a < b;
+}
+
+long leq (unsigned long a, unsigned long b)
+{
+  return a <= b;
+}
+
+long geq (unsigned long a, unsigned long b)
+{
+  return a >= b;
+}
+
+long gt (unsigned long a, unsigned long b)
+{
+  return a > b;
+}
+
+/* { dg-final { scan-assembler-times "xor\t%" 2 } } */
+/* { dg-final { scan-assembler-times "cmp\t%" 4 } } */
+/* { dg-final { scan-assembler-times "movrne\t%" 1 } } */
+/* { dg-final { scan-assembler-times "movre\t%" 1 } } */
+/* { dg-final { scan-assembler-times "movlu\t%" 1 } } */
+/* { dg-final { scan-assembler-times "movleu\t%" 1 } } */
+/* { dg-final { scan-assembler-times "movgeu\t%" 1 } } */
+/* { dg-final { scan-assembler-times "movgu\t%" 1 } } */
+/* { dg-final { scan-assembler-not "sra\t%" } } */
+/* { dg-final { scan-assembler-not "and\t%" } } */
diff --git a/gcc/testsuite/gcc.target/sparc/setcc-5.c b/gcc/testsuite/gcc.target/sparc/setcc-5.c
new file mode 100644 (file)
index 0000000..58f1ee3
--- /dev/null
@@ -0,0 +1,42 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-options "-O1 -mvis3" } */
+
+long neq (long a, long b)
+{
+  return a != b;
+}
+
+long eq (long a, long b)
+{
+  return a == b;
+}
+
+long lt (unsigned long a, unsigned long b)
+{
+  return a < b;
+}
+
+long leq (unsigned long a, unsigned long b)
+{
+  return a <= b;
+}
+
+long geq (unsigned long a, unsigned long b)
+{
+  return a >= b;
+}
+
+long gt (unsigned long a, unsigned long b)
+{
+  return a > b;
+}
+
+/* { dg-final { scan-assembler-times "xor\t%" 2 } } */
+/* { dg-final { scan-assembler-times "cmp\t%" 4 } } */
+/* { dg-final { scan-assembler-times "addxc\t%" 3 } } */
+/* { dg-final { scan-assembler-times "movre\t%" 1 } } */
+/* { dg-final { scan-assembler-times "movleu\t%" 1 } } */
+/* { dg-final { scan-assembler-times "movgeu\t%" 1 } } */
+/* { dg-final { scan-assembler-not "sra\t%" } } */
+/* { dg-final { scan-assembler-not "and\t%" } } */