This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[cond-optab] Convert rs6000
- From: Paolo Bonzini <bonzini at gnu dot org>
- To: <gcc-patches at gcc dot gnu dot org>
- Date: Thu, 26 Mar 2009 04:35:50 -0400
- Subject: [cond-optab] Convert rs6000
The rs6000 code needed a lot of search-and-replace, but otherwise it is
quite plain. It is also different in that it sometimes prefers the
standard portable sequences for sCC.
Paolo
2009-03-26 Paolo Bonzini <bonzini@gnu.org>
* config/rs6000/predicates.md (rs6000_cbranch_operator): New.
(trap_comparison_operator): Delete.
* config/rs6000/rs6000-protos.h (rs6000_emit_sCOND,
rs6000_emit_cbranch): Accept mode and operands.
* config/rs6000/rs6000.c (rs6000_compare_op0, rs6000_compare_op1,
rs6000_compare_fp_p): Delete.
(rs6000_generate_compare): Accept mode and comparison. Extract code
and op0/op1 from there. Replace references to rs6000_compare_op0
and rs6000_compare_op1.
(rs6000_emit_sCOND): Adjust call to rs6000_generate_compare and
extract result from passed operands.
(rs6000_emit_cbranch): Adjust call to rs6000_generate_compare and
extract loc from passed operands.
(rs6000_emit_cmove): Likewise.
* config/rs6000/rs6000.h (rs6000_compare_op0, rs6000_compare_op1,
rs6000_compare_fp_p): Delete.
* config/rs6000/rs6000.md (cmp<GPR>, cmp<FP>, bCC, sCC): Delete.
(cbranch<GPR>4, cbranch<FP>4): New.
(cstore<mode>4): New. Consolidate here all choices about when to use
portable or specialized sCC sequences.
(stack_protect_test): Use cbranchsi4.
(conditional_trap): Replace with ctrap<GPR>4.
(conditional trap insn): Replace trap_comparison_operator with
ordered_comparison_operator.
Index: gcc/config/rs6000/predicates.md
===================================================================
--- gcc/config/rs6000/predicates.md (branch cond-optab)
+++ gcc/config/rs6000/predicates.md (working copy)
@@ -830,6 +830,11 @@
GET_MODE (XEXP (op, 0))),
1"))))
+(define_predicate "rs6000_cbranch_operator"
+ (if_then_else (match_test "TARGET_HARD_FLOAT && !TARGET_FPRS")
+ (match_operand 0 "ordered_comparison_operator")
+ (match_operand 0 "comparison_operator")))
+
;; Return 1 if OP is a comparison operation that is valid for an SCC insn --
;; it must be a positive comparison.
(define_predicate "scc_comparison_operator"
@@ -842,11 +847,6 @@
(and (match_operand 0 "branch_comparison_operator")
(match_code "eq,lt,gt,ltu,gtu,unordered")))
-;; Return 1 is OP is a comparison operation that is valid for a trap insn.
-(define_predicate "trap_comparison_operator"
- (and (match_operand 0 "comparison_operator")
- (match_code "eq,ne,le,lt,ge,gt,leu,ltu,geu,gtu")))
-
;; Return 1 if OP is a load multiple operation, known to be a PARALLEL.
(define_predicate "load_multiple_operation"
(match_code "parallel")
Index: gcc/config/rs6000/rs6000-protos.h
===================================================================
--- gcc/config/rs6000/rs6000-protos.h (branch cond-optab)
+++ gcc/config/rs6000/rs6000-protos.h (working copy)
@@ -81,8 +81,8 @@ extern void print_operand_address (FILE
extern bool rs6000_output_addr_const_extra (FILE *, rtx);
extern enum rtx_code rs6000_reverse_condition (enum machine_mode,
enum rtx_code);
-extern void rs6000_emit_sCOND (enum rtx_code, rtx);
-extern void rs6000_emit_cbranch (enum rtx_code, rtx);
+extern void rs6000_emit_sCOND (enum machine_mode, rtx[]);
+extern void rs6000_emit_cbranch (enum machine_mode, rtx[]);
extern char * output_cbranch (rtx, const char *, int, rtx);
extern char * output_e500_flip_gt_bit (rtx, rtx);
extern rtx rs6000_emit_set_const (rtx, enum machine_mode, rtx, int);
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c (branch cond-optab)
+++ gcc/config/rs6000/rs6000.c (working copy)
@@ -190,11 +190,6 @@ int rs6000_darwin64_abi;
/* Set to nonzero once AIX common-mode calls have been defined. */
static GTY(()) int common_mode_defined;
-/* Save information from a "cmpxx" operation until the branch or scc is
- emitted. */
-rtx rs6000_compare_op0, rs6000_compare_op1;
-int rs6000_compare_fp_p;
-
/* Label number of label created for -mrelocatable, to call to so we can
get the address of the GOT section */
int rs6000_pic_labelno;
@@ -752,7 +747,7 @@ struct processor_costs power6_cost = {
static bool rs6000_function_ok_for_sibcall (tree, tree);
static const char *rs6000_invalid_within_doloop (const_rtx);
-static rtx rs6000_generate_compare (enum rtx_code);
+static rtx rs6000_generate_compare (rtx, enum machine_mode);
static void rs6000_emit_stack_tie (void);
static void rs6000_frame_related (rtx, rtx, HOST_WIDE_INT, rtx, rtx);
static bool spe_func_has_64bit_regs_p (void);
@@ -12774,21 +12769,24 @@ rs6000_reverse_condition (enum machine_m
represents the result of the compare. */
static rtx
-rs6000_generate_compare (enum rtx_code code)
+rs6000_generate_compare (rtx cmp, enum machine_mode mode)
{
enum machine_mode comp_mode;
rtx compare_result;
+ enum rtx_code code = GET_CODE (cmp);
+ rtx op0 = XEXP (cmp, 0);
+ rtx op1 = XEXP (cmp, 1);
- if (rs6000_compare_fp_p)
+ if (FLOAT_MODE_P (mode))
comp_mode = CCFPmode;
else if (code == GTU || code == LTU
|| code == GEU || code == LEU)
comp_mode = CCUNSmode;
else if ((code == EQ || code == NE)
- && GET_CODE (rs6000_compare_op0) == SUBREG
- && GET_CODE (rs6000_compare_op1) == SUBREG
- && SUBREG_PROMOTED_UNSIGNED_P (rs6000_compare_op0)
- && SUBREG_PROMOTED_UNSIGNED_P (rs6000_compare_op1))
+ && GET_CODE (op0) == SUBREG
+ && GET_CODE (op1) == SUBREG
+ && SUBREG_PROMOTED_UNSIGNED_P (op0)
+ && SUBREG_PROMOTED_UNSIGNED_P (op1))
/* These are unsigned values, perhaps there will be a later
ordering compare that can be shared with this one.
Unfortunately we cannot detect the signedness of the operands
@@ -12802,13 +12800,13 @@ rs6000_generate_compare (enum rtx_code c
/* E500 FP compare instructions on the GPRs. Yuck! */
if ((!TARGET_FPRS && TARGET_HARD_FLOAT)
- && rs6000_compare_fp_p)
+ && FLOAT_MODE_P (mode))
{
rtx cmp, or_result, compare_result2;
- enum machine_mode op_mode = GET_MODE (rs6000_compare_op0);
+ enum machine_mode op_mode = GET_MODE (op0);
if (op_mode == VOIDmode)
- op_mode = GET_MODE (rs6000_compare_op1);
+ op_mode = GET_MODE (op1);
/* The E500 FP compare instructions toggle the GT bit (CR bit 1) only.
This explains the following mess. */
@@ -12820,26 +12818,20 @@ rs6000_generate_compare (enum rtx_code c
{
case SFmode:
cmp = (flag_finite_math_only && !flag_trapping_math)
- ? gen_tstsfeq_gpr (compare_result, rs6000_compare_op0,
- rs6000_compare_op1)
- : gen_cmpsfeq_gpr (compare_result, rs6000_compare_op0,
- rs6000_compare_op1);
+ ? gen_tstsfeq_gpr (compare_result, op0, op1)
+ : gen_cmpsfeq_gpr (compare_result, op0, op1);
break;
case DFmode:
cmp = (flag_finite_math_only && !flag_trapping_math)
- ? gen_tstdfeq_gpr (compare_result, rs6000_compare_op0,
- rs6000_compare_op1)
- : gen_cmpdfeq_gpr (compare_result, rs6000_compare_op0,
- rs6000_compare_op1);
+ ? gen_tstdfeq_gpr (compare_result, op0, op1)
+ : gen_cmpdfeq_gpr (compare_result, op0, op1);
break;
case TFmode:
cmp = (flag_finite_math_only && !flag_trapping_math)
- ? gen_tsttfeq_gpr (compare_result, rs6000_compare_op0,
- rs6000_compare_op1)
- : gen_cmptfeq_gpr (compare_result, rs6000_compare_op0,
- rs6000_compare_op1);
+ ? gen_tsttfeq_gpr (compare_result, op0, op1)
+ : gen_cmptfeq_gpr (compare_result, op0, op1);
break;
default:
@@ -12852,26 +12844,20 @@ rs6000_generate_compare (enum rtx_code c
{
case SFmode:
cmp = (flag_finite_math_only && !flag_trapping_math)
- ? gen_tstsfgt_gpr (compare_result, rs6000_compare_op0,
- rs6000_compare_op1)
- : gen_cmpsfgt_gpr (compare_result, rs6000_compare_op0,
- rs6000_compare_op1);
+ ? gen_tstsfgt_gpr (compare_result, op0, op1)
+ : gen_cmpsfgt_gpr (compare_result, op0, op1);
break;
case DFmode:
cmp = (flag_finite_math_only && !flag_trapping_math)
- ? gen_tstdfgt_gpr (compare_result, rs6000_compare_op0,
- rs6000_compare_op1)
- : gen_cmpdfgt_gpr (compare_result, rs6000_compare_op0,
- rs6000_compare_op1);
+ ? gen_tstdfgt_gpr (compare_result, op0, op1)
+ : gen_cmpdfgt_gpr (compare_result, op0, op1);
break;
case TFmode:
cmp = (flag_finite_math_only && !flag_trapping_math)
- ? gen_tsttfgt_gpr (compare_result, rs6000_compare_op0,
- rs6000_compare_op1)
- : gen_cmptfgt_gpr (compare_result, rs6000_compare_op0,
- rs6000_compare_op1);
+ ? gen_tsttfgt_gpr (compare_result, op0, op1)
+ : gen_cmptfgt_gpr (compare_result, op0, op1);
break;
default:
@@ -12884,26 +12870,20 @@ rs6000_generate_compare (enum rtx_code c
{
case SFmode:
cmp = (flag_finite_math_only && !flag_trapping_math)
- ? gen_tstsflt_gpr (compare_result, rs6000_compare_op0,
- rs6000_compare_op1)
- : gen_cmpsflt_gpr (compare_result, rs6000_compare_op0,
- rs6000_compare_op1);
+ ? gen_tstsflt_gpr (compare_result, op0, op1)
+ : gen_cmpsflt_gpr (compare_result, op0, op1);
break;
case DFmode:
cmp = (flag_finite_math_only && !flag_trapping_math)
- ? gen_tstdflt_gpr (compare_result, rs6000_compare_op0,
- rs6000_compare_op1)
- : gen_cmpdflt_gpr (compare_result, rs6000_compare_op0,
- rs6000_compare_op1);
+ ? gen_tstdflt_gpr (compare_result, op0, op1)
+ : gen_cmpdflt_gpr (compare_result, op0, op1);
break;
case TFmode:
cmp = (flag_finite_math_only && !flag_trapping_math)
- ? gen_tsttflt_gpr (compare_result, rs6000_compare_op0,
- rs6000_compare_op1)
- : gen_cmptflt_gpr (compare_result, rs6000_compare_op0,
- rs6000_compare_op1);
+ ? gen_tsttflt_gpr (compare_result, op0, op1)
+ : gen_cmptflt_gpr (compare_result, op0, op1);
break;
default:
@@ -12935,26 +12915,20 @@ rs6000_generate_compare (enum rtx_code c
{
case SFmode:
cmp = (flag_finite_math_only && !flag_trapping_math)
- ? gen_tstsfeq_gpr (compare_result2, rs6000_compare_op0,
- rs6000_compare_op1)
- : gen_cmpsfeq_gpr (compare_result2, rs6000_compare_op0,
- rs6000_compare_op1);
+ ? gen_tstsfeq_gpr (compare_result2, op0, op1)
+ : gen_cmpsfeq_gpr (compare_result2, op0, op1);
break;
case DFmode:
cmp = (flag_finite_math_only && !flag_trapping_math)
- ? gen_tstdfeq_gpr (compare_result2, rs6000_compare_op0,
- rs6000_compare_op1)
- : gen_cmpdfeq_gpr (compare_result2, rs6000_compare_op0,
- rs6000_compare_op1);
+ ? gen_tstdfeq_gpr (compare_result2, op0, op1)
+ : gen_cmpdfeq_gpr (compare_result2, op0, op1);
break;
case TFmode:
cmp = (flag_finite_math_only && !flag_trapping_math)
- ? gen_tsttfeq_gpr (compare_result2, rs6000_compare_op0,
- rs6000_compare_op1)
- : gen_cmptfeq_gpr (compare_result2, rs6000_compare_op0,
- rs6000_compare_op1);
+ ? gen_tsttfeq_gpr (compare_result2, op0, op1)
+ : gen_cmptfeq_gpr (compare_result2, op0, op1);
break;
default:
@@ -12984,16 +12958,14 @@ rs6000_generate_compare (enum rtx_code c
/* Generate XLC-compatible TFmode compare as PARALLEL with extra
CLOBBERs to match cmptf_internal2 pattern. */
if (comp_mode == CCFPmode && TARGET_XL_COMPAT
- && GET_MODE (rs6000_compare_op0) == TFmode
+ && GET_MODE (op0) == TFmode
&& !TARGET_IEEEQUAD
&& TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128)
emit_insn (gen_rtx_PARALLEL (VOIDmode,
gen_rtvec (9,
gen_rtx_SET (VOIDmode,
compare_result,
- gen_rtx_COMPARE (comp_mode,
- rs6000_compare_op0,
- rs6000_compare_op1)),
+ gen_rtx_COMPARE (comp_mode, op0, op1)),
gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (DFmode)),
gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (DFmode)),
gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (DFmode)),
@@ -13002,29 +12974,25 @@ rs6000_generate_compare (enum rtx_code c
gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (DFmode)),
gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (DFmode)),
gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (DFmode)))));
- else if (GET_CODE (rs6000_compare_op1) == UNSPEC
- && XINT (rs6000_compare_op1, 1) == UNSPEC_SP_TEST)
+ else if (GET_CODE (op1) == UNSPEC
+ && XINT (op1, 1) == UNSPEC_SP_TEST)
{
- rtx op1 = XVECEXP (rs6000_compare_op1, 0, 0);
+ rtx op1 = XVECEXP (op1, 0, 0);
comp_mode = CCEQmode;
compare_result = gen_reg_rtx (CCEQmode);
if (TARGET_64BIT)
- emit_insn (gen_stack_protect_testdi (compare_result,
- rs6000_compare_op0, op1));
+ emit_insn (gen_stack_protect_testdi (compare_result, op0, op1));
else
- emit_insn (gen_stack_protect_testsi (compare_result,
- rs6000_compare_op0, op1));
+ emit_insn (gen_stack_protect_testsi (compare_result, op0, op1));
}
else
emit_insn (gen_rtx_SET (VOIDmode, compare_result,
- gen_rtx_COMPARE (comp_mode,
- rs6000_compare_op0,
- rs6000_compare_op1)));
+ gen_rtx_COMPARE (comp_mode, op0, op1)));
}
/* Some kinds of FP comparisons need an OR operation;
under flag_finite_math_only we don't bother. */
- if (rs6000_compare_fp_p
+ if (FLOAT_MODE_P (mode)
&& !flag_finite_math_only
&& !(TARGET_HARD_FLOAT && !TARGET_FPRS)
&& (code == LE || code == GE
@@ -13067,16 +13035,17 @@ rs6000_generate_compare (enum rtx_code c
/* Emit the RTL for an sCOND pattern. */
void
-rs6000_emit_sCOND (enum rtx_code code, rtx result)
+rs6000_emit_sCOND (enum machine_mode mode, rtx operands[])
{
rtx condition_rtx;
enum machine_mode op_mode;
enum rtx_code cond_code;
+ rtx result = operands[0];
- condition_rtx = rs6000_generate_compare (code);
+ condition_rtx = rs6000_generate_compare (operands[1], mode);
cond_code = GET_CODE (condition_rtx);
- if (rs6000_compare_fp_p
+ if (FLOAT_MODE_P (mode)
&& !TARGET_FPRS && TARGET_HARD_FLOAT)
{
rtx t;
@@ -13111,11 +13080,11 @@ rs6000_emit_sCOND (enum rtx_code code, r
condition_rtx = gen_rtx_EQ (VOIDmode, not_result, const0_rtx);
}
- op_mode = GET_MODE (rs6000_compare_op0);
+ op_mode = GET_MODE (XEXP (operands[1], 0));
if (op_mode == VOIDmode)
- op_mode = GET_MODE (rs6000_compare_op1);
+ op_mode = GET_MODE (XEXP (operands[1], 1));
- if (TARGET_POWERPC64 && (op_mode == DImode || rs6000_compare_fp_p))
+ if (TARGET_POWERPC64 && (op_mode == DImode || FLOAT_MODE_P (mode)))
{
PUT_MODE (condition_rtx, DImode);
convert_move (result, condition_rtx, 0);
@@ -13130,12 +13099,12 @@ rs6000_emit_sCOND (enum rtx_code code, r
/* Emit a branch of kind CODE to location LOC. */
void
-rs6000_emit_cbranch (enum rtx_code code, rtx loc)
+rs6000_emit_cbranch (enum machine_mode mode, rtx operands[])
{
rtx condition_rtx, loc_ref;
- condition_rtx = rs6000_generate_compare (code);
- loc_ref = gen_rtx_LABEL_REF (VOIDmode, loc);
+ condition_rtx = rs6000_generate_compare (operands[0], mode);
+ loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands[3]);
emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
gen_rtx_IF_THEN_ELSE (VOIDmode, condition_rtx,
loc_ref, pc_rtx)));
@@ -13581,8 +13550,8 @@ int
rs6000_emit_cmove (rtx dest, rtx op, rtx true_cond, rtx false_cond)
{
enum rtx_code code = GET_CODE (op);
- rtx op0 = rs6000_compare_op0;
- rtx op1 = rs6000_compare_op1;
+ rtx op0 = XEXP (op, 0);
+ rtx op1 = XEXP (op, 1);
REAL_VALUE_TYPE c1;
enum machine_mode compare_mode = GET_MODE (op0);
enum machine_mode result_mode = GET_MODE (dest);
@@ -13602,7 +13571,7 @@ rs6000_emit_cmove (rtx dest, rtx op, rtx
/* First, work out if the hardware can do this at all, or
if it's too slow.... */
- if (! rs6000_compare_fp_p)
+ if (!FLOAT_MODE_P (compare_mode))
{
if (TARGET_ISEL)
return rs6000_emit_int_cmove (dest, op, true_cond, false_cond);
@@ -13767,13 +13736,13 @@ rs6000_emit_int_cmove (rtx dest, rtx op,
rtx condition_rtx, cr;
/* All isel implementations thus far are 32-bits. */
- if (GET_MODE (rs6000_compare_op0) != SImode)
+ if (GET_MODE (XEXP (op, 0)) != SImode)
return 0;
/* We still have to do the compare, because isel doesn't do a
compare, it just looks at the CRx bits set by a previous compare
instruction. */
- condition_rtx = rs6000_generate_compare (GET_CODE (op));
+ condition_rtx = rs6000_generate_compare (op, SImode);
cr = XEXP (condition_rtx, 0);
if (GET_MODE (cr) == CCmode)
Index: gcc/config/rs6000/rs6000.h
===================================================================
--- gcc/config/rs6000/rs6000.h (branch cond-optab)
+++ gcc/config/rs6000/rs6000.h (working copy)
@@ -2020,12 +2020,6 @@ do { \
/* Given a condition code and a mode, return the inverse condition. */
#define REVERSE_CONDITION(CODE, MODE) rs6000_reverse_condition (MODE, CODE)
-/* Define the information needed to generate branch and scc insns. This is
- stored from the compare operation. */
-
-extern GTY(()) rtx rs6000_compare_op0;
-extern GTY(()) rtx rs6000_compare_op1;
-extern int rs6000_compare_fp_p;
/* Control the assembler format that we output. */
Index: gcc/config/rs6000/rs6000.md
===================================================================
--- gcc/config/rs6000/rs6000.md (branch cond-optab)
+++ gcc/config/rs6000/rs6000.md (working copy)
@@ -11790,262 +11790,80 @@
;; signed & unsigned, and one type of branch.
;;
;; Start with the DEFINE_EXPANDs to generate the rtl for compares, scc
-;; insns, and branches. We store the operands of compares until we see
-;; how it is used.
-(define_expand "cmp<mode>"
- [(set (cc0)
- (compare (match_operand:GPR 0 "gpc_reg_operand" "")
- (match_operand:GPR 1 "reg_or_short_operand" "")))]
- ""
- "
-{
- /* Take care of the possibility that operands[1] might be negative but
- this might be a logical operation. That insn doesn't exist. */
- if (GET_CODE (operands[1]) == CONST_INT
- && INTVAL (operands[1]) < 0)
- operands[1] = force_reg (<MODE>mode, operands[1]);
-
- rs6000_compare_op0 = operands[0];
- rs6000_compare_op1 = operands[1];
- rs6000_compare_fp_p = 0;
- DONE;
-}")
+;; insns, and branches.
-(define_expand "cmp<mode>"
- [(set (cc0) (compare (match_operand:FP 0 "gpc_reg_operand" "")
- (match_operand:FP 1 "gpc_reg_operand" "")))]
+(define_expand "cbranch<mode>4"
+ [(use (match_operator 0 "rs6000_cbranch_operator"
+ [(match_operand:GPR 1 "gpc_reg_operand" "")
+ (match_operand:GPR 2 "reg_or_short_operand" "")]))
+ (use (match_operand 3 ""))]
""
"
{
- rs6000_compare_op0 = operands[0];
- rs6000_compare_op1 = operands[1];
- rs6000_compare_fp_p = 1;
- DONE;
-}")
-
-(define_expand "beq"
- [(use (match_operand 0 "" ""))]
- ""
- "{ rs6000_emit_cbranch (EQ, operands[0]); DONE; }")
-
-(define_expand "bne"
- [(use (match_operand 0 "" ""))]
- ""
- "{ rs6000_emit_cbranch (NE, operands[0]); DONE; }")
-
-(define_expand "bge"
- [(use (match_operand 0 "" ""))]
- ""
- "{ rs6000_emit_cbranch (GE, operands[0]); DONE; }")
-
-(define_expand "bgt"
- [(use (match_operand 0 "" ""))]
- ""
- "{ rs6000_emit_cbranch (GT, operands[0]); DONE; }")
-
-(define_expand "ble"
- [(use (match_operand 0 "" ""))]
- ""
- "{ rs6000_emit_cbranch (LE, operands[0]); DONE; }")
-
-(define_expand "blt"
- [(use (match_operand 0 "" ""))]
- ""
- "{ rs6000_emit_cbranch (LT, operands[0]); DONE; }")
-
-(define_expand "bgeu"
- [(use (match_operand 0 "" ""))]
- ""
- "{ rs6000_emit_cbranch (GEU, operands[0]); DONE; }")
-
-(define_expand "bgtu"
- [(use (match_operand 0 "" ""))]
- ""
- "{ rs6000_emit_cbranch (GTU, operands[0]); DONE; }")
-
-(define_expand "bleu"
- [(use (match_operand 0 "" ""))]
- ""
- "{ rs6000_emit_cbranch (LEU, operands[0]); DONE; }")
-
-(define_expand "bltu"
- [(use (match_operand 0 "" ""))]
- ""
- "{ rs6000_emit_cbranch (LTU, operands[0]); DONE; }")
-
-(define_expand "bunordered"
- [(use (match_operand 0 "" ""))]
- "! (TARGET_HARD_FLOAT && !TARGET_FPRS)"
- "{ rs6000_emit_cbranch (UNORDERED, operands[0]); DONE; }")
-
-(define_expand "bordered"
- [(use (match_operand 0 "" ""))]
- "! (TARGET_HARD_FLOAT && !TARGET_FPRS)"
- "{ rs6000_emit_cbranch (ORDERED, operands[0]); DONE; }")
-
-(define_expand "buneq"
- [(use (match_operand 0 "" ""))]
- "! (TARGET_HARD_FLOAT && !TARGET_FPRS)"
- "{ rs6000_emit_cbranch (UNEQ, operands[0]); DONE; }")
-
-(define_expand "bunge"
- [(use (match_operand 0 "" ""))]
- "! (TARGET_HARD_FLOAT && !TARGET_FPRS)"
- "{ rs6000_emit_cbranch (UNGE, operands[0]); DONE; }")
-
-(define_expand "bungt"
- [(use (match_operand 0 "" ""))]
- "! (TARGET_HARD_FLOAT && !TARGET_FPRS)"
- "{ rs6000_emit_cbranch (UNGT, operands[0]); DONE; }")
-
-(define_expand "bunle"
- [(use (match_operand 0 "" ""))]
- "! (TARGET_HARD_FLOAT && !TARGET_FPRS)"
- "{ rs6000_emit_cbranch (UNLE, operands[0]); DONE; }")
-
-(define_expand "bunlt"
- [(use (match_operand 0 "" ""))]
- "! (TARGET_HARD_FLOAT && !TARGET_FPRS)"
- "{ rs6000_emit_cbranch (UNLT, operands[0]); DONE; }")
-
-(define_expand "bltgt"
- [(use (match_operand 0 "" ""))]
- "! (TARGET_HARD_FLOAT && !TARGET_FPRS)"
- "{ rs6000_emit_cbranch (LTGT, operands[0]); DONE; }")
-
-;; For SNE, we would prefer that the xor/abs sequence be used for integers.
-;; For SEQ, likewise, except that comparisons with zero should be done
-;; with an scc insns. However, due to the order that combine see the
-;; resulting insns, we must, in fact, allow SEQ for integers. Fail in
-;; the cases we don't want to handle.
-(define_expand "seq"
- [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
- ""
- "{ rs6000_emit_sCOND (EQ, operands[0]); DONE; }")
-
-(define_expand "sne"
- [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
- ""
- "
-{
- if (! rs6000_compare_fp_p)
- FAIL;
+ /* Take care of the possibility that operands[2] might be negative but
+ this might be a logical operation. That insn doesn't exist. */
+ if (GET_CODE (operands[2]) == CONST_INT
+ && INTVAL (operands[2]) < 0)
+ operands[2] = force_reg (<MODE>mode, operands[2]);
- rs6000_emit_sCOND (NE, operands[0]);
+ rs6000_emit_cbranch (<MODE>mode, operands);
DONE;
}")
-;; A >= 0 is best done the portable way for A an integer.
-(define_expand "sge"
- [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
+(define_expand "cbranch<mode>4"
+ [(use (match_operator 0 "rs6000_cbranch_operator"
+ [(match_operand:FP 1 "gpc_reg_operand" "")
+ (match_operand:FP 2 "gpc_reg_operand" "")]))
+ (use (match_operand 3 ""))]
""
"
{
- if (! rs6000_compare_fp_p && rs6000_compare_op1 == const0_rtx)
- FAIL;
-
- rs6000_emit_sCOND (GE, operands[0]);
+ rs6000_emit_cbranch (<MODE>mode, operands);
DONE;
}")
-;; A > 0 is best done using the portable sequence, so fail in that case.
-(define_expand "sgt"
- [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
+(define_expand "cstore<mode>4"
+ [(use (match_operator 1 "rs6000_cbranch_operator"
+ [(match_operand:GPR 2 "gpc_reg_operand" "")
+ (match_operand:GPR 3 "reg_or_short_operand" "")]))
+ (clobber (match_operand:SI 0 "register_operand"))]
""
"
{
- if (! rs6000_compare_fp_p && rs6000_compare_op1 == const0_rtx)
+ /* Take care of the possibility that operands[3] might be negative but
+ this might be a logical operation. That insn doesn't exist. */
+ if (GET_CODE (operands[3]) == CONST_INT
+ && INTVAL (operands[3]) < 0)
+ operands[3] = force_reg (<MODE>mode, operands[3]);
+
+ /* For SNE, we would prefer that the xor/abs sequence be used for integers.
+ For SEQ, likewise, except that comparisons with zero should be done
+ with an scc insns. However, due to the order that combine see the
+ resulting insns, we must, in fact, allow SEQ for integers. Fail in
+ the cases we don't want to handle or are best handled by portable
+ code. */
+ if (GET_CODE (operands[1]) == NE)
FAIL;
-
- rs6000_emit_sCOND (GT, operands[0]);
- DONE;
-}")
-
-;; A <= 0 is best done the portable way for A an integer.
-(define_expand "sle"
- [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
- ""
- "
-{
- if (! rs6000_compare_fp_p && rs6000_compare_op1 == const0_rtx)
+ if ((GET_CODE (operands[1]) == LT || GET_CODE (operands[1]) == LE
+ || GET_CODE (operands[1]) == GT || GET_CODE (operands[1]) == GE)
+ && operands[3] == const0_rtx)
FAIL;
-
- rs6000_emit_sCOND (LE, operands[0]);
+ rs6000_emit_sCOND (<MODE>mode, operands);
DONE;
}")
-;; A < 0 is best done in the portable way for A an integer.
-(define_expand "slt"
- [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
+(define_expand "cstore<mode>4"
+ [(use (match_operator 1 "rs6000_cbranch_operator"
+ [(match_operand:FP 2 "gpc_reg_operand" "")
+ (match_operand:FP 3 "gpc_reg_operand" "")]))
+ (clobber (match_operand:SI 0 "register_operand"))]
""
"
{
- if (! rs6000_compare_fp_p && rs6000_compare_op1 == const0_rtx)
- FAIL;
-
- rs6000_emit_sCOND (LT, operands[0]);
+ rs6000_emit_sCOND (<MODE>mode, operands);
DONE;
}")
-(define_expand "sgeu"
- [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
- ""
- "{ rs6000_emit_sCOND (GEU, operands[0]); DONE; }")
-
-(define_expand "sgtu"
- [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
- ""
- "{ rs6000_emit_sCOND (GTU, operands[0]); DONE; }")
-
-(define_expand "sleu"
- [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
- ""
- "{ rs6000_emit_sCOND (LEU, operands[0]); DONE; }")
-
-(define_expand "sltu"
- [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
- ""
- "{ rs6000_emit_sCOND (LTU, operands[0]); DONE; }")
-
-(define_expand "sunordered"
- [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
- "! (TARGET_HARD_FLOAT && !TARGET_FPRS)"
- "{ rs6000_emit_sCOND (UNORDERED, operands[0]); DONE; }")
-
-(define_expand "sordered"
- [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
- "! (TARGET_HARD_FLOAT && !TARGET_FPRS)"
- "{ rs6000_emit_sCOND (ORDERED, operands[0]); DONE; }")
-
-(define_expand "suneq"
- [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
- "! (TARGET_HARD_FLOAT && !TARGET_FPRS)"
- "{ rs6000_emit_sCOND (UNEQ, operands[0]); DONE; }")
-
-(define_expand "sunge"
- [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
- "! (TARGET_HARD_FLOAT && !TARGET_FPRS)"
- "{ rs6000_emit_sCOND (UNGE, operands[0]); DONE; }")
-
-(define_expand "sungt"
- [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
- "! (TARGET_HARD_FLOAT && !TARGET_FPRS)"
- "{ rs6000_emit_sCOND (UNGT, operands[0]); DONE; }")
-
-(define_expand "sunle"
- [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
- "! (TARGET_HARD_FLOAT && !TARGET_FPRS)"
- "{ rs6000_emit_sCOND (UNLE, operands[0]); DONE; }")
-
-(define_expand "sunlt"
- [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
- "! (TARGET_HARD_FLOAT && !TARGET_FPRS)"
- "{ rs6000_emit_sCOND (UNLT, operands[0]); DONE; }")
-
-(define_expand "sltgt"
- [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
- "! (TARGET_HARD_FLOAT && !TARGET_FPRS)"
- "{ rs6000_emit_sCOND (LTGT, operands[0]); DONE; }")
(define_expand "stack_protect_set"
[(match_operand 0 "memory_operand" "")
@@ -12088,16 +11906,16 @@
(match_operand 2 "" "")]
""
{
+ rtx test, op0, op1;
#ifdef TARGET_THREAD_SSP_OFFSET
rtx tlsreg = gen_rtx_REG (Pmode, TARGET_64BIT ? 13 : 2);
rtx addr = gen_rtx_PLUS (Pmode, tlsreg, GEN_INT (TARGET_THREAD_SSP_OFFSET));
operands[1] = gen_rtx_MEM (Pmode, addr);
#endif
- rs6000_compare_op0 = operands[0];
- rs6000_compare_op1 = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, operands[1]),
- UNSPEC_SP_TEST);
- rs6000_compare_fp_p = 0;
- emit_jump_insn (gen_beq (operands[2]));
+ op0 = operands[0];
+ op1 = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, operands[1]), UNSPEC_SP_TEST);
+ test = gen_rtx_EQ (VOIDmode, op0, op1);
+ emit_jump_insn (gen_cbranchsi4 (test, op0, op1, operands[2]));
DONE;
})
@@ -14668,17 +14486,16 @@
"{t 31,0,0|trap}"
[(set_attr "type" "trap")])
-(define_expand "conditional_trap"
- [(trap_if (match_operator 0 "trap_comparison_operator"
- [(match_dup 2) (match_dup 3)])
- (match_operand 1 "const_int_operand" ""))]
+(define_expand "ctrap<mode>4"
+ [(trap_if (match_operator 0 "ordered_comparison_operator"
+ [(match_operand:GPR 1 "register_operand")
+ (match_operand:GPR 2 "reg_or_short_operand")])
+ (match_operand 3 "zero_constant" ""))]
""
- "if (rs6000_compare_fp_p || operands[1] != const0_rtx) FAIL;
- operands[2] = rs6000_compare_op0;
- operands[3] = rs6000_compare_op1;")
+ "")
(define_insn ""
- [(trap_if (match_operator 0 "trap_comparison_operator"
+ [(trap_if (match_operator 0 "ordered_comparison_operator"
[(match_operand:GPR 1 "register_operand" "r")
(match_operand:GPR 2 "reg_or_short_operand" "rI")])
(const_int 0))]