aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/sparc
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2013-04-10 19:41:57 +0000
committerDavid S. Miller <davem@gcc.gnu.org>2013-04-10 12:41:57 -0700
commit42e37616ecd67d50559ca16df0e4228397b0668c (patch)
tree03cbdc17b2b7d1af99a46a569ba37bb1f11fc28f /gcc/config/sparc
parent95ca411e0437d9954a40a2134bba237b1f2ef0fc (diff)
downloadgcc-42e37616ecd67d50559ca16df0e4228397b0668c.zip
gcc-42e37616ecd67d50559ca16df0e4228397b0668c.tar.gz
gcc-42e37616ecd67d50559ca16df0e4228397b0668c.tar.bz2
Improve cstore code generation on 64-bit sparc.
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
Diffstat (limited to 'gcc/config/sparc')
-rw-r--r--gcc/config/sparc/predicates.md5
-rw-r--r--gcc/config/sparc/sparc.c23
-rw-r--r--gcc/config/sparc/sparc.md137
3 files changed, 69 insertions, 96 deletions
diff --git a/gcc/config/sparc/predicates.md b/gcc/config/sparc/predicates.md
index b8524e5..073bce2 100644
--- a/gcc/config/sparc/predicates.md
+++ b/gcc/config/sparc/predicates.md
@@ -265,6 +265,11 @@
(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")
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index 3e98325..4a73c73 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -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);
#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"
diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md
index 832032b..292cb20 100644
--- a/gcc/config/sparc/sparc.md
+++ b/gcc/config/sparc/sparc.md
@@ -615,11 +615,14 @@
;; 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)
@@ -631,7 +634,7 @@
[(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)
@@ -643,7 +646,7 @@
[(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; })
@@ -652,12 +655,12 @@
;; 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); })
@@ -666,17 +669,17 @@
[(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); })
@@ -685,8 +688,8 @@
[(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); })
@@ -694,8 +697,8 @@
[(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); })
@@ -708,9 +711,9 @@
;; 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))]
""
@@ -718,11 +721,11 @@
""
[(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))))
@@ -736,35 +739,16 @@
""
[(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)))))]
""
@@ -843,9 +827,9 @@
""
[(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))]
""
@@ -853,11 +837,11 @@
""
[(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))))
@@ -871,25 +855,7 @@
""
[(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))))
@@ -1021,9 +987,9 @@
;; ??? 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")])
@@ -1042,28 +1008,20 @@
"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)))
@@ -1080,28 +1038,21 @@
"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"