* compare-elim.c (maybe_select_cc_mode): Update calls to
SELECT_CC_MODE.
* combine (try_combine): Likewise.
(simplify_set): Pass original compare mode to SELECT_CC_MODE.
* config/frv/frv.h (SELECT_CC_MODE): Update.
* config/frv/frv.c (frv_emit_comparison): Update call to
SELECT_CC_MODE.
* config/s390/s390.h (SELECT_CC_MODE): Update.
* config/sparc/sparc.c (gen_comapre_reg_1): Update call to
SELECT_CC_MODE.
* config/sparc/sparc.h (SELECT_CC_MODE): Update.
* config/mep/mep.h (SELECT_CC_MODE): Likewise.
* config/rx/rx.h (SELECT_CC_MODE): Likewise.
* config/i386/i386.h (SELECT_CC_MODE): Likewise.
* config/i386/i386.md (fp_jcc_1_387, fp_jcc_1r_387,
fp_jcc_3_387): Update calls to SELECT_CC_MODE.
* config/i386/i386.c (ix86_expand_int_compare): Likewise.
* config/pdp11/pdp11.h(SELECT_CC_MODE): Update.
* config/mn10300/mn10300.h (SELECT_CC_MODE): Update.
* config/ia64/ia64.h (SELECT_CC_MDOE): Update.
* config/rs6000/rs6000.h (SELECT_CC_MODE): Update.
* config/arc/arc.c (gen_compare_reg): Update call to
SELECT_CC_MODE.
* config/arc/arc.h (SELECT_CC_MODE): Update.
* config/score/score.h (SELECT_CC_MODE): Update.
* config/arm/arm.c (arm_select_dominance_cc_mode): Update
calls to arm_select_cc_mode.
(arm_select_cc_mode): Use the new added mode argument.
Don't change CCFPmode or CCFPEmode if one of them is preferred
and can be used for the given operands.
(arm_gen_compare_reg, get_arm_condition_code): Update call to
SELECT_CC_MODE.
* config/arm/arm.h (SELECT_CC_MODE): Update.
* config/arm/arm-protos.h (arm_select_cc_mode): Update declaration
of arm_select_cc_mode.
* config/arm/arm.md (compare_scc, and_scc_scc_nod,
and 4 define_splits): Update calls to SELECT_CC_MODE.
* config/pa/pa.h (SELECT_CC_MODE): Update.
* config/v850/v850.h (SELECT_CC_MODE): Update.
* config/mmix/mmix.h (SELECT_CC_MODE): Update.
* config/mmix/mmix.c (mmix_gen_compare_reg): Update call to
SELECT_CC_MODE.
* doc/tm.texi.in: Docutment the new mode argument for
SELECT_CC_MODE.
* doc/tm.texi: Regenerate.
testsuite/
* gcc.target/arm/fp-comp-builtin.c: New test.
===================================================================
@@ -5900,7 +5900,7 @@ two places, the @file{md} file and in @c
@findex CCmode
@findex MODE_CC
-@defmac SELECT_CC_MODE (@var{op}, @var{x}, @var{y})
+@defmac SELECT_CC_MODE (@var{op}, @var{x}, @var{y}, @var{mode})
On many machines, the condition code may be produced by other instructions
than compares, for example the branch can use directly the condition
code set by a subtract instruction. However, on some machines
@@ -5914,9 +5914,12 @@ unsigned comparison) produced the condit
If other modes than @code{CCmode} are required, add them to
@file{@var{machine}-modes.def} and define @code{SELECT_CC_MODE} to choose
-a mode given an operand of a compare. This is needed because the modes
+a mode given operands of a compare. This is needed because the modes
have to be chosen not only during RTL generation but also, for example,
-by instruction combination. The result of @code{SELECT_CC_MODE} should
+by instruction combination. When @var{mode} is not @code{VOIDmode},
+it's preferred if it can be used for the given operands. This is used
+by instruction combination to assist some targets, like the ARM, to
+choose better mode. The result of @code{SELECT_CC_MODE} should
be consistent with the mode used in the patterns; for example to support
the case of the add on the SPARC discussed above, we have the pattern
===================================================================
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mfpu=vfp -mfloat-abi=softfp" } */
+/* { dg-require-effective-target arm_vfp_ok } */
+
+float
+foo (float x, float y)
+{
+ return __builtin_isgreaterequal (x, y) ? x : y;
+}
+
+/* { dg-final { scan-assembler "fcmps" } } */
+/* { dg-final { scan-assembler-not "fcmpes" } } */
===================================================================
@@ -425,7 +425,7 @@ maybe_select_cc_mode (struct comparison
common case of exactly one use. */
if (n == 1)
{
- sel_mode = SELECT_CC_MODE (cmp->uses[0].code, a, b);
+ sel_mode = SELECT_CC_MODE (cmp->uses[0].code, a, b, VOIDmode);
if (sel_mode != cmp->orig_mode)
{
flags = gen_rtx_REG (sel_mode, targetm.flags_regnum);
@@ -436,11 +436,11 @@ maybe_select_cc_mode (struct comparison
{
int i;
- sel_mode = SELECT_CC_MODE (cmp->uses[0].code, a, b);
+ sel_mode = SELECT_CC_MODE (cmp->uses[0].code, a, b, VOIDmode);
for (i = 1; i < n; ++i)
{
enum machine_mode new_mode;
- new_mode = SELECT_CC_MODE (cmp->uses[i].code, a, b);
+ new_mode = SELECT_CC_MODE (cmp->uses[i].code, a, b, VOIDmode);
if (new_mode != sel_mode)
{
sel_mode = targetm.cc_modes_compatible (sel_mode, new_mode);
===================================================================
@@ -3030,7 +3030,7 @@ try_combine (rtx i3, rtx i2, rtx i1, rtx
&& (cc_use = find_single_use (SET_DEST (newpat), i3,
&undobuf.other_insn))
&& ((compare_mode = SELECT_CC_MODE (GET_CODE (*cc_use),
- i2src, const0_rtx))
+ i2src, const0_rtx, VOIDmode))
!= GET_MODE (SET_DEST (newpat))))
{
if (can_change_dest_mode (SET_DEST (newpat), added_sets_2,
@@ -6288,7 +6288,7 @@ simplify_set (rtx x)
if (GET_MODE_CLASS (GET_MODE (op0)) == MODE_CC)
compare_mode = GET_MODE (op0);
else
- compare_mode = SELECT_CC_MODE (new_code, op0, op1);
+ compare_mode = SELECT_CC_MODE (new_code, op0, op1, compare_mode);
#ifndef HAVE_cc0
/* If the mode changed, we have to change SET_DEST, the mode in the
===================================================================
@@ -1680,7 +1680,7 @@ __asm__("\n" \
/* We define extra CC modes in frv-modes.def so we need a selector. */
-#define SELECT_CC_MODE frv_select_cc_mode
+#define SELECT_CC_MODE(OP,X,Y,M) frv_select_cc_mode ((OP), (X), (Y))
/* A C expression whose value is one if it is always safe to reverse a
comparison whose mode is MODE. If `SELECT_CC_MODE' can ever return MODE for
===================================================================
@@ -4807,7 +4807,7 @@ frv_emit_comparison (enum rtx_code test,
/* Possibly disable using anything but a fixed register in order to work
around cse moving comparisons past function calls. */
- cc_mode = SELECT_CC_MODE (test, op0, op1);
+ cc_mode = SELECT_CC_MODE (test, op0, op1, VOIDmode);
cc_reg = ((TARGET_ALLOC_CC)
? gen_reg_rtx (cc_mode)
: gen_rtx_REG (cc_mode,
===================================================================
@@ -767,7 +767,7 @@ ((GET_CODE (X) == SYMBOL_REF && tls_symb
/* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
return the mode to be used for the comparison. */
-#define SELECT_CC_MODE(OP, X, Y) s390_select_ccmode ((OP), (X), (Y))
+#define SELECT_CC_MODE(OP, X, Y, M) s390_select_ccmode ((OP), (X), (Y))
/* Canonicalize a comparison from one we don't have to one we do have. */
#define CANONICALIZE_COMPARISON(CODE, OP0, OP1) \
===================================================================
@@ -2099,7 +2099,7 @@ gen_compare_reg_1 (enum rtx_code code, r
if (GET_MODE_CLASS (GET_MODE (x)) == MODE_CC)
return x;
- mode = SELECT_CC_MODE (code, x, y);
+ mode = SELECT_CC_MODE (code, x, y, VOIDmode);
/* ??? We don't have movcc patterns so we cannot generate pseudo regs for the
fcc regs (cse can't tell they're really call clobbered regs and will
===================================================================
@@ -1758,7 +1758,7 @@ (! TARGET_PTR64 ? SImode : flag_pic ? DI
CCFP[E]mode is used. CC_NOOVmode should be used when the first operand
is a PLUS, MINUS, NEG, or ASHIFT. CCmode should be used when no special
processing is needed. */
-#define SELECT_CC_MODE(OP,X,Y) select_cc_mode ((OP), (X), (Y))
+#define SELECT_CC_MODE(OP,X,Y,M) select_cc_mode ((OP), (X), (Y))
/* Return nonzero if MODE implies a floating point inequality can be
reversed. For SPARC this is always true because we have a full
===================================================================
@@ -573,7 +573,7 @@ typedef struct
#define LEGITIMATE_CONSTANT_P(X) \
mep_legitimate_constant_p(X)
-#define SELECT_CC_MODE(OP, X, Y) CCmode
+#define SELECT_CC_MODE(OP, X, Y, M) CCmode
/* Moves between control regs need a scratch. */
===================================================================
@@ -623,4 +623,4 @@ typedef unsigned int CUMULATIVE_ARGS;
#define BRANCH_COST(SPEED,PREDICT) 1
#define REGISTER_MOVE_COST(MODE,FROM,TO) 2
-#define SELECT_CC_MODE(OP,X,Y) rx_select_cc_mode(OP, X, Y)
+#define SELECT_CC_MODE(OP,X,Y,M) rx_select_cc_mode(OP, X, Y)
===================================================================
@@ -1844,7 +1844,7 @@ do { \
For integer comparisons against zero, reduce to CCNOmode or CCZmode if
possible, to allow for more combinations. */
-#define SELECT_CC_MODE(OP, X, Y) ix86_cc_mode ((OP), (X), (Y))
+#define SELECT_CC_MODE(OP, X, Y, M) ix86_cc_mode ((OP), (X), (Y))
/* Return nonzero if MODE implies a floating point inequality can be
reversed. */
===================================================================
@@ -10948,7 +10948,7 @@ (define_insn "*fp_jcc_1_387"
&& (GET_MODE (operands[1]) == SFmode || GET_MODE (operands[1]) == DFmode)
&& GET_MODE (operands[1]) == GET_MODE (operands[2])
&& SELECT_CC_MODE (GET_CODE (operands[0]),
- operands[1], operands[2]) == CCFPmode
+ operands[1], operands[2], VOIDmode) == CCFPmode
&& !TARGET_CMOVE"
"#")
@@ -10966,7 +10966,7 @@ (define_insn "*fp_jcc_1r_387"
&& (GET_MODE (operands[1]) == SFmode || GET_MODE (operands[1]) == DFmode)
&& GET_MODE (operands[1]) == GET_MODE (operands[2])
&& SELECT_CC_MODE (GET_CODE (operands[0]),
- operands[1], operands[2]) == CCFPmode
+ operands[1], operands[2], VOIDmode) == CCFPmode
&& !TARGET_CMOVE"
"#")
@@ -11013,7 +11013,7 @@ (define_insn "*fp_jcc_3_387"
"X87_FLOAT_MODE_P (GET_MODE (operands[1]))
&& GET_MODE (operands[1]) == GET_MODE (operands[2])
&& SELECT_CC_MODE (GET_CODE (operands[0]),
- operands[1], operands[2]) == CCFPmode
+ operands[1], operands[2], VOIDmode) == CCFPmode
&& !TARGET_CMOVE"
"#")
===================================================================
@@ -17188,7 +17188,7 @@ ix86_expand_int_compare (enum rtx_code c
enum machine_mode cmpmode;
rtx tmp, flags;
- cmpmode = SELECT_CC_MODE (code, op0, op1);
+ cmpmode = SELECT_CC_MODE (code, op0, op1, VOIDmode);
flags = gen_rtx_REG (cmpmode, FLAGS_REG);
/* This is very simple, but making the interface the same as in the
===================================================================
@@ -500,7 +500,7 @@ extern int may_call_alloca;
return the mode to be used for the comparison. For floating-point, CCFPmode
should be used. */
-#define SELECT_CC_MODE(OP,X,Y) \
+#define SELECT_CC_MODE(OP,X,Y,M) \
(GET_MODE_CLASS(GET_MODE(X)) == MODE_FLOAT? CCFPmode : CCmode)
/* Specify the machine mode that pointers have.
===================================================================
@@ -598,7 +598,7 @@ ((GET_CODE (X) == SYMBOL_REF || GET_CODE
/* Non-global SYMBOL_REFs have SYMBOL_REF_FLAG enabled. */
#define MN10300_GLOBAL_P(X) (! SYMBOL_REF_FLAG (X))
-#define SELECT_CC_MODE(OP, X, Y) mn10300_select_cc_mode (OP, X, Y)
+#define SELECT_CC_MODE(OP, X, Y, M) mn10300_select_cc_mode (OP, X, Y)
#define REVERSIBLE_CC_MODE(MODE) 0
/* Nonzero if access to memory by bytes or half words is no faster
===================================================================
@@ -497,7 +497,7 @@ while (0)
/* We define CCImode in ia64-modes.def so we need a selector. */
-#define SELECT_CC_MODE(OP,X,Y) CCmode
+#define SELECT_CC_MODE(OP,X,Y,M) CCmode
/* Order of allocation of registers */
===================================================================
@@ -1920,7 +1920,7 @@ extern unsigned rs6000_pmode;
doing an inequality comparison on the result of a
comparison. CCmode should be used in all other cases. */
-#define SELECT_CC_MODE(OP,X,Y) \
+#define SELECT_CC_MODE(OP,X,Y,M) \
(SCALAR_FLOAT_MODE_P (GET_MODE (X)) ? CCFPmode \
: (OP) == GTU || (OP) == LTU || (OP) == GEU || (OP) == LEU ? CCUNSmode \
: (((OP) == EQ || (OP) == NE) && COMPARISON_P (X) \
===================================================================
@@ -755,7 +755,7 @@ proper_comparison_operator (rtx op, enum
rtx
gen_compare_reg (enum rtx_code code, rtx x, rtx y)
{
- enum machine_mode mode = SELECT_CC_MODE (code, x, y);
+ enum machine_mode mode = SELECT_CC_MODE (code, x, y, VOIDmode);
return gen_rtx_REG (mode, 61);
}
===================================================================
@@ -654,7 +654,7 @@ (GET_CODE (X) == PLUS \
/* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
return the mode to be used for the comparison. */
-#define SELECT_CC_MODE(OP, X, Y) \
+#define SELECT_CC_MODE(OP, X, Y, M) \
arc_select_cc_mode (OP, X, Y)
/* Return nonzero if SELECT_CC_MODE will never return MODE for a
===================================================================
@@ -666,7 +666,7 @@ typedef struct score_args
#define LEGITIMATE_CONSTANT_P(X) 1
/* Condition Code Status. */
-#define SELECT_CC_MODE(OP, X, Y) score_select_cc_mode (OP, X, Y)
+#define SELECT_CC_MODE(OP, X, Y, M) score_select_cc_mode (OP, X, Y)
/* Return nonzero if SELECT_CC_MODE will never return MODE for a
floating point inequality comparison. */
===================================================================
@@ -10493,9 +10493,11 @@ arm_select_dominance_cc_mode (rtx x, rtx
/* Currently we will probably get the wrong result if the individual
comparisons are not simple. This also ensures that it is safe to
reverse a comparison if necessary. */
- if ((arm_select_cc_mode (cond1 = GET_CODE (x), XEXP (x, 0), XEXP (x, 1))
+ if ((arm_select_cc_mode (cond1 = GET_CODE (x),
+ XEXP (x, 0), XEXP (x, 1), VOIDmode)
!= CCmode)
- || (arm_select_cc_mode (cond2 = GET_CODE (y), XEXP (y, 0), XEXP (y, 1))
+ || (arm_select_cc_mode (cond2 = GET_CODE (y),
+ XEXP (y, 0), XEXP (y, 1), VOIDmode)
!= CCmode))
return CCmode;
@@ -10627,12 +10629,15 @@ arm_select_dominance_cc_mode (rtx x, rtx
}
enum machine_mode
-arm_select_cc_mode (enum rtx_code op, rtx x, rtx y)
+arm_select_cc_mode (enum rtx_code op, rtx x, rtx y, enum machine_mode mode)
{
/* All floating point compares return CCFP if it is an equality
comparison, and CCFPE otherwise. */
if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
{
+ if (mode == CCFPmode || mode == CCFPEmode)
+ return mode;
+
switch (op)
{
case EQ:
@@ -10822,7 +10827,7 @@ arm_gen_compare_reg (enum rtx_code code,
if (dimode_comparison && !REG_P (x))
x = force_reg (DImode, x);
- mode = SELECT_CC_MODE (code, x, y);
+ mode = SELECT_CC_MODE (code, x, y, VOIDmode);
cc_reg = gen_rtx_REG (mode, CC_REGNUM);
if (dimode_comparison
@@ -17033,7 +17038,7 @@ get_arm_condition_code (rtx comparison)
if (GET_MODE_CLASS (mode) != MODE_CC)
mode = SELECT_CC_MODE (comp_code, XEXP (comparison, 0),
- XEXP (comparison, 1));
+ XEXP (comparison, 1), VOIDmode);
switch (mode)
{
===================================================================
@@ -2081,7 +2081,7 @@ extern int making_const_table;
/* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
return the mode to be used for the comparison. */
-#define SELECT_CC_MODE(OP, X, Y) arm_select_cc_mode (OP, X, Y)
+#define SELECT_CC_MODE(OP, X, Y, M) arm_select_cc_mode (OP, X, Y, M)
#define REVERSIBLE_CC_MODE(MODE) 1
===================================================================
@@ -106,7 +106,7 @@ extern bool gen_const_stm_seq (rtx *, in
extern rtx arm_gen_load_multiple (int *, int, rtx, int, rtx, HOST_WIDE_INT *);
extern rtx arm_gen_store_multiple (int *, int, rtx, int, rtx, HOST_WIDE_INT *);
extern int arm_gen_movmemqi (rtx *);
-extern enum machine_mode arm_select_cc_mode (RTX_CODE, rtx, rtx);
+extern enum machine_mode arm_select_cc_mode (RTX_CODE, rtx, rtx, enum machine_mode);
extern enum machine_mode arm_select_dominance_cc_mode (rtx, rtx,
HOST_WIDE_INT);
extern rtx arm_gen_compare_reg (RTX_CODE, rtx, rtx);
===================================================================
@@ -8728,7 +8728,7 @@ (define_insn_and_split "*compare_scc"
{
rtx tmp1;
enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
- operands[2], operands[3]);
+ operands[2], operands[3], VOIDmode);
enum rtx_code rc = GET_CODE (operands[1]);
tmp1 = gen_rtx_REG (mode, CC_REGNUM);
@@ -9118,7 +9118,8 @@ (define_insn_and_split "*and_scc_scc_nod
(match_dup 0)
(const_int 0)))]
"operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
- operands[4], operands[5]),
+ operands[4], operands[5],
+ VOIDmode),
CC_REGNUM);
operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
operands[5]);"
@@ -10064,7 +10065,8 @@ (define_split
"
{
enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
- operands[2], operands[3]);
+ operands[2], operands[3],
+ VOIDmode);
enum rtx_code rc = GET_CODE (operands[1]);
operands[5] = gen_rtx_REG (mode, CC_REGNUM);
@@ -10092,7 +10094,8 @@ (define_split
"
{
enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
- operands[2], operands[3]);
+ operands[2], operands[3],
+ VOIDmode);
operands[5] = gen_rtx_REG (mode, CC_REGNUM);
operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
@@ -10115,7 +10118,8 @@ (define_split
"
{
enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
- operands[2], operands[3]);
+ operands[2], operands[3],
+ VOIDmode);
enum rtx_code rc = GET_CODE (operands[1]);
operands[6] = gen_rtx_REG (mode, CC_REGNUM);
@@ -10147,7 +10151,8 @@ (define_split
"
{
enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
- operands[2], operands[3]);
+ operands[2], operands[3],
+ VOIDmode);
enum rtx_code rc = GET_CODE (operands[1]);
operands[6] = gen_rtx_REG (mode, CC_REGNUM);
===================================================================
@@ -1291,7 +1291,7 @@ do { \
should be used. CC_NOOVmode should be used when the first operand is a
PLUS, MINUS, or NEG. CCmode should be used when no special processing is
needed. */
-#define SELECT_CC_MODE(OP,X,Y) \
+#define SELECT_CC_MODE(OP,X,Y,M) \
(GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT ? CCFPmode : CCmode) \
/* A function address in a call instruction
===================================================================
@@ -766,7 +766,7 @@ do { \
For integer comparisons against zero, reduce to CCNOmode or CCZmode if
possible, to allow for more combinations. */
-#define SELECT_CC_MODE(OP, X, Y) v850_select_cc_mode (OP, X, Y)
+#define SELECT_CC_MODE(OP, X, Y, M) v850_select_cc_mode (OP, X, Y)
/* Tell final.c how to eliminate redundant test instructions. */
===================================================================
@@ -624,7 +624,7 @@ typedef struct { int regs; int lib; } CU
/* Node: Condition Code */
-#define SELECT_CC_MODE(OP, X, Y) \
+#define SELECT_CC_MODE(OP, X, Y, M) \
mmix_select_cc_mode (OP, X, Y)
/* A definition of CANONICALIZE_COMPARISON that changed LE and GT
===================================================================
@@ -2468,7 +2468,7 @@ mmix_shiftable_wyde_value (unsigned HOST
rtx
mmix_gen_compare_reg (RTX_CODE code, rtx x, rtx y)
{
- enum machine_mode ccmode = SELECT_CC_MODE (code, x, y);
+ enum machine_mode ccmode = SELECT_CC_MODE (code, x, y, VOIDmode);
return gen_reg_rtx (ccmode);
}