This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[SPARC] overhaul of V9 cond move patterns
- From: Eric Botcazou <ebotcazou at adacore dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Sun, 21 Sep 2008 21:28:39 +0200
- Subject: [SPARC] overhaul of V9 cond move patterns
This started with an ICE caused by the expansion of a MAX_EXPR in soft TFmode
with -mcpu=v9: the movtfcc expander will directly invoke gen_compare_reg if
you don't have a previous compare-against-zero sequence. And the latter
will directly emit a compare:
emit_insn (gen_rtx_SET (VOIDmode, cc_reg, gen_rtx_COMPARE (mode, x, y)));
which is not recognizable in soft TFmode.
This hasn't been reported before, presumably because MAX_EXPR is not generated
directly by the C family of compilers (Laurent Guerby reported it as a build
failure of the Ada runtime on SPARC64/Linux). And when the cond moves are
synthesized by the ifcvt pass, the calls to the compare routine have already
been emitted so the comparison is done on the result in word mode, not TFmode.
Fixed by creating a wrapper around gen_compare_reg, gen_compare_operator,
responsible for emitting the call to the compare routine in soft TFmode.
While I was at it, I've also factored the numerous cond move patterns with
the help of mode iterators.
Tested on SPARC/Solaris and SPARC64/Solaris and by verifying that the code
generated at -O2 for the code base of the compiler is strictly identical
before and after the patch. Applied on the mainline.
2008-09-21 Eric Botcazou <ebotcazou@adacore.com>
* config/sparc/sparc-protos.h (gen_compare_operator): Declare.
(sparc_emit_float_lib_cmp): Change return type.
* config/sparc/sparc.c (gen_compare_reg): Add comment about TFmode.
(gen_compare_operator): New function.
(sparc_emit_float_lib_cmp): Return the new operator to be used in
the comparison sequence. Minor tweaks.
* config/sparc/sparc.md (seq, sne, sgt, slt, sge, sle): Assert
that the final operator and the result of sparc_emit_float_lib_cmp
match for software TFmode; use emit_insn in lieu of emit_jump_insn.
(beq, bne, bgt, blt, bge, ble, bunordered, bordered, bungt, bunlt,
buneq, bunge, bunle, bltgt): Assert that the final operator and the
result of sparc_emit_float_lib_cmp match for software TFmode.
(movqicc, movhicc, movsicc, movdicc): Merge into...
(mov<I:mode>cc): ...this.
(movsfcc, movdfcc, movtfcc): Merge into...
(mov<F:mode>cc): ...this.
(movqi_cc_sp64, movhi_cc_sp64, movsi_cc_sp64, movdi_cc_sp64): Merge
into...
(mov<I:mode>_cc_v9): ...this.
(movdi_cc_sp64_trunc): Delete.
(movqi_cc_reg_sp64, movhi_cc_reg_sp64, movsi_cc_reg_sp64,
movdi_cc_reg_sp64): Merge into...
(mov<I:mode>_cc_reg_sp64): ...this.
(movsf_cc_sp64): Rename into...
(movsf_cc_v9): ...this.
(movdf_cc_sp64): Rename into...
(movdf_cc_v9): ...this.
(movtf_cc_hq_sp64): Rename into...
(movtf_cc_hq_v9): ...this.
(movtf_cc_sp64): Rename into...
(movtf_cc_v9): ...this. Adjust for renaming of movdf_cc_sp64.
--
Eric Botcazou
Index: config/sparc/sparc.md
===================================================================
--- config/sparc/sparc.md (revision 140483)
+++ config/sparc/sparc.md (working copy)
@@ -621,8 +621,10 @@ (define_expand "seq"
}
else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
{
- sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, EQ);
- emit_jump_insn (gen_sne (operands[0]));
+ enum rtx_code code
+ = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, EQ);
+ gcc_assert (code == NE);
+ emit_insn (gen_sne (operands[0]));
DONE;
}
else if (TARGET_V9)
@@ -673,8 +675,10 @@ (define_expand "sne"
}
else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
{
- sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, NE);
- emit_jump_insn (gen_sne (operands[0]));
+ enum rtx_code code
+ = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, NE);
+ gcc_assert (code == NE);
+ emit_insn (gen_sne (operands[0]));
DONE;
}
else if (TARGET_V9)
@@ -693,8 +697,10 @@ (define_expand "sgt"
{
if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
{
- sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GT);
- emit_jump_insn (gen_sne (operands[0]));
+ enum rtx_code code
+ = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GT);
+ gcc_assert (code == NE);
+ emit_insn (gen_sne (operands[0]));
DONE;
}
else if (TARGET_V9)
@@ -713,8 +719,10 @@ (define_expand "slt"
{
if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
{
- sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LT);
- emit_jump_insn (gen_sne (operands[0]));
+ enum rtx_code code
+ = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LT);
+ gcc_assert (code == NE);
+ emit_insn (gen_sne (operands[0]));
DONE;
}
else if (TARGET_V9)
@@ -733,8 +741,10 @@ (define_expand "sge"
{
if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
{
- sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GE);
- emit_jump_insn (gen_sne (operands[0]));
+ enum rtx_code code
+ = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GE);
+ gcc_assert (code == NE);
+ emit_insn (gen_sne (operands[0]));
DONE;
}
else if (TARGET_V9)
@@ -753,8 +763,10 @@ (define_expand "sle"
{
if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
{
- sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LE);
- emit_jump_insn (gen_sne (operands[0]));
+ enum rtx_code code
+ = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LE);
+ gcc_assert (code == NE);
+ emit_insn (gen_sne (operands[0]));
DONE;
}
else if (TARGET_V9)
@@ -1270,7 +1282,9 @@ (define_expand "beq"
}
else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
{
- sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, EQ);
+ enum rtx_code code
+ = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, EQ);
+ gcc_assert (code == NE);
emit_jump_insn (gen_bne (operands[0]));
DONE;
}
@@ -1293,7 +1307,9 @@ (define_expand "bne"
}
else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
{
- sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, NE);
+ enum rtx_code code
+ = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, NE);
+ gcc_assert (code == NE);
emit_jump_insn (gen_bne (operands[0]));
DONE;
}
@@ -1316,7 +1332,9 @@ (define_expand "bgt"
}
else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
{
- sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GT);
+ enum rtx_code code
+ = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GT);
+ gcc_assert (code == NE);
emit_jump_insn (gen_bne (operands[0]));
DONE;
}
@@ -1349,7 +1367,9 @@ (define_expand "blt"
}
else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
{
- sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LT);
+ enum rtx_code code
+ = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LT);
+ gcc_assert (code == NE);
emit_jump_insn (gen_bne (operands[0]));
DONE;
}
@@ -1382,7 +1402,9 @@ (define_expand "bge"
}
else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
{
- sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GE);
+ enum rtx_code code
+ = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GE);
+ gcc_assert (code == NE);
emit_jump_insn (gen_bne (operands[0]));
DONE;
}
@@ -1415,7 +1437,9 @@ (define_expand "ble"
}
else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
{
- sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LE);
+ enum rtx_code code
+ = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LE);
+ gcc_assert (code == NE);
emit_jump_insn (gen_bne (operands[0]));
DONE;
}
@@ -1441,8 +1465,9 @@ (define_expand "bunordered"
{
if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
{
- sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1,
- UNORDERED);
+ enum rtx_code code
+ = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNORDERED);
+ gcc_assert (code == EQ);
emit_jump_insn (gen_beq (operands[0]));
DONE;
}
@@ -1458,7 +1483,9 @@ (define_expand "bordered"
{
if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
{
- sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, ORDERED);
+ enum rtx_code code
+ = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, ORDERED);
+ gcc_assert (code == NE);
emit_jump_insn (gen_bne (operands[0]));
DONE;
}
@@ -1474,7 +1501,9 @@ (define_expand "bungt"
{
if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
{
- sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNGT);
+ enum rtx_code code
+ = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNGT);
+ gcc_assert (code == GT);
emit_jump_insn (gen_bgt (operands[0]));
DONE;
}
@@ -1490,7 +1519,9 @@ (define_expand "bunlt"
{
if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
{
- sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNLT);
+ enum rtx_code code
+ = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNLT);
+ gcc_assert (code == NE);
emit_jump_insn (gen_bne (operands[0]));
DONE;
}
@@ -1506,7 +1537,9 @@ (define_expand "buneq"
{
if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
{
- sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNEQ);
+ enum rtx_code code
+ = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNEQ);
+ gcc_assert (code == EQ);
emit_jump_insn (gen_beq (operands[0]));
DONE;
}
@@ -1522,7 +1555,9 @@ (define_expand "bunge"
{
if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
{
- sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNGE);
+ enum rtx_code code
+ = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNGE);
+ gcc_assert (code == NE);
emit_jump_insn (gen_bne (operands[0]));
DONE;
}
@@ -1538,7 +1573,9 @@ (define_expand "bunle"
{
if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
{
- sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNLE);
+ enum rtx_code code
+ = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNLE);
+ gcc_assert (code == NE);
emit_jump_insn (gen_bne (operands[0]));
DONE;
}
@@ -1554,7 +1591,9 @@ (define_expand "bltgt"
{
if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
{
- sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LTGT);
+ enum rtx_code code
+ = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LTGT);
+ gcc_assert (code == NE);
emit_jump_insn (gen_bne (operands[0]));
DONE;
}
@@ -3015,7 +3054,7 @@ (define_split
})
-;; SPARC-V9 conditional move instructions.
+;; SPARC-V9 conditional move instructions
;; We can handle larger constants here for some flavors, but for now we keep
;; it simple and only allow those constants supported by all flavors.
@@ -3023,40 +3062,14 @@ (define_split
;; 3 contains the constant if one is present, but we handle either for
;; generality (sparc.c puts a constant in operand 2).
-(define_expand "movqicc"
- [(set (match_operand:QI 0 "register_operand" "")
- (if_then_else:QI (match_operand 1 "comparison_operator" "")
- (match_operand:QI 2 "arith10_operand" "")
- (match_operand:QI 3 "arith10_operand" "")))]
- "TARGET_V9"
-{
- enum rtx_code code = GET_CODE (operands[1]);
-
- if (GET_MODE (sparc_compare_op0) == DImode
- && ! TARGET_ARCH64)
- FAIL;
-
- if (sparc_compare_op1 == const0_rtx
- && GET_CODE (sparc_compare_op0) == REG
- && GET_MODE (sparc_compare_op0) == DImode
- && v9_regcmp_p (code))
- {
- operands[1] = gen_rtx_fmt_ee (code, DImode,
- sparc_compare_op0, sparc_compare_op1);
- }
- else
- {
- rtx cc_reg = gen_compare_reg (code);
- operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
- }
-})
+(define_mode_iterator I [QI HI SI DI])
-(define_expand "movhicc"
- [(set (match_operand:HI 0 "register_operand" "")
- (if_then_else:HI (match_operand 1 "comparison_operator" "")
- (match_operand:HI 2 "arith10_operand" "")
- (match_operand:HI 3 "arith10_operand" "")))]
- "TARGET_V9"
+(define_expand "mov<I:mode>cc"
+ [(set (match_operand:I 0 "register_operand" "")
+ (if_then_else:I (match_operand 1 "comparison_operator" "")
+ (match_operand:I 2 "arith10_operand" "")
+ (match_operand:I 3 "arith10_operand" "")))]
+ "TARGET_V9 && !(<I:MODE>mode == DImode && TARGET_ARCH32)"
{
enum rtx_code code = GET_CODE (operands[1]);
@@ -3068,72 +3081,18 @@ (define_expand "movhicc"
&& GET_CODE (sparc_compare_op0) == REG
&& GET_MODE (sparc_compare_op0) == DImode
&& v9_regcmp_p (code))
- {
- operands[1] = gen_rtx_fmt_ee (code, DImode,
- sparc_compare_op0, sparc_compare_op1);
- }
- else
- {
- rtx cc_reg = gen_compare_reg (code);
- operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
- }
-})
-
-(define_expand "movsicc"
- [(set (match_operand:SI 0 "register_operand" "")
- (if_then_else:SI (match_operand 1 "comparison_operator" "")
- (match_operand:SI 2 "arith10_operand" "")
- (match_operand:SI 3 "arith10_operand" "")))]
- "TARGET_V9"
-{
- enum rtx_code code = GET_CODE (operands[1]);
- enum machine_mode op0_mode = GET_MODE (sparc_compare_op0);
-
- if (sparc_compare_op1 == const0_rtx
- && GET_CODE (sparc_compare_op0) == REG
- && (TARGET_ARCH64 && op0_mode == DImode && v9_regcmp_p (code)))
- {
- operands[1] = gen_rtx_fmt_ee (code, op0_mode,
- sparc_compare_op0, sparc_compare_op1);
- }
+ operands[1] = gen_rtx_fmt_ee (code, DImode, sparc_compare_op0, const0_rtx);
else
- {
- rtx cc_reg = gen_compare_reg (code);
- operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg),
- cc_reg, const0_rtx);
- }
+ operands[1] = gen_compare_operator (code);
})
-(define_expand "movdicc"
- [(set (match_operand:DI 0 "register_operand" "")
- (if_then_else:DI (match_operand 1 "comparison_operator" "")
- (match_operand:DI 2 "arith10_operand" "")
- (match_operand:DI 3 "arith10_operand" "")))]
- "TARGET_ARCH64"
-{
- enum rtx_code code = GET_CODE (operands[1]);
-
- if (sparc_compare_op1 == const0_rtx
- && GET_CODE (sparc_compare_op0) == REG
- && GET_MODE (sparc_compare_op0) == DImode
- && v9_regcmp_p (code))
- {
- operands[1] = gen_rtx_fmt_ee (code, DImode,
- sparc_compare_op0, sparc_compare_op1);
- }
- else
- {
- rtx cc_reg = gen_compare_reg (code);
- operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg),
- cc_reg, const0_rtx);
- }
-})
+(define_mode_iterator F [SF DF TF])
-(define_expand "movsfcc"
- [(set (match_operand:SF 0 "register_operand" "")
- (if_then_else:SF (match_operand 1 "comparison_operator" "")
- (match_operand:SF 2 "register_operand" "")
- (match_operand:SF 3 "register_operand" "")))]
+(define_expand "mov<F:mode>cc"
+ [(set (match_operand:F 0 "register_operand" "")
+ (if_then_else:F (match_operand 1 "comparison_operator" "")
+ (match_operand:F 2 "register_operand" "")
+ (match_operand:F 3 "register_operand" "")))]
"TARGET_V9 && TARGET_FPU"
{
enum rtx_code code = GET_CODE (operands[1]);
@@ -3146,160 +3105,73 @@ (define_expand "movsfcc"
&& GET_CODE (sparc_compare_op0) == REG
&& GET_MODE (sparc_compare_op0) == DImode
&& v9_regcmp_p (code))
- {
- operands[1] = gen_rtx_fmt_ee (code, DImode,
- sparc_compare_op0, sparc_compare_op1);
- }
+ operands[1] = gen_rtx_fmt_ee (code, DImode, sparc_compare_op0, const0_rtx);
else
- {
- rtx cc_reg = gen_compare_reg (code);
- operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
- }
+ operands[1] = gen_compare_operator (code);
})
-(define_expand "movdfcc"
- [(set (match_operand:DF 0 "register_operand" "")
- (if_then_else:DF (match_operand 1 "comparison_operator" "")
- (match_operand:DF 2 "register_operand" "")
- (match_operand:DF 3 "register_operand" "")))]
- "TARGET_V9 && TARGET_FPU"
-{
- enum rtx_code code = GET_CODE (operands[1]);
-
- if (GET_MODE (sparc_compare_op0) == DImode
- && ! TARGET_ARCH64)
- FAIL;
-
- if (sparc_compare_op1 == const0_rtx
- && GET_CODE (sparc_compare_op0) == REG
- && GET_MODE (sparc_compare_op0) == DImode
- && v9_regcmp_p (code))
- {
- operands[1] = gen_rtx_fmt_ee (code, DImode,
- sparc_compare_op0, sparc_compare_op1);
- }
- else
- {
- rtx cc_reg = gen_compare_reg (code);
- operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
- }
-})
-
-(define_expand "movtfcc"
- [(set (match_operand:TF 0 "register_operand" "")
- (if_then_else:TF (match_operand 1 "comparison_operator" "")
- (match_operand:TF 2 "register_operand" "")
- (match_operand:TF 3 "register_operand" "")))]
- "TARGET_V9 && TARGET_FPU"
-{
- enum rtx_code code = GET_CODE (operands[1]);
-
- if (GET_MODE (sparc_compare_op0) == DImode
- && ! TARGET_ARCH64)
- FAIL;
-
- if (sparc_compare_op1 == const0_rtx
- && GET_CODE (sparc_compare_op0) == REG
- && GET_MODE (sparc_compare_op0) == DImode
- && v9_regcmp_p (code))
- {
- operands[1] = gen_rtx_fmt_ee (code, DImode,
- sparc_compare_op0, sparc_compare_op1);
- }
- else
- {
- rtx cc_reg = gen_compare_reg (code);
- operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
- }
-})
-
-;; Conditional move define_insns.
-
-(define_insn "*movqi_cc_sp64"
- [(set (match_operand:QI 0 "register_operand" "=r,r")
- (if_then_else:QI (match_operator 1 "comparison_operator"
- [(match_operand 2 "icc_or_fcc_register_operand" "X,X")
- (const_int 0)])
- (match_operand:QI 3 "arith11_operand" "rL,0")
- (match_operand:QI 4 "arith11_operand" "0,rL")))]
- "TARGET_V9"
- "@
- mov%C1\t%x2, %3, %0
- mov%c1\t%x2, %4, %0"
- [(set_attr "type" "cmove")])
-
-(define_insn "*movhi_cc_sp64"
- [(set (match_operand:HI 0 "register_operand" "=r,r")
- (if_then_else:HI (match_operator 1 "comparison_operator"
- [(match_operand 2 "icc_or_fcc_register_operand" "X,X")
- (const_int 0)])
- (match_operand:HI 3 "arith11_operand" "rL,0")
- (match_operand:HI 4 "arith11_operand" "0,rL")))]
- "TARGET_V9"
- "@
- mov%C1\t%x2, %3, %0
- mov%c1\t%x2, %4, %0"
- [(set_attr "type" "cmove")])
-
-(define_insn "*movsi_cc_sp64"
- [(set (match_operand:SI 0 "register_operand" "=r,r")
- (if_then_else:SI (match_operator 1 "comparison_operator"
- [(match_operand 2 "icc_or_fcc_register_operand" "X,X")
- (const_int 0)])
- (match_operand:SI 3 "arith11_operand" "rL,0")
- (match_operand:SI 4 "arith11_operand" "0,rL")))]
- "TARGET_V9"
- "@
- mov%C1\t%x2, %3, %0
- mov%c1\t%x2, %4, %0"
- [(set_attr "type" "cmove")])
+;; Conditional move define_insns
-(define_insn "*movdi_cc_sp64"
- [(set (match_operand:DI 0 "register_operand" "=r,r")
- (if_then_else:DI (match_operator 1 "comparison_operator"
- [(match_operand 2 "icc_or_fcc_register_operand" "X,X")
- (const_int 0)])
- (match_operand:DI 3 "arith11_operand" "rL,0")
- (match_operand:DI 4 "arith11_operand" "0,rL")))]
- "TARGET_ARCH64"
+(define_insn "*mov<I:mode>_cc_v9"
+ [(set (match_operand:I 0 "register_operand" "=r,r")
+ (if_then_else:I (match_operator 1 "comparison_operator"
+ [(match_operand 2 "icc_or_fcc_register_operand" "X,X")
+ (const_int 0)])
+ (match_operand:I 3 "arith11_operand" "rL,0")
+ (match_operand:I 4 "arith11_operand" "0,rL")))]
+ "TARGET_V9 && !(<I:MODE>mode == DImode && TARGET_ARCH32)"
"@
mov%C1\t%x2, %3, %0
mov%c1\t%x2, %4, %0"
[(set_attr "type" "cmove")])
-(define_insn "*movdi_cc_sp64_trunc"
- [(set (match_operand:SI 0 "register_operand" "=r,r")
- (if_then_else:SI (match_operator 1 "comparison_operator"
- [(match_operand 2 "icc_or_fcc_register_operand" "X,X")
+(define_insn "*mov<I:mode>_cc_reg_sp64"
+ [(set (match_operand:I 0 "register_operand" "=r,r")
+ (if_then_else:I (match_operator 1 "v9_register_compare_operator"
+ [(match_operand:DI 2 "register_operand" "r,r")
(const_int 0)])
- (match_operand:SI 3 "arith11_operand" "rL,0")
- (match_operand:SI 4 "arith11_operand" "0,rL")))]
+ (match_operand:I 3 "arith10_operand" "rM,0")
+ (match_operand:I 4 "arith10_operand" "0,rM")))]
"TARGET_ARCH64"
"@
- mov%C1\t%x2, %3, %0
- mov%c1\t%x2, %4, %0"
+ movr%D1\t%2, %r3, %0
+ movr%d1\t%2, %r4, %0"
[(set_attr "type" "cmove")])
-(define_insn "*movsf_cc_sp64"
+(define_insn "*movsf_cc_v9"
[(set (match_operand:SF 0 "register_operand" "=f,f")
(if_then_else:SF (match_operator 1 "comparison_operator"
[(match_operand 2 "icc_or_fcc_register_operand" "X,X")
(const_int 0)])
- (match_operand:SF 3 "register_operand" "f,0")
- (match_operand:SF 4 "register_operand" "0,f")))]
+ (match_operand:SF 3 "register_operand" "f,0")
+ (match_operand:SF 4 "register_operand" "0,f")))]
"TARGET_V9 && TARGET_FPU"
"@
fmovs%C1\t%x2, %3, %0
fmovs%c1\t%x2, %4, %0"
[(set_attr "type" "fpcmove")])
-(define_insn "movdf_cc_sp64"
+(define_insn "*movsf_cc_reg_sp64"
+ [(set (match_operand:SF 0 "register_operand" "=f,f")
+ (if_then_else:SF (match_operator 1 "v9_register_compare_operator"
+ [(match_operand:DI 2 "register_operand" "r,r")
+ (const_int 0)])
+ (match_operand:SF 3 "register_operand" "f,0")
+ (match_operand:SF 4 "register_operand" "0,f")))]
+ "TARGET_ARCH64 && TARGET_FPU"
+ "@
+ fmovrs%D1\t%2, %3, %0
+ fmovrs%d1\t%2, %4, %0"
+ [(set_attr "type" "fpcrmove")])
+
+;; Named because invoked by movtf_cc_v9
+(define_insn "movdf_cc_v9"
[(set (match_operand:DF 0 "register_operand" "=e,e")
(if_then_else:DF (match_operator 1 "comparison_operator"
[(match_operand 2 "icc_or_fcc_register_operand" "X,X")
(const_int 0)])
- (match_operand:DF 3 "register_operand" "e,0")
- (match_operand:DF 4 "register_operand" "0,e")))]
+ (match_operand:DF 3 "register_operand" "e,0")
+ (match_operand:DF 4 "register_operand" "0,e")))]
"TARGET_V9 && TARGET_FPU"
"@
fmovd%C1\t%x2, %3, %0
@@ -3307,26 +3179,54 @@ (define_insn "movdf_cc_sp64"
[(set_attr "type" "fpcmove")
(set_attr "fptype" "double")])
-(define_insn "*movtf_cc_hq_sp64"
+;; Named because invoked by movtf_cc_reg_sp64
+(define_insn "movdf_cc_reg_sp64"
+ [(set (match_operand:DF 0 "register_operand" "=e,e")
+ (if_then_else:DF (match_operator 1 "v9_register_compare_operator"
+ [(match_operand:DI 2 "register_operand" "r,r")
+ (const_int 0)])
+ (match_operand:DF 3 "register_operand" "e,0")
+ (match_operand:DF 4 "register_operand" "0,e")))]
+ "TARGET_ARCH64 && TARGET_FPU"
+ "@
+ fmovrd%D1\t%2, %3, %0
+ fmovrd%d1\t%2, %4, %0"
+ [(set_attr "type" "fpcrmove")
+ (set_attr "fptype" "double")])
+
+(define_insn "*movtf_cc_hq_v9"
[(set (match_operand:TF 0 "register_operand" "=e,e")
(if_then_else:TF (match_operator 1 "comparison_operator"
[(match_operand 2 "icc_or_fcc_register_operand" "X,X")
(const_int 0)])
- (match_operand:TF 3 "register_operand" "e,0")
- (match_operand:TF 4 "register_operand" "0,e")))]
+ (match_operand:TF 3 "register_operand" "e,0")
+ (match_operand:TF 4 "register_operand" "0,e")))]
"TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD"
"@
fmovq%C1\t%x2, %3, %0
fmovq%c1\t%x2, %4, %0"
[(set_attr "type" "fpcmove")])
-(define_insn_and_split "*movtf_cc_sp64"
+(define_insn "*movtf_cc_reg_hq_sp64"
+ [(set (match_operand:TF 0 "register_operand" "=e,e")
+ (if_then_else:TF (match_operator 1 "v9_register_compare_operator"
+ [(match_operand:DI 2 "register_operand" "r,r")
+ (const_int 0)])
+ (match_operand:TF 3 "register_operand" "e,0")
+ (match_operand:TF 4 "register_operand" "0,e")))]
+ "TARGET_ARCH64 && TARGET_FPU && TARGET_HARD_QUAD"
+ "@
+ fmovrq%D1\t%2, %3, %0
+ fmovrq%d1\t%2, %4, %0"
+ [(set_attr "type" "fpcrmove")])
+
+(define_insn_and_split "*movtf_cc_v9"
[(set (match_operand:TF 0 "register_operand" "=e,e")
(if_then_else:TF (match_operator 1 "comparison_operator"
[(match_operand 2 "icc_or_fcc_register_operand" "X,X")
(const_int 0)])
- (match_operand:TF 3 "register_operand" "e,0")
- (match_operand:TF 4 "register_operand" "0,e")))]
+ (match_operand:TF 3 "register_operand" "e,0")
+ (match_operand:TF 4 "register_operand" "0,e")))]
"TARGET_V9 && TARGET_FPU && !TARGET_HARD_QUAD"
"#"
"&& reload_completed"
@@ -3351,117 +3251,25 @@ (define_insn_and_split "*movtf_cc_sp64"
if ((third && reg_overlap_mentioned_p (dest1, srcb2))
|| (!third && reg_overlap_mentioned_p (dest1, srca2)))
{
- emit_insn (gen_movdf_cc_sp64 (dest2, operands[1], operands[2], srca2, srcb2));
- emit_insn (gen_movdf_cc_sp64 (dest1, operands[1], operands[2], srca1, srcb1));
+ emit_insn (gen_movdf_cc_v9 (dest2, operands[1], operands[2], srca2, srcb2));
+ emit_insn (gen_movdf_cc_v9 (dest1, operands[1], operands[2], srca1, srcb1));
}
else
{
- emit_insn (gen_movdf_cc_sp64 (dest1, operands[1], operands[2], srca1, srcb1));
- emit_insn (gen_movdf_cc_sp64 (dest2, operands[1], operands[2], srca2, srcb2));
+ emit_insn (gen_movdf_cc_v9 (dest1, operands[1], operands[2], srca1, srcb1));
+ emit_insn (gen_movdf_cc_v9 (dest2, operands[1], operands[2], srca2, srcb2));
}
DONE;
}
[(set_attr "length" "2")])
-(define_insn "*movqi_cc_reg_sp64"
- [(set (match_operand:QI 0 "register_operand" "=r,r")
- (if_then_else:QI (match_operator 1 "v9_register_compare_operator"
- [(match_operand:DI 2 "register_operand" "r,r")
- (const_int 0)])
- (match_operand:QI 3 "arith10_operand" "rM,0")
- (match_operand:QI 4 "arith10_operand" "0,rM")))]
- "TARGET_ARCH64"
- "@
- movr%D1\t%2, %r3, %0
- movr%d1\t%2, %r4, %0"
- [(set_attr "type" "cmove")])
-
-(define_insn "*movhi_cc_reg_sp64"
- [(set (match_operand:HI 0 "register_operand" "=r,r")
- (if_then_else:HI (match_operator 1 "v9_register_compare_operator"
- [(match_operand:DI 2 "register_operand" "r,r")
- (const_int 0)])
- (match_operand:HI 3 "arith10_operand" "rM,0")
- (match_operand:HI 4 "arith10_operand" "0,rM")))]
- "TARGET_ARCH64"
- "@
- movr%D1\t%2, %r3, %0
- movr%d1\t%2, %r4, %0"
- [(set_attr "type" "cmove")])
-
-(define_insn "*movsi_cc_reg_sp64"
- [(set (match_operand:SI 0 "register_operand" "=r,r")
- (if_then_else:SI (match_operator 1 "v9_register_compare_operator"
- [(match_operand:DI 2 "register_operand" "r,r")
- (const_int 0)])
- (match_operand:SI 3 "arith10_operand" "rM,0")
- (match_operand:SI 4 "arith10_operand" "0,rM")))]
- "TARGET_ARCH64"
- "@
- movr%D1\t%2, %r3, %0
- movr%d1\t%2, %r4, %0"
- [(set_attr "type" "cmove")])
-
-(define_insn "*movdi_cc_reg_sp64"
- [(set (match_operand:DI 0 "register_operand" "=r,r")
- (if_then_else:DI (match_operator 1 "v9_register_compare_operator"
- [(match_operand:DI 2 "register_operand" "r,r")
- (const_int 0)])
- (match_operand:DI 3 "arith10_operand" "rM,0")
- (match_operand:DI 4 "arith10_operand" "0,rM")))]
- "TARGET_ARCH64"
- "@
- movr%D1\t%2, %r3, %0
- movr%d1\t%2, %r4, %0"
- [(set_attr "type" "cmove")])
-
-(define_insn "*movsf_cc_reg_sp64"
- [(set (match_operand:SF 0 "register_operand" "=f,f")
- (if_then_else:SF (match_operator 1 "v9_register_compare_operator"
- [(match_operand:DI 2 "register_operand" "r,r")
- (const_int 0)])
- (match_operand:SF 3 "register_operand" "f,0")
- (match_operand:SF 4 "register_operand" "0,f")))]
- "TARGET_ARCH64 && TARGET_FPU"
- "@
- fmovrs%D1\t%2, %3, %0
- fmovrs%d1\t%2, %4, %0"
- [(set_attr "type" "fpcrmove")])
-
-(define_insn "movdf_cc_reg_sp64"
- [(set (match_operand:DF 0 "register_operand" "=e,e")
- (if_then_else:DF (match_operator 1 "v9_register_compare_operator"
- [(match_operand:DI 2 "register_operand" "r,r")
- (const_int 0)])
- (match_operand:DF 3 "register_operand" "e,0")
- (match_operand:DF 4 "register_operand" "0,e")))]
- "TARGET_ARCH64 && TARGET_FPU"
- "@
- fmovrd%D1\t%2, %3, %0
- fmovrd%d1\t%2, %4, %0"
- [(set_attr "type" "fpcrmove")
- (set_attr "fptype" "double")])
-
-(define_insn "*movtf_cc_reg_hq_sp64"
- [(set (match_operand:TF 0 "register_operand" "=e,e")
- (if_then_else:TF (match_operator 1 "v9_register_compare_operator"
- [(match_operand:DI 2 "register_operand" "r,r")
- (const_int 0)])
- (match_operand:TF 3 "register_operand" "e,0")
- (match_operand:TF 4 "register_operand" "0,e")))]
- "TARGET_ARCH64 && TARGET_FPU && TARGET_HARD_QUAD"
- "@
- fmovrq%D1\t%2, %3, %0
- fmovrq%d1\t%2, %4, %0"
- [(set_attr "type" "fpcrmove")])
-
(define_insn_and_split "*movtf_cc_reg_sp64"
[(set (match_operand:TF 0 "register_operand" "=e,e")
(if_then_else:TF (match_operator 1 "v9_register_compare_operator"
[(match_operand:DI 2 "register_operand" "r,r")
(const_int 0)])
- (match_operand:TF 3 "register_operand" "e,0")
- (match_operand:TF 4 "register_operand" "0,e")))]
+ (match_operand:TF 3 "register_operand" "e,0")
+ (match_operand:TF 4 "register_operand" "0,e")))]
"TARGET_ARCH64 && TARGET_FPU && ! TARGET_HARD_QUAD"
"#"
"&& reload_completed"
Index: config/sparc/sparc-protos.h
===================================================================
--- config/sparc/sparc-protos.h (revision 140483)
+++ config/sparc/sparc-protos.h (working copy)
@@ -54,7 +54,8 @@ extern void sparc_output_scratch_registe
extern enum machine_mode select_cc_mode (enum rtx_code, rtx, rtx);
/* Define the function that build the compare insn for scc and bcc. */
extern rtx gen_compare_reg (enum rtx_code code);
-extern void sparc_emit_float_lib_cmp (rtx, rtx, enum rtx_code);
+extern rtx gen_compare_operator (enum rtx_code code);
+extern enum rtx_code sparc_emit_float_lib_cmp (rtx, rtx, enum rtx_code);
extern void sparc_emit_floatunsdi (rtx [2], enum machine_mode);
extern void sparc_emit_fixunsdi (rtx [2], enum machine_mode);
extern void emit_tfmode_binop (enum rtx_code, rtx *);
Index: config/sparc/sparc.c
===================================================================
--- config/sparc/sparc.c (revision 140483)
+++ config/sparc/sparc.c (working copy)
@@ -2001,8 +2001,7 @@ select_cc_mode (enum rtx_code op, rtx x,
}
}
-/* X and Y are two things to compare using CODE. Emit the compare insn and
- return the rtx for the cc reg in the proper mode. */
+/* Emit the compare insn and return the CC reg for a CODE comparison. */
rtx
gen_compare_reg (enum rtx_code code)
@@ -2065,12 +2064,28 @@ gen_compare_reg (enum rtx_code code)
else
cc_reg = gen_rtx_REG (mode, SPARC_ICC_REG);
- emit_insn (gen_rtx_SET (VOIDmode, cc_reg,
- gen_rtx_COMPARE (mode, x, y)));
+ /* We shouldn't get there for TFmode if !TARGET_HARD_QUAD. If we do, this
+ will only result in an unrecognizable insn so no point in asserting. */
+ emit_insn (gen_rtx_SET (VOIDmode, cc_reg, gen_rtx_COMPARE (mode, x, y)));
return cc_reg;
}
+/* Same as above but return the whole compare operator. */
+
+rtx
+gen_compare_operator (enum rtx_code code)
+{
+ rtx cc_reg;
+
+ if (GET_MODE (sparc_compare_op0) == TFmode && !TARGET_HARD_QUAD)
+ code
+ = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, code);
+
+ cc_reg = gen_compare_reg (code);
+ return gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
+}
+
/* This function is used for v9 only.
CODE is the code for an Scc's comparison.
OPERANDS[0] is the target of the Scc insn.
@@ -6099,41 +6114,45 @@ output_cbranch (rtx op, rtx dest, int la
}
/* Emit a library call comparison between floating point X and Y.
- COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.).
+ COMPARISON is the operator to compare with (EQ, NE, GT, etc).
+ Return the new operator to be used in the comparison sequence.
+
TARGET_ARCH64 uses _Qp_* functions, which use pointers to TFmode
values as arguments instead of the TFmode registers themselves,
that's why we cannot call emit_float_lib_cmp. */
-void
+
+enum rtx_code
sparc_emit_float_lib_cmp (rtx x, rtx y, enum rtx_code comparison)
{
const char *qpfunc;
rtx slot0, slot1, result, tem, tem2;
enum machine_mode mode;
+ enum rtx_code new_comparison;
switch (comparison)
{
case EQ:
- qpfunc = (TARGET_ARCH64) ? "_Qp_feq" : "_Q_feq";
+ qpfunc = (TARGET_ARCH64 ? "_Qp_feq" : "_Q_feq");
break;
case NE:
- qpfunc = (TARGET_ARCH64) ? "_Qp_fne" : "_Q_fne";
+ qpfunc = (TARGET_ARCH64 ? "_Qp_fne" : "_Q_fne");
break;
case GT:
- qpfunc = (TARGET_ARCH64) ? "_Qp_fgt" : "_Q_fgt";
+ qpfunc = (TARGET_ARCH64 ? "_Qp_fgt" : "_Q_fgt");
break;
case GE:
- qpfunc = (TARGET_ARCH64) ? "_Qp_fge" : "_Q_fge";
+ qpfunc = (TARGET_ARCH64 ? "_Qp_fge" : "_Q_fge");
break;
case LT:
- qpfunc = (TARGET_ARCH64) ? "_Qp_flt" : "_Q_flt";
+ qpfunc = (TARGET_ARCH64 ? "_Qp_flt" : "_Q_flt");
break;
case LE:
- qpfunc = (TARGET_ARCH64) ? "_Qp_fle" : "_Q_fle";
+ qpfunc = (TARGET_ARCH64 ? "_Qp_fle" : "_Q_fle");
break;
case ORDERED:
@@ -6144,7 +6163,7 @@ sparc_emit_float_lib_cmp (rtx x, rtx y,
case UNGE:
case UNLE:
case LTGT:
- qpfunc = (TARGET_ARCH64) ? "_Qp_cmp" : "_Q_cmp";
+ qpfunc = (TARGET_ARCH64 ? "_Qp_cmp" : "_Q_cmp");
break;
default:
@@ -6153,27 +6172,26 @@ sparc_emit_float_lib_cmp (rtx x, rtx y,
if (TARGET_ARCH64)
{
- if (GET_CODE (x) != MEM)
+ if (MEM_P (x))
+ slot0 = x;
+ else
{
slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
emit_move_insn (slot0, x);
}
- else
- slot0 = x;
- if (GET_CODE (y) != MEM)
+ if (MEM_P (y))
+ slot1 = y;
+ else
{
slot1 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
emit_move_insn (slot1, y);
}
- else
- slot1 = y;
emit_library_call (gen_rtx_SYMBOL_REF (Pmode, qpfunc), LCT_NORMAL,
DImode, 2,
XEXP (slot0, 0), Pmode,
XEXP (slot1, 0), Pmode);
-
mode = DImode;
}
else
@@ -6181,7 +6199,6 @@ sparc_emit_float_lib_cmp (rtx x, rtx y,
emit_library_call (gen_rtx_SYMBOL_REF (Pmode, qpfunc), LCT_NORMAL,
SImode, 2,
x, TFmode, y, TFmode);
-
mode = SImode;
}
@@ -6195,20 +6212,22 @@ sparc_emit_float_lib_cmp (rtx x, rtx y,
switch (comparison)
{
default:
- emit_cmp_insn (result, const0_rtx, NE, NULL_RTX, mode, 0);
+ new_comparison = NE;
+ emit_cmp_insn (result, const0_rtx, new_comparison, NULL_RTX, mode, 0);
break;
case ORDERED:
case UNORDERED:
- emit_cmp_insn (result, GEN_INT(3), comparison == UNORDERED ? EQ : NE,
- NULL_RTX, mode, 0);
+ new_comparison = (comparison == UNORDERED ? EQ : NE);
+ emit_cmp_insn (result, GEN_INT(3), new_comparison, NULL_RTX, mode, 0);
break;
case UNGT:
case UNGE:
- emit_cmp_insn (result, const1_rtx,
- comparison == UNGT ? GT : NE, NULL_RTX, mode, 0);
+ new_comparison = (comparison == UNGT ? GT : NE);
+ emit_cmp_insn (result, const1_rtx, new_comparison, NULL_RTX, mode, 0);
break;
case UNLE:
- emit_cmp_insn (result, const2_rtx, NE, NULL_RTX, mode, 0);
+ new_comparison = NE;
+ emit_cmp_insn (result, const2_rtx, new_comparison, NULL_RTX, mode, 0);
break;
case UNLT:
tem = gen_reg_rtx (mode);
@@ -6216,7 +6235,8 @@ sparc_emit_float_lib_cmp (rtx x, rtx y,
emit_insn (gen_andsi3 (tem, result, const1_rtx));
else
emit_insn (gen_anddi3 (tem, result, const1_rtx));
- emit_cmp_insn (tem, const0_rtx, NE, NULL_RTX, mode, 0);
+ new_comparison = NE;
+ emit_cmp_insn (tem, const0_rtx, new_comparison, NULL_RTX, mode, 0);
break;
case UNEQ:
case LTGT:
@@ -6230,10 +6250,12 @@ sparc_emit_float_lib_cmp (rtx x, rtx y,
emit_insn (gen_andsi3 (tem2, tem, const2_rtx));
else
emit_insn (gen_anddi3 (tem2, tem, const2_rtx));
- emit_cmp_insn (tem2, const0_rtx, comparison == UNEQ ? EQ : NE,
- NULL_RTX, mode, 0);
+ new_comparison = (comparison == UNEQ ? EQ : NE);
+ emit_cmp_insn (tem2, const0_rtx, new_comparison, NULL_RTX, mode, 0);
break;
}
+
+ return new_comparison;
}
/* Generate an unsigned DImode to FP conversion. This is the same code