summaryrefslogtreecommitdiff
path: root/gcc/config
diff options
context:
space:
mode:
authorbonzini <bonzini@138bc75d-0d04-0410-961f-82ee72b054a4>2009-05-12 09:43:48 +0000
committerbonzini <bonzini@138bc75d-0d04-0410-961f-82ee72b054a4>2009-05-12 09:43:48 +0000
commit74f4459c661b0597a1cb1080a1e6c34db40f921d (patch)
tree06c940a96a184a178bfadd53e04213225655a68d /gcc/config
parent58b52637eb213c90766269829beb56b15f621af8 (diff)
downloadgcc-74f4459c661b0597a1cb1080a1e6c34db40f921d.tar.gz
Merge cond-optab branch.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@147425 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config')
-rw-r--r--gcc/config/alpha/alpha-protos.h4
-rw-r--r--gcc/config/alpha/alpha.c119
-rw-r--r--gcc/config/alpha/alpha.h18
-rw-r--r--gcc/config/alpha/alpha.md239
-rw-r--r--gcc/config/alpha/predicates.md6
-rw-r--r--gcc/config/arc/arc.c17
-rw-r--r--gcc/config/arc/arc.h5
-rw-r--r--gcc/config/arc/arc.md337
-rw-r--r--gcc/config/arm/arm.c4
-rw-r--r--gcc/config/arm/arm.h4
-rw-r--r--gcc/config/arm/arm.md448
-rw-r--r--gcc/config/arm/predicates.md8
-rw-r--r--gcc/config/avr/avr-protos.h4
-rw-r--r--gcc/config/avr/avr.c43
-rw-r--r--gcc/config/avr/avr.md274
-rw-r--r--gcc/config/bfin/bfin.c18
-rw-r--r--gcc/config/bfin/bfin.h1
-rw-r--r--gcc/config/bfin/bfin.md275
-rw-r--r--gcc/config/bfin/predicates.md8
-rw-r--r--gcc/config/cris/cris.c22
-rw-r--r--gcc/config/cris/cris.md130
-rw-r--r--gcc/config/crx/crx-protos.h4
-rw-r--r--gcc/config/crx/crx.c41
-rw-r--r--gcc/config/crx/crx.h7
-rw-r--r--gcc/config/crx/crx.md79
-rw-r--r--gcc/config/fr30/fr30.c6
-rw-r--r--gcc/config/fr30/fr30.h10
-rw-r--r--gcc/config/fr30/fr30.md176
-rw-r--r--gcc/config/frv/frv-protos.h4
-rw-r--r--gcc/config/frv/frv.c29
-rw-r--r--gcc/config/frv/frv.h3
-rw-r--r--gcc/config/frv/frv.md330
-rw-r--r--gcc/config/h8300/h8300-protos.h3
-rw-r--r--gcc/config/h8300/h8300.c33
-rw-r--r--gcc/config/h8300/h8300.md495
-rw-r--r--gcc/config/i386/i386-protos.h2
-rw-r--r--gcc/config/i386/i386.c20
-rw-r--r--gcc/config/i386/i386.md318
-rw-r--r--gcc/config/ia64/ia64-protos.h9
-rw-r--r--gcc/config/ia64/ia64.c35
-rw-r--r--gcc/config/ia64/ia64.md367
-rw-r--r--gcc/config/ia64/predicates.md5
-rw-r--r--gcc/config/iq2000/iq2000-protos.h2
-rw-r--r--gcc/config/iq2000/iq2000.c64
-rw-r--r--gcc/config/iq2000/iq2000.h7
-rw-r--r--gcc/config/iq2000/iq2000.md400
-rw-r--r--gcc/config/iq2000/predicates.md8
-rw-r--r--gcc/config/m32c/cond.md102
-rw-r--r--gcc/config/m32c/m32c-protos.h4
-rw-r--r--gcc/config/m32c/m32c.c79
-rw-r--r--gcc/config/m32c/m32c.md3
-rw-r--r--gcc/config/m32r/m32r-protos.h1
-rw-r--r--gcc/config/m32r/m32r.c153
-rw-r--r--gcc/config/m32r/m32r.h6
-rw-r--r--gcc/config/m32r/m32r.md415
-rw-r--r--gcc/config/m68hc11/m68hc11.c15
-rw-r--r--gcc/config/m68hc11/m68hc11.h2
-rw-r--r--gcc/config/m68hc11/m68hc11.md297
-rw-r--r--gcc/config/m68k/constraints.md5
-rw-r--r--gcc/config/m68k/m68k.c29
-rw-r--r--gcc/config/m68k/m68k.h1
-rw-r--r--gcc/config/m68k/m68k.md553
-rw-r--r--gcc/config/m68k/predicates.md23
-rw-r--r--gcc/config/mcore/mcore-protos.h6
-rw-r--r--gcc/config/mcore/mcore.c66
-rw-r--r--gcc/config/mcore/mcore.md340
-rw-r--r--gcc/config/mips/mips-protos.h6
-rw-r--r--gcc/config/mips/mips-ps-3d.md2
-rw-r--r--gcc/config/mips/mips.c118
-rw-r--r--gcc/config/mips/mips.h1
-rw-r--r--gcc/config/mips/mips.md159
-rw-r--r--gcc/config/mips/predicates.md6
-rw-r--r--gcc/config/mmix/mmix-protos.h1
-rw-r--r--gcc/config/mmix/mmix.c62
-rw-r--r--gcc/config/mmix/mmix.h5
-rw-r--r--gcc/config/mmix/mmix.md250
-rw-r--r--gcc/config/mmix/predicates.md5
-rw-r--r--gcc/config/mn10300/mn10300.c8
-rw-r--r--gcc/config/mn10300/mn10300.md204
-rw-r--r--gcc/config/pa/pa-protos.h3
-rw-r--r--gcc/config/pa/pa.c81
-rw-r--r--gcc/config/pa/pa.h12
-rw-r--r--gcc/config/pa/pa.md531
-rw-r--r--gcc/config/pdp11/pdp11-protos.h2
-rw-r--r--gcc/config/pdp11/pdp11.c23
-rw-r--r--gcc/config/pdp11/pdp11.h3
-rw-r--r--gcc/config/pdp11/pdp11.md522
-rw-r--r--gcc/config/picochip/picochip.md113
-rw-r--r--gcc/config/rs6000/predicates.md10
-rw-r--r--gcc/config/rs6000/rs6000-protos.h4
-rw-r--r--gcc/config/rs6000/rs6000.c153
-rw-r--r--gcc/config/rs6000/rs6000.h6
-rw-r--r--gcc/config/rs6000/rs6000.md307
-rw-r--r--gcc/config/s390/predicates.md8
-rw-r--r--gcc/config/s390/s390.c17
-rw-r--r--gcc/config/s390/s390.h6
-rw-r--r--gcc/config/s390/s390.md208
-rw-r--r--gcc/config/score/score-conv.h5
-rw-r--r--gcc/config/score/score-protos.h1
-rw-r--r--gcc/config/score/score.c18
-rw-r--r--gcc/config/score/score.md124
-rw-r--r--gcc/config/score/score3.c13
-rw-r--r--gcc/config/score/score3.h1
-rw-r--r--gcc/config/score/score7.c13
-rw-r--r--gcc/config/score/score7.h1
-rw-r--r--gcc/config/sh/predicates.md11
-rw-r--r--gcc/config/sh/sh-protos.h8
-rw-r--r--gcc/config/sh/sh.c281
-rw-r--r--gcc/config/sh/sh.md1509
-rw-r--r--gcc/config/sparc/sparc-protos.h9
-rw-r--r--gcc/config/sparc/sparc.c278
-rw-r--r--gcc/config/sparc/sparc.h6
-rw-r--r--gcc/config/sparc/sparc.md917
-rw-r--r--gcc/config/spu/spu-protos.h3
-rw-r--r--gcc/config/spu/spu.c59
-rw-r--r--gcc/config/spu/spu.h5
-rw-r--r--gcc/config/spu/spu.md187
-rw-r--r--gcc/config/stormy16/stormy16-protos.h2
-rw-r--r--gcc/config/stormy16/stormy16.c34
-rw-r--r--gcc/config/stormy16/stormy16.h7
-rw-r--r--gcc/config/stormy16/stormy16.md105
-rw-r--r--gcc/config/v850/v850.c5
-rw-r--r--gcc/config/v850/v850.md302
-rw-r--r--gcc/config/vax/vax-protos.h2
-rw-r--r--gcc/config/vax/vax.c54
-rw-r--r--gcc/config/vax/vax.h1
-rw-r--r--gcc/config/vax/vax.md81
-rw-r--r--gcc/config/xtensa/predicates.md3
-rw-r--r--gcc/config/xtensa/xtensa-protos.h4
-rw-r--r--gcc/config/xtensa/xtensa.c63
-rw-r--r--gcc/config/xtensa/xtensa.h11
-rw-r--r--gcc/config/xtensa/xtensa.md77
132 files changed, 4007 insertions, 9570 deletions
diff --git a/gcc/config/alpha/alpha-protos.h b/gcc/config/alpha/alpha-protos.h
index 66c68aebc91..7a12d498246 100644
--- a/gcc/config/alpha/alpha-protos.h
+++ b/gcc/config/alpha/alpha-protos.h
@@ -88,8 +88,8 @@ extern int check_float_value (enum machine_mode, REAL_VALUE_TYPE *, int);
#endif
#ifdef RTX_CODE
-extern rtx alpha_emit_conditional_branch (enum rtx_code);
-extern rtx alpha_emit_setcc (enum rtx_code);
+extern void alpha_emit_conditional_branch (rtx[], enum machine_mode);
+extern bool alpha_emit_setcc (rtx[], enum machine_mode);
extern int alpha_split_conditional_move (enum rtx_code, rtx, rtx, rtx, rtx);
extern void alpha_emit_xfloating_arith (enum rtx_code, rtx[]);
extern void alpha_emit_xfloating_cvt (enum rtx_code, rtx[]);
diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c
index bb6542a37f9..512599d0982 100644
--- a/gcc/config/alpha/alpha.c
+++ b/gcc/config/alpha/alpha.c
@@ -81,11 +81,6 @@ enum alpha_fp_rounding_mode alpha_fprm;
enum alpha_fp_trap_mode alpha_fptm;
-/* Save information from a "cmpxx" operation until the branch or scc is
- emitted. */
-
-struct alpha_compare alpha_compare;
-
/* Nonzero if inside of a function, because the Alpha asm can't
handle .files inside of functions. */
@@ -2424,19 +2419,20 @@ alpha_emit_floatuns (rtx operands[2])
/* Generate the comparison for a conditional branch. */
-rtx
-alpha_emit_conditional_branch (enum rtx_code code)
+void
+alpha_emit_conditional_branch (rtx operands[], enum machine_mode cmp_mode)
{
enum rtx_code cmp_code, branch_code;
- enum machine_mode cmp_mode, branch_mode = VOIDmode;
- rtx op0 = alpha_compare.op0, op1 = alpha_compare.op1;
+ enum machine_mode branch_mode = VOIDmode;
+ enum rtx_code code = GET_CODE (operands[0]);
+ rtx op0 = operands[1], op1 = operands[2];
rtx tem;
- if (alpha_compare.fp_p && GET_MODE (op0) == TFmode)
+ if (cmp_mode == TFmode)
{
op0 = alpha_emit_xfloating_compare (&code, op0, op1);
op1 = const0_rtx;
- alpha_compare.fp_p = 0;
+ cmp_mode = DImode;
}
/* The general case: fold the comparison code to the types of compares
@@ -2457,7 +2453,7 @@ alpha_emit_conditional_branch (enum rtx_code code)
case GE: case GT: case GEU: case GTU:
/* For FP, we swap them, for INT, we reverse them. */
- if (alpha_compare.fp_p)
+ if (cmp_mode == DFmode)
{
cmp_code = swap_condition (code);
branch_code = NE;
@@ -2474,9 +2470,8 @@ alpha_emit_conditional_branch (enum rtx_code code)
gcc_unreachable ();
}
- if (alpha_compare.fp_p)
+ if (cmp_mode == DFmode)
{
- cmp_mode = DFmode;
if (flag_unsafe_math_optimizations && cmp_code != UNORDERED)
{
/* When we are not as concerned about non-finite values, and we
@@ -2501,8 +2496,6 @@ alpha_emit_conditional_branch (enum rtx_code code)
}
else
{
- cmp_mode = DImode;
-
/* The following optimizations are only for signed compares. */
if (code != LEU && code != LTU && code != GEU && code != GTU)
{
@@ -2544,36 +2537,38 @@ alpha_emit_conditional_branch (enum rtx_code code)
emit_move_insn (tem, gen_rtx_fmt_ee (cmp_code, cmp_mode, op0, op1));
}
- /* Zero the operands. */
- memset (&alpha_compare, 0, sizeof (alpha_compare));
-
- /* Return the branch comparison. */
- return gen_rtx_fmt_ee (branch_code, branch_mode, tem, CONST0_RTX (cmp_mode));
+ /* Emit the branch instruction. */
+ tem = gen_rtx_SET (VOIDmode, pc_rtx,
+ gen_rtx_IF_THEN_ELSE (VOIDmode,
+ gen_rtx_fmt_ee (branch_code,
+ branch_mode, tem,
+ CONST0_RTX (cmp_mode)),
+ gen_rtx_LABEL_REF (VOIDmode,
+ operands[3]),
+ pc_rtx));
+ emit_jump_insn (tem);
}
/* Certain simplifications can be done to make invalid setcc operations
valid. Return the final comparison, or NULL if we can't work. */
-rtx
-alpha_emit_setcc (enum rtx_code code)
+bool
+alpha_emit_setcc (rtx operands[], enum machine_mode cmp_mode)
{
enum rtx_code cmp_code;
- rtx op0 = alpha_compare.op0, op1 = alpha_compare.op1;
- int fp_p = alpha_compare.fp_p;
+ enum rtx_code code = GET_CODE (operands[1]);
+ rtx op0 = operands[2], op1 = operands[3];
rtx tmp;
- /* Zero the operands. */
- memset (&alpha_compare, 0, sizeof (alpha_compare));
-
- if (fp_p && GET_MODE (op0) == TFmode)
+ if (cmp_mode == TFmode)
{
op0 = alpha_emit_xfloating_compare (&code, op0, op1);
op1 = const0_rtx;
- fp_p = 0;
+ cmp_mode = DImode;
}
- if (fp_p && !TARGET_FIX)
- return NULL_RTX;
+ if (cmp_mode == DFmode && !TARGET_FIX)
+ return 0;
/* The general case: fold the comparison code to the types of compares
that we have, choosing the branch as necessary. */
@@ -2584,12 +2579,12 @@ alpha_emit_setcc (enum rtx_code code)
case EQ: case LE: case LT: case LEU: case LTU:
case UNORDERED:
/* We have these compares. */
- if (fp_p)
+ if (cmp_mode == DFmode)
cmp_code = code, code = NE;
break;
case NE:
- if (!fp_p && op1 == const0_rtx)
+ if (cmp_mode == DImode && op1 == const0_rtx)
break;
/* FALLTHRU */
@@ -2601,10 +2596,10 @@ alpha_emit_setcc (enum rtx_code code)
case GE: case GT: case GEU: case GTU:
/* These normally need swapping, but for integer zero we have
special patterns that recognize swapped operands. */
- if (!fp_p && op1 == const0_rtx)
+ if (cmp_mode == DImode && op1 == const0_rtx)
break;
code = swap_condition (code);
- if (fp_p)
+ if (cmp_mode == DFmode)
cmp_code = code, code = NE;
tmp = op0, op0 = op1, op1 = tmp;
break;
@@ -2613,7 +2608,7 @@ alpha_emit_setcc (enum rtx_code code)
gcc_unreachable ();
}
- if (!fp_p)
+ if (cmp_mode == DImode)
{
if (!register_operand (op0, DImode))
op0 = force_reg (DImode, op0);
@@ -2624,18 +2619,18 @@ alpha_emit_setcc (enum rtx_code code)
/* Emit an initial compare instruction, if necessary. */
if (cmp_code != UNKNOWN)
{
- enum machine_mode mode = fp_p ? DFmode : DImode;
-
- tmp = gen_reg_rtx (mode);
+ tmp = gen_reg_rtx (cmp_mode);
emit_insn (gen_rtx_SET (VOIDmode, tmp,
- gen_rtx_fmt_ee (cmp_code, mode, op0, op1)));
+ gen_rtx_fmt_ee (cmp_code, cmp_mode, op0, op1)));
- op0 = fp_p ? gen_lowpart (DImode, tmp) : tmp;
+ op0 = cmp_mode == DImode ? gen_lowpart (DImode, tmp) : tmp;
op1 = const0_rtx;
}
- /* Return the setcc comparison. */
- return gen_rtx_fmt_ee (code, DImode, op0, op1);
+ /* Emit the setcc instruction. */
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0],
+ gen_rtx_fmt_ee (code, DImode, op0, op1)));
+ return true;
}
@@ -2651,20 +2646,17 @@ alpha_emit_conditional_move (rtx cmp, enum machine_mode mode)
{
enum rtx_code code = GET_CODE (cmp);
enum rtx_code cmov_code = NE;
- rtx op0 = alpha_compare.op0;
- rtx op1 = alpha_compare.op1;
- int fp_p = alpha_compare.fp_p;
+ rtx op0 = XEXP (cmp, 0);
+ rtx op1 = XEXP (cmp, 1);
enum machine_mode cmp_mode
= (GET_MODE (op0) == VOIDmode ? DImode : GET_MODE (op0));
- enum machine_mode cmp_op_mode = fp_p ? DFmode : DImode;
enum machine_mode cmov_mode = VOIDmode;
int local_fast_math = flag_unsafe_math_optimizations;
rtx tem;
- /* Zero the operands. */
- memset (&alpha_compare, 0, sizeof (alpha_compare));
+ gcc_assert (cmp_mode == DFmode || cmp_mode == DImode);
- if (fp_p != FLOAT_MODE_P (mode))
+ if (FLOAT_MODE_P (cmp_mode) != FLOAT_MODE_P (mode))
{
enum rtx_code cmp_code;
@@ -2691,7 +2683,7 @@ alpha_emit_conditional_move (rtx cmp, enum machine_mode mode)
case GE: case GT: case GEU: case GTU:
/* These normally need swapping, but for integer zero we have
special patterns that recognize swapped operands. */
- if (!fp_p && op1 == const0_rtx)
+ if (cmp_mode == DImode && op1 == const0_rtx)
cmp_code = code, code = NE;
else
{
@@ -2705,22 +2697,21 @@ alpha_emit_conditional_move (rtx cmp, enum machine_mode mode)
gcc_unreachable ();
}
- tem = gen_reg_rtx (cmp_op_mode);
+ tem = gen_reg_rtx (cmp_mode);
emit_insn (gen_rtx_SET (VOIDmode, tem,
- gen_rtx_fmt_ee (cmp_code, cmp_op_mode,
+ gen_rtx_fmt_ee (cmp_code, cmp_mode,
op0, op1)));
- cmp_mode = cmp_op_mode = fp_p ? DImode : DFmode;
- op0 = gen_lowpart (cmp_op_mode, tem);
- op1 = CONST0_RTX (cmp_op_mode);
- fp_p = !fp_p;
+ cmp_mode = cmp_mode == DImode ? DFmode : DImode;
+ op0 = gen_lowpart (cmp_mode, tem);
+ op1 = CONST0_RTX (cmp_mode);
local_fast_math = 1;
}
/* We may be able to use a conditional move directly.
This avoids emitting spurious compares. */
if (signed_comparison_operator (cmp, VOIDmode)
- && (!fp_p || local_fast_math)
+ && (cmp_mode == DImode || local_fast_math)
&& (op0 == CONST0_RTX (cmp_mode) || op1 == CONST0_RTX (cmp_mode)))
return gen_rtx_fmt_ee (code, VOIDmode, op0, op1);
@@ -2757,7 +2748,7 @@ alpha_emit_conditional_move (rtx cmp, enum machine_mode mode)
gcc_unreachable ();
}
- if (!fp_p)
+ if (cmp_mode == DImode)
{
if (!reg_or_0_operand (op0, DImode))
op0 = force_reg (DImode, op0);
@@ -2768,12 +2759,12 @@ alpha_emit_conditional_move (rtx cmp, enum machine_mode mode)
/* ??? We mark the branch mode to be CCmode to prevent the compare
and cmov from being combined, since the compare insn follows IEEE
rules that the cmov does not. */
- if (fp_p && !local_fast_math)
+ if (cmp_mode == DFmode && !local_fast_math)
cmov_mode = CCmode;
- tem = gen_reg_rtx (cmp_op_mode);
- emit_move_insn (tem, gen_rtx_fmt_ee (code, cmp_op_mode, op0, op1));
- return gen_rtx_fmt_ee (cmov_code, cmov_mode, tem, CONST0_RTX (cmp_op_mode));
+ tem = gen_reg_rtx (cmp_mode);
+ emit_move_insn (tem, gen_rtx_fmt_ee (code, cmp_mode, op0, op1));
+ return gen_rtx_fmt_ee (cmov_code, cmov_mode, tem, CONST0_RTX (cmp_mode));
}
/* Simplify a conditional move of two constants into a setcc with
diff --git a/gcc/config/alpha/alpha.h b/gcc/config/alpha/alpha.h
index f33e8e63854..ed9bd747f39 100644
--- a/gcc/config/alpha/alpha.h
+++ b/gcc/config/alpha/alpha.h
@@ -803,24 +803,6 @@ extern int alpha_memory_latency;
#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
function_arg((CUM), (MODE), (TYPE), (NAMED))
-/* Try to output insns to set TARGET equal to the constant C if it can be
- done in less than N insns. Do all computations in MODE. Returns the place
- where the output has been placed if it can be done and the insns have been
- emitted. If it would take more than N insns, zero is returned and no
- insns and emitted. */
-
-/* Define the information needed to generate branch and scc insns. This is
- stored from the compare operation. Note that we can't use "rtx" here
- since it hasn't been defined! */
-
-struct alpha_compare
-{
- struct rtx_def *op0, *op1;
- int fp_p;
-};
-
-extern struct alpha_compare alpha_compare;
-
/* Make (or fake) .linkage entry for function call.
IS_LOCAL is 0 if name is used in call, 1 if name is used in definition. */
diff --git a/gcc/config/alpha/alpha.md b/gcc/config/alpha/alpha.md
index 543ed533080..e6a05780bba 100644
--- a/gcc/config/alpha/alpha.md
+++ b/gcc/config/alpha/alpha.md
@@ -3963,206 +3963,53 @@
;; These are the main define_expand's used to make conditional branches
;; and compares.
-(define_expand "cmpdf"
- [(set (cc0) (compare (match_operand:DF 0 "reg_or_0_operand" "")
- (match_operand:DF 1 "reg_or_0_operand" "")))]
+(define_expand "cbranchdf4"
+ [(use (match_operator 0 "alpha_cbranch_operator"
+ [(match_operand:DF 1 "reg_or_0_operand" "")
+ (match_operand:DF 2 "reg_or_0_operand" "")]))
+ (use (match_operand 3 ""))]
"TARGET_FP"
-{
- alpha_compare.op0 = operands[0];
- alpha_compare.op1 = operands[1];
- alpha_compare.fp_p = 1;
- DONE;
-})
+ { alpha_emit_conditional_branch (operands, DFmode); DONE; })
-(define_expand "cmptf"
- [(set (cc0) (compare (match_operand:TF 0 "general_operand" "")
- (match_operand:TF 1 "general_operand" "")))]
+(define_expand "cbranchtf4"
+ [(use (match_operator 0 "alpha_cbranch_operator"
+ [(match_operand:TF 1 "general_operand")
+ (match_operand:TF 2 "general_operand")]))
+ (use (match_operand 3 ""))]
"TARGET_HAS_XFLOATING_LIBS"
-{
- alpha_compare.op0 = operands[0];
- alpha_compare.op1 = operands[1];
- alpha_compare.fp_p = 1;
- DONE;
-})
-
-(define_expand "cmpdi"
- [(set (cc0) (compare (match_operand:DI 0 "some_operand" "")
- (match_operand:DI 1 "some_operand" "")))]
- ""
-{
- alpha_compare.op0 = operands[0];
- alpha_compare.op1 = operands[1];
- alpha_compare.fp_p = 0;
- DONE;
-})
-
-(define_expand "beq"
- [(set (pc)
- (if_then_else (match_dup 1)
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "{ operands[1] = alpha_emit_conditional_branch (EQ); }")
-
-(define_expand "bne"
- [(set (pc)
- (if_then_else (match_dup 1)
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "{ operands[1] = alpha_emit_conditional_branch (NE); }")
-
-(define_expand "blt"
- [(set (pc)
- (if_then_else (match_dup 1)
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "{ operands[1] = alpha_emit_conditional_branch (LT); }")
+ { alpha_emit_conditional_branch (operands, TFmode); DONE; })
-(define_expand "ble"
- [(set (pc)
- (if_then_else (match_dup 1)
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "{ operands[1] = alpha_emit_conditional_branch (LE); }")
-
-(define_expand "bgt"
- [(set (pc)
- (if_then_else (match_dup 1)
- (label_ref (match_operand 0 "" ""))
- (pc)))]
+(define_expand "cbranchdi4"
+ [(use (match_operator 0 "alpha_cbranch_operator"
+ [(match_operand:DI 1 "some_operand")
+ (match_operand:DI 2 "some_operand")]))
+ (use (match_operand 3 ""))]
""
- "{ operands[1] = alpha_emit_conditional_branch (GT); }")
+ { alpha_emit_conditional_branch (operands, DImode); DONE; })
-(define_expand "bge"
- [(set (pc)
- (if_then_else (match_dup 1)
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "{ operands[1] = alpha_emit_conditional_branch (GE); }")
-
-(define_expand "bltu"
- [(set (pc)
- (if_then_else (match_dup 1)
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "{ operands[1] = alpha_emit_conditional_branch (LTU); }")
-
-(define_expand "bleu"
- [(set (pc)
- (if_then_else (match_dup 1)
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "{ operands[1] = alpha_emit_conditional_branch (LEU); }")
-
-(define_expand "bgtu"
- [(set (pc)
- (if_then_else (match_dup 1)
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "{ operands[1] = alpha_emit_conditional_branch (GTU); }")
-
-(define_expand "bgeu"
- [(set (pc)
- (if_then_else (match_dup 1)
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "{ operands[1] = alpha_emit_conditional_branch (GEU); }")
-
-(define_expand "bunordered"
- [(set (pc)
- (if_then_else (match_dup 1)
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "{ operands[1] = alpha_emit_conditional_branch (UNORDERED); }")
-
-(define_expand "bordered"
- [(set (pc)
- (if_then_else (match_dup 1)
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "{ operands[1] = alpha_emit_conditional_branch (ORDERED); }")
-
-(define_expand "seq"
- [(set (match_operand:DI 0 "register_operand" "")
- (match_dup 1))]
- ""
- "{ if ((operands[1] = alpha_emit_setcc (EQ)) == NULL_RTX) FAIL; }")
-
-(define_expand "sne"
- [(set (match_operand:DI 0 "register_operand" "")
- (match_dup 1))]
- ""
- "{ if ((operands[1] = alpha_emit_setcc (NE)) == NULL_RTX) FAIL; }")
-
-(define_expand "slt"
- [(set (match_operand:DI 0 "register_operand" "")
- (match_dup 1))]
- ""
- "{ if ((operands[1] = alpha_emit_setcc (LT)) == NULL_RTX) FAIL; }")
-
-(define_expand "sle"
- [(set (match_operand:DI 0 "register_operand" "")
- (match_dup 1))]
- ""
- "{ if ((operands[1] = alpha_emit_setcc (LE)) == NULL_RTX) FAIL; }")
-
-(define_expand "sgt"
- [(set (match_operand:DI 0 "register_operand" "")
- (match_dup 1))]
- ""
- "{ if ((operands[1] = alpha_emit_setcc (GT)) == NULL_RTX) FAIL; }")
-
-(define_expand "sge"
- [(set (match_operand:DI 0 "register_operand" "")
- (match_dup 1))]
- ""
- "{ if ((operands[1] = alpha_emit_setcc (GE)) == NULL_RTX) FAIL; }")
-
-(define_expand "sltu"
- [(set (match_operand:DI 0 "register_operand" "")
- (match_dup 1))]
- ""
- "{ if ((operands[1] = alpha_emit_setcc (LTU)) == NULL_RTX) FAIL; }")
-
-(define_expand "sleu"
- [(set (match_operand:DI 0 "register_operand" "")
- (match_dup 1))]
- ""
- "{ if ((operands[1] = alpha_emit_setcc (LEU)) == NULL_RTX) FAIL; }")
-
-(define_expand "sgtu"
- [(set (match_operand:DI 0 "register_operand" "")
- (match_dup 1))]
- ""
- "{ if ((operands[1] = alpha_emit_setcc (GTU)) == NULL_RTX) FAIL; }")
-
-(define_expand "sgeu"
- [(set (match_operand:DI 0 "register_operand" "")
- (match_dup 1))]
- ""
- "{ if ((operands[1] = alpha_emit_setcc (GEU)) == NULL_RTX) FAIL; }")
+(define_expand "cstoredf4"
+ [(use (match_operator:DI 1 "alpha_cbranch_operator"
+ [(match_operand:DF 2 "reg_or_0_operand")
+ (match_operand:DF 3 "reg_or_0_operand")]))
+ (clobber (match_operand:DI 0 "register_operand"))]
+ "TARGET_FP"
+ { if (!alpha_emit_setcc (operands, DFmode)) FAIL; else DONE; })
-(define_expand "sunordered"
- [(set (match_operand:DI 0 "register_operand" "")
- (match_dup 1))]
- ""
- "{ if ((operands[1] = alpha_emit_setcc (UNORDERED)) == NULL_RTX) FAIL; }")
+(define_expand "cstoretf4"
+ [(use (match_operator:DI 1 "alpha_cbranch_operator"
+ [(match_operand:TF 2 "general_operand")
+ (match_operand:TF 3 "general_operand")]))
+ (clobber (match_operand:DI 0 "register_operand"))]
+ "TARGET_HAS_XFLOATING_LIBS"
+ { if (!alpha_emit_setcc (operands, TFmode)) FAIL; else DONE; })
-(define_expand "sordered"
- [(set (match_operand:DI 0 "register_operand" "")
- (match_dup 1))]
+(define_expand "cstoredi4"
+ [(use (match_operator:DI 1 "alpha_cbranch_operator"
+ [(match_operand:DI 2 "some_operand")
+ (match_operand:DI 3 "some_operand")]))
+ (clobber (match_operand:DI 0 "register_operand"))]
""
- "{ if ((operands[1] = alpha_emit_setcc (ORDERED)) == NULL_RTX) FAIL; }")
+ { if (!alpha_emit_setcc (operands, DImode)) FAIL; else DONE; })
;; These are the main define_expand's used to make conditional moves.
@@ -6766,7 +6613,7 @@
rtx loop_label = gen_label_rtx ();
rtx want = gen_reg_rtx (Pmode);
rtx tmp = gen_reg_rtx (Pmode);
- rtx memref;
+ rtx memref, test;
emit_insn (gen_subdi3 (want, stack_pointer_rtx,
force_reg (Pmode, operands[1])));
@@ -6775,8 +6622,8 @@
if (!CONST_INT_P (operands[1]))
{
out_label = gen_label_rtx ();
- emit_insn (gen_cmpdi (want, tmp));
- emit_jump_insn (gen_bgeu (out_label));
+ test = gen_rtx_GEU (VOIDmode, want, tmp);
+ emit_jump_insn (gen_cbranchdi4 (test, want, tmp, out_label));
}
emit_label (loop_label);
@@ -6784,8 +6631,8 @@
MEM_VOLATILE_P (memref) = 1;
emit_move_insn (memref, const0_rtx);
emit_insn (gen_adddi3 (tmp, tmp, GEN_INT(-8192)));
- emit_insn (gen_cmpdi (tmp, want));
- emit_jump_insn (gen_bgtu (loop_label));
+ test = gen_rtx_GTU (VOIDmode, tmp, want);
+ emit_jump_insn (gen_cbranchdi4 (test, tmp, want, loop_label));
memref = gen_rtx_MEM (DImode, want);
MEM_VOLATILE_P (memref) = 1;
diff --git a/gcc/config/alpha/predicates.md b/gcc/config/alpha/predicates.md
index 425134ac820..ec11eaa3d1f 100644
--- a/gcc/config/alpha/predicates.md
+++ b/gcc/config/alpha/predicates.md
@@ -543,6 +543,12 @@
(and (match_code "reg")
(match_operand 0 "register_operand")))
+;; Return 1 if OP is a valid Alpha comparison operator for "cbranch"
+;; instructions.
+(define_predicate "alpha_cbranch_operator"
+ (ior (match_operand 0 "ordered_comparison_operator")
+ (match_code "ordered,unordered")))
+
;; Return 1 if OP is a valid Alpha comparison operator for "cmp" style
;; instructions.
(define_predicate "alpha_comparison_operator"
diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
index 3f81f611f80..1f456b63cd7 100644
--- a/gcc/config/arc/arc.c
+++ b/gcc/config/arc/arc.c
@@ -49,10 +49,6 @@ int arc_cpu_type;
cpu (or NULL). */
const char *arc_mangle_cpu;
-/* Save the operands last given to a compare for use when we
- generate a scc or bcc insn. */
-rtx arc_compare_op0, arc_compare_op1;
-
/* Name of text, data, and rodata sections used in varasm.c. */
const char *arc_text_section;
const char *arc_data_section;
@@ -729,21 +725,14 @@ proper_comparison_operator (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
/* Misc. utilities. */
-/* 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. */
+/* X and Y are two things to compare using CODE. Return the rtx
+ for the cc reg in the proper mode. */
rtx
gen_compare_reg (enum rtx_code code, rtx x, rtx y)
{
enum machine_mode mode = SELECT_CC_MODE (code, x, y);
- rtx cc_reg;
-
- cc_reg = gen_rtx_REG (mode, 61);
-
- emit_insn (gen_rtx_SET (VOIDmode, cc_reg,
- gen_rtx_COMPARE (mode, x, y)));
-
- return cc_reg;
+ return gen_rtx_REG (mode, 61);
}
/* Return 1 if VALUE, a const_double, will fit in a limm (4 byte number).
diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h
index db6829bc560..4153ad6f6b6 100644
--- a/gcc/config/arc/arc.h
+++ b/gcc/config/arc/arc.h
@@ -1067,11 +1067,6 @@ do { if ((LOG) != 0) fprintf (FILE, "\t.align %d\n", 1 << (LOG)); } while (0)
/* ??? Not defined in tm.texi. */
#define SETJMP_VIA_SAVE_AREA
-/* Define the information needed to generate branch and scc insns. This is
- stored from the compare operation. Note that we can't use "rtx" here
- since it hasn't been defined! */
-extern struct rtx_def *arc_compare_op0, *arc_compare_op1;
-
/* ARC function types. */
enum arc_function_type {
ARC_FUNCTION_UNKNOWN, ARC_FUNCTION_NORMAL,
diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
index b67984babbb..09e47daf1d1 100644
--- a/gcc/config/arc/arc.md
+++ b/gcc/config/arc/arc.md
@@ -585,29 +585,11 @@
"
{
enum rtx_code code = GET_CODE (operands[1]);
- rtx ccreg
- = gen_rtx_REG (SELECT_CC_MODE (code, arc_compare_op0, arc_compare_op1),
- 61);
-
- operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
+ rtx cc_reg = gen_compare_reg (code, XEXP (operands[1], 0),
+ XEXP (operands[1], 1));
+ operands[1] = gen_rtx_fmt_ee (code, VOIDmode, cc_reg, const0_rtx);
}")
-;(define_expand "movdicc"
-; [(set (match_operand:DI 0 "register_operand" "")
-; (if_then_else:DI (match_operand 1 "comparison_operator" "")
-; (match_operand:DI 2 "nonmemory_operand" "")
-; (match_operand:DI 3 "register_operand" "")))]
-; "0 /* ??? this would work better if we had cmpdi */"
-; "
-;{
-; enum rtx_code code = GET_CODE (operands[1]);
-; rtx ccreg
-; = gen_rtx_REG (SELECT_CC_MODE (code, arc_compare_op0, arc_compare_op1),
-; 61);
-;
-; operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
-;}")
-
(define_expand "movsfcc"
[(set (match_operand:SF 0 "register_operand" "")
(if_then_else:SF (match_operand 1 "comparison_operator" "")
@@ -617,29 +599,11 @@
"
{
enum rtx_code code = GET_CODE (operands[1]);
- rtx ccreg
- = gen_rtx_REG (SELECT_CC_MODE (code, arc_compare_op0, arc_compare_op1),
- 61);
-
- operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
+ rtx cc_reg = gen_compare_reg (code, XEXP (operands[1], 0),
+ XEXP (operands[1], 1));
+ operands[1] = gen_rtx_fmt_ee (code, VOIDmode, cc_reg, const0_rtx);
}")
-;(define_expand "movdfcc"
-; [(set (match_operand:DF 0 "register_operand" "")
-; (if_then_else:DF (match_operand 1 "comparison_operator" "")
-; (match_operand:DF 2 "nonmemory_operand" "")
-; (match_operand:DF 3 "register_operand" "")))]
-; "0 /* ??? can generate less efficient code if constants involved */"
-; "
-;{
-; enum rtx_code code = GET_CODE (operands[1]);
-; rtx ccreg
-; = gen_rtx_REG (SELECT_CC_MODE (code, arc_compare_op0, arc_compare_op1),
-; 61);
-;
-; operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
-;}")
-
(define_insn "*movsicc_insn"
[(set (match_operand:SI 0 "register_operand" "=r")
(if_then_else:SI (match_operand 1 "comparison_operator" "")
@@ -649,32 +613,6 @@
"mov.%d1 %0,%S2"
[(set_attr "type" "cmove")])
-; ??? This doesn't properly handle constants.
-;(define_insn "*movdicc_insn"
-; [(set (match_operand:DI 0 "register_operand" "=r,r")
-; (if_then_else:DI (match_operand 1 "comparison_operator" "")
-; (match_operand:DI 2 "nonmemory_operand" "r,Ji")
-; (match_operand:DI 3 "register_operand" "0,0")))]
-; "0"
-; "*
-;{
-; switch (which_alternative)
-; {
-; case 0 :
-; /* We normally copy the low-numbered register first. However, if
-; the first register operand 0 is the same as the second register of
-; operand 1, we must copy in the opposite order. */
-; if (REGNO (operands[0]) == REGNO (operands[2]) + 1)
-; return \"mov.%d1 %R0,%R2\;mov.%d1 %0,%2\";
-; else
-; return \"mov.%d1 %0,%2\;mov.%d1 %R0,%R2\";
-; case 1 :
-; return \"mov.%d1 %0,%2\;mov.%d1 %R0,%R2\";
-; }
-;}"
-; [(set_attr "type" "cmove,cmove")
-; (set_attr "length" "2,4")])
-
(define_insn "*movsfcc_insn"
[(set (match_operand:SF 0 "register_operand" "=r,r")
(if_then_else:SF (match_operand 1 "comparison_operator" "")
@@ -686,30 +624,6 @@
mov.%d1 %0,%2 ; %A2"
[(set_attr "type" "cmove,cmove")])
-;(define_insn "*movdfcc_insn"
-; [(set (match_operand:DF 0 "register_operand" "=r,r")
-; (if_then_else:DF (match_operand 1 "comparison_operator" "")
-; (match_operand:DF 2 "nonmemory_operand" "r,E")
-; (match_operand:DF 3 "register_operand" "0,0")))]
-; "0"
-; "*
-;{
-; switch (which_alternative)
-; {
-; case 0 :
-; /* We normally copy the low-numbered register first. However, if
-; the first register operand 0 is the same as the second register of
-; operand 1, we must copy in the opposite order. */
-; if (REGNO (operands[0]) == REGNO (operands[2]) + 1)
-; return \"mov.%d1 %R0,%R2\;mov.%d1 %0,%2\";
-; else
-; return \"mov.%d1 %0,%2\;mov.%d1 %R0,%R2\";
-; case 1 :
-; return \"mov.%d1 %0,%L2\;mov.%d1 %R0,%H2 ; %A2\";
-; }
-;}"
-; [(set_attr "type" "cmove,cmove")
-; (set_attr "length" "2,4")])
;; Zero extension instructions.
;; ??? We don't support volatile memrefs here, but I'm not sure why.
@@ -1156,22 +1070,6 @@
;; Compare instructions.
;; This controls RTL generation and register allocation.
-;; We generate RTL for comparisons and branches by having the cmpxx
-;; patterns store away the operands. Then, the scc and bcc patterns
-;; emit RTL for both the compare and the branch.
-
-(define_expand "cmpsi"
- [(set (reg:CC 61)
- (compare:CC (match_operand:SI 0 "register_operand" "")
- (match_operand:SI 1 "nonmemory_operand" "")))]
- ""
- "
-{
- arc_compare_op0 = operands[0];
- arc_compare_op1 = operands[1];
- DONE;
-}")
-
;; ??? We may be able to relax this a bit by adding a new constant 'K' for 0.
;; This assumes sub.f 0,symbol,0 is a valid insn.
;; Note that "sub.f 0,r0,1" is an 8 byte insn. To avoid unnecessarily
@@ -1211,96 +1109,25 @@
sub.f 0,%0,%1"
[(set_attr "type" "compare,compare,compare")])
-;; Next come the scc insns.
-
-(define_expand "seq"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (eq:SI (match_dup 1) (const_int 0)))]
- ""
- "
-{
- operands[1] = gen_compare_reg (EQ, arc_compare_op0, arc_compare_op1);
-}")
+;; Next come the scc insn and its expander.
-(define_expand "sne"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (ne:SI (match_dup 1) (const_int 0)))]
- ""
- "
-{
- operands[1] = gen_compare_reg (NE, arc_compare_op0, arc_compare_op1);
-}")
-
-(define_expand "sgt"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (gt:SI (match_dup 1) (const_int 0)))]
- ""
- "
-{
- operands[1] = gen_compare_reg (GT, arc_compare_op0, arc_compare_op1);
-}")
-
-(define_expand "sle"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (le:SI (match_dup 1) (const_int 0)))]
- ""
- "
-{
- operands[1] = gen_compare_reg (LE, arc_compare_op0, arc_compare_op1);
-}")
-
-(define_expand "sge"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (ge:SI (match_dup 1) (const_int 0)))]
- ""
- "
-{
- operands[1] = gen_compare_reg (GE, arc_compare_op0, arc_compare_op1);
-}")
-
-(define_expand "slt"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (lt:SI (match_dup 1) (const_int 0)))]
- ""
- "
-{
- operands[1] = gen_compare_reg (LT, arc_compare_op0, arc_compare_op1);
-}")
-
-(define_expand "sgtu"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (gtu:SI (match_dup 1) (const_int 0)))]
- ""
- "
-{
- operands[1] = gen_compare_reg (GTU, arc_compare_op0, arc_compare_op1);
-}")
-
-(define_expand "sleu"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (leu:SI (match_dup 1) (const_int 0)))]
- ""
- "
-{
- operands[1] = gen_compare_reg (LEU, arc_compare_op0, arc_compare_op1);
-}")
-
-(define_expand "sgeu"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (geu:SI (match_dup 1) (const_int 0)))]
- ""
- "
-{
- operands[1] = gen_compare_reg (GEU, arc_compare_op0, arc_compare_op1);
-}")
-
-(define_expand "sltu"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (ltu:SI (match_dup 1) (const_int 0)))]
+(define_expand "cstoresi4"
+ [(set (match_dup 4)
+ (match_op_dup 5
+ [(match_operand:SI 2 "register_operand" "")
+ (match_operand:SI 3 "nonmemory_operand" "")]))
+ (set (match_operand:SI 0 "register_operand")
+ (match_operator:SI 1 "ordered_comparison_operator"
+ [(match_dup 4)
+ (const_int 0)]))]
""
"
{
- operands[1] = gen_compare_reg (LTU, arc_compare_op0, arc_compare_op1);
+ operands[4] = gen_compare_reg (GET_CODE (operands[1]),
+ operands[2], operands[3]);
+ operands[5] = gen_rtx_fmt_ee (COMPARE,
+ GET_MODE (operands[4]),
+ operands[2], operands[3]);
}")
(define_insn "*scc_insn"
@@ -1332,114 +1159,26 @@
;; These control RTL generation for conditional jump insns
-(define_expand "beq"
- [(set (pc)
- (if_then_else (eq (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- operands[1] = gen_compare_reg (EQ, arc_compare_op0, arc_compare_op1);
-}")
-
-(define_expand "bne"
- [(set (pc)
- (if_then_else (ne (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- operands[1] = gen_compare_reg (NE, arc_compare_op0, arc_compare_op1);
-}")
-
-(define_expand "bgt"
- [(set (pc)
- (if_then_else (gt (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- operands[1] = gen_compare_reg (GT, arc_compare_op0, arc_compare_op1);
-}")
-
-(define_expand "ble"
- [(set (pc)
- (if_then_else (le (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- operands[1] = gen_compare_reg (LE, arc_compare_op0, arc_compare_op1);
-}")
-
-(define_expand "bge"
- [(set (pc)
- (if_then_else (ge (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- operands[1] = gen_compare_reg (GE, arc_compare_op0, arc_compare_op1);
-}")
-
-(define_expand "blt"
- [(set (pc)
- (if_then_else (lt (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- operands[1] = gen_compare_reg (LT, arc_compare_op0, arc_compare_op1);
-}")
-
-(define_expand "bgtu"
- [(set (pc)
- (if_then_else (gtu (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- operands[1] = gen_compare_reg (GTU, arc_compare_op0, arc_compare_op1);
-}")
-
-(define_expand "bleu"
- [(set (pc)
- (if_then_else (leu (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- operands[1] = gen_compare_reg (LEU, arc_compare_op0, arc_compare_op1);
-}")
-
-(define_expand "bgeu"
- [(set (pc)
- (if_then_else (geu (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- operands[1] = gen_compare_reg (GEU, arc_compare_op0, arc_compare_op1);
-}")
-
-(define_expand "bltu"
- [(set (pc)
- (if_then_else (ltu (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
+(define_expand "cbranchsi4"
+ [(set (match_dup 4)
+ (match_op_dup 5
+ [(match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "nonmemory_operand" "")]))
+ (set (pc)
+ (if_then_else
+ (match_operator 0 "ordered_comparison_operator"
+ [(match_dup 4)
+ (const_int 0)])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
""
"
{
- operands[1] = gen_compare_reg (LTU, arc_compare_op0, arc_compare_op1);
+ operands[4] = gen_compare_reg (GET_CODE (operands[0]),
+ operands[1], operands[2]);
+ operands[5] = gen_rtx_fmt_ee (COMPARE,
+ GET_MODE (operands[4]),
+ operands[1], operands[2]);
}")
;; Now match both normal and inverted jump.
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 1d9b4265843..18e009d1368 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -418,10 +418,6 @@ extern FILE * asm_out_file;
/* True if we are currently building a constant table. */
int making_const_table;
-/* Define the information needed to generate branch insns. This is
- stored from the compare operation. */
-rtx arm_compare_op0, arm_compare_op1;
-
/* The processor for which instructions should be scheduled. */
enum processor_type arm_tune = arm_none;
diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
index e7bc7a7a2d5..e0430908901 100644
--- a/gcc/config/arm/arm.h
+++ b/gcc/config/arm/arm.h
@@ -124,10 +124,6 @@ extern arm_cc arm_current_cc;
extern int arm_target_label;
extern int arm_ccfsm_state;
extern GTY(()) rtx arm_target_insn;
-/* Define the information needed to generate branch insns. This is
- stored from the compare operation. */
-extern GTY(()) rtx arm_compare_op0;
-extern GTY(()) rtx arm_compare_op1;
/* The label of the current constant pool. */
extern rtx pool_vector_label;
/* Set to 1 when a return insn is output, this means that the epilogue
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 801865287b7..b18173e1aff 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -6386,8 +6386,16 @@
(match_operand:SI 2 "nonmemory_operand" "")])
(label_ref (match_operand 3 "" ""))
(pc)))]
- "TARGET_THUMB1"
+ "TARGET_THUMB1 || TARGET_32BIT"
"
+ if (!TARGET_THUMB1)
+ {
+ if (!arm_add_operand (operands[2], SImode))
+ operands[2] = force_reg (SImode, operands[2]);
+ emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
+ operands[3]));
+ DONE;
+ }
if (thumb1_cmpneg_operand (operands[2], SImode))
{
emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
@@ -6398,6 +6406,43 @@
operands[2] = force_reg (SImode, operands[2]);
")
+(define_expand "cbranchsf4"
+ [(set (pc) (if_then_else
+ (match_operator 0 "arm_comparison_operator"
+ [(match_operand:SF 1 "s_register_operand" "")
+ (match_operand:SF 2 "arm_float_compare_operand" "")])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
+ "TARGET_32BIT && TARGET_HARD_FLOAT"
+ "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
+ operands[3])); DONE;"
+)
+
+(define_expand "cbranchdf4"
+ [(set (pc) (if_then_else
+ (match_operator 0 "arm_comparison_operator"
+ [(match_operand:DF 1 "s_register_operand" "")
+ (match_operand:DF 2 "arm_float_compare_operand" "")])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
+ "TARGET_32BIT && TARGET_HARD_FLOAT"
+ "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
+ operands[3])); DONE;"
+)
+
+;; this uses the Cirrus DI compare instruction
+(define_expand "cbranchdi4"
+ [(set (pc) (if_then_else
+ (match_operator 0 "arm_comparison_operator"
+ [(match_operand:DI 1 "cirrus_fp_register" "")
+ (match_operand:DI 2 "cirrus_fp_register" "")])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
+ "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
+ operands[3])); DONE;"
+)
+
(define_insn "*cbranchsi4_insn"
[(set (pc) (if_then_else
(match_operator 0 "arm_comparison_operator"
@@ -7451,39 +7496,6 @@
;; Comparison and test insns
-(define_expand "cmpsi"
- [(match_operand:SI 0 "s_register_operand" "")
- (match_operand:SI 1 "arm_add_operand" "")]
- "TARGET_32BIT"
- "{
- arm_compare_op0 = operands[0];
- arm_compare_op1 = operands[1];
- DONE;
- }"
-)
-
-(define_expand "cmpsf"
- [(match_operand:SF 0 "s_register_operand" "")
- (match_operand:SF 1 "arm_float_compare_operand" "")]
- "TARGET_32BIT && TARGET_HARD_FLOAT"
- "
- arm_compare_op0 = operands[0];
- arm_compare_op1 = operands[1];
- DONE;
- "
-)
-
-(define_expand "cmpdf"
- [(match_operand:DF 0 "s_register_operand" "")
- (match_operand:DF 1 "arm_float_compare_operand" "")]
- "TARGET_32BIT && TARGET_HARD_FLOAT"
- "
- arm_compare_op0 = operands[0];
- arm_compare_op1 = operands[1];
- DONE;
- "
-)
-
(define_insn "*arm_cmpsi_insn"
[(set (reg:CC CC_REGNUM)
(compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
@@ -7562,17 +7574,6 @@
(set_attr "cirrus" "compare")]
)
-;; Cirrus DI compare instruction
-(define_expand "cmpdi"
- [(match_operand:DI 0 "cirrus_fp_register" "")
- (match_operand:DI 1 "cirrus_fp_register" "")]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
- "{
- arm_compare_op0 = operands[0];
- arm_compare_op1 = operands[1];
- DONE;
- }")
-
(define_insn "*cirrus_cmpdi"
[(set (reg:CC CC_REGNUM)
(compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
@@ -7600,170 +7601,16 @@
;; Conditional branch insns
-(define_expand "beq"
- [(set (pc)
- (if_then_else (eq (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_32BIT"
- "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
-)
-
-(define_expand "bne"
+(define_expand "cbranch_cc"
[(set (pc)
- (if_then_else (ne (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_32BIT"
- "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
-)
-
-(define_expand "bgt"
- [(set (pc)
- (if_then_else (gt (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
+ (if_then_else (match_operator 0 "" [(match_operand 1 "" "")
+ (match_operand 2 "" "")])
+ (label_ref (match_operand 3 "" ""))
(pc)))]
"TARGET_32BIT"
- "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
-)
-
-(define_expand "ble"
- [(set (pc)
- (if_then_else (le (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_32BIT"
- "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
-)
-
-(define_expand "bge"
- [(set (pc)
- (if_then_else (ge (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_32BIT"
- "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
-)
-
-(define_expand "blt"
- [(set (pc)
- (if_then_else (lt (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_32BIT"
- "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
-)
-
-(define_expand "bgtu"
- [(set (pc)
- (if_then_else (gtu (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_32BIT"
- "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
-)
-
-(define_expand "bleu"
- [(set (pc)
- (if_then_else (leu (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_32BIT"
- "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
-)
-
-(define_expand "bgeu"
- [(set (pc)
- (if_then_else (geu (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_32BIT"
- "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
-)
-
-(define_expand "bltu"
- [(set (pc)
- (if_then_else (ltu (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_32BIT"
- "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
-)
-
-(define_expand "bunordered"
- [(set (pc)
- (if_then_else (unordered (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
- "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
- arm_compare_op1);"
-)
-
-(define_expand "bordered"
- [(set (pc)
- (if_then_else (ordered (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
- "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
- arm_compare_op1);"
-)
-
-(define_expand "bungt"
- [(set (pc)
- (if_then_else (ungt (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
- "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
-)
-
-(define_expand "bunlt"
- [(set (pc)
- (if_then_else (unlt (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
- "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
-)
-
-(define_expand "bunge"
- [(set (pc)
- (if_then_else (unge (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
- "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
-)
-
-(define_expand "bunle"
- [(set (pc)
- (if_then_else (unle (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
- "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
-)
-
-;; The following two patterns need two branch instructions, since there is
-;; no single instruction that will handle all cases.
-(define_expand "buneq"
- [(set (pc)
- (if_then_else (uneq (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
- "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
-)
-
-(define_expand "bltgt"
- [(set (pc)
- (if_then_else (ltgt (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
- "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
+ "operands[1] = arm_gen_compare_reg (GET_CODE (operands[0]),
+ operands[1], operands[2]);
+ operands[2] = const0_rtx;"
)
;;
@@ -7876,141 +7723,16 @@
; scc insns
-(define_expand "seq"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (eq:SI (match_dup 1) (const_int 0)))]
- "TARGET_32BIT"
- "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
-)
-
-(define_expand "sne"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (ne:SI (match_dup 1) (const_int 0)))]
- "TARGET_32BIT"
- "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
-)
-
-(define_expand "sgt"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (gt:SI (match_dup 1) (const_int 0)))]
- "TARGET_32BIT"
- "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
-)
-
-(define_expand "sle"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (le:SI (match_dup 1) (const_int 0)))]
- "TARGET_32BIT"
- "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
-)
-
-(define_expand "sge"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (ge:SI (match_dup 1) (const_int 0)))]
- "TARGET_32BIT"
- "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
-)
-
-(define_expand "slt"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (lt:SI (match_dup 1) (const_int 0)))]
- "TARGET_32BIT"
- "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
-)
-
-(define_expand "sgtu"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (gtu:SI (match_dup 1) (const_int 0)))]
- "TARGET_32BIT"
- "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
-)
-
-(define_expand "sleu"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (leu:SI (match_dup 1) (const_int 0)))]
- "TARGET_32BIT"
- "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
-)
-
-(define_expand "sgeu"
+(define_expand "cstore_cc"
[(set (match_operand:SI 0 "s_register_operand" "")
- (geu:SI (match_dup 1) (const_int 0)))]
+ (match_operator:SI 1 "" [(match_operand 2 "" "")
+ (match_operand 3 "" "")]))]
"TARGET_32BIT"
- "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
-)
-
-(define_expand "sltu"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (ltu:SI (match_dup 1) (const_int 0)))]
- "TARGET_32BIT"
- "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
-)
-
-(define_expand "sunordered"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (unordered:SI (match_dup 1) (const_int 0)))]
- "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
- "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
- arm_compare_op1);"
-)
-
-(define_expand "sordered"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (ordered:SI (match_dup 1) (const_int 0)))]
- "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
- "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
- arm_compare_op1);"
-)
-
-(define_expand "sungt"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (ungt:SI (match_dup 1) (const_int 0)))]
- "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
- "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
- arm_compare_op1);"
-)
-
-(define_expand "sunge"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (unge:SI (match_dup 1) (const_int 0)))]
- "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
- "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
- arm_compare_op1);"
-)
-
-(define_expand "sunlt"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (unlt:SI (match_dup 1) (const_int 0)))]
- "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
- "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
- arm_compare_op1);"
-)
-
-(define_expand "sunle"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (unle:SI (match_dup 1) (const_int 0)))]
- "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
- "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
- arm_compare_op1);"
+ "operands[2] = arm_gen_compare_reg (GET_CODE (operands[1]),
+ operands[2], operands[3]);
+ operands[3] = const0_rtx;"
)
-;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
-;;; simple ARM instructions.
-;
-; (define_expand "suneq"
-; [(set (match_operand:SI 0 "s_register_operand" "")
-; (uneq:SI (match_dup 1) (const_int 0)))]
-; "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
-; "gcc_unreachable ();"
-; )
-;
-; (define_expand "sltgt"
-; [(set (match_operand:SI 0 "s_register_operand" "")
-; (ltgt:SI (match_dup 1) (const_int 0)))]
-; "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
-; "gcc_unreachable ();"
-; )
-
(define_insn "*mov_scc"
[(set (match_operand:SI 0 "s_register_operand" "=r")
(match_operator:SI 1 "arm_comparison_operator"
@@ -8046,10 +7768,19 @@
(match_operator:SI 1 "arm_comparison_operator"
[(match_operand:SI 2 "s_register_operand" "")
(match_operand:SI 3 "reg_or_int_operand" "")]))]
- "TARGET_THUMB1"
+ "TARGET_32BIT || TARGET_THUMB1"
"{
rtx op3, scratch, scratch2;
+ if (!TARGET_THUMB1)
+ {
+ if (!arm_add_operand (operands[3], SImode))
+ operands[3] = force_reg (SImode, operands[3]);
+ emit_insn (gen_cstore_cc (operands[0], operands[1],
+ operands[2], operands[3]));
+ DONE;
+ }
+
if (operands[3] == const0_rtx)
{
switch (GET_CODE (operands[1]))
@@ -8170,6 +7901,38 @@
DONE;
}")
+(define_expand "cstoresf4"
+ [(set (match_operand:SI 0 "s_register_operand" "")
+ (match_operator:SI 1 "arm_comparison_operator"
+ [(match_operand:SF 2 "s_register_operand" "")
+ (match_operand:SF 3 "arm_float_compare_operand" "")]))]
+ "TARGET_32BIT && TARGET_HARD_FLOAT"
+ "emit_insn (gen_cstore_cc (operands[0], operands[1],
+ operands[2], operands[3])); DONE;"
+)
+
+(define_expand "cstoredf4"
+ [(set (match_operand:SI 0 "s_register_operand" "")
+ (match_operator:SI 1 "arm_comparison_operator"
+ [(match_operand:DF 2 "s_register_operand" "")
+ (match_operand:DF 3 "arm_float_compare_operand" "")]))]
+ "TARGET_32BIT && TARGET_HARD_FLOAT"
+ "emit_insn (gen_cstore_cc (operands[0], operands[1],
+ operands[2], operands[3])); DONE;"
+)
+
+;; this uses the Cirrus DI compare instruction
+(define_expand "cstoredi4"
+ [(set (match_operand:SI 0 "s_register_operand" "")
+ (match_operator:SI 1 "arm_comparison_operator"
+ [(match_operand:DI 2 "cirrus_fp_register" "")
+ (match_operand:DI 3 "cirrus_fp_register" "")]))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
+ "emit_insn (gen_cstore_cc (operands[0], operands[1],
+ operands[2], operands[3])); DONE;"
+)
+
+
(define_expand "cstoresi_eq0_thumb1"
[(parallel
[(set (match_operand:SI 0 "s_register_operand" "")
@@ -8250,7 +8013,8 @@
if (code == UNEQ || code == LTGT)
FAIL;
- ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
+ ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
+ XEXP (operands[1], 1));
operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
}"
)
@@ -8275,7 +8039,8 @@
|| (!arm_float_add_operand (operands[3], SFmode)))
operands[3] = force_reg (SFmode, operands[3]);
- ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
+ ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
+ XEXP (operands[1], 1));
operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
}"
)
@@ -8294,7 +8059,8 @@
if (code == UNEQ || code == LTGT)
FAIL;
- ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
+ ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
+ XEXP (operands[1], 1));
operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
}"
)
diff --git a/gcc/config/arm/predicates.md b/gcc/config/arm/predicates.md
index c7d63355d34..b45faf43cbc 100644
--- a/gcc/config/arm/predicates.md
+++ b/gcc/config/arm/predicates.md
@@ -191,9 +191,13 @@
(define_special_predicate "equality_operator"
(match_code "eq,ne"))
-;; True for comparisons other than LTGT or UNEQ.
+;; True for integer comparisons and, if FP is active, for comparisons
+;; other than LTGT or UNEQ.
(define_special_predicate "arm_comparison_operator"
- (match_code "eq,ne,le,lt,ge,gt,geu,gtu,leu,ltu,unordered,ordered,unlt,unle,unge,ungt"))
+ (ior (match_code "eq,ne,le,lt,ge,gt,geu,gtu,leu,ltu")
+ (and (match_test "TARGET_32BIT && TARGET_HARD_FLOAT
+ && (TARGET_FPA || TARGET_VFP)")
+ (match_code "unordered,ordered,unlt,unle,unge,ungt"))))
(define_special_predicate "minmax_operator"
(and (match_code "smin,smax,umin,umax")
diff --git a/gcc/config/avr/avr-protos.h b/gcc/config/avr/avr-protos.h
index 44246901b32..f4d2119a998 100644
--- a/gcc/config/avr/avr-protos.h
+++ b/gcc/config/avr/avr-protos.h
@@ -72,8 +72,8 @@ extern const char *out_movhi_mr_r (rtx insn, rtx op[], int *l);
extern const char *out_movsi_r_mr (rtx insn, rtx op[], int *l);
extern const char *out_movsi_mr_r (rtx insn, rtx op[], int *l);
extern const char *output_movsisf (rtx insn, rtx operands[], int *l);
-extern const char *out_tstsi (rtx insn, int *l);
-extern const char *out_tsthi (rtx insn, int *l);
+extern const char *out_tstsi (rtx insn, rtx src, int *l);
+extern const char *out_tsthi (rtx insn, rtx src, int *l);
extern const char *ret_cond_branch (rtx x, int len, int reverse);
extern const char *ashlqi3_out (rtx insn, rtx operands[], int *len);
diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c
index 6bcc8e80372..4811b92637f 100644
--- a/gcc/config/avr/avr.c
+++ b/gcc/config/avr/avr.c
@@ -2915,21 +2915,21 @@ compare_eq_p (rtx insn)
/* Output test instruction for HImode. */
const char *
-out_tsthi (rtx insn, int *l)
+out_tsthi (rtx insn, rtx op, int *l)
{
if (compare_sign_p (insn))
{
if (l) *l = 1;
return AS1 (tst,%B0);
}
- if (reg_unused_after (insn, SET_SRC (PATTERN (insn)))
+ if (reg_unused_after (insn, op)
&& compare_eq_p (insn))
{
/* Faster than sbiw if we can clobber the operand. */
if (l) *l = 1;
return AS2 (or,%A0,%B0);
}
- if (test_hard_reg_class (ADDW_REGS, SET_SRC (PATTERN (insn))))
+ if (test_hard_reg_class (ADDW_REGS, op))
{
if (l) *l = 1;
return AS2 (sbiw,%0,0);
@@ -2943,14 +2943,14 @@ out_tsthi (rtx insn, int *l)
/* Output test instruction for SImode. */
const char *
-out_tstsi (rtx insn, int *l)
+out_tstsi (rtx insn, rtx op, int *l)
{
if (compare_sign_p (insn))
{
if (l) *l = 1;
return AS1 (tst,%D0);
}
- if (test_hard_reg_class (ADDW_REGS, SET_SRC (PATTERN (insn))))
+ if (test_hard_reg_class (ADDW_REGS, op))
{
if (l) *l = 3;
return (AS2 (sbiw,%A0,0) CR_TAB
@@ -4367,8 +4367,8 @@ adjust_insn_length (rtx insn, int len)
{
switch (GET_MODE (op[1]))
{
- case HImode: out_tsthi (insn,&len); break;
- case SImode: out_tstsi (insn,&len); break;
+ case HImode: out_tsthi (insn, op[1], &len); break;
+ case SImode: out_tstsi (insn, op[1], &len); break;
default: break;
}
}
@@ -5734,6 +5734,21 @@ avr_reorg (void)
XEXP (pattern,1) = x;
INSN_CODE (next) = -1;
}
+ else if (true_regnum (XEXP (pattern, 0)) >= 0
+ && XEXP (pattern, 1) == const0_rtx)
+ {
+ /* This is a tst insn, we can reverse it. */
+ rtx next = next_real_insn (insn);
+ rtx pat = PATTERN (next);
+ rtx src = SET_SRC (pat);
+ rtx t = XEXP (src,0);
+
+ PUT_CODE (t, swap_condition (GET_CODE (t)));
+ XEXP (pattern, 1) = XEXP (pattern, 0);
+ XEXP (pattern, 0) = const0_rtx;
+ INSN_CODE (next) = -1;
+ INSN_CODE (insn) = -1;
+ }
else if (true_regnum (XEXP (pattern,0)) >= 0
&& GET_CODE (XEXP (pattern,1)) == CONST_INT)
{
@@ -5753,20 +5768,6 @@ avr_reorg (void)
}
}
}
- else if (true_regnum (SET_SRC (pattern)) >= 0)
- {
- /* This is a tst insn */
- rtx next = next_real_insn (insn);
- rtx pat = PATTERN (next);
- rtx src = SET_SRC (pat);
- rtx t = XEXP (src,0);
-
- PUT_CODE (t, swap_condition (GET_CODE (t)));
- SET_SRC (pattern) = gen_rtx_COMPARE (GET_MODE (SET_SRC (pattern)), const0_rtx,
- SET_SRC (pattern));
- INSN_CODE (next) = -1;
- INSN_CODE (insn) = -1;
- }
}
}
}
diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md
index 269e2c5ddb5..86a217dc23c 100644
--- a/gcc/config/avr/avr.md
+++ b/gcc/config/avr/avr.md
@@ -2202,53 +2202,65 @@
;;<=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=>
;; compare
-(define_insn "tstqi"
+; Optimize negated tests into reverse compare if overflow is undefined.
+(define_insn "*negated_tstqi"
[(set (cc0)
- (match_operand:QI 0 "register_operand" "r"))]
- ""
- "tst %0"
+ (compare (neg:QI (match_operand:QI 0 "register_operand" "r"))
+ (const_int 0)))]
+ "(!flag_wrapv && !flag_trapv && flag_strict_overflow)"
+ "cp __zero_reg__,%0"
[(set_attr "cc" "compare")
(set_attr "length" "1")])
(define_insn "*reversed_tstqi"
[(set (cc0)
- (compare (const_int 0)
+ (compare (const_int 0)
(match_operand:QI 0 "register_operand" "r")))]
""
"cp __zero_reg__,%0"
- [(set_attr "cc" "compare")
- (set_attr "length" "1")])
+[(set_attr "cc" "compare")
+ (set_attr "length" "2")])
-(define_insn "tsthi"
+(define_insn "*negated_tsthi"
[(set (cc0)
- (match_operand:HI 0 "register_operand" "!w,r"))]
- ""
- "* return out_tsthi (insn,NULL);"
-[(set_attr "cc" "compare,compare")
- (set_attr "length" "1,2")])
+ (compare (neg:HI (match_operand:HI 0 "register_operand" "r"))
+ (const_int 0)))]
+ "(!flag_wrapv && !flag_trapv && flag_strict_overflow)"
+ "cp __zero_reg__,%A0
+ cpc __zero_reg__,%B0"
+[(set_attr "cc" "compare")
+ (set_attr "length" "2")])
+;; Leave here the clobber used by the cmphi pattern for simplicity, even
+;; though it is unused, because this pattern is synthesized by avr_reorg.
(define_insn "*reversed_tsthi"
[(set (cc0)
(compare (const_int 0)
- (match_operand:HI 0 "register_operand" "r")))]
+ (match_operand:HI 0 "register_operand" "r")))
+ (clobber (match_scratch:QI 1 "=X"))]
""
"cp __zero_reg__,%A0
cpc __zero_reg__,%B0"
[(set_attr "cc" "compare")
(set_attr "length" "2")])
-(define_insn "tstsi"
+(define_insn "*negated_tstsi"
[(set (cc0)
- (match_operand:SI 0 "register_operand" "r"))]
- ""
- "* return out_tstsi (insn,NULL);"
+ (compare (neg:SI (match_operand:SI 0 "register_operand" "r"))
+ (const_int 0)))]
+ "(!flag_wrapv && !flag_trapv && flag_strict_overflow)"
+ "cp __zero_reg__,%A0
+ cpc __zero_reg__,%B0
+ cpc __zero_reg__,%C0
+ cpc __zero_reg__,%D0"
[(set_attr "cc" "compare")
(set_attr "length" "4")])
(define_insn "*reversed_tstsi"
[(set (cc0)
- (compare (const_int 0)
- (match_operand:SI 0 "register_operand" "r")))]
+ (compare (const_int 0)
+ (match_operand:SI 0 "register_operand" "r")))
+ (clobber (match_scratch:QI 1 "=X"))]
""
"cp __zero_reg__,%A0
cpc __zero_reg__,%B0
@@ -2258,16 +2270,17 @@
(set_attr "length" "4")])
-(define_insn "cmpqi"
+(define_insn "*cmpqi"
[(set (cc0)
- (compare (match_operand:QI 0 "register_operand" "r,d")
- (match_operand:QI 1 "nonmemory_operand" "r,i")))]
+ (compare (match_operand:QI 0 "register_operand" "r,r,d")
+ (match_operand:QI 1 "nonmemory_operand" "L,r,i")))]
""
"@
+ tst %0
cp %0,%1
cpi %0,lo8(%1)"
- [(set_attr "cc" "compare,compare")
- (set_attr "length" "1,1")])
+ [(set_attr "cc" "compare,compare,compare")
+ (set_attr "length" "1,1,1")])
(define_insn "*cmpqi_sign_extend"
[(set (cc0)
@@ -2279,19 +2292,22 @@
[(set_attr "cc" "compare")
(set_attr "length" "1")])
-(define_insn "cmphi"
+(define_insn "*cmphi"
[(set (cc0)
- (compare (match_operand:HI 0 "register_operand" "r,d,d,r,r")
- (match_operand:HI 1 "nonmemory_operand" "r,M,i,M,i")))
- (clobber (match_scratch:QI 2 "=X,X,&d,&d,&d"))]
+ (compare (match_operand:HI 0 "register_operand" "!w,r,r,d,d,r,r")
+ (match_operand:HI 1 "nonmemory_operand" "L,L,r,M,i,M,i")))
+ (clobber (match_scratch:QI 2 "=X,X,X,X,&d,&d,&d"))]
""
"*{
switch (which_alternative)
{
- case 0:
+ case 0: case 1:
+ return out_tsthi (insn, operands[0], NULL);
+
+ case 2:
return (AS2 (cp,%A0,%A1) CR_TAB
AS2 (cpc,%B0,%B1));
- case 1:
+ case 3:
if (reg_unused_after (insn, operands[0])
&& INTVAL (operands[1]) >= 0 && INTVAL (operands[1]) <= 63
&& test_hard_reg_class (ADDW_REGS, operands[0]))
@@ -2299,7 +2315,7 @@
else
return (AS2 (cpi,%0,%1) CR_TAB
AS2 (cpc,%B0,__zero_reg__));
- case 2:
+ case 4:
if (reg_unused_after (insn, operands[0]))
return (AS2 (subi,%0,lo8(%1)) CR_TAB
AS2 (sbci,%B0,hi8(%1)));
@@ -2307,12 +2323,12 @@
return (AS2 (ldi, %2,hi8(%1)) CR_TAB
AS2 (cpi, %A0,lo8(%1)) CR_TAB
AS2 (cpc, %B0,%2));
- case 3:
+ case 5:
return (AS2 (ldi, %2,lo8(%1)) CR_TAB
AS2 (cp, %A0,%2) CR_TAB
AS2 (cpc, %B0,__zero_reg__));
- case 4:
+ case 6:
return (AS2 (ldi, %2,lo8(%1)) CR_TAB
AS2 (cp, %A0,%2) CR_TAB
AS2 (ldi, %2,hi8(%1)) CR_TAB
@@ -2320,25 +2336,28 @@
}
return \"bug\";
}"
- [(set_attr "cc" "compare,compare,compare,compare,compare")
- (set_attr "length" "2,2,3,3,4")])
+ [(set_attr "cc" "compare,compare,compare,compare,compare,compare,compare")
+ (set_attr "length" "1,2,2,2,3,3,4")])
-(define_insn "cmpsi"
+(define_insn "*cmpsi"
[(set (cc0)
- (compare (match_operand:SI 0 "register_operand" "r,d,d,r,r")
- (match_operand:SI 1 "nonmemory_operand" "r,M,i,M,i")))
- (clobber (match_scratch:QI 2 "=X,X,&d,&d,&d"))]
+ (compare (match_operand:SI 0 "register_operand" "r,r,d,d,r,r")
+ (match_operand:SI 1 "nonmemory_operand" "L,r,M,i,M,i")))
+ (clobber (match_scratch:QI 2 "=X,X,X,&d,&d,&d"))]
""
"*{
switch (which_alternative)
{
case 0:
+ return out_tstsi (insn, operands[0], NULL);
+
+ case 1:
return (AS2 (cp,%A0,%A1) CR_TAB
AS2 (cpc,%B0,%B1) CR_TAB
AS2 (cpc,%C0,%C1) CR_TAB
AS2 (cpc,%D0,%D1));
- case 1:
+ case 2:
if (reg_unused_after (insn, operands[0])
&& INTVAL (operands[1]) >= 0 && INTVAL (operands[1]) <= 63
&& test_hard_reg_class (ADDW_REGS, operands[0]))
@@ -2350,7 +2369,7 @@
AS2 (cpc,%B0,__zero_reg__) CR_TAB
AS2 (cpc,%C0,__zero_reg__) CR_TAB
AS2 (cpc,%D0,__zero_reg__));
- case 2:
+ case 3:
if (reg_unused_after (insn, operands[0]))
return (AS2 (subi,%A0,lo8(%1)) CR_TAB
AS2 (sbci,%B0,hi8(%1)) CR_TAB
@@ -2364,13 +2383,13 @@
AS2 (cpc, %C0,%2) CR_TAB
AS2 (ldi, %2,hhi8(%1)) CR_TAB
AS2 (cpc, %D0,%2));
- case 3:
+ case 4:
return (AS2 (ldi,%2,lo8(%1)) CR_TAB
AS2 (cp,%A0,%2) CR_TAB
AS2 (cpc,%B0,__zero_reg__) CR_TAB
AS2 (cpc,%C0,__zero_reg__) CR_TAB
AS2 (cpc,%D0,__zero_reg__));
- case 4:
+ case 5:
return (AS2 (ldi, %2,lo8(%1)) CR_TAB
AS2 (cp, %A0,%2) CR_TAB
AS2 (ldi, %2,hi8(%1)) CR_TAB
@@ -2382,113 +2401,53 @@
}
return \"bug\";
}"
- [(set_attr "cc" "compare,compare,compare,compare,compare")
- (set_attr "length" "4,4,7,5,8")])
-
-; Optimize negated tests into reverse compare if overflow is undefined.
-(define_insn_and_split "negated_tst<mode>"
- [(set (cc0)
- (neg:QISI (match_operand:QISI 0 "register_operand")))]
+ [(set_attr "cc" "compare,compare,compare,compare,compare,compare")
+ (set_attr "length" "4,4,4,7,5,8")])
- "(!flag_wrapv && !flag_trapv && flag_strict_overflow)"
- "#"
- ""
- [(set (cc0)
- (compare (const_int 0)
- (match_dup 0)))]
- "")
;; ----------------------------------------------------------------------
;; JUMP INSTRUCTIONS
;; ----------------------------------------------------------------------
;; Conditional jump instructions
-(define_expand "beq"
- [(set (pc)
- (if_then_else (eq (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "bne"
- [(set (pc)
- (if_then_else (ne (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "bge"
- [(set (pc)
- (if_then_else (ge (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "bgeu"
- [(set (pc)
- (if_then_else (geu (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "blt"
- [(set (pc)
- (if_then_else (lt (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "bltu"
- [(set (pc)
- (if_then_else (ltu (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-
-
-/****************************************************************
- AVR not have following conditional jumps: LE,LEU,GT,GTU.
- Convert them all to proper jumps.
-*****************************************************************/
-
-(define_expand "ble"
- [(set (pc)
- (if_then_else (le (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "bleu"
- [(set (pc)
- (if_then_else (leu (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
+(define_expand "cbranchsi4"
+ [(parallel [(set (cc0)
+ (compare (match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "nonmemory_operand" "")))
+ (clobber (match_scratch:QI 4 ""))])
+ (set (pc)
+ (if_then_else
+ (match_operator 0 "ordered_comparison_operator" [(cc0)
+ (const_int 0)])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
+ "")
+
+(define_expand "cbranchhi4"
+ [(parallel [(set (cc0)
+ (compare (match_operand:HI 1 "register_operand" "")
+ (match_operand:HI 2 "nonmemory_operand" "")))
+ (clobber (match_scratch:QI 4 ""))])
+ (set (pc)
+ (if_then_else
+ (match_operator 0 "ordered_comparison_operator" [(cc0)
+ (const_int 0)])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
+ "")
-(define_expand "bgt"
- [(set (pc)
- (if_then_else (gt (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
+(define_expand "cbranchqi4"
+ [(set (cc0)
+ (compare (match_operand:QI 1 "register_operand" "")
+ (match_operand:QI 2 "nonmemory_operand" "")))
+ (set (pc)
+ (if_then_else
+ (match_operator 0 "ordered_comparison_operator" [(cc0)
+ (const_int 0)])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
+ "")
-(define_expand "bgtu"
- [(set (pc)
- (if_then_else (gtu (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
;; Test a single bit in a QI/HI/SImode register.
(define_insn "*sbrx_branch"
@@ -2557,7 +2516,8 @@
;; Convert sign tests to bit 7/15/31 tests that match the above insns.
(define_peephole2
- [(set (cc0) (match_operand:QI 0 "register_operand" ""))
+ [(set (cc0) (compare (match_operand:QI 0 "register_operand" "")
+ (const_int 0)))
(set (pc) (if_then_else (ge (cc0) (const_int 0))
(label_ref (match_operand 1 "" ""))
(pc)))]
@@ -2571,7 +2531,8 @@
"")
(define_peephole2
- [(set (cc0) (match_operand:QI 0 "register_operand" ""))
+ [(set (cc0) (compare (match_operand:QI 0 "register_operand" "")
+ (const_int 0)))
(set (pc) (if_then_else (lt (cc0) (const_int 0))
(label_ref (match_operand 1 "" ""))
(pc)))]
@@ -2585,7 +2546,9 @@
"")
(define_peephole2
- [(set (cc0) (match_operand:HI 0 "register_operand" ""))
+ [(parallel [(set (cc0) (compare (match_operand:HI 0 "register_operand" "")
+ (const_int 0)))
+ (clobber (match_operand:HI 2 ""))])
(set (pc) (if_then_else (ge (cc0) (const_int 0))
(label_ref (match_operand 1 "" ""))
(pc)))]
@@ -2597,7 +2560,9 @@
"")
(define_peephole2
- [(set (cc0) (match_operand:HI 0 "register_operand" ""))
+ [(parallel [(set (cc0) (compare (match_operand:HI 0 "register_operand" "")
+ (const_int 0)))
+ (clobber (match_operand:HI 2 ""))])
(set (pc) (if_then_else (lt (cc0) (const_int 0))
(label_ref (match_operand 1 "" ""))
(pc)))]
@@ -2609,7 +2574,9 @@
"")
(define_peephole2
- [(set (cc0) (match_operand:SI 0 "register_operand" ""))
+ [(parallel [(set (cc0) (compare (match_operand:SI 0 "register_operand" "")
+ (const_int 0)))
+ (clobber (match_operand:SI 2 ""))])
(set (pc) (if_then_else (ge (cc0) (const_int 0))
(label_ref (match_operand 1 "" ""))
(pc)))]
@@ -2621,7 +2588,9 @@
"operands[2] = GEN_INT (-2147483647 - 1);")
(define_peephole2
- [(set (cc0) (match_operand:SI 0 "register_operand" ""))
+ [(parallel [(set (cc0) (compare (match_operand:SI 0 "register_operand" "")
+ (const_int 0)))
+ (clobber (match_operand:SI 2 ""))])
(set (pc) (if_then_else (lt (cc0) (const_int 0))
(label_ref (match_operand 1 "" ""))
(pc)))]
@@ -2650,6 +2619,11 @@
[(set_attr "type" "branch")
(set_attr "cc" "clobber")])
+;; ****************************************************************
+;; AVR does not have following conditional jumps: LE,LEU,GT,GTU.
+;; Convert them all to proper jumps.
+;; ****************************************************************/
+
(define_insn "difficult_branch"
[(set (pc)
(if_then_else (match_operator 1 "difficult_comparison_operator"
@@ -3150,7 +3124,9 @@
}")
(define_peephole
- [(set (cc0) (match_operand:QI 0 "register_operand" ""))
+ [(set (cc0)
+ (compare (match_operand:QI 0 "register_operand" "")
+ (const_int 0)))
(set (pc)
(if_then_else (eq (cc0) (const_int 0))
(label_ref (match_operand 1 "" ""))
diff --git a/gcc/config/bfin/bfin.c b/gcc/config/bfin/bfin.c
index 077d5c544a7..ac237d73bd2 100644
--- a/gcc/config/bfin/bfin.c
+++ b/gcc/config/bfin/bfin.c
@@ -67,10 +67,6 @@ struct GTY(()) machine_function
int has_loopreg_clobber;
};
-/* Test and compare insns in bfin.md store the information needed to
- generate branch and scc insns here. */
-rtx bfin_compare_op0, bfin_compare_op1;
-
/* RTX for condition code flag register and RETS register */
extern GTY(()) rtx bfin_cc_rtx;
extern GTY(()) rtx bfin_rets_rtx;
@@ -2714,7 +2710,7 @@ rtx
bfin_gen_compare (rtx cmp, enum machine_mode mode ATTRIBUTE_UNUSED)
{
enum rtx_code code1, code2;
- rtx op0 = bfin_compare_op0, op1 = bfin_compare_op1;
+ rtx op0 = XEXP (cmp, 0), op1 = XEXP (cmp, 1);
rtx tem = bfin_cc_rtx;
enum rtx_code code = GET_CODE (cmp);
@@ -2742,7 +2738,7 @@ bfin_gen_compare (rtx cmp, enum machine_mode mode ATTRIBUTE_UNUSED)
code2 = EQ;
break;
}
- emit_insn (gen_rtx_SET (BImode, tem,
+ emit_insn (gen_rtx_SET (VOIDmode, tem,
gen_rtx_fmt_ee (code1, BImode, op0, op1)));
}
@@ -4219,17 +4215,17 @@ bfin_optimize_loop (loop_info loop)
{
/* If loop->iter_reg is a DREG or PREG, we can split it here
without scratch register. */
- rtx insn;
+ rtx insn, test;
emit_insn_before (gen_addsi3 (loop->iter_reg,
loop->iter_reg,
constm1_rtx),
loop->loop_end);
- emit_insn_before (gen_cmpsi (loop->iter_reg, const0_rtx),
- loop->loop_end);
-
- insn = emit_jump_insn_before (gen_bne (loop->start_label),
+ test = gen_rtx_NE (VOIDmode, loop->iter_reg, const0_rtx);
+ insn = emit_jump_insn_before (gen_cbranchsi4 (test,
+ loop->iter_reg, const0_rtx,
+ loop->start_label),
loop->loop_end);
JUMP_LABEL (insn) = loop->start_label;
diff --git a/gcc/config/bfin/bfin.h b/gcc/config/bfin/bfin.h
index d97fe8faaf4..352f4b4c208 100644
--- a/gcc/config/bfin/bfin.h
+++ b/gcc/config/bfin/bfin.h
@@ -1292,7 +1292,6 @@ do { \
#define ASM_OUTPUT_REG_PUSH(FILE, REGNO) fprintf (FILE, "[SP--] = %s;\n", reg_names[REGNO])
#define ASM_OUTPUT_REG_POP(FILE, REGNO) fprintf (FILE, "%s = [SP++];\n", reg_names[REGNO])
-extern struct rtx_def *bfin_compare_op0, *bfin_compare_op1;
extern struct rtx_def *bfin_cc_rtx, *bfin_rets_rtx;
/* This works for GAS and some other assemblers. */
diff --git a/gcc/config/bfin/bfin.md b/gcc/config/bfin/bfin.md
index 4397b7a139a..755a0d3ced6 100644
--- a/gcc/config/bfin/bfin.md
+++ b/gcc/config/bfin/bfin.md
@@ -2255,29 +2255,6 @@
;; Conditional branch patterns
;; The Blackfin has only few condition codes: eq, lt, lte, ltu, leu
-;; The only outcome of this pattern is that global variables
-;; bfin_compare_op[01] are set for use in bcond patterns.
-
-(define_expand "cmpbi"
- [(set (cc0) (compare (match_operand:BI 0 "register_operand" "")
- (match_operand:BI 1 "immediate_operand" "")))]
- ""
-{
- bfin_compare_op0 = operands[0];
- bfin_compare_op1 = operands[1];
- DONE;
-})
-
-(define_expand "cmpsi"
- [(set (cc0) (compare (match_operand:SI 0 "register_operand" "")
- (match_operand:SI 1 "reg_or_const_int_operand" "")))]
- ""
-{
- bfin_compare_op0 = operands[0];
- bfin_compare_op1 = operands[1];
- DONE;
-})
-
(define_insn "compare_eq"
[(set (match_operand:BI 0 "register_operand" "=C,C")
(eq:BI (match_operand:SI 1 "register_operand" "d,a")
@@ -2326,106 +2303,6 @@
"cc =%1<%2 (iu);"
[(set_attr "type" "compare")])
-(define_expand "beq"
- [(set (match_dup 1) (match_dup 2))
- (set (pc)
- (if_then_else (match_dup 3)
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- rtx op0 = bfin_compare_op0, op1 = bfin_compare_op1;
- operands[1] = bfin_cc_rtx; /* hard register: CC */
- operands[2] = gen_rtx_EQ (BImode, op0, op1);
- /* If we have a BImode input, then we already have a compare result, and
- do not need to emit another comparison. */
- if (GET_MODE (bfin_compare_op0) == BImode)
- {
- gcc_assert (bfin_compare_op1 == const0_rtx);
- emit_insn (gen_cbranchbi4 (operands[2], op0, op1, operands[0]));
- DONE;
- }
-
- operands[3] = gen_rtx_NE (BImode, operands[1], const0_rtx);
-})
-
-(define_expand "bne"
- [(set (match_dup 1) (match_dup 2))
- (set (pc)
- (if_then_else (match_dup 3)
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- rtx op0 = bfin_compare_op0, op1 = bfin_compare_op1;
- /* If we have a BImode input, then we already have a compare result, and
- do not need to emit another comparison. */
- if (GET_MODE (bfin_compare_op0) == BImode)
- {
- rtx cmp = gen_rtx_NE (BImode, op0, op1);
-
- gcc_assert (bfin_compare_op1 == const0_rtx);
- emit_insn (gen_cbranchbi4 (cmp, op0, op1, operands[0]));
- DONE;
- }
-
- operands[1] = bfin_cc_rtx; /* hard register: CC */
- operands[2] = gen_rtx_EQ (BImode, op0, op1);
- operands[3] = gen_rtx_EQ (BImode, operands[1], const0_rtx);
-})
-
-(define_expand "bgt"
- [(set (match_dup 1) (match_dup 2))
- (set (pc)
- (if_then_else (match_dup 3)
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- operands[1] = bfin_cc_rtx;
- operands[2] = gen_rtx_LE (BImode, bfin_compare_op0, bfin_compare_op1);
- operands[3] = gen_rtx_EQ (BImode, operands[1], const0_rtx);
-})
-
-(define_expand "bgtu"
- [(set (match_dup 1) (match_dup 2))
- (set (pc)
- (if_then_else (match_dup 3)
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- operands[1] = bfin_cc_rtx;
- operands[2] = gen_rtx_LEU (BImode, bfin_compare_op0, bfin_compare_op1);
- operands[3] = gen_rtx_EQ (BImode, operands[1], const0_rtx);
-})
-
-(define_expand "blt"
- [(set (match_dup 1) (match_dup 2))
- (set (pc)
- (if_then_else (match_dup 3)
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- operands[1] = bfin_cc_rtx;
- operands[2] = gen_rtx_LT (BImode, bfin_compare_op0, bfin_compare_op1);
- operands[3] = gen_rtx_NE (BImode, operands[1], const0_rtx);
-})
-
-(define_expand "bltu"
- [(set (match_dup 1) (match_dup 2))
- (set (pc)
- (if_then_else (match_dup 3)
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- operands[1] = bfin_cc_rtx;
- operands[2] = gen_rtx_LTU (BImode, bfin_compare_op0, bfin_compare_op1);
- operands[3] = gen_rtx_NE (BImode, operands[1], const0_rtx);
-})
-
;; Same as above, but and CC with the overflow bit generated by the first
;; multiplication.
(define_insn "flag_mul_macv2hi_parts_acconly_andcc0"
@@ -2490,63 +2367,25 @@
(set_attr "length" "6")
(set_attr "seq_insns" "multi")])
-(define_expand "bge"
- [(set (match_dup 1) (match_dup 2))
- (set (pc)
- (if_then_else (match_dup 3)
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- operands[1] = bfin_cc_rtx;
- operands[2] = gen_rtx_LT (BImode, bfin_compare_op0, bfin_compare_op1);
- operands[3] = gen_rtx_EQ (BImode, operands[1], const0_rtx);
-})
-
-(define_expand "bgeu"
- [(set (match_dup 1) (match_dup 2))
- (set (pc)
- (if_then_else (match_dup 3)
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- operands[1] = bfin_cc_rtx;
- operands[2] = gen_rtx_LTU (BImode, bfin_compare_op0, bfin_compare_op1);
- operands[3] = gen_rtx_EQ (BImode, operands[1], const0_rtx);
-})
-
-(define_expand "ble"
- [(set (match_dup 1) (match_dup 2))
- (set (pc)
- (if_then_else (match_dup 3)
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- operands[1] = bfin_cc_rtx;
- operands[2] = gen_rtx_LE (BImode, bfin_compare_op0, bfin_compare_op1);
- operands[3] = gen_rtx_NE (BImode, operands[1], const0_rtx);
-})
-
-(define_expand "bleu"
- [(set (match_dup 1) (match_dup 2))
- (set (pc)
- (if_then_else (match_dup 3)
- (label_ref (match_operand 0 "" ""))
- (pc)))
- ]
+(define_expand "cbranchsi4"
+ [(set (pc)
+ (if_then_else (match_operator 0 "ordered_comparison_operator"
+ [(match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "reg_or_const_int_operand" "")])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
""
{
- operands[1] = bfin_cc_rtx;
- operands[2] = gen_rtx_LEU (BImode, bfin_compare_op0, bfin_compare_op1);
- operands[3] = gen_rtx_NE (BImode, operands[1], const0_rtx);
+ rtx bi_compare = bfin_gen_compare (operands[0], SImode);
+ emit_jump_insn (gen_cbranchbi4 (bi_compare, bfin_cc_rtx, CONST0_RTX (BImode),
+ operands[3]));
+ DONE;
})
(define_insn "cbranchbi4"
[(set (pc)
(if_then_else
- (match_operator 0 "bfin_cbranch_operator"
+ (match_operator 0 "bfin_bimode_comparison_operator"
[(match_operand:BI 1 "register_operand" "C")
(match_operand:BI 2 "immediate_operand" "P0")])
(label_ref (match_operand 3 "" ""))
@@ -2564,7 +2403,7 @@
(define_insn "cbranch_predicted_taken"
[(set (pc)
(if_then_else
- (match_operator 0 "bfin_cbranch_operator"
+ (match_operator 0 "bfin_bimode_comparison_operator"
[(match_operand:BI 1 "register_operand" "C")
(match_operand:BI 2 "immediate_operand" "P0")])
(label_ref (match_operand 3 "" ""))
@@ -2580,7 +2419,7 @@
(define_insn "cbranch_with_nops"
[(set (pc)
(if_then_else
- (match_operator 0 "bfin_cbranch_operator"
+ (match_operator 0 "bfin_bimode_comparison_operator"
[(match_operand:BI 1 "register_operand" "C")
(match_operand:BI 2 "immediate_operand" "P0")])
(label_ref (match_operand 3 "" ""))
@@ -2594,60 +2433,49 @@
[(set_attr "type" "brcc")
(set_attr "length" "8")])
-;; setcc insns. */
-(define_expand "seq"
- [(set (match_dup 1) (eq:BI (match_dup 2) (match_dup 3)))
- (set (match_operand:SI 0 "register_operand" "")
- (ne:SI (match_dup 1) (const_int 0)))]
- ""
-{
- operands[2] = bfin_compare_op0;
- operands[3] = bfin_compare_op1;
- operands[1] = bfin_cc_rtx;
-})
+;; setcc insns.
-(define_expand "slt"
- [(set (match_dup 1) (lt:BI (match_dup 2) (match_dup 3)))
+(define_expand "cstorebi4"
+ [(set (match_dup 4)
+ (match_operator:BI 1 "bfin_bimode_comparison_operator"
+ [(match_operand:BI 2 "register_operand" "")
+ (match_operand:BI 3 "reg_or_const_int_operand" "")]))
(set (match_operand:SI 0 "register_operand" "")
- (ne:SI (match_dup 1) (const_int 0)))]
+ (ne:SI (match_dup 4) (const_int 0)))]
""
{
- operands[2] = bfin_compare_op0;
- operands[3] = bfin_compare_op1;
- operands[1] = bfin_cc_rtx;
-})
+ /* It could be expanded as a movbisi instruction, but the portable
+ alternative produces better code. */
+ if (GET_CODE (operands[1]) == NE)
+ FAIL;
-(define_expand "sle"
- [(set (match_dup 1) (le:BI (match_dup 2) (match_dup 3)))
- (set (match_operand:SI 0 "register_operand" "")
- (ne:SI (match_dup 1) (const_int 0)))]
- ""
-{
- operands[2] = bfin_compare_op0;
- operands[3] = bfin_compare_op1;
- operands[1] = bfin_cc_rtx;
+ operands[4] = bfin_cc_rtx;
})
-(define_expand "sltu"
- [(set (match_dup 1) (ltu:BI (match_dup 2) (match_dup 3)))
- (set (match_operand:SI 0 "register_operand" "")
- (ne:SI (match_dup 1) (const_int 0)))]
+(define_expand "cstoresi4"
+ [(set (match_operand:SI 0 "register_operand")
+ (match_operator:SI 1 "ordered_comparison_operator"
+ [(match_operand:SI 2 "register_operand" "")
+ (match_operand:SI 3 "reg_or_const_int_operand" "")]))]
""
{
- operands[2] = bfin_compare_op0;
- operands[3] = bfin_compare_op1;
- operands[1] = bfin_cc_rtx;
-})
+ rtx bi_compare, test;
-(define_expand "sleu"
- [(set (match_dup 1) (leu:BI (match_dup 2) (match_dup 3)))
- (set (match_operand:SI 0 "register_operand" "")
- (ne:SI (match_dup 1) (const_int 0)))]
- ""
-{
- operands[2] = bfin_compare_op0;
- operands[3] = bfin_compare_op1;
- operands[1] = bfin_cc_rtx;
+ if (!bfin_direct_comparison_operator (operands[1], SImode))
+ {
+ if (!register_operand (operands[3], SImode)
+ || GET_CODE (operands[1]) == NE)
+ FAIL;
+ test = gen_rtx_fmt_ee (swap_condition (GET_CODE (operands[1])),
+ SImode, operands[3], operands[2]);
+ }
+ else
+ test = operands[1];
+
+ bi_compare = bfin_gen_compare (test, SImode);
+ gcc_assert (GET_CODE (bi_compare) == NE);
+ emit_insn (gen_movbisi (operands[0], bfin_cc_rtx));
+ DONE;
})
(define_insn "nop"
@@ -2676,13 +2504,16 @@
"CC = %1;"
[(set_attr "length" "2")])
-(define_insn "movbisi"
+(define_insn_and_split "movbisi"
[(set (match_operand:SI 0 "register_operand" "=d")
(ne:SI (match_operand:BI 1 "register_operand" "C")
(const_int 0)))]
""
- "%0 = CC;"
- [(set_attr "length" "2")])
+ "#"
+ ""
+ [(set (match_operand:SI 0 "register_operand" "")
+ (zero_extend:SI (match_operand:BI 1 "register_operand" "")))]
+ "")
(define_insn "notbi"
[(set (match_operand:BI 0 "register_operand" "=C")
diff --git a/gcc/config/bfin/predicates.md b/gcc/config/bfin/predicates.md
index 7aac5b0534c..bce725a7009 100644
--- a/gcc/config/bfin/predicates.md
+++ b/gcc/config/bfin/predicates.md
@@ -172,10 +172,14 @@
&& REGNO (op) <= LAST_VIRTUAL_REGISTER));
})
-;; Test for an operator valid in a conditional branch
-(define_predicate "bfin_cbranch_operator"
+;; Test for an operator valid in a BImode conditional branch
+(define_predicate "bfin_bimode_comparison_operator"
(match_code "eq,ne"))
+;; Test for an operator whose result is accessible with movbisi.
+(define_predicate "bfin_direct_comparison_operator"
+ (match_code "eq,lt,le,leu,ltu"))
+
;; The following two are used to compute the addrtype attribute. They return
;; true if passed a memory address usable for a 16-bit load or store using a
;; P or I register, respectively. If neither matches, we know we have a
diff --git a/gcc/config/cris/cris.c b/gcc/config/cris/cris.c
index 2112670de6c..bc634ddbf3e 100644
--- a/gcc/config/cris/cris.c
+++ b/gcc/config/cris/cris.c
@@ -1431,13 +1431,18 @@ cris_normal_notice_update_cc (rtx exp, rtx insn)
if (SET_DEST (exp) == cc0_rtx)
{
CC_STATUS_INIT;
- cc_status.value1 = SET_SRC (exp);
- /* Handle flags for the special btstq on one bit. */
- if (GET_CODE (SET_SRC (exp)) == ZERO_EXTRACT
- && XEXP (SET_SRC (exp), 1) == const1_rtx)
+ if (GET_CODE (SET_SRC (exp)) == COMPARE
+ && XEXP (SET_SRC (exp), 1) == const0_rtx)
+ cc_status.value1 = XEXP (SET_SRC (exp), 0);
+ else
+ cc_status.value1 = SET_SRC (exp);
+
+ /* Handle flags for the special btstq on one bit. */
+ if (GET_CODE (cc_status.value1) == ZERO_EXTRACT
+ && XEXP (cc_status.value1, 1) == const1_rtx)
{
- if (CONST_INT_P (XEXP (SET_SRC (exp), 0)))
+ if (CONST_INT_P (XEXP (cc_status.value1, 0)))
/* Using cmpq. */
cc_status.flags = CC_INVERTED;
else
@@ -1445,7 +1450,7 @@ cris_normal_notice_update_cc (rtx exp, rtx insn)
cc_status.flags = CC_Z_IN_NOT_N;
}
- if (GET_CODE (SET_SRC (exp)) == COMPARE)
+ else if (GET_CODE (SET_SRC (exp)) == COMPARE)
{
if (!REG_P (XEXP (SET_SRC (exp), 0))
&& XEXP (SET_SRC (exp), 1) != const0_rtx)
@@ -1855,6 +1860,11 @@ cris_rtx_costs (rtx x, int code, int outer_code, int *total,
}
return false;
+ case ZERO_EXTRACT:
+ if (outer_code != COMPARE)
+ return false;
+ /* fall through */
+
case ZERO_EXTEND: case SIGN_EXTEND:
*total = rtx_cost (XEXP (x, 0), outer_code, speed);
return true;
diff --git a/gcc/config/cris/cris.md b/gcc/config/cris/cris.md
index f4b2128ea19..79eb8da3b0d 100644
--- a/gcc/config/cris/cris.md
+++ b/gcc/config/cris/cris.md
@@ -248,40 +248,16 @@
;; Test insns.
-;; DImode
-;;
-;; Allow register and offsettable mem operands only; post-increment is
-;; not worth the trouble.
-
-(define_expand "tstdi"
- [(set (cc0) (match_operand:DI 0 "nonimmediate_operand"))]
- ""
-{
- if (TARGET_V32 && MEM_P (operands[0]))
- operands[0] = force_reg (DImode, operands[0]);
-})
-
-(define_insn "*tstdi_non_v32"
- [(set (cc0)
- (match_operand:DI 0 "nonimmediate_operand" "r,o"))]
- "!TARGET_V32"
- "test.d %M0\;ax\;test.d %H0")
-
-(define_insn "*tstdi_v32"
- [(set (cc0)
- (match_operand:DI 0 "register_operand" "r"))]
- "TARGET_V32"
- "cmpq 0,%M0\;ax\;cmpq 0,%H0")
-
;; No test insns with side-effect on the mem addressing.
;;
;; See note on cmp-insns with side-effects (or lack of them)
;; Normal named test patterns from SI on.
-(define_insn "tstsi"
+(define_insn "*tstsi"
[(set (cc0)
- (match_operand:SI 0 "nonimmediate_operand" "r,Q>,m"))]
+ (compare (match_operand:SI 0 "nonimmediate_operand" "r,Q>,m")
+ (const_int 0)))]
""
{
if (which_alternative == 0 && TARGET_V32)
@@ -290,15 +266,10 @@
}
[(set_attr "slottable" "yes,yes,no")])
-(define_expand "tst<mode>"
- [(set (cc0)
- (match_operand:BW 0 "nonimmediate_operand"))]
- ""
- "")
-
(define_insn "*tst<mode>_cmp"
[(set (cc0)
- (match_operand:BW 0 "nonimmediate_operand" "r,Q>,m"))]
+ (compare (match_operand:BW 0 "nonimmediate_operand" "r,Q>,m")
+ (const_int 0)))]
"cris_cc0_user_requires_cmp (insn)"
"@
cmp<m> 0,%0
@@ -308,7 +279,8 @@
(define_insn "*tst<mode>_non_cmp"
[(set (cc0)
- (match_operand:BW 0 "nonimmediate_operand" "r,Q>,m"))]
+ (compare (match_operand:BW 0 "nonimmediate_operand" "r,Q>,m")
+ (const_int 0)))]
"!cris_cc0_user_requires_cmp (insn)"
"@
move<m> %0,%0
@@ -332,24 +304,13 @@
;; DImode for anything else but a structure/block-mode. Just do the
;; obvious stuff for the straight-forward constraint letters.
-(define_expand "cmpdi"
- [(set (cc0)
- (compare (match_operand:DI 0 "nonimmediate_operand" "")
- (match_operand:DI 1 "general_operand" "")))]
- ""
-{
- if (TARGET_V32 && !REG_P (operands[0]))
- operands[0] = force_reg (DImode, operands[0]);
- if (TARGET_V32 && MEM_P (operands[1]))
- operands[1] = force_reg (DImode, operands[1]);
-})
-
(define_insn "*cmpdi_non_v32"
[(set (cc0)
- (compare (match_operand:DI 0 "nonimmediate_operand" "r,r,r,r,r,r,o")
- (match_operand:DI 1 "general_operand" "Kc,I,P,n,r,o,r")))]
+ (compare (match_operand:DI 0 "nonimmediate_operand" "rm,r,r,r,r,r,r,o")
+ (match_operand:DI 1 "general_operand" "M,Kc,I,P,n,r,o,r")))]
"!TARGET_V32"
"@
+ test.d %M0\;ax\;test.d %H0
cmpq %1,%M0\;ax\;cmpq 0,%H0
cmpq %1,%M0\;ax\;cmpq -1,%H0
cmp%e1.%z1 %1,%M0\;ax\;cmpq %H1,%H0
@@ -415,9 +376,9 @@
(set_attr "cc" "rev")])
;; The "normal" compare patterns, from SI on. Special-cases with zero
-;; should not happen.
+;; are covered above.
-(define_insn "cmpsi"
+(define_insn "*cmpsi"
[(set (cc0)
(compare
(match_operand:SI 0 "nonimmediate_operand" "r,r,r, Q>,r,r,m")
@@ -434,7 +395,7 @@
[(set_attr "slottable" "yes,yes,yes,yes,no,no,no")
(set_attr "cc" "normal,normal,normal,rev,normal,normal,rev")])
-(define_insn "cmp<mode>"
+(define_insn "*cmp<mode>"
[(set (cc0)
(compare (match_operand:BW 0 "nonimmediate_operand" "r,r, Q>,r,m")
(match_operand:BW 1 "general_operand" "r,Q>,r, g,r")))]
@@ -457,10 +418,12 @@
;; extends subregs for lower-size modes. FIXME: Add testcase.
(define_insn "*btst"
[(set (cc0)
- (zero_extract
- (match_operand:SI 0 "nonmemory_operand" "r, r,r, r,r, r,Kp")
- (match_operand:SI 1 "const_int_operand" "Kc,n,Kc,n,Kc,n,n")
- (match_operand:SI 2 "nonmemory_operand" "M, M,Kc,n,r, r,r")))]
+ (compare
+ (zero_extract:SI
+ (match_operand:SI 0 "nonmemory_operand" "r, r,r, r,r, r,Kp")
+ (match_operand:SI 1 "const_int_operand" "Kc,n,Kc,n,Kc,n,n")
+ (match_operand:SI 2 "nonmemory_operand" "M, M,Kc,n,r, r,r"))
+ (const_int 0)))]
;; Either it is a single bit, or consecutive ones starting at 0.
;; The btst ones depend on stuff in NOTICE_UPDATE_CC.
"CONST_INT_P (operands[1])
@@ -3550,6 +3513,36 @@
;; Conditional branches.
+(define_expand "cbranch<mode>4"
+ [(set (cc0) (compare
+ (match_operand:BWD 1 "nonimmediate_operand")
+ (match_operand:BWD 2 "general_operand")))
+ (set (pc)
+ (if_then_else (match_operator 0 "ordered_comparison_operator"
+ [(cc0) (const_int 0)])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
+ ""
+ "")
+
+(define_expand "cbranchdi4"
+ [(set (cc0)
+ (compare (match_operand:DI 1 "nonimmediate_operand" "")
+ (match_operand:DI 2 "general_operand" "")))
+ (set (pc)
+ (if_then_else (match_operator 0 "ordered_comparison_operator"
+ [(cc0) (const_int 0)])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
+ ""
+{
+ if (TARGET_V32 && !REG_P (operands[1]))
+ operands[1] = force_reg (DImode, operands[1]);
+ if (TARGET_V32 && MEM_P (operands[2]))
+ operands[2] = force_reg (DImode, operands[2]);
+})
+
+
;; We suffer from the same overflow-bit-gets-in-the-way problem as
;; e.g. m68k, so we have to check if overflow bit is set on all "signed"
;; conditions.
@@ -3634,6 +3627,31 @@
;; Set on condition: sCC.
+(define_expand "cstoredi4"
+ [(set (cc0) (compare
+ (match_operand:DI 2 "nonimmediate_operand")
+ (match_operand:DI 3 "general_operand")))
+ (set (match_operand:SI 0 "register_operand")
+ (match_operator:SI 1 "ordered_comparison_operator"
+ [(cc0) (const_int 0)]))]
+ ""
+{
+ if (TARGET_V32 && !REG_P (operands[2]))
+ operands[2] = force_reg (DImode, operands[2]);
+ if (TARGET_V32 && MEM_P (operands[3]))
+ operands[3] = force_reg (DImode, operands[3]);
+})
+
+(define_expand "cstore<mode>4"
+ [(set (cc0) (compare
+ (match_operand:BWD 2 "nonimmediate_operand")
+ (match_operand:BWD 3 "general_operand")))
+ (set (match_operand:SI 0 "register_operand")
+ (match_operator:SI 1 "ordered_comparison_operator"
+ [(cc0) (const_int 0)]))]
+ ""
+ "")
+
;; Like bCC, we have to check the overflow bit for
;; signed conditions.
diff --git a/gcc/config/crx/crx-protos.h b/gcc/config/crx/crx-protos.h
index 0be641dd89e..386fab9fe43 100644
--- a/gcc/config/crx/crx-protos.h
+++ b/gcc/config/crx/crx-protos.h
@@ -62,10 +62,6 @@ extern void crx_print_operand (FILE *, rtx, int);
extern void crx_print_operand_address (FILE *, rtx);
/* Misc functions called from crx.md. */
-extern rtx crx_expand_compare (enum rtx_code, enum machine_mode);
-extern void crx_expand_branch (enum rtx_code, rtx);
-extern void crx_expand_scond (enum rtx_code, rtx);
-
extern void crx_expand_movmem_single (rtx, rtx, rtx, rtx, rtx, unsigned HOST_WIDE_INT *);
extern int crx_expand_movmem (rtx, rtx, rtx, rtx);
#endif /* RTX_CODE */
diff --git a/gcc/config/crx/crx.c b/gcc/config/crx/crx.c
index 6f10afd2e5f..cc3248fb5ee 100644
--- a/gcc/config/crx/crx.c
+++ b/gcc/config/crx/crx.c
@@ -124,10 +124,6 @@ static enum machine_mode output_memory_reference_mode;
/* Table of machine attributes. */
const struct attribute_spec crx_attribute_table[];
-/* Test and compare insns use these globals to generate branch insns. */
-rtx crx_compare_op0 = NULL_RTX;
-rtx crx_compare_op1 = NULL_RTX;
-
/*****************************************************************************/
/* TARGETM FUNCTION PROTOTYPES */
/*****************************************************************************/
@@ -1217,43 +1213,6 @@ crx_expand_movmem (rtx dstbase, rtx srcbase, rtx count_exp, rtx align_exp)
return 1;
}
-rtx
-crx_expand_compare (enum rtx_code code, enum machine_mode mode)
-{
- rtx op0, op1, cc_reg, ret;
-
- op0 = crx_compare_op0;
- op1 = crx_compare_op1;
-
- /* Emit the compare that writes into CC_REGNUM) */
- cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
- ret = gen_rtx_COMPARE (CCmode, op0, op1);
- emit_insn (gen_rtx_SET (VOIDmode, cc_reg, ret));
- /* debug_rtx (get_last_insn ()); */
-
- /* Return the rtx for using the result in CC_REGNUM */
- return gen_rtx_fmt_ee (code, mode, cc_reg, const0_rtx);
-}
-
-void
-crx_expand_branch (enum rtx_code code, rtx label)
-{
- rtx tmp = crx_expand_compare (code, VOIDmode);
- tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
- gen_rtx_LABEL_REF (VOIDmode, label),
- pc_rtx);
- emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, tmp));
- /* debug_rtx (get_last_insn ()); */
-}
-
-void
-crx_expand_scond (enum rtx_code code, rtx dest)
-{
- rtx tmp = crx_expand_compare (code, GET_MODE (dest));
- emit_move_insn (dest, tmp);
- /* debug_rtx (get_last_insn ()); */
-}
-
static void
mpushpop_str (char *stringbuffer, const char *mnemonic, char *mask)
{
diff --git a/gcc/config/crx/crx.h b/gcc/config/crx/crx.h
index 69065f3795b..cac465701bf 100644
--- a/gcc/config/crx/crx.h
+++ b/gcc/config/crx/crx.h
@@ -520,11 +520,4 @@ struct cumulative_args
#define FUNCTION_MODE QImode
-/*****************************************************************************/
-/* EXTERNAL DECLARATIONS FOR VARIABLES DEFINED IN CRX.C */
-/*****************************************************************************/
-
-extern rtx crx_compare_op0; /* operand 0 for comparisons */
-extern rtx crx_compare_op1; /* operand 1 for comparisons */
-
#endif /* ! GCC_CRX_H */
diff --git a/gcc/config/crx/crx.md b/gcc/config/crx/crx.md
index b9655544ffc..229e345d32f 100644
--- a/gcc/config/crx/crx.md
+++ b/gcc/config/crx/crx.md
@@ -63,6 +63,10 @@
(ior (match_code "symbol_ref")
(match_operand 0 "register_operand")))
+(define_predicate "cc_reg_operand"
+ (and (match_code "reg")
+ (match_test "REGNO (op) == CC_REGNUM")))
+
(define_predicate "nosp_reg_operand"
(and (match_operand 0 "register_operand")
(match_test "REGNO (op) != SP_REGNUM")))
@@ -107,8 +111,6 @@
(define_code_iterator mima_oprnd [smax umax smin umin])
(define_code_attr mimaIsa [(smax "maxs") (umax "maxu") (smin "mins") (umin "minu")])
-(define_code_iterator any_cond [eq ne gt gtu lt ltu ge geu le leu])
-
;; Addition Instructions
(define_insn "adddi3"
@@ -522,9 +524,21 @@
;; Compare and Branch Instructions
+(define_insn "cbranchcc4"
+ [(set (pc)
+ (if_then_else (match_operator 0 "ordered_comparison_operator"
+ [(match_operand:CC 1 "cc_reg_operand" "r")
+ (match_operand 2 "cst4_operand" "L")])
+ (label_ref (match_operand 3 ""))
+ (pc)))]
+ ""
+ "b%d0\t%l3"
+ [(set_attr "length" "6")]
+)
+
(define_insn "cbranch<mode>4"
[(set (pc)
- (if_then_else (match_operator 0 "comparison_operator"
+ (if_then_else (match_operator 0 "ordered_comparison_operator"
[(match_operand:CRXIM 1 "register_operand" "r")
(match_operand:CRXIM 2 "reg_or_cst4_operand" "rL")])
(label_ref (match_operand 3 "" ""))
@@ -535,18 +549,18 @@
[(set_attr "length" "6")]
)
-;; Compare Instructions
-(define_expand "cmp<mode>"
+;; Scond Instructions
+
+(define_expand "cstore<mode>4"
[(set (reg:CC CC_REGNUM)
- (compare:CC (match_operand:CRXIM 0 "register_operand" "")
- (match_operand:CRXIM 1 "nonmemory_operand" "")))]
+ (compare:CC (match_operand:CRXIM 2 "register_operand" "")
+ (match_operand:CRXIM 3 "nonmemory_operand" "")))
+ (set (match_operand:SI 0 "register_operand")
+ (match_operator:SI 1 "ordered_comparison_operator"
+ [(reg:CC CC_REGNUM) (const_int 0)]))]
+ ""
""
- {
- crx_compare_op0 = operands[0];
- crx_compare_op1 = operands[1];
- DONE;
- }
)
(define_insn "cmp<mode>_internal"
@@ -558,48 +572,9 @@
[(set_attr "length" "2,<lImmArith>")]
)
-;; Conditional Branch Instructions
-
-(define_expand "b<code>"
- [(set (pc)
- (if_then_else (any_cond (reg:CC CC_REGNUM)
- (const_int 0))
- (label_ref (match_operand 0 ""))
- (pc)))]
- ""
- {
- crx_expand_branch (<CODE>, operands[0]);
- DONE;
- }
-)
-
-(define_insn "bCOND_internal"
- [(set (pc)
- (if_then_else (match_operator 0 "comparison_operator"
- [(reg:CC CC_REGNUM)
- (const_int 0)])
- (label_ref (match_operand 1 ""))
- (pc)))]
- ""
- "b%d0\t%l1"
- [(set_attr "length" "6")]
-)
-
-;; Scond Instructions
-
-(define_expand "s<code>"
- [(set (match_operand:SI 0 "register_operand")
- (any_cond:SI (reg:CC CC_REGNUM) (const_int 0)))]
- ""
- {
- crx_expand_scond (<CODE>, operands[0]);
- DONE;
- }
-)
-
(define_insn "sCOND_internal"
[(set (match_operand:SI 0 "register_operand" "=r")
- (match_operator:SI 1 "comparison_operator"
+ (match_operator:SI 1 "ordered_comparison_operator"
[(reg:CC CC_REGNUM) (const_int 0)]))]
""
"s%d1\t%0"
diff --git a/gcc/config/fr30/fr30.c b/gcc/config/fr30/fr30.c
index e7f2e3cfd86..5642c548a29 100644
--- a/gcc/config/fr30/fr30.c
+++ b/gcc/config/fr30/fr30.c
@@ -48,12 +48,6 @@
/*}}}*/
/*{{{ Function Prologues & Epilogues */
-/* Define the information needed to generate branch and scc insns. This is
- stored from the compare operation. */
-
-struct rtx_def * fr30_compare_op0;
-struct rtx_def * fr30_compare_op1;
-
/* The FR30 stack looks like this:
Before call After call
diff --git a/gcc/config/fr30/fr30.h b/gcc/config/fr30/fr30.h
index c1e8e0a9723..b958a678db4 100644
--- a/gcc/config/fr30/fr30.h
+++ b/gcc/config/fr30/fr30.h
@@ -1106,16 +1106,6 @@ fprintf (STREAM, "\t.word .L%d\n", VALUE)
#endif
/*}}}*/
-/*{{{ Exported variables */
-
-/* Define the information needed to generate branch and scc insns. This is
- stored from the compare operation. Note that we can't use "rtx" here
- since it hasn't been defined! */
-
-extern struct rtx_def * fr30_compare_op0;
-extern struct rtx_def * fr30_compare_op1;
-
-/*}}}*/
/* Local Variables: */
/* folded-file: t */
diff --git a/gcc/config/fr30/fr30.md b/gcc/config/fr30/fr30.md
index a198ea3544d..fa115c4cfa1 100644
--- a/gcc/config/fr30/fr30.md
+++ b/gcc/config/fr30/fr30.md
@@ -916,23 +916,7 @@
;;}}}
;;{{{ Comparisons
-;; Note, we store the operands in the comparison insns, and use them later
-;; when generating the branch or scc operation.
-
-;; First the routines called by the machine independent part of the compiler
-(define_expand "cmpsi"
- [(set (reg:CC 16)
- (compare:CC (match_operand:SI 0 "register_operand" "")
- (match_operand:SI 1 "nonmemory_operand" "")))]
- ""
- "{
- fr30_compare_op0 = operands[0];
- fr30_compare_op1 = operands[1];
- DONE;
- }"
-)
-
-;; Now, the actual comparisons, generated by the branch and/or scc operations
+;; The actual comparisons, generated by the cbranch and/or cstore expanders
(define_insn "*cmpsi_internal"
[(set (reg:CC 16)
@@ -951,165 +935,19 @@
;; Define_expands called by the machine independent part of the compiler
;; to allocate a new comparison register
-(define_expand "beq"
- [(set (reg:CC 16)
- (compare:CC (match_dup 1)
- (match_dup 2)))
- (set (pc)
- (if_then_else (eq:CC (reg:CC 16)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "{
- operands[1] = fr30_compare_op0;
- operands[2] = fr30_compare_op1;
- }"
-)
-
-(define_expand "bne"
- [(set (reg:CC 16)
- (compare:CC (match_dup 1)
- (match_dup 2)))
- (set (pc)
- (if_then_else (ne:CC (reg:CC 16)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "{
- operands[1] = fr30_compare_op0;
- operands[2] = fr30_compare_op1;
- }"
-)
-
-(define_expand "blt"
- [(set (reg:CC 16)
- (compare:CC (match_dup 1)
- (match_dup 2)))
- (set (pc)
- (if_then_else (lt:CC (reg:CC 16)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "{
- operands[1] = fr30_compare_op0;
- operands[2] = fr30_compare_op1;
- }"
-)
-
-(define_expand "ble"
- [(set (reg:CC 16)
- (compare:CC (match_dup 1)
- (match_dup 2)))
- (set (pc)
- (if_then_else (le:CC (reg:CC 16)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "{
- operands[1] = fr30_compare_op0;
- operands[2] = fr30_compare_op1;
- }"
-)
-
-(define_expand "bgt"
+(define_expand "cbranchsi4"
[(set (reg:CC 16)
- (compare:CC (match_dup 1)
- (match_dup 2)))
+ (compare:CC (match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "nonmemory_operand" "")))
(set (pc)
- (if_then_else (gt:CC (reg:CC 16)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
+ (if_then_else (match_operator:CC 0 "ordered_comparison_operator"
+ [(reg:CC 16) (const_int 0)])
+ (label_ref (match_operand 3 "" ""))
(pc)))]
""
- "{
- operands[1] = fr30_compare_op0;
- operands[2] = fr30_compare_op1;
- }"
-)
-
-(define_expand "bge"
- [(set (reg:CC 16)
- (compare:CC (match_dup 1)
- (match_dup 2)))
- (set (pc)
- (if_then_else (ge:CC (reg:CC 16)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "{
- operands[1] = fr30_compare_op0;
- operands[2] = fr30_compare_op1;
- }"
-)
-
-(define_expand "bltu"
- [(set (reg:CC 16)
- (compare:CC (match_dup 1)
- (match_dup 2)))
- (set (pc)
- (if_then_else (ltu:CC (reg:CC 16)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "{
- operands[1] = fr30_compare_op0;
- operands[2] = fr30_compare_op1;
- }"
-)
-
-(define_expand "bleu"
- [(set (reg:CC 16)
- (compare:CC (match_dup 1)
- (match_dup 2)))
- (set (pc)
- (if_then_else (leu:CC (reg:CC 16)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "{
- operands[1] = fr30_compare_op0;
- operands[2] = fr30_compare_op1;
- }"
-)
-
-(define_expand "bgtu"
- [(set (reg:CC 16)
- (compare:CC (match_dup 1)
- (match_dup 2)))
- (set (pc)
- (if_then_else (gtu:CC (reg:CC 16)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
""
- "{
- operands[1] = fr30_compare_op0;
- operands[2] = fr30_compare_op1;
- }"
)
-(define_expand "bgeu"
- [(set (reg:CC 16)
- (compare:CC (match_dup 1)
- (match_dup 2)))
- (set (pc)
- (if_then_else (geu:CC (reg:CC 16)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "{
- operands[1] = fr30_compare_op0;
- operands[2] = fr30_compare_op1;
- }"
-)
;; Actual branches. We must allow for the (label_ref) and the (pc) to be
;; swapped. If they are swapped, it reverses the sense of the branch.
diff --git a/gcc/config/frv/frv-protos.h b/gcc/config/frv/frv-protos.h
index c34d02cf96f..98ada2286a5 100644
--- a/gcc/config/frv/frv-protos.h
+++ b/gcc/config/frv/frv-protos.h
@@ -81,8 +81,8 @@ extern const char *output_move_single (rtx *, rtx);
extern const char *output_move_double (rtx *, rtx);
extern const char *output_condmove_single
(rtx *, rtx);
-extern int frv_emit_cond_branch (enum rtx_code, rtx);
-extern int frv_emit_scc (enum rtx_code, rtx);
+extern int frv_emit_cond_branch (rtx *);
+extern int frv_emit_scc (rtx *);
extern rtx frv_split_scc (rtx, rtx, rtx, rtx, HOST_WIDE_INT);
extern int frv_emit_cond_move (rtx, rtx, rtx, rtx);
extern rtx frv_split_cond_move (rtx *);
diff --git a/gcc/config/frv/frv.c b/gcc/config/frv/frv.c
index 4e8c1b24cf8..e5476523f13 100644
--- a/gcc/config/frv/frv.c
+++ b/gcc/config/frv/frv.c
@@ -193,11 +193,6 @@ typedef struct
int base_offset;
} frv_frame_accessor_t;
-/* Define the information needed to generate branch and scc insns. This is
- stored from the compare operation. */
-rtx frv_compare_op0;
-rtx frv_compare_op1;
-
/* Conditional execution support gathered together in one structure. */
typedef struct
{
@@ -4768,19 +4763,18 @@ frv_emit_comparison (enum rtx_code test, rtx op0, rtx op1)
}
-/* Emit code for a conditional branch. The comparison operands were previously
- stored in frv_compare_op0 and frv_compare_op1.
-
+/* Emit code for a conditional branch.
XXX: I originally wanted to add a clobber of a CCR register to use in
conditional execution, but that confuses the rest of the compiler. */
int
-frv_emit_cond_branch (enum rtx_code test, rtx label)
+frv_emit_cond_branch (rtx operands[])
{
rtx test_rtx;
rtx label_ref;
rtx if_else;
- rtx cc_reg = frv_emit_comparison (test, frv_compare_op0, frv_compare_op1);
+ enum rtx_code test = GET_CODE (operands[0]);
+ rtx cc_reg = frv_emit_comparison (test, operands[1], operands[2]);
enum machine_mode cc_mode = GET_MODE (cc_reg);
/* Branches generate:
@@ -4788,7 +4782,7 @@ frv_emit_cond_branch (enum rtx_code test, rtx label)
(if_then_else (<test>, <cc_reg>, (const_int 0))
(label_ref <branch_label>)
(pc))) */
- label_ref = gen_rtx_LABEL_REF (VOIDmode, label);
+ label_ref = gen_rtx_LABEL_REF (VOIDmode, operands[3]);
test_rtx = gen_rtx_fmt_ee (test, cc_mode, cc_reg, const0_rtx);
if_else = gen_rtx_IF_THEN_ELSE (cc_mode, test_rtx, label_ref, pc_rtx);
emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, if_else));
@@ -4796,23 +4790,23 @@ frv_emit_cond_branch (enum rtx_code test, rtx label)
}
-/* Emit code to set a gpr to 1/0 based on a comparison. The comparison
- operands were previously stored in frv_compare_op0 and frv_compare_op1. */
+/* Emit code to set a gpr to 1/0 based on a comparison. */
int
-frv_emit_scc (enum rtx_code test, rtx target)
+frv_emit_scc (rtx operands[])
{
rtx set;
rtx test_rtx;
rtx clobber;
rtx cr_reg;
- rtx cc_reg = frv_emit_comparison (test, frv_compare_op0, frv_compare_op1);
+ enum rtx_code test = GET_CODE (operands[1]);
+ rtx cc_reg = frv_emit_comparison (test, operands[2], operands[3]);
/* SCC instructions generate:
(parallel [(set <target> (<test>, <cc_reg>, (const_int 0))
(clobber (<ccr_reg>))]) */
test_rtx = gen_rtx_fmt_ee (test, SImode, cc_reg, const0_rtx);
- set = gen_rtx_SET (VOIDmode, target, test_rtx);
+ set = gen_rtx_SET (VOIDmode, operands[0], test_rtx);
cr_reg = ((TARGET_ALLOC_CC)
? gen_reg_rtx (CC_CCRmode)
@@ -4874,7 +4868,8 @@ frv_emit_cond_move (rtx dest, rtx test_rtx, rtx src1, rtx src2)
rtx cr_reg;
rtx if_rtx;
enum rtx_code test = GET_CODE (test_rtx);
- rtx cc_reg = frv_emit_comparison (test, frv_compare_op0, frv_compare_op1);
+ rtx cc_reg = frv_emit_comparison (test,
+ XEXP (test_rtx, 0), XEXP (test_rtx, 1));
enum machine_mode cc_mode = GET_MODE (cc_reg);
/* Conditional move instructions generate:
diff --git a/gcc/config/frv/frv.h b/gcc/config/frv/frv.h
index b6fdca4aa0a..e510de08901 100644
--- a/gcc/config/frv/frv.h
+++ b/gcc/config/frv/frv.h
@@ -2913,9 +2913,6 @@ enum frv_builtins
/* Enable prototypes on the call rtl functions. */
#define MD_CALL_PROTOTYPES 1
-extern GTY(()) rtx frv_compare_op0; /* operand save for */
-extern GTY(()) rtx frv_compare_op1; /* comparison generation */
-
#define CPU_UNITS_QUERY 1
#ifdef __FRV_FDPIC__
diff --git a/gcc/config/frv/frv.md b/gcc/config/frv/frv.md
index aadf02c4fbd..9315f9b623c 100644
--- a/gcc/config/frv/frv.md
+++ b/gcc/config/frv/frv.md
@@ -3734,59 +3734,7 @@
;; ::
;; ::::::::::::::::::::
-;; Note, we store the operands in the comparison insns, and use them later
-;; when generating the branch or scc operation.
-
-;; First the routines called by the machine independent part of the compiler
-(define_expand "cmpsi"
- [(set (cc0)
- (compare (match_operand:SI 0 "integer_register_operand" "")
- (match_operand:SI 1 "gpr_or_int10_operand" "")))]
- ""
- "
-{
- frv_compare_op0 = operands[0];
- frv_compare_op1 = operands[1];
- DONE;
-}")
-
-;(define_expand "cmpdi"
-; [(set (cc0)
-; (compare (match_operand:DI 0 "register_operand" "")
-; (match_operand:DI 1 "nonmemory_operand" "")))]
-; ""
-; "
-;{
-; frv_compare_op0 = operands[0];
-; frv_compare_op1 = operands[1];
-; DONE;
-;}")
-
-(define_expand "cmpsf"
- [(set (cc0)
- (compare (match_operand:SF 0 "fpr_operand" "")
- (match_operand:SF 1 "fpr_operand" "")))]
- "TARGET_HARD_FLOAT"
- "
-{
- frv_compare_op0 = operands[0];
- frv_compare_op1 = operands[1];
- DONE;
-}")
-
-(define_expand "cmpdf"
- [(set (cc0)
- (compare (match_operand:DF 0 "fpr_operand" "")
- (match_operand:DF 1 "fpr_operand" "")))]
- "TARGET_HARD_FLOAT && TARGET_DOUBLE"
- "
-{
- frv_compare_op0 = operands[0];
- frv_compare_op1 = operands[1];
- DONE;
-}")
-
-;; Now, the actual comparisons, generated by the branch and/or scc operations
+;; The comparisons are generated by the branch and/or scc operations
(define_insn "cmpsi_cc"
[(set (match_operand:CC 0 "icc_operand" "=t,t")
@@ -3847,137 +3795,31 @@
;; ::::::::::::::::::::
;; Define_expands called by the machine independent part of the compiler
-;; to allocate a new comparison register. Each of these named patterns
-;; must be present, and they cannot be amalgamated into one pattern.
-;;
-;; If a fixed condition code register is being used, (as opposed to, say,
-;; using cc0), then the expands should look like this:
-;;
-;; (define_expand "<name_of_test>"
-;; [(set (reg:CC <number_of_CC_register>)
-;; (compare:CC (match_dup 1)
-;; (match_dup 2)))
-;; (set (pc)
-;; (if_then_else (eq:CC (reg:CC <number_of_CC_register>)
-;; (const_int 0))
-;; (label_ref (match_operand 0 "" ""))
-;; (pc)))]
-;; ""
-;; "{
-;; operands[1] = frv_compare_op0;
-;; operands[2] = frv_compare_op1;
-;; }"
-;; )
-
-(define_expand "beq"
- [(use (match_operand 0 "" ""))]
- ""
- "
-{
- if (! frv_emit_cond_branch (EQ, operands[0]))
- FAIL;
-
- DONE;
-}")
-
-(define_expand "bne"
- [(use (match_operand 0 "" ""))]
- ""
- "
-{
- if (! frv_emit_cond_branch (NE, operands[0]))
- FAIL;
-
- DONE;
-}")
-
-(define_expand "blt"
- [(use (match_operand 0 "" ""))]
- ""
- "
-{
- if (! frv_emit_cond_branch (LT, operands[0]))
- FAIL;
-
- DONE;
-}")
-
-(define_expand "ble"
- [(use (match_operand 0 "" ""))]
- ""
- "
-{
- if (! frv_emit_cond_branch (LE, operands[0]))
- FAIL;
-
- DONE;
-}")
-
-(define_expand "bgt"
- [(use (match_operand 0 "" ""))]
- ""
- "
-{
- if (! frv_emit_cond_branch (GT, operands[0]))
- FAIL;
-
- DONE;
-}")
-
-(define_expand "bge"
- [(use (match_operand 0 "" ""))]
- ""
- "
-{
- if (! frv_emit_cond_branch (GE, operands[0]))
- FAIL;
-
- DONE;
-}")
-
-(define_expand "bltu"
- [(use (match_operand 0 "" ""))]
- ""
- "
-{
- if (! frv_emit_cond_branch (LTU, operands[0]))
- FAIL;
-
- DONE;
-}")
-
-(define_expand "bleu"
- [(use (match_operand 0 "" ""))]
- ""
- "
-{
- if (! frv_emit_cond_branch (LEU, operands[0]))
- FAIL;
-
- DONE;
-}")
+;; to allocate a new comparison register.
-(define_expand "bgtu"
- [(use (match_operand 0 "" ""))]
- ""
- "
-{
- if (! frv_emit_cond_branch (GTU, operands[0]))
- FAIL;
+(define_expand "cbranchdf4"
+ [(use (match_operator 0 "ordered_comparison_operator"
+ [(match_operand:DF 1 "fpr_operand" "")
+ (match_operand:DF 2 "fpr_operand" "")]))
+ (use (match_operand 3 ""))]
+ "TARGET_HARD_FLOAT && TARGET_DOUBLE"
+ { if (frv_emit_cond_branch (operands)) DONE; gcc_unreachable (); })
- DONE;
-}")
+(define_expand "cbranchsf4"
+ [(use (match_operator 0 "ordered_comparison_operator"
+ [(match_operand:SF 1 "fpr_operand" "")
+ (match_operand:SF 2 "fpr_operand" "")]))
+ (use (match_operand 3 ""))]
+ "TARGET_HARD_FLOAT"
+ { if (frv_emit_cond_branch (operands)) DONE; gcc_unreachable (); })
-(define_expand "bgeu"
- [(use (match_operand 0 "" ""))]
+(define_expand "cbranchsi4"
+ [(use (match_operator 0 "ordered_comparison_operator"
+ [(match_operand:SI 1 "integer_register_operand" "")
+ (match_operand:SI 2 "gpr_or_int10_operand" "")]))
+ (use (match_operand 3 ""))]
""
- "
-{
- if (! frv_emit_cond_branch (GEU, operands[0]))
- FAIL;
-
- DONE;
-}")
+ { if (frv_emit_cond_branch (operands)) DONE; gcc_unreachable (); })
;; Actual branches. We must allow for the (label_ref) and the (pc) to be
;; swapped. If they are swapped, it reverses the sense of the branch.
@@ -4142,115 +3984,29 @@
;; Define_expands called by the machine independent part of the compiler
;; to allocate a new comparison register
-(define_expand "seq"
- [(match_operand:SI 0 "integer_register_operand" "")]
- "TARGET_SCC"
- "
-{
- if (! frv_emit_scc (EQ, operands[0]))
- FAIL;
-
- DONE;
-}")
-
-(define_expand "sne"
- [(match_operand:SI 0 "integer_register_operand" "")]
- "TARGET_SCC"
- "
-{
- if (! frv_emit_scc (NE, operands[0]))
- FAIL;
-
- DONE;
-}")
-
-(define_expand "slt"
- [(match_operand:SI 0 "integer_register_operand" "")]
- "TARGET_SCC"
- "
-{
- if (! frv_emit_scc (LT, operands[0]))
- FAIL;
-
- DONE;
-}")
-
-(define_expand "sle"
- [(match_operand:SI 0 "integer_register_operand" "")]
- "TARGET_SCC"
- "
-{
- if (! frv_emit_scc (LE, operands[0]))
- FAIL;
-
- DONE;
-}")
-
-(define_expand "sgt"
- [(match_operand:SI 0 "integer_register_operand" "")]
- "TARGET_SCC"
- "
-{
- if (! frv_emit_scc (GT, operands[0]))
- FAIL;
-
- DONE;
-}")
-
-(define_expand "sge"
- [(match_operand:SI 0 "integer_register_operand" "")]
- "TARGET_SCC"
- "
-{
- if (! frv_emit_scc (GE, operands[0]))
- FAIL;
-
- DONE;
-}")
-
-(define_expand "sltu"
- [(match_operand:SI 0 "integer_register_operand" "")]
- "TARGET_SCC"
- "
-{
- if (! frv_emit_scc (LTU, operands[0]))
- FAIL;
-
- DONE;
-}")
-
-(define_expand "sleu"
- [(match_operand:SI 0 "integer_register_operand" "")]
- "TARGET_SCC"
- "
-{
- if (! frv_emit_scc (LEU, operands[0]))
- FAIL;
-
- DONE;
-}")
-
-(define_expand "sgtu"
- [(match_operand:SI 0 "integer_register_operand" "")]
- "TARGET_SCC"
- "
-{
- if (! frv_emit_scc (GTU, operands[0]))
- FAIL;
-
- DONE;
-}")
+(define_expand "cstoredf4"
+ [(use (match_operator:SI 1 "ordered_comparison_operator"
+ [(match_operand:DF 2 "fpr_operand")
+ (match_operand:DF 3 "fpr_operand")]))
+ (clobber (match_operand:SI 0 "register_operand"))]
+ "TARGET_HARD_FLOAT && TARGET_DOUBLE"
+ { if (frv_emit_scc (operands)) DONE; else FAIL; })
-(define_expand "sgeu"
- [(match_operand:SI 0 "integer_register_operand" "")]
- "TARGET_SCC"
- "
-{
- if (! frv_emit_scc (GEU, operands[0]))
- FAIL;
+(define_expand "cstoresf4"
+ [(use (match_operator:SI 1 "ordered_comparison_operator"
+ [(match_operand:SF 2 "fpr_operand")
+ (match_operand:SF 3 "fpr_operand")]))
+ (clobber (match_operand:SI 0 "register_operand"))]
+ "TARGET_HARD_FLOAT"
+ { if (frv_emit_scc (operands)) DONE; else FAIL; })
- DONE;
-}")
+(define_expand "cstoresi4"
+ [(use (match_operator:SI 1 "ordered_comparison_operator"
+ [(match_operand:SI 2 "integer_register_operand")
+ (match_operand:SI 3 "gpr_or_int10_operand")]))
+ (clobber (match_operand:SI 0 "register_operand"))]
+ ""
+ { if (frv_emit_scc (operands)) DONE; else FAIL; })
(define_insn "*scc_int"
[(set (match_operand:SI 0 "integer_register_operand" "=d")
diff --git a/gcc/config/h8300/h8300-protos.h b/gcc/config/h8300/h8300-protos.h
index 2e7b72fe6c4..4a0b64790a7 100644
--- a/gcc/config/h8300/h8300-protos.h
+++ b/gcc/config/h8300/h8300-protos.h
@@ -44,7 +44,8 @@ extern const char *output_logical_op (enum machine_mode, rtx *);
extern unsigned int compute_logical_op_length (enum machine_mode,
rtx *);
extern int compute_logical_op_cc (enum machine_mode, rtx *);
-extern void h8300_expand_branch (enum rtx_code, rtx);
+extern void h8300_expand_branch (rtx[]);
+extern void h8300_expand_store (rtx[]);
extern bool expand_a_shift (enum machine_mode, int, rtx[]);
extern int h8300_shift_needs_scratch_p (int, enum machine_mode);
extern int expand_a_rotate (rtx[]);
diff --git a/gcc/config/h8300/h8300.c b/gcc/config/h8300/h8300.c
index 34d1f82687c..9946d28078f 100644
--- a/gcc/config/h8300/h8300.c
+++ b/gcc/config/h8300/h8300.c
@@ -1226,6 +1226,11 @@ h8300_rtx_costs (rtx x, int code, int outer_code, int *total, bool speed)
*total = 20;
return true;
+ case COMPARE:
+ if (XEXP (x, 1) == const0_rtx)
+ *total = 0;
+ return false;
+
case AND:
if (!h8300_dst_operand (XEXP (x, 0), VOIDmode)
|| !h8300_src_operand (XEXP (x, 1), VOIDmode))
@@ -3503,16 +3508,42 @@ compute_logical_op_cc (enum machine_mode mode, rtx *operands)
/* Expand a conditional branch. */
void
-h8300_expand_branch (enum rtx_code code, rtx label)
+h8300_expand_branch (rtx operands[])
{
+ enum rtx_code code = GET_CODE (operands[0]);
+ rtx op0 = operands[1];
+ rtx op1 = operands[2];
+ rtx label = operands[3];
rtx tmp;
+ tmp = gen_rtx_COMPARE (VOIDmode, op0, op1);
+ emit_insn (gen_rtx_SET (VOIDmode, cc0_rtx, tmp));
+
tmp = gen_rtx_fmt_ee (code, VOIDmode, cc0_rtx, const0_rtx);
tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
gen_rtx_LABEL_REF (VOIDmode, label),
pc_rtx);
emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, tmp));
}
+
+
+/* Expand a conditional store. */
+
+void
+h8300_expand_store (rtx operands[])
+{
+ rtx dest = operands[0];
+ enum rtx_code code = GET_CODE (operands[1]);
+ rtx op0 = operands[2];
+ rtx op1 = operands[3];
+ rtx tmp;
+
+ tmp = gen_rtx_COMPARE (VOIDmode, op0, op1);
+ emit_insn (gen_rtx_SET (VOIDmode, cc0_rtx, tmp));
+
+ tmp = gen_rtx_fmt_ee (code, GET_MODE (dest), cc0_rtx, const0_rtx);
+ emit_insn (gen_rtx_SET (VOIDmode, dest, tmp));
+}
/* Shifts.
diff --git a/gcc/config/h8300/h8300.md b/gcc/config/h8300/h8300.md
index 61f876c8399..c05e8c6966f 100644
--- a/gcc/config/h8300/h8300.md
+++ b/gcc/config/h8300/h8300.md
@@ -961,28 +961,33 @@
;; ----------------------------------------------------------------------
(define_insn ""
- [(set (cc0) (zero_extract:HI (match_operand:QI 0 "bit_memory_operand" "r,U")
- (const_int 1)
- (match_operand 1 "const_int_operand" "n,n")))]
+ [(set (cc0) (compare
+ (zero_extract:QI (match_operand:QI 0 "bit_memory_operand" "r,U")
+ (const_int 1)
+ (match_operand 1 "const_int_operand" "n,n"))
+ (const_int 0)))]
"TARGET_H8300"
"btst %Z1,%Y0"
[(set_attr "length" "2,4")
(set_attr "cc" "set_zn,set_zn")])
(define_insn ""
- [(set (cc0) (zero_extract:HI (match_operand:HI 0 "register_operand" "r")
- (const_int 1)
- (match_operand 1 "const_int_operand" "n")))]
+ [(set (cc0) (compare
+ (zero_extract:HI (match_operand:HI 0 "register_operand" "r")
+ (const_int 1)
+ (match_operand 1 "const_int_operand" "n"))
+ (const_int 0)))]
"TARGET_H8300"
"btst %Z1,%Y0"
[(set_attr "length" "2")
(set_attr "cc" "set_zn")])
(define_insn_and_split "*tst_extzv_1_n"
- [(set (cc0)
- (zero_extract:SI (match_operand:QI 0 "general_operand_src" "r,U,mn>")
- (const_int 1)
- (match_operand 1 "const_int_operand" "n,n,n")))
+ [(set (cc0) (compare
+ (zero_extract:SI (match_operand:QI 0 "general_operand_src" "r,U,mn>")
+ (const_int 1)
+ (match_operand 1 "const_int_operand" "n,n,n"))
+ (const_int 0)))
(clobber (match_scratch:QI 2 "=X,X,&r"))]
"(TARGET_H8300H || TARGET_H8300S)"
"@
@@ -993,18 +998,20 @@
&& !OK_FOR_U (operands[0])"
[(set (match_dup 2)
(match_dup 0))
- (parallel [(set (cc0) (zero_extract:SI (match_dup 2)
- (const_int 1)
- (match_dup 1)))
+ (parallel [(set (cc0) (compare (zero_extract:SI (match_dup 2)
+ (const_int 1)
+ (match_dup 1))
+ (const_int 0)))
(clobber (scratch:QI))])]
""
[(set_attr "length" "2,8,10")
(set_attr "cc" "set_zn,set_zn,set_zn")])
(define_insn ""
- [(set (cc0) (zero_extract:SI (match_operand:SI 0 "register_operand" "r")
- (const_int 1)
- (match_operand 1 "const_int_operand" "n")))]
+ [(set (cc0) (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "r")
+ (const_int 1)
+ (match_operand 1 "const_int_operand" "n"))
+ (const_int 0)))]
"(TARGET_H8300H || TARGET_H8300S)
&& INTVAL (operands[1]) <= 15"
"btst %Z1,%Y0"
@@ -1012,10 +1019,10 @@
(set_attr "cc" "set_zn")])
(define_insn_and_split "*tstsi_upper_bit"
- [(set (cc0)
- (zero_extract:SI (match_operand:SI 0 "register_operand" "r")
- (const_int 1)
- (match_operand 1 "const_int_operand" "n")))
+ [(set (cc0) (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "r")
+ (const_int 1)
+ (match_operand 1 "const_int_operand" "n"))
+ (const_int 0)))
(clobber (match_scratch:SI 2 "=&r"))]
"(TARGET_H8300H || TARGET_H8300S)
&& INTVAL (operands[1]) >= 16"
@@ -1026,18 +1033,18 @@
(const_int -65536))
(lshiftrt:SI (match_dup 0)
(const_int 16))))
- (set (cc0)
- (zero_extract:SI (match_dup 2)
- (const_int 1)
- (match_dup 3)))]
+ (set (cc0) (compare (zero_extract:SI (match_dup 2)
+ (const_int 1)
+ (match_dup 3))
+ (const_int 0)))]
"operands[3] = GEN_INT (INTVAL (operands[1]) - 16);")
(define_insn "*tstsi_variable_bit"
- [(set (cc0)
- (zero_extract:SI (match_operand:SI 0 "register_operand" "r")
- (const_int 1)
- (and:SI (match_operand:SI 1 "register_operand" "r")
- (const_int 7))))]
+ [(set (cc0) (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "r")
+ (const_int 1)
+ (and:SI (match_operand:SI 1 "register_operand" "r")
+ (const_int 7)))
+ (const_int 0)))]
"TARGET_H8300H || TARGET_H8300S"
"btst %w1,%w0"
[(set_attr "length" "2")
@@ -1045,10 +1052,12 @@
(define_insn_and_split "*tstsi_variable_bit_qi"
[(set (cc0)
- (zero_extract:SI (zero_extend:SI (match_operand:QI 0 "general_operand_src" "r,U,mn>"))
- (const_int 1)
- (and:SI (match_operand:SI 1 "register_operand" "r,r,r")
- (const_int 7))))
+ (compare
+ (zero_extract:SI (zero_extend:SI (match_operand:QI 0 "general_operand_src" "r,U,mn>"))
+ (const_int 1)
+ (and:SI (match_operand:SI 1 "register_operand" "r,r,r")
+ (const_int 7)))
+ (const_int 0)))
(clobber (match_scratch:QI 2 "=X,X,&r"))]
"(TARGET_H8300H || TARGET_H8300S)"
"@
@@ -1059,55 +1068,59 @@
&& !OK_FOR_U (operands[0])"
[(set (match_dup 2)
(match_dup 0))
- (parallel [(set (cc0) (zero_extract:SI (zero_extend:SI (match_dup 2))
- (const_int 1)
- (and:SI (match_dup 1)
- (const_int 7))))
+ (parallel [(set (cc0) (compare (zero_extract:SI (zero_extend:SI (match_dup 2))
+ (const_int 1)
+ (and:SI (match_dup 1)
+ (const_int 7)))
+ (const_int 0)))
(clobber (scratch:QI))])]
""
[(set_attr "length" "2,8,10")
(set_attr "cc" "set_zn,set_zn,set_zn")])
-(define_insn "tstqi"
- [(set (cc0) (match_operand:QI 0 "register_operand" "r"))]
+(define_insn "*tstqi"
+ [(set (cc0) (compare (match_operand:QI 0 "register_operand" "r")
+ (const_int 0)))]
""
"mov.b %X0,%X0"
[(set_attr "length" "2")
(set_attr "cc" "set_znv")])
-(define_insn "tsthi"
- [(set (cc0) (match_operand:HI 0 "register_operand" "r"))]
+(define_insn "*tsthi"
+ [(set (cc0) (compare (match_operand:HI 0 "register_operand" "r")
+ (const_int 0)))]
""
"mov.w %T0,%T0"
[(set_attr "length" "2")
(set_attr "cc" "set_znv")])
(define_insn "*tsthi_upper"
- [(set (cc0)
- (and:HI (match_operand:HI 0 "register_operand" "r")
- (const_int -256)))]
+ [(set (cc0) (compare (and:HI (match_operand:HI 0 "register_operand" "r")
+ (const_int -256))
+ (const_int 0)))]
""
"mov.b %t0,%t0"
[(set_attr "length" "2")
(set_attr "cc" "set_znv")])
-(define_insn "tstsi"
- [(set (cc0) (match_operand:SI 0 "register_operand" "r"))]
+(define_insn "*tstsi"
+ [(set (cc0) (compare (match_operand:SI 0 "register_operand" "r")
+ (const_int 0)))]
"TARGET_H8300H || TARGET_H8300S"
"mov.l %S0,%S0"
[(set_attr "length" "2")
(set_attr "cc" "set_znv")])
(define_insn "*tstsi_upper"
- [(set (cc0)
- (and:SI (match_operand:SI 0 "register_operand" "r")
- (const_int -65536)))]
+ [(set (cc0) (compare (and:SI (match_operand:SI 0 "register_operand" "r")
+ (const_int -65536))
+ (const_int 0)))]
""
"mov.w %e0,%e0"
[(set_attr "length" "2")
(set_attr "cc" "set_znv")])
-(define_insn "cmpqi"
+(define_insn "*cmpqi"
[(set (cc0)
(compare (match_operand:QI 0 "h8300_dst_operand" "rQ")
(match_operand:QI 1 "h8300_src_operand" "rQi")))]
@@ -1116,19 +1129,6 @@
[(set_attr "length_table" "addb")
(set_attr "cc" "compare")])
-(define_expand "cmphi"
- [(set (cc0)
- (compare (match_operand:HI 0 "h8300_dst_operand" "")
- (match_operand:HI 1 "h8300_src_operand" "")))]
- ""
- "
-{
- /* Force operand1 into a register if we're compiling
- for the H8/300. */
- if (GET_CODE (operands[1]) != REG && TARGET_H8300)
- operands[1] = force_reg (HImode, operands[1]);
-}")
-
(define_insn "*cmphi_h8300_znvc"
[(set (cc0)
(compare (match_operand:HI 0 "register_operand" "r")
@@ -2155,55 +2155,37 @@
;; Conditional jump instructions
-(define_expand "ble"
- [(match_operand 0 "" "")]
- ""
- "h8300_expand_branch (LE, operands[0]); DONE;")
-
-(define_expand "bleu"
- [(match_operand 0 "" "")]
+(define_expand "cbranchqi4"
+ [(use (match_operator 0 "ordered_comparison_operator"
+ [(match_operand:QI 1 "h8300_dst_operand" "")
+ (match_operand:QI 2 "h8300_src_operand" "")]))
+ (use (match_operand 3 ""))]
""
- "h8300_expand_branch (LEU, operands[0]); DONE;")
+ "h8300_expand_branch (operands); DONE;")
-(define_expand "bge"
- [(match_operand 0 "" "")]
+(define_expand "cbranchhi4"
+ [(use (match_operator 0 "ordered_comparison_operator"
+ [(match_operand:HI 1 "h8300_dst_operand" "")
+ (match_operand:HI 2 "h8300_src_operand" "")]))
+ (use (match_operand 3 ""))]
""
- "h8300_expand_branch (GE, operands[0]); DONE;")
-
-(define_expand "bgeu"
- [(match_operand 0 "" "")]
- ""
- "h8300_expand_branch (GEU, operands[0]); DONE;")
-
-(define_expand "blt"
- [(match_operand 0 "" "")]
- ""
- "h8300_expand_branch (LT, operands[0]); DONE;")
-
-(define_expand "bltu"
- [(match_operand 0 "" "")]
- ""
- "h8300_expand_branch (LTU, operands[0]); DONE;")
-
-(define_expand "bgt"
- [(match_operand 0 "" "")]
- ""
- "h8300_expand_branch (GT, operands[0]); DONE;")
-
-(define_expand "bgtu"
- [(match_operand 0 "" "")]
- ""
- "h8300_expand_branch (GTU, operands[0]); DONE;")
-
-(define_expand "beq"
- [(match_operand 0 "" "")]
- ""
- "h8300_expand_branch (EQ, operands[0]); DONE;")
+ "
+{
+ /* Force operand1 into a register if we're compiling
+ for the H8/300. */
+ if ((GET_CODE (operands[2]) != REG && operands[2] != const0_rtx)
+ && TARGET_H8300)
+ operands[2] = force_reg (HImode, operands[2]);
+ h8300_expand_branch (operands); DONE;
+}")
-(define_expand "bne"
- [(match_operand 0 "" "")]
- ""
- "h8300_expand_branch (NE, operands[0]); DONE;")
+(define_expand "cbranchsi4"
+ [(use (match_operator 0 "ordered_comparison_operator"
+ [(match_operand:SI 1 "h8300_dst_operand" "")
+ (match_operand:SI 2 "h8300_src_operand" "")]))
+ (use (match_operand 3 ""))]
+ "TARGET_H8300H || TARGET_H8300S"
+ "h8300_expand_branch (operands); DONE;")
(define_insn "branch_true"
[(set (pc)
@@ -3019,8 +3001,8 @@
(clobber (match_operand:QI 3 "register_operand" ""))]
"epilogue_completed
&& find_regno_note (insn, REG_DEAD, REGNO (operands[1]))"
- [(set (cc0)
- (match_dup 1))
+ [(set (cc0) (compare (match_dup 1)
+ (const_int 0)))
(set (pc)
(if_then_else (le (cc0) (const_int 0))
(label_ref (match_dup 5))
@@ -3032,8 +3014,8 @@
(clobber (scratch:QI))])
(set (match_dup 1)
(plus:QI (match_dup 1) (const_int -1)))
- (set (cc0)
- (match_dup 1))
+ (set (cc0) (compare (match_dup 1)
+ (const_int 0)))
(set (pc)
(if_then_else (ne (cc0) (const_int 0))
(label_ref (match_dup 4))
@@ -3052,8 +3034,8 @@
&& !find_regno_note (insn, REG_DEAD, REGNO (operands[1]))"
[(set (match_dup 3)
(match_dup 1))
- (set (cc0)
- (match_dup 3))
+ (set (cc0) (compare (match_dup 3)
+ (const_int 0)))
(set (pc)
(if_then_else (le (cc0) (const_int 0))
(label_ref (match_dup 5))
@@ -3065,8 +3047,8 @@
(clobber (scratch:QI))])
(set (match_dup 3)
(plus:QI (match_dup 3) (const_int -1)))
- (set (cc0)
- (match_dup 3))
+ (set (cc0) (compare (match_dup 3)
+ (const_int 0)))
(set (pc)
(if_then_else (ne (cc0) (const_int 0))
(label_ref (match_dup 4))
@@ -3413,17 +3395,29 @@
[(set_attr "cc" "none_0hit")
(set_attr "length_table" "bitfield")])
-(define_expand "seq"
- [(set (match_operand:HI 0 "register_operand" "")
- (eq:HI (cc0) (const_int 0)))]
+(define_expand "cstoreqi4"
+ [(use (match_operator 1 "eqne_operator"
+ [(match_operand:QI 2 "h8300_dst_operand" "")
+ (match_operand:QI 3 "h8300_src_operand" "")]))
+ (clobber (match_operand:HI 0 "register_operand"))]
"TARGET_H8300SX"
- "")
+ "h8300_expand_store (operands); DONE;")
-(define_expand "sne"
- [(set (match_operand:HI 0 "register_operand" "")
- (ne:HI (cc0) (const_int 0)))]
+(define_expand "cstorehi4"
+ [(use (match_operator 1 "eqne_operator"
+ [(match_operand:HI 2 "h8300_dst_operand" "")
+ (match_operand:HI 3 "h8300_src_operand" "")]))
+ (clobber (match_operand:HI 0 "register_operand"))]
"TARGET_H8300SX"
- "")
+ "h8300_expand_store (operands); DONE;")
+
+(define_expand "cstoresi4"
+ [(use (match_operator 1 "eqne_operator"
+ [(match_operand:SI 2 "h8300_dst_operand" "")
+ (match_operand:SI 3 "h8300_src_operand" "")]))
+ (clobber (match_operand:HI 0 "register_operand"))]
+ "TARGET_H8300SX"
+ "h8300_expand_store (operands); DONE;")
(define_insn "*bstzhireg"
[(set (match_operand:HI 0 "register_operand" "=r")
@@ -3451,13 +3445,7 @@
[(set (cc0) (match_dup 5))
(set (zero_extract:QI (match_dup 0) (const_int 1) (match_dup 1))
(match_op_dup:QI 2 [(cc0) (const_int 0)]))]
- "
-{
- if (operands[4] == const0_rtx && GET_CODE (operands[3]) == REG)
- operands[5] = operands[3];
- else
- operands[5] = gen_rtx_COMPARE (VOIDmode, operands[3], operands[4]);
-}"
+ "operands[5] = gen_rtx_COMPARE (VOIDmode, operands[3], operands[4]);"
[(set_attr "cc" "set_znv,compare")])
(define_insn "*bstz"
@@ -3499,13 +3487,7 @@
(if_then_else:QI
(match_op_dup 1 [(cc0) (const_int 0)])
(ior:QI (match_dup 4) (match_dup 5)) (match_dup 4)))]
- "
-{
- if (operands[3] == const0_rtx && GET_CODE (operands[2]) == REG)
- operands[6] = operands[2];
- else
- operands[6] = gen_rtx_COMPARE (VOIDmode, operands[2], operands[3]);
-}"
+ "operands[6] = gen_rtx_COMPARE (VOIDmode, operands[2], operands[3]);"
[(set_attr "cc" "set_znv,compare")])
(define_insn "*condbset"
@@ -3541,13 +3523,7 @@
(if_then_else:QI
(match_op_dup 1 [(cc0) (const_int 0)])
(and:QI (match_dup 4) (match_dup 5)) (match_dup 4)))]
- "
-{
- if (operands[3] == const0_rtx && GET_CODE (operands[2]) == REG)
- operands[6] = operands[2];
- else
- operands[6] = gen_rtx_COMPARE (VOIDmode, operands[2], operands[3]);
-}"
+ "operands[6] = gen_rtx_COMPARE (VOIDmode, operands[2], operands[3]);"
[(set_attr "cc" "set_znv,compare")])
(define_insn "*condbclr"
@@ -3587,13 +3563,7 @@
(ashift:QI (const_int 1)
(match_operand:QI 5 "register_operand" "r,r")))
(match_dup 4)))]
- "
-{
- if (operands[3] == const0_rtx && GET_CODE (operands[2]) == REG)
- operands[6] = operands[2];
- else
- operands[6] = gen_rtx_COMPARE (VOIDmode, operands[2], operands[3]);
-}"
+ "operands[6] = gen_rtx_COMPARE (VOIDmode, operands[2], operands[3]);"
[(set_attr "cc" "set_znv,compare")])
(define_insn "*condbsetreg"
@@ -3634,13 +3604,7 @@
(ashift:QI (const_int 1)
(match_operand:QI 5 "register_operand" "r,r")))
(match_dup 4)))]
- "
-{
- if (operands[3] == const0_rtx && GET_CODE (operands[2]) == REG)
- operands[6] = operands[2];
- else
- operands[6] = gen_rtx_COMPARE (VOIDmode, operands[2], operands[3]);
-}"
+ "operands[6] = gen_rtx_COMPARE (VOIDmode, operands[2], operands[3]);"
[(set_attr "cc" "set_znv,compare")])
(define_insn "*condbclrreg"
@@ -3878,10 +3842,10 @@
"(TARGET_H8300H || TARGET_H8300S)"
"#"
"&& reload_completed"
- [(set (cc0)
- (zero_extract:SI (match_dup 1)
- (const_int 1)
- (const_int 0)))
+ [(set (cc0) (compare (zero_extract:SI (match_dup 1)
+ (const_int 1)
+ (const_int 0))
+ (const_int 0)))
(set (pc)
(if_then_else (eq (cc0)
(const_int 0))
@@ -3901,10 +3865,10 @@
"(TARGET_H8300H || TARGET_H8300S)"
"#"
"&& reload_completed"
- [(set (cc0)
- (zero_extract:SI (match_dup 1)
- (const_int 1)
- (const_int 0)))
+ [(set (cc0) (compare (zero_extract:SI (match_dup 1)
+ (const_int 1)
+ (const_int 0))
+ (const_int 0)))
(set (pc)
(if_then_else (ne (cc0)
(const_int 0))
@@ -4398,8 +4362,8 @@
""
"#"
""
- [(set (cc0)
- (match_dup 0))
+ [(set (cc0) (compare (match_dup 0)
+ (const_int 0)))
(set (pc)
(if_then_else (ge (cc0)
(const_int 0))
@@ -4418,8 +4382,8 @@
""
"#"
""
- [(set (cc0)
- (match_dup 0))
+ [(set (cc0) (compare (match_dup 0)
+ (const_int 0)))
(set (pc)
(if_then_else (lt (cc0)
(const_int 0))
@@ -4852,8 +4816,8 @@
[(set (match_operand:HI 0 "register_operand" "")
(plus:HI (match_dup 0)
(match_operand 1 "incdec_operand" "")))
- (set (cc0)
- (match_dup 0))
+ (set (cc0) (compare (match_dup 0)
+ (const_int 0)))
(set (pc)
(if_then_else (match_operator 3 "eqne_operator"
[(cc0) (const_int 0)])
@@ -4864,8 +4828,8 @@
(unspec:HI [(match_dup 0)
(match_dup 1)]
UNSPEC_INCDEC))
- (set (cc0)
- (match_dup 0))
+ (set (cc0) (compare (match_dup 0)
+ (const_int 0)))
(set (pc)
(if_then_else (match_op_dup 3 [(cc0) (const_int 0)])
(label_ref (match_dup 2))
@@ -4878,8 +4842,8 @@
[(set (match_operand:SI 0 "register_operand" "")
(plus:SI (match_dup 0)
(match_operand 1 "incdec_operand" "")))
- (set (cc0)
- (match_dup 0))
+ (set (cc0) (compare (match_dup 0)
+ (const_int 0)))
(set (pc)
(if_then_else (match_operator 3 "eqne_operator"
[(cc0) (const_int 0)])
@@ -4890,8 +4854,8 @@
(unspec:SI [(match_dup 0)
(match_dup 1)]
UNSPEC_INCDEC))
- (set (cc0)
- (match_dup 0))
+ (set (cc0) (compare (match_dup 0)
+ (const_int 0)))
(set (pc)
(if_then_else (match_op_dup 3 [(cc0) (const_int 0)])
(label_ref (match_dup 2))
@@ -4900,9 +4864,10 @@
(define_peephole2
[(parallel [(set (cc0)
- (zero_extract:SI (match_operand:QI 0 "register_operand" "")
- (const_int 1)
- (const_int 7)))
+ (compare (zero_extract:SI (match_operand:QI 0 "register_operand" "")
+ (const_int 1)
+ (const_int 7))
+ (const_int 0)))
(clobber (scratch:QI))])
(set (pc)
(if_then_else (match_operator 1 "eqne_operator"
@@ -4910,8 +4875,8 @@
(label_ref (match_operand 2 "" ""))
(pc)))]
"(TARGET_H8300H || TARGET_H8300S)"
- [(set (cc0)
- (match_dup 0))
+ [(set (cc0) (compare (match_dup 0)
+ (const_int 0)))
(set (pc)
(if_then_else (match_op_dup 3 [(cc0) (const_int 0)])
(label_ref (match_dup 2))
@@ -5032,6 +4997,45 @@
"operands[3] = gen_lowpart (HImode, operands[0]);
operands[4] = gen_lowpart (HImode, operands[1]);")
+;; Convert a memory comparison to a move if there is a scratch register.
+
+(define_peephole2
+ [(match_scratch:QI 1 "r")
+ (set (cc0)
+ (compare (match_operand:QI 0 "memory_operand" "")
+ (const_int 0)))]
+ ""
+ [(set (match_dup 1)
+ (match_dup 0))
+ (set (cc0) (compare (match_dup 1)
+ (const_int 0)))]
+ "")
+
+(define_peephole2
+ [(match_scratch:HI 1 "r")
+ (set (cc0)
+ (compare (match_operand:HI 0 "memory_operand" "")
+ (const_int 0)))]
+ "(TARGET_H8300H || TARGET_H8300S)"
+ [(set (match_dup 1)
+ (match_dup 0))
+ (set (cc0) (compare (match_dup 1)
+ (const_int 0)))]
+ "")
+
+(define_peephole2
+ [(match_scratch:SI 1 "r")
+ (set (cc0)
+ (compare (match_operand:SI 0 "memory_operand" "")
+ (const_int 0)))]
+ "(TARGET_H8300H || TARGET_H8300S)"
+ [(set (match_dup 1)
+ (match_dup 0))
+ (set (cc0) (compare (match_dup 1)
+ (const_int 0)))]
+ "")
+
+
;; (compare (reg:HI) (const_int)) takes 4 bytes, so we try to achieve
;; the equivalent with shorter sequences. Here is the summary. Cases
;; are grouped for each define_peephole2.
@@ -5073,13 +5077,14 @@
(label_ref (match_operand 2 "" ""))
(pc)))]
"(TARGET_H8300H || TARGET_H8300S)
+ && INTVAL (operands[1]) != 0
&& peep2_reg_dead_p (1, operands[0])"
[(set (match_dup 0)
(unspec:HI [(match_dup 0)
(match_dup 4)]
UNSPEC_INCDEC))
- (set (cc0)
- (match_dup 0))
+ (set (cc0) (compare (match_dup 0)
+ (const_int 0)))
(set (pc)
(if_then_else (match_op_dup 3 [(cc0) (const_int 0)])
(label_ref (match_dup 2))
@@ -5113,8 +5118,8 @@
(ashiftrt:HI (match_dup 0)
(match_dup 4)))
(clobber (scratch:QI))])
- (set (cc0)
- (match_dup 0))
+ (set (cc0) (compare (match_dup 0)
+ (const_int 0)))
(set (pc)
(if_then_else (match_dup 2)
(label_ref (match_dup 3))
@@ -5148,8 +5153,8 @@
(ashiftrt:HI (match_dup 0)
(match_dup 4)))
(clobber (scratch:QI))])
- (set (cc0)
- (match_dup 0))
+ (set (cc0) (compare (match_dup 0)
+ (const_int 0)))
(set (pc)
(if_then_else (match_dup 5)
(label_ref (match_dup 3))
@@ -5182,9 +5187,9 @@
(label_ref (match_operand 2 "" ""))
(pc)))]
"TARGET_H8300H || TARGET_H8300S"
- [(set (cc0)
- (and:HI (match_dup 0)
- (const_int -256)))
+ [(set (cc0) (compare (and:HI (match_dup 0)
+ (const_int -256))
+ (const_int 0)))
(set (pc)
(if_then_else (match_dup 1)
(label_ref (match_dup 2))
@@ -5211,9 +5216,9 @@
(label_ref (match_operand 2 "" ""))
(pc)))]
"TARGET_H8300H || TARGET_H8300S"
- [(set (cc0)
- (and:HI (match_dup 0)
- (const_int -256)))
+ [(set (cc0) (compare (and:HI (match_dup 0)
+ (const_int -256))
+ (const_int 0)))
(set (pc)
(if_then_else (match_dup 3)
(label_ref (match_dup 2))
@@ -5307,13 +5312,14 @@
(label_ref (match_operand 2 "" ""))
(pc)))]
"(TARGET_H8300H || TARGET_H8300S)
+ && INTVAL (operands[1]) != 0
&& peep2_reg_dead_p (1, operands[0])"
[(set (match_dup 0)
(unspec:SI [(match_dup 0)
(match_dup 4)]
UNSPEC_INCDEC))
- (set (cc0)
- (match_dup 0))
+ (set (cc0) (compare (match_dup 0)
+ (const_int 0)))
(set (pc)
(if_then_else (match_op_dup 3 [(cc0) (const_int 0)])
(label_ref (match_dup 2))
@@ -5348,8 +5354,8 @@
[(set (match_dup 0)
(plus:SI (match_dup 0)
(match_dup 4)))
- (set (cc0)
- (match_dup 0))
+ (set (cc0) (compare (match_dup 0)
+ (const_int 0)))
(set (pc)
(if_then_else (match_op_dup 3 [(cc0) (const_int 0)])
(label_ref (match_dup 2))
@@ -5381,13 +5387,14 @@
&& ((INTVAL (operands[1]) & 0x00ff) == INTVAL (operands[1])
|| (INTVAL (operands[1]) & 0xff00) == INTVAL (operands[1])
|| INTVAL (operands[1]) == 0x0000ffff)
+ && INTVAL (operands[1]) != 0
&& INTVAL (operands[1]) != 1
&& INTVAL (operands[1]) != 2"
[(set (match_dup 0)
(xor:SI (match_dup 0)
(match_dup 1)))
- (set (cc0)
- (match_dup 0))
+ (set (cc0) (compare (match_dup 0)
+ (const_int 0)))
(set (pc)
(if_then_else (match_op_dup 3 [(cc0) (const_int 0)])
(label_ref (match_dup 2))
@@ -5425,8 +5432,8 @@
(match_dup 4)))
(set (match_dup 0)
(not:SI (match_dup 0)))
- (set (cc0)
- (match_dup 0))
+ (set (cc0) (compare (match_dup 0)
+ (const_int 0)))
(set (pc)
(if_then_else (match_op_dup 3 [(cc0) (const_int 0)])
(label_ref (match_dup 2))
@@ -5464,8 +5471,8 @@
(unspec:SI [(match_dup 0)
(const_int -1)]
UNSPEC_INCDEC))
- (set (cc0)
- (match_dup 0))
+ (set (cc0) (compare (match_dup 0)
+ (const_int 0)))
(set (pc)
(if_then_else (match_op_dup 3 [(cc0) (const_int 0)])
(label_ref (match_dup 2))
@@ -5507,8 +5514,8 @@
(ashiftrt:SI (match_dup 4)
(match_dup 5)))
(clobber (scratch:QI))])
- (set (cc0)
- (match_dup 4))
+ (set (cc0) (compare (match_dup 4)
+ (const_int 0)))
(set (pc)
(if_then_else (match_dup 2)
(label_ref (match_dup 3))
@@ -5550,8 +5557,8 @@
(ashiftrt:SI (match_dup 4)
(match_dup 5)))
(clobber (scratch:QI))])
- (set (cc0)
- (match_dup 4))
+ (set (cc0) (compare (match_dup 4)
+ (const_int 0)))
(set (pc)
(if_then_else (match_dup 6)
(label_ref (match_dup 3))
@@ -5591,8 +5598,8 @@
(ashiftrt:SI (match_dup 0)
(match_dup 4)))
(clobber (scratch:QI))])
- (set (cc0)
- (match_dup 0))
+ (set (cc0) (compare (match_dup 0)
+ (const_int 0)))
(set (pc)
(if_then_else (match_dup 2)
(label_ref (match_dup 3))
@@ -5626,8 +5633,8 @@
(ashiftrt:SI (match_dup 0)
(match_dup 4)))
(clobber (scratch:QI))])
- (set (cc0)
- (match_dup 0))
+ (set (cc0) (compare (match_dup 0)
+ (const_int 0)))
(set (pc)
(if_then_else (match_dup 5)
(label_ref (match_dup 3))
@@ -5672,8 +5679,8 @@
[(set (match_dup 0)
(and:SI (match_dup 0)
(match_dup 4)))
- (set (cc0)
- (match_dup 0))
+ (set (cc0) (compare (match_dup 0)
+ (const_int 0)))
(set (pc)
(if_then_else (match_dup 2)
(label_ref (match_dup 3))
@@ -5712,8 +5719,8 @@
[(set (match_dup 0)
(and:SI (match_dup 0)
(match_dup 4)))
- (set (cc0)
- (match_dup 0))
+ (set (cc0) (compare (match_dup 0)
+ (const_int 0)))
(set (pc)
(if_then_else (match_dup 5)
(label_ref (match_dup 3))
@@ -5746,9 +5753,9 @@
(label_ref (match_operand 2 "" ""))
(pc)))]
"TARGET_H8300H || TARGET_H8300S"
- [(set (cc0)
- (and:SI (match_dup 0)
- (const_int -65536)))
+ [(set (cc0) (compare (and:SI (match_dup 0)
+ (const_int -65536))
+ (const_int 0)))
(set (pc)
(if_then_else (match_dup 1)
(label_ref (match_dup 2))
@@ -5775,9 +5782,9 @@
(label_ref (match_operand 2 "" ""))
(pc)))]
"TARGET_H8300H || TARGET_H8300S"
- [(set (cc0)
- (and:SI (match_dup 0)
- (const_int -65536)))
+ [(set (cc0) (compare (and:SI (match_dup 0)
+ (const_int -65536))
+ (const_int 0)))
(set (pc)
(if_then_else (match_dup 3)
(label_ref (match_dup 2))
@@ -5814,6 +5821,7 @@
(label_ref (match_operand 2 "" ""))
(pc)))]
"(TARGET_H8300H || TARGET_H8300S)
+ && INTVAL (operands[1]) != 0
&& !peep2_reg_dead_p (1, operands[0])
&& !same_cmp_following_p (insn)"
[(set (match_dup 4)
@@ -5822,8 +5830,8 @@
(unspec:SI [(match_dup 4)
(match_dup 5)]
UNSPEC_INCDEC))
- (set (cc0)
- (match_dup 4))
+ (set (cc0) (compare (match_dup 4)
+ (const_int 0)))
(set (pc)
(if_then_else (match_op_dup 3 [(cc0) (const_int 0)])
(label_ref (match_dup 2))
@@ -5836,8 +5844,8 @@
[(set (match_operand:HI 0 "register_operand" "")
(and:HI (match_dup 0)
(match_operand:HI 1 "const_int_qi_operand" "")))
- (set (cc0)
- (match_dup 0))
+ (set (cc0) (compare (match_dup 0)
+ (const_int 0)))
(set (pc)
(if_then_else (match_operator 3 "eqne_operator"
[(cc0) (const_int 0)])
@@ -5847,8 +5855,8 @@
[(set (match_dup 4)
(and:QI (match_dup 4)
(match_dup 5)))
- (set (cc0)
- (match_dup 4))
+ (set (cc0) (compare (match_dup 4)
+ (const_int 0)))
(set (pc)
(if_then_else (match_op_dup 3 [(cc0) (const_int 0)])
(label_ref (match_dup 2))
@@ -5860,8 +5868,8 @@
[(set (match_operand:SI 0 "register_operand" "")
(and:SI (match_dup 0)
(match_operand:SI 1 "const_int_qi_operand" "")))
- (set (cc0)
- (match_dup 0))
+ (set (cc0) (compare (match_dup 0)
+ (const_int 0)))
(set (pc)
(if_then_else (match_operator 3 "eqne_operator"
[(cc0) (const_int 0)])
@@ -5871,8 +5879,8 @@
[(set (match_dup 4)
(and:QI (match_dup 4)
(match_dup 5)))
- (set (cc0)
- (match_dup 4))
+ (set (cc0) (compare (match_dup 4)
+ (const_int 0)))
(set (pc)
(if_then_else (match_op_dup 3 [(cc0) (const_int 0)])
(label_ref (match_dup 2))
@@ -5884,8 +5892,8 @@
[(set (match_operand:SI 0 "register_operand" "")
(and:SI (match_dup 0)
(match_operand:SI 1 "const_int_hi_operand" "")))
- (set (cc0)
- (match_dup 0))
+ (set (cc0) (compare (match_dup 0)
+ (const_int 0)))
(set (pc)
(if_then_else (match_operator 3 "eqne_operator"
[(cc0) (const_int 0)])
@@ -5895,8 +5903,8 @@
[(set (match_dup 4)
(and:HI (match_dup 4)
(match_dup 5)))
- (set (cc0)
- (match_dup 4))
+ (set (cc0) (compare (match_dup 4)
+ (const_int 0)))
(set (pc)
(if_then_else (match_op_dup 3 [(cc0) (const_int 0)])
(label_ref (match_dup 2))
@@ -5911,8 +5919,8 @@
(set (match_dup 0)
(xor:SI (match_dup 0)
(match_operand:SI 2 "const_int_qi_operand" "")))
- (set (cc0)
- (match_dup 0))
+ (set (cc0) (compare (match_dup 0)
+ (const_int 0)))
(set (pc)
(if_then_else (match_operator 4 "eqne_operator"
[(cc0) (const_int 0)])
@@ -5926,8 +5934,8 @@
(set (match_dup 5)
(xor:QI (match_dup 5)
(match_dup 7)))
- (set (cc0)
- (match_dup 5))
+ (set (cc0) (compare (match_dup 5)
+ (const_int 0)))
(set (pc)
(if_then_else (match_op_dup 4 [(cc0) (const_int 0)])
(label_ref (match_dup 3))
@@ -6088,7 +6096,8 @@
(match_operand 2 "h8300_src_operand" "")))]
"TARGET_H8300SX
&& peep2_reg_dead_p (2, operands[0])
- && !reg_overlap_mentioned_p (operands[0], operands[2])"
+ && !reg_overlap_mentioned_p (operands[0], operands[2])
+ && operands[2] != const0_rtx"
[(set (cc0)
(compare (match_dup 1)
(match_dup 2)))])
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index 803a9da7ca3..9452d2a60ec 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -106,7 +106,7 @@ extern int ix86_match_ccmode (rtx, enum machine_mode);
extern rtx ix86_expand_compare (enum rtx_code, rtx *, rtx *);
extern int ix86_use_fcomi_compare (enum rtx_code);
extern void ix86_expand_branch (enum rtx_code, rtx);
-extern int ix86_expand_setcc (enum rtx_code, rtx);
+extern void ix86_expand_setcc (enum rtx_code, rtx);
extern int ix86_expand_int_movcc (rtx[]);
extern int ix86_expand_fp_movcc (rtx[]);
extern bool ix86_expand_fp_vcond (rtx[]);
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index aefb891ff5b..bb013a144f6 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -14947,15 +14947,12 @@ ix86_split_fp_branch (enum rtx_code code, rtx op1, rtx op2,
emit_label (label);
}
-int
+void
ix86_expand_setcc (enum rtx_code code, rtx dest)
{
rtx ret, tmp, tmpreg, equiv;
rtx second_test, bypass_test;
- if (GET_MODE (ix86_compare_op0) == (TARGET_64BIT ? TImode : DImode))
- return 0; /* FAIL */
-
gcc_assert (GET_MODE (dest) == QImode);
ret = ix86_expand_compare (code, &second_test, &bypass_test);
@@ -14994,8 +14991,6 @@ ix86_expand_setcc (enum rtx_code code, rtx dest)
ix86_compare_op0, ix86_compare_op1);
set_unique_reg_note (get_last_insn (), REG_EQUAL, equiv);
}
-
- return 1; /* DONE */
}
/* Expand comparison setting or clearing carry flag. Return true when
@@ -15143,6 +15138,8 @@ ix86_expand_int_movcc (rtx operands[])
bool sign_bit_compare_p = false;;
start_sequence ();
+ ix86_compare_op0 = XEXP (operands[1], 0);
+ ix86_compare_op1 = XEXP (operands[1], 1);
compare_op = ix86_expand_compare (code, &second_test, &bypass_test);
compare_seq = get_insns ();
end_sequence ();
@@ -15860,6 +15857,8 @@ ix86_expand_fp_movcc (rtx operands[])
enum rtx_code code = GET_CODE (operands[1]);
rtx tmp, compare_op, second_test, bypass_test;
+ ix86_compare_op0 = XEXP (operands[1], 0);
+ ix86_compare_op1 = XEXP (operands[1], 1);
if (TARGET_SSE_MATH && SSE_FLOAT_MODE_P (mode))
{
enum machine_mode cmode;
@@ -16387,6 +16386,8 @@ ix86_expand_int_addcc (rtx operands[])
bool fpcmp = false;
enum machine_mode mode = GET_MODE (operands[0]);
+ ix86_compare_op0 = XEXP (operands[1], 0);
+ ix86_compare_op1 = XEXP (operands[1], 1);
if (operands[3] != const1_rtx
&& operands[3] != constm1_rtx)
return 0;
@@ -28870,13 +28871,14 @@ void ix86_emit_i387_log1p (rtx op0, rtx op1)
rtx tmp = gen_reg_rtx (XFmode);
rtx tmp2 = gen_reg_rtx (XFmode);
+ rtx test;
emit_insn (gen_absxf2 (tmp, op1));
- emit_insn (gen_cmpxf (tmp,
+ test = gen_rtx_GE (VOIDmode, tmp,
CONST_DOUBLE_FROM_REAL_VALUE (
REAL_VALUE_ATOF ("0.29289321881345247561810596348408353", XFmode),
- XFmode)));
- emit_jump_insn (gen_bge (label1));
+ XFmode));
+ emit_jump_insn (gen_cbranchxf4 (test, XEXP (test, 0), XEXP (test, 1), label1));
emit_move_insn (tmp2, standard_80387_constant_rtx (4)); /* fldln2 */
emit_insn (gen_fyl2xp1xf3_i387 (op0, op1, tmp2));
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 1bb96fd07db..198b59d2e47 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -759,77 +759,183 @@
(include "constraints.md")
-;; Compare instructions.
+;; Compare and branch/compare and store instructions.
-;; All compare insns have expanders that save the operands away without
-;; actually generating RTL. The bCOND or sCOND (emitted immediately
-;; after the cmp) will actually emit the cmpM.
+(define_expand "cbranchti4"
+ [(set (reg:CC FLAGS_REG)
+ (compare:CC (match_operand:TI 1 "nonimmediate_operand" "")
+ (match_operand:TI 2 "x86_64_general_operand" "")))
+ (set (pc) (if_then_else
+ (match_operator 0 "comparison_operator"
+ [(reg:CC FLAGS_REG)
+ (const_int 0)])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
+ "TARGET_64BIT"
+{
+ if (MEM_P (operands[1]) && MEM_P (operands[2]))
+ operands[1] = force_reg (TImode, operands[1]);
+ ix86_compare_op0 = operands[1];
+ ix86_compare_op1 = operands[2];
+ ix86_expand_branch (GET_CODE (operands[0]), operands[3]);
+ DONE;
+})
-(define_expand "cmpti"
+(define_expand "cbranchdi4"
[(set (reg:CC FLAGS_REG)
- (compare:CC (match_operand:TI 0 "nonimmediate_operand" "")
- (match_operand:TI 1 "x86_64_general_operand" "")))]
+ (compare:CC (match_operand:DI 1 "nonimmediate_operand" "")
+ (match_operand:DI 2 "x86_64_general_operand" "")))
+ (set (pc) (if_then_else
+ (match_operator 0 "comparison_operator"
+ [(reg:CC FLAGS_REG)
+ (const_int 0)])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
+ ""
+{
+ if (MEM_P (operands[1]) && MEM_P (operands[2]))
+ operands[1] = force_reg (DImode, operands[1]);
+ ix86_compare_op0 = operands[1];
+ ix86_compare_op1 = operands[2];
+ ix86_expand_branch (GET_CODE (operands[0]), operands[3]);
+ DONE;
+})
+
+(define_expand "cstoredi4"
+ [(set (reg:CC FLAGS_REG)
+ (compare:CC (match_operand:DI 2 "nonimmediate_operand" "")
+ (match_operand:DI 3 "x86_64_general_operand" "")))
+ (set (match_operand:QI 0 "register_operand" "")
+ (match_operator 1 "comparison_operator"
+ [(reg:CC FLAGS_REG)
+ (const_int 0)]))]
"TARGET_64BIT"
{
- if (MEM_P (operands[0]) && MEM_P (operands[1]))
- operands[0] = force_reg (TImode, operands[0]);
- ix86_compare_op0 = operands[0];
- ix86_compare_op1 = operands[1];
+ if (MEM_P (operands[2]) && MEM_P (operands[3]))
+ operands[2] = force_reg (DImode, operands[2]);
+ ix86_compare_op0 = operands[2];
+ ix86_compare_op1 = operands[3];
+ ix86_expand_setcc (GET_CODE (operands[1]), operands[0]);
DONE;
})
-(define_expand "cmpdi"
+(define_expand "cbranchsi4"
[(set (reg:CC FLAGS_REG)
- (compare:CC (match_operand:DI 0 "nonimmediate_operand" "")
- (match_operand:DI 1 "x86_64_general_operand" "")))]
+ (compare:CC (match_operand:SI 1 "cmpsi_operand" "")
+ (match_operand:SI 2 "general_operand" "")))
+ (set (pc) (if_then_else
+ (match_operator 0 "comparison_operator"
+ [(reg:CC FLAGS_REG)
+ (const_int 0)])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
""
{
- if (MEM_P (operands[0]) && MEM_P (operands[1]))
- operands[0] = force_reg (DImode, operands[0]);
- ix86_compare_op0 = operands[0];
- ix86_compare_op1 = operands[1];
+ if (MEM_P (operands[1]) && MEM_P (operands[2]))
+ operands[1] = force_reg (SImode, operands[1]);
+ ix86_compare_op0 = operands[1];
+ ix86_compare_op1 = operands[2];
+ ix86_expand_branch (GET_CODE (operands[0]), operands[3]);
DONE;
})
-(define_expand "cmpsi"
+(define_expand "cstoresi4"
[(set (reg:CC FLAGS_REG)
- (compare:CC (match_operand:SI 0 "cmpsi_operand" "")
- (match_operand:SI 1 "general_operand" "")))]
+ (compare:CC (match_operand:SI 2 "cmpsi_operand" "")
+ (match_operand:SI 3 "general_operand" "")))
+ (set (match_operand:QI 0 "register_operand" "")
+ (match_operator 1 "comparison_operator"
+ [(reg:CC FLAGS_REG)
+ (const_int 0)]))]
""
{
- if (MEM_P (operands[0]) && MEM_P (operands[1]))
- operands[0] = force_reg (SImode, operands[0]);
- ix86_compare_op0 = operands[0];
- ix86_compare_op1 = operands[1];
+ if (MEM_P (operands[2]) && MEM_P (operands[3]))
+ operands[2] = force_reg (SImode, operands[2]);
+ ix86_compare_op0 = operands[2];
+ ix86_compare_op1 = operands[3];
+ ix86_expand_setcc (GET_CODE (operands[1]), operands[0]);
DONE;
})
-(define_expand "cmphi"
+(define_expand "cbranchhi4"
[(set (reg:CC FLAGS_REG)
- (compare:CC (match_operand:HI 0 "nonimmediate_operand" "")
- (match_operand:HI 1 "general_operand" "")))]
+ (compare:CC (match_operand:HI 1 "nonimmediate_operand" "")
+ (match_operand:HI 2 "general_operand" "")))
+ (set (pc) (if_then_else
+ (match_operator 0 "comparison_operator"
+ [(reg:CC FLAGS_REG)
+ (const_int 0)])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
""
{
- if (MEM_P (operands[0]) && MEM_P (operands[1]))
- operands[0] = force_reg (HImode, operands[0]);
- ix86_compare_op0 = operands[0];
- ix86_compare_op1 = operands[1];
+ if (MEM_P (operands[1]) && MEM_P (operands[2]))
+ operands[1] = force_reg (HImode, operands[1]);
+ ix86_compare_op0 = operands[1];
+ ix86_compare_op1 = operands[2];
+ ix86_expand_branch (GET_CODE (operands[0]), operands[3]);
DONE;
})
-(define_expand "cmpqi"
+(define_expand "cstorehi4"
[(set (reg:CC FLAGS_REG)
- (compare:CC (match_operand:QI 0 "nonimmediate_operand" "")
- (match_operand:QI 1 "general_operand" "")))]
- "TARGET_QIMODE_MATH"
+ (compare:CC (match_operand:HI 2 "nonimmediate_operand" "")
+ (match_operand:HI 3 "general_operand" "")))
+ (set (match_operand:QI 0 "register_operand" "")
+ (match_operator 1 "comparison_operator"
+ [(reg:CC FLAGS_REG)
+ (const_int 0)]))]
+ ""
{
- if (MEM_P (operands[0]) && MEM_P (operands[1]))
- operands[0] = force_reg (QImode, operands[0]);
- ix86_compare_op0 = operands[0];
- ix86_compare_op1 = operands[1];
+ if (MEM_P (operands[2]) && MEM_P (operands[3]))
+ operands[2] = force_reg (HImode, operands[2]);
+ ix86_compare_op0 = operands[2];
+ ix86_compare_op1 = operands[3];
+ ix86_expand_setcc (GET_CODE (operands[1]), operands[0]);
+ DONE;
+})
+
+
+(define_expand "cbranchqi4"
+ [(set (reg:CC FLAGS_REG)
+ (compare:CC (match_operand:QI 1 "nonimmediate_operand" "")
+ (match_operand:QI 2 "general_operand" "")))
+ (set (pc) (if_then_else
+ (match_operator 0 "comparison_operator"
+ [(reg:CC FLAGS_REG)
+ (const_int 0)])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
+ ""
+{
+ if (MEM_P (operands[1]) && MEM_P (operands[2]))
+ operands[1] = force_reg (QImode, operands[1]);
+ ix86_compare_op0 = operands[1];
+ ix86_compare_op1 = operands[2];
+ ix86_expand_branch (GET_CODE (operands[0]), operands[3]);
+ DONE;
+})
+
+
+(define_expand "cstoreqi4"
+ [(set (reg:CC FLAGS_REG)
+ (compare:CC (match_operand:QI 2 "nonimmediate_operand" "")
+ (match_operand:QI 3 "general_operand" "")))
+ (set (match_operand:QI 0 "register_operand" "")
+ (match_operator 1 "comparison_operator"
+ [(reg:CC FLAGS_REG)
+ (const_int 0)]))]
+ ""
+{
+ if (MEM_P (operands[2]) && MEM_P (operands[3]))
+ operands[2] = force_reg (QImode, operands[2]);
+ ix86_compare_op0 = operands[2];
+ ix86_compare_op1 = operands[3];
+ ix86_expand_setcc (GET_CODE (operands[1]), operands[0]);
DONE;
})
+
(define_insn "cmpdi_ccno_1_rex64"
[(set (reg FLAGS_REG)
(compare (match_operand:DI 0 "nonimmediate_operand" "r,?mr")
@@ -1078,39 +1184,103 @@
;; which would allow mix and match FP modes on the compares. Which is what
;; the old patterns did, but with many more of them.
-(define_expand "cmpxf"
+(define_expand "cbranchxf4"
+ [(set (reg:CC FLAGS_REG)
+ (compare:CC (match_operand:XF 1 "nonmemory_operand" "")
+ (match_operand:XF 2 "nonmemory_operand" "")))
+ (set (pc) (if_then_else
+ (match_operator 0 "comparison_operator"
+ [(reg:CC FLAGS_REG)
+ (const_int 0)])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
+ "TARGET_80387"
+{
+ ix86_compare_op0 = operands[1];
+ ix86_compare_op1 = operands[2];
+ ix86_expand_branch (GET_CODE (operands[0]), operands[3]);
+ DONE;
+})
+
+(define_expand "cstorexf4"
[(set (reg:CC FLAGS_REG)
- (compare:CC (match_operand:XF 0 "nonmemory_operand" "")
- (match_operand:XF 1 "nonmemory_operand" "")))]
+ (compare:CC (match_operand:XF 2 "nonmemory_operand" "")
+ (match_operand:XF 3 "nonmemory_operand" "")))
+ (set (match_operand:QI 0 "register_operand" "")
+ (match_operator 1 "comparison_operator"
+ [(reg:CC FLAGS_REG)
+ (const_int 0)]))]
"TARGET_80387"
{
- ix86_compare_op0 = operands[0];
- ix86_compare_op1 = operands[1];
+ ix86_compare_op0 = operands[2];
+ ix86_compare_op1 = operands[3];
+ ix86_expand_setcc (GET_CODE (operands[1]), operands[0]);
DONE;
})
-(define_expand "cmp<mode>"
+(define_expand "cbranch<mode>4"
[(set (reg:CC FLAGS_REG)
- (compare:CC (match_operand:MODEF 0 "cmp_fp_expander_operand" "")
- (match_operand:MODEF 1 "cmp_fp_expander_operand" "")))]
+ (compare:CC (match_operand:MODEF 1 "cmp_fp_expander_operand" "")
+ (match_operand:MODEF 2 "cmp_fp_expander_operand" "")))
+ (set (pc) (if_then_else
+ (match_operator 0 "comparison_operator"
+ [(reg:CC FLAGS_REG)
+ (const_int 0)])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
"TARGET_80387 || (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)"
{
- ix86_compare_op0 = operands[0];
- ix86_compare_op1 = operands[1];
+ ix86_compare_op0 = operands[1];
+ ix86_compare_op1 = operands[2];
+ ix86_expand_branch (GET_CODE (operands[0]), operands[3]);
DONE;
})
-(define_expand "cmpcc"
+(define_expand "cstore<mode>4"
[(set (reg:CC FLAGS_REG)
- (compare:CC (match_operand 0 "flags_reg_operand" "")
- (match_operand 1 "general_operand" "")))]
+ (compare:CC (match_operand:MODEF 2 "cmp_fp_expander_operand" "")
+ (match_operand:MODEF 3 "cmp_fp_expander_operand" "")))
+ (set (match_operand:QI 0 "register_operand" "")
+ (match_operator 1 "comparison_operator"
+ [(reg:CC FLAGS_REG)
+ (const_int 0)]))]
+ "TARGET_80387 || (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)"
+{
+ ix86_compare_op0 = operands[2];
+ ix86_compare_op1 = operands[3];
+ ix86_expand_setcc (GET_CODE (operands[1]), operands[0]);
+ DONE;
+})
+
+(define_expand "cbranchcc4"
+ [(set (pc) (if_then_else
+ (match_operator 0 "comparison_operator"
+ [(match_operand 1 "flags_reg_operand" "")
+ (match_operand 2 "const0_operand" "")])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
+ ""
+{
+ ix86_compare_op0 = operands[1];
+ ix86_compare_op1 = operands[2];
+ ix86_expand_branch (GET_CODE (operands[0]), operands[3]);
+ DONE;
+})
+
+(define_expand "cstorecc4"
+ [(set (match_operand:QI 0 "register_operand" "")
+ (match_operator 1 "comparison_operator"
+ [(match_operand 2 "flags_reg_operand" "")
+ (match_operand 3 "const0_operand" "")]))]
""
{
- ix86_compare_op0 = operands[0];
- ix86_compare_op1 = operands[1];
+ ix86_compare_op0 = operands[2];
+ ix86_compare_op1 = operands[3];
+ ix86_expand_setcc (GET_CODE (operands[1]), operands[0]);
DONE;
})
+
;; FP compares, step 1:
;; Set the FP condition codes.
;;
@@ -14182,18 +14352,6 @@
;; to avoid partial register stalls. Otherwise do things the setcc+movzx
;; way, which can later delete the movzx if only QImode is needed.
-(define_expand "s<code>"
- [(set (match_operand:QI 0 "register_operand" "")
- (int_cond:QI (reg:CC FLAGS_REG) (const_int 0)))]
- ""
- "if (ix86_expand_setcc (<CODE>, operands[0])) DONE; else FAIL;")
-
-(define_expand "s<code>"
- [(set (match_operand:QI 0 "register_operand" "")
- (fp_cond:QI (reg:CC FLAGS_REG) (const_int 0)))]
- "TARGET_80387 || TARGET_SSE"
- "if (ix86_expand_setcc (<CODE>, operands[0])) DONE; else FAIL;")
-
(define_insn "*setcc_1"
[(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
(match_operator:QI 1 "ix86_comparison_operator"
@@ -14322,27 +14480,6 @@
;; Basic conditional jump instructions.
;; We ignore the overflow flag for signed branch instructions.
-;; For all bCOND expanders, also expand the compare or test insn that
-;; generates reg FLAGS_REG. Generate an equality comparison if `beq' or `bne'.
-
-(define_expand "b<code>"
- [(set (pc)
- (if_then_else (int_cond:CC (reg:CC FLAGS_REG)
- (const_int 0))
- (label_ref (match_operand 0 ""))
- (pc)))]
- ""
- "ix86_expand_branch (<CODE>, operands[0]); DONE;")
-
-(define_expand "b<code>"
- [(set (pc)
- (if_then_else (fp_cond:CC (reg:CC FLAGS_REG)
- (const_int 0))
- (label_ref (match_operand 0 ""))
- (pc)))]
- "TARGET_80387 || TARGET_SSE_MATH"
- "ix86_expand_branch (<CODE>, operands[0]); DONE;")
-
(define_insn "*jcc_1"
[(set (pc)
(if_then_else (match_operator 1 "ix86_comparison_operator"
@@ -22004,9 +22141,8 @@
emit_insn (gen_stack_protect_test_si (flags, operands[0], operands[1]));
#endif
- ix86_compare_op0 = flags;
- ix86_compare_op1 = const0_rtx;
- emit_jump_insn (gen_beq (operands[2]));
+ emit_jump_insn (gen_cbranchcc4 (gen_rtx_EQ (VOIDmode, flags, const0_rtx),
+ flags, const0_rtx, operands[2]));
DONE;
})
diff --git a/gcc/config/ia64/ia64-protos.h b/gcc/config/ia64/ia64-protos.h
index e3b78641eb8..0859c7f53af 100644
--- a/gcc/config/ia64/ia64-protos.h
+++ b/gcc/config/ia64/ia64-protos.h
@@ -18,13 +18,6 @@ You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
-/* Variables defined in ia64.c. */
-
-#ifdef RTX_CODE
-extern GTY(()) rtx ia64_compare_op0;
-extern GTY(()) rtx ia64_compare_op1;
-#endif
-
/* Functions defined in ia64.c */
extern int bundling_p;
@@ -43,7 +36,7 @@ extern void ia64_emit_cond_move (rtx, rtx, rtx);
extern int ia64_depz_field_mask (rtx, rtx);
extern void ia64_split_tmode_move (rtx[]);
extern bool ia64_expand_movxf_movrf (enum machine_mode, rtx[]);
-extern rtx ia64_expand_compare (enum rtx_code, enum machine_mode);
+extern void ia64_expand_compare (rtx *, rtx *, rtx *);
extern void ia64_expand_vecint_cmov (rtx[]);
extern bool ia64_expand_vecint_minmax (enum rtx_code, enum machine_mode, rtx[]);
extern void ia64_expand_widen_sum (rtx[], bool);
diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c
index acf73c52969..1f433a6fb0f 100644
--- a/gcc/config/ia64/ia64.c
+++ b/gcc/config/ia64/ia64.c
@@ -63,11 +63,6 @@ along with GCC; see the file COPYING3. If not see
ASM_OUTPUT_LABELREF. */
int ia64_asm_output_label = 0;
-/* Define the information needed to generate branch and scc insns. This is
- stored from the compare operation. */
-struct rtx_def * ia64_compare_op0;
-struct rtx_def * ia64_compare_op1;
-
/* Register names for ia64_expand_prologue. */
static const char * const ia64_reg_numbers[96] =
{ "r32", "r33", "r34", "r35", "r36", "r37", "r38", "r39",
@@ -1493,28 +1488,28 @@ ia64_expand_movxf_movrf (enum machine_mode mode, rtx operands[])
return false;
}
-/* Emit comparison instruction if necessary, returning the expression
- that holds the compare result in the proper mode. */
+/* Emit comparison instruction if necessary, replacing *EXPR, *OP0, *OP1
+ with the expression that holds the compare result (in VOIDmode). */
static GTY(()) rtx cmptf_libfunc;
-rtx
-ia64_expand_compare (enum rtx_code code, enum machine_mode mode)
+void
+ia64_expand_compare (rtx *expr, rtx *op0, rtx *op1)
{
- rtx op0 = ia64_compare_op0, op1 = ia64_compare_op1;
+ enum rtx_code code = GET_CODE (*expr);
rtx cmp;
/* If we have a BImode input, then we already have a compare result, and
do not need to emit another comparison. */
- if (GET_MODE (op0) == BImode)
+ if (GET_MODE (*op0) == BImode)
{
- gcc_assert ((code == NE || code == EQ) && op1 == const0_rtx);
- cmp = op0;
+ gcc_assert ((code == NE || code == EQ) && *op1 == const0_rtx);
+ cmp = *op0;
}
/* HPUX TFmode compare requires a library call to _U_Qfcmp, which takes a
magic number as its third argument, that indicates what to do.
The return value is an integer to be compared against zero. */
- else if (TARGET_HPUX && GET_MODE (op0) == TFmode)
+ else if (TARGET_HPUX && GET_MODE (*op0) == TFmode)
{
enum qfcmp_magic {
QCMP_INV = 1, /* Raise FP_INVALID on SNaN as a side effect. */
@@ -1527,7 +1522,7 @@ ia64_expand_compare (enum rtx_code code, enum machine_mode mode)
enum rtx_code ncode;
rtx ret, insns;
- gcc_assert (cmptf_libfunc && GET_MODE (op1) == TFmode);
+ gcc_assert (cmptf_libfunc && GET_MODE (*op1) == TFmode);
switch (code)
{
/* 1 = equal, 0 = not equal. Equality operators do
@@ -1552,7 +1547,7 @@ ia64_expand_compare (enum rtx_code code, enum machine_mode mode)
start_sequence ();
ret = emit_library_call_value (cmptf_libfunc, 0, LCT_CONST, DImode, 3,
- op0, TFmode, op1, TFmode,
+ *op0, TFmode, *op1, TFmode,
GEN_INT (magic), DImode);
cmp = gen_reg_rtx (BImode);
emit_insn (gen_rtx_SET (VOIDmode, cmp,
@@ -1563,18 +1558,20 @@ ia64_expand_compare (enum rtx_code code, enum machine_mode mode)
end_sequence ();
emit_libcall_block (insns, cmp, cmp,
- gen_rtx_fmt_ee (code, BImode, op0, op1));
+ gen_rtx_fmt_ee (code, BImode, *op0, *op1));
code = NE;
}
else
{
cmp = gen_reg_rtx (BImode);
emit_insn (gen_rtx_SET (VOIDmode, cmp,
- gen_rtx_fmt_ee (code, BImode, op0, op1)));
+ gen_rtx_fmt_ee (code, BImode, *op0, *op1)));
code = NE;
}
- return gen_rtx_fmt_ee (code, mode, cmp, const0_rtx);
+ *expr = gen_rtx_fmt_ee (code, VOIDmode, cmp, const0_rtx);
+ *op0 = cmp;
+ *op1 = const0_rtx;
}
/* Generate an integral vector comparison. Return true if the condition has
diff --git a/gcc/config/ia64/ia64.md b/gcc/config/ia64/ia64.md
index 26e71f841b5..e5a6d81730c 100644
--- a/gcc/config/ia64/ia64.md
+++ b/gcc/config/ia64/ia64.md
@@ -409,6 +409,7 @@
(set_attr "speculable2" "no, no, no, no, yes,no,no, no, no, yes,no, no, no, no, no, no, no, no, no")])
(define_mode_iterator MODE [BI QI HI SI DI SF DF XF TI])
+(define_mode_iterator MODE_FOR_CMP [BI SI DI SF DF XF (TF "TARGET_HPUX")])
(define_mode_iterator MODE_FOR_EXTEND [QI HI SI])
(define_mode_attr output_a [
@@ -4759,82 +4760,76 @@
;; ::
;; ::::::::::::::::::::
-(define_expand "cmpbi"
- [(set (cc0)
- (compare (match_operand:BI 0 "register_operand" "")
- (match_operand:BI 1 "const_int_operand" "")))]
+(define_expand "cbranchbi4"
+ [(set (pc)
+ (if_then_else (match_operator 0 "ia64_cbranch_operator"
+ [(match_operand:BI 1 "register_operand" "")
+ (match_operand:BI 2 "const_int_operand" "")])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
""
-{
- ia64_compare_op0 = operands[0];
- ia64_compare_op1 = operands[1];
- DONE;
-})
+ "ia64_expand_compare (&operands[0], &operands[1], &operands[2]);")
-(define_expand "cmpsi"
- [(set (cc0)
- (compare (match_operand:SI 0 "gr_register_operand" "")
- (match_operand:SI 1 "gr_reg_or_8bit_and_adjusted_operand" "")))]
+(define_expand "cbranchsi4"
+ [(set (pc)
+ (if_then_else (match_operator 0 "ia64_cbranch_operator"
+ [(match_operand:SI 1 "gr_register_operand" "")
+ (match_operand:SI 2 "gr_reg_or_8bit_and_adjusted_operand" "")])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
""
-{
- ia64_compare_op0 = operands[0];
- ia64_compare_op1 = operands[1];
- DONE;
-})
+ "ia64_expand_compare (&operands[0], &operands[1], &operands[2]);")
-(define_expand "cmpdi"
- [(set (cc0)
- (compare (match_operand:DI 0 "gr_register_operand" "")
- (match_operand:DI 1 "gr_reg_or_8bit_and_adjusted_operand" "")))]
+(define_expand "cbranchdi4"
+ [(set (pc)
+ (if_then_else (match_operator 0 "ia64_cbranch_operator"
+ [(match_operand:DI 1 "gr_register_operand" "")
+ (match_operand:DI 2 "gr_reg_or_8bit_and_adjusted_operand" "")])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
""
-{
- ia64_compare_op0 = operands[0];
- ia64_compare_op1 = operands[1];
- DONE;
-})
+ "ia64_expand_compare (&operands[0], &operands[1], &operands[2]);")
-(define_expand "cmpsf"
- [(set (cc0)
- (compare (match_operand:SF 0 "fr_reg_or_fp01_operand" "")
- (match_operand:SF 1 "fr_reg_or_fp01_operand" "")))]
+(define_expand "cbranchsf4"
+ [(set (pc)
+ (if_then_else (match_operator 0 "ia64_cbranch_operator"
+ [(match_operand:SF 1 "fr_reg_or_fp01_operand" "")
+ (match_operand:SF 2 "fr_reg_or_fp01_operand" "")])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
""
-{
- ia64_compare_op0 = operands[0];
- ia64_compare_op1 = operands[1];
- DONE;
-})
+ "ia64_expand_compare (&operands[0], &operands[1], &operands[2]);")
-(define_expand "cmpdf"
- [(set (cc0)
- (compare (match_operand:DF 0 "fr_reg_or_fp01_operand" "")
- (match_operand:DF 1 "fr_reg_or_fp01_operand" "")))]
+(define_expand "cbranchdf4"
+ [(set (pc)
+ (if_then_else (match_operator 0 "ia64_cbranch_operator"
+ [(match_operand:DF 1 "fr_reg_or_fp01_operand" "")
+ (match_operand:DF 2 "fr_reg_or_fp01_operand" "")])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
""
-{
- ia64_compare_op0 = operands[0];
- ia64_compare_op1 = operands[1];
- DONE;
-})
+ "ia64_expand_compare (&operands[0], &operands[1], &operands[2]);")
-(define_expand "cmpxf"
- [(set (cc0)
- (compare (match_operand:XF 0 "xfreg_or_fp01_operand" "")
- (match_operand:XF 1 "xfreg_or_fp01_operand" "")))]
+(define_expand "cbranchxf4"
+ [(set (pc)
+ (if_then_else (match_operator 0 "ia64_cbranch_operator"
+ [(match_operand:XF 1 "xfreg_or_fp01_operand" "")
+ (match_operand:XF 2 "xfreg_or_fp01_operand" "")])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
""
-{
- ia64_compare_op0 = operands[0];
- ia64_compare_op1 = operands[1];
- DONE;
-})
+ "ia64_expand_compare (&operands[0], &operands[1], &operands[2]);")
-(define_expand "cmptf"
- [(set (cc0)
- (compare (match_operand:TF 0 "gr_register_operand" "")
- (match_operand:TF 1 "gr_register_operand" "")))]
+(define_expand "cbranchtf4"
+ [(set (pc)
+ (if_then_else (match_operator 0 "ia64_cbranch_operator"
+ [(match_operand:TF 1 "gr_register_operand" "")
+ (match_operand:TF 2 "gr_register_operand" "")])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
"TARGET_HPUX"
-{
- ia64_compare_op0 = operands[0];
- ia64_compare_op1 = operands[1];
- DONE;
-})
+ "ia64_expand_compare (&operands[0], &operands[1], &operands[2]);")
+
(define_insn "*cmpsi_normal"
[(set (match_operand:BI 0 "register_operand" "=c")
@@ -4933,102 +4928,6 @@
;; ::
;; ::::::::::::::::::::
-(define_expand "beq"
- [(set (pc)
- (if_then_else (match_dup 1)
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "operands[1] = ia64_expand_compare (EQ, VOIDmode);")
-
-(define_expand "bne"
- [(set (pc)
- (if_then_else (match_dup 1)
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "operands[1] = ia64_expand_compare (NE, VOIDmode);")
-
-(define_expand "blt"
- [(set (pc)
- (if_then_else (match_dup 1)
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "operands[1] = ia64_expand_compare (LT, VOIDmode);")
-
-(define_expand "ble"
- [(set (pc)
- (if_then_else (match_dup 1)
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "operands[1] = ia64_expand_compare (LE, VOIDmode);")
-
-(define_expand "bgt"
- [(set (pc)
- (if_then_else (match_dup 1)
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "operands[1] = ia64_expand_compare (GT, VOIDmode);")
-
-(define_expand "bge"
- [(set (pc)
- (if_then_else (match_dup 1)
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "operands[1] = ia64_expand_compare (GE, VOIDmode);")
-
-(define_expand "bltu"
- [(set (pc)
- (if_then_else (match_dup 1)
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "operands[1] = ia64_expand_compare (LTU, VOIDmode);")
-
-(define_expand "bleu"
- [(set (pc)
- (if_then_else (match_dup 1)
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "operands[1] = ia64_expand_compare (LEU, VOIDmode);")
-
-(define_expand "bgtu"
- [(set (pc)
- (if_then_else (match_dup 1)
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "operands[1] = ia64_expand_compare (GTU, VOIDmode);")
-
-(define_expand "bgeu"
- [(set (pc)
- (if_then_else (match_dup 1)
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "operands[1] = ia64_expand_compare (GEU, VOIDmode);")
-
-(define_expand "bunordered"
- [(set (pc)
- (if_then_else (match_dup 1)
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "operands[1] = ia64_expand_compare (UNORDERED, VOIDmode);")
-
-(define_expand "bordered"
- [(set (pc)
- (if_then_else (match_dup 1)
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "operands[1] = ia64_expand_compare (ORDERED, VOIDmode);")
-
(define_insn "*br_true"
[(set (pc)
(if_then_else (match_operator 0 "predicate_operator"
@@ -5094,65 +4993,61 @@
;; ::
;; ::::::::::::::::::::
-(define_expand "seq"
- [(set (match_operand:DI 0 "gr_register_operand" "") (match_dup 1))]
+(define_expand "cstorebi4"
+ [(set (match_operand:DI 0 "gr_register_operand" "")
+ (match_operator:DI 1 "ia64_cbranch_operator"
+ [(match_operand:BI 2 "register_operand" "")
+ (match_operand:BI 3 "const_int_operand" "")]))]
""
- "operands[1] = ia64_expand_compare (EQ, DImode);")
+ "ia64_expand_compare (&operands[0], &operands[1], &operands[2]);")
-(define_expand "sne"
- [(set (match_operand:DI 0 "gr_register_operand" "") (match_dup 1))]
+(define_expand "cstoresi4"
+ [(set (match_operand:DI 0 "gr_register_operand" "")
+ (match_operator:DI 1 "ia64_cbranch_operator"
+ [(match_operand:SI 2 "gr_register_operand" "")
+ (match_operand:SI 3 "gr_reg_or_8bit_and_adjusted_operand" "")]))]
""
- "operands[1] = ia64_expand_compare (NE, DImode);")
+ "ia64_expand_compare (&operands[1], &operands[2], &operands[3]);")
-(define_expand "slt"
- [(set (match_operand:DI 0 "gr_register_operand" "") (match_dup 1))]
+(define_expand "cstoredi4"
+ [(set (match_operand:DI 0 "gr_register_operand" "")
+ (match_operator:DI 1 "ia64_cbranch_operator"
+ [(match_operand:DI 2 "gr_register_operand" "")
+ (match_operand:DI 3 "gr_reg_or_8bit_and_adjusted_operand" "")]))]
""
- "operands[1] = ia64_expand_compare (LT, DImode);")
+ "ia64_expand_compare (&operands[1], &operands[2], &operands[3]);")
-(define_expand "sle"
- [(set (match_operand:DI 0 "gr_register_operand" "") (match_dup 1))]
+(define_expand "cstoresf4"
+ [(set (match_operand:DI 0 "gr_register_operand" "")
+ (match_operator:DI 1 "ia64_cbranch_operator"
+ [(match_operand:SF 2 "fr_reg_or_fp01_operand" "")
+ (match_operand:SF 3 "fr_reg_or_fp01_operand" "")]))]
""
- "operands[1] = ia64_expand_compare (LE, DImode);")
+ "ia64_expand_compare (&operands[1], &operands[2], &operands[3]);")
-(define_expand "sgt"
- [(set (match_operand:DI 0 "gr_register_operand" "") (match_dup 1))]
+(define_expand "cstoredf4"
+ [(set (match_operand:DI 0 "gr_register_operand" "")
+ (match_operator:DI 1 "ia64_cbranch_operator"
+ [(match_operand:DF 2 "fr_reg_or_fp01_operand" "")
+ (match_operand:DF 3 "fr_reg_or_fp01_operand" "")]))]
""
- "operands[1] = ia64_expand_compare (GT, DImode);")
+ "ia64_expand_compare (&operands[1], &operands[2], &operands[3]);")
-(define_expand "sge"
- [(set (match_operand:DI 0 "gr_register_operand" "") (match_dup 1))]
+(define_expand "cstorexf4"
+ [(set (match_operand:DI 0 "gr_register_operand" "")
+ (match_operator:DI 1 "ia64_cbranch_operator"
+ [(match_operand:XF 2 "xfreg_or_fp01_operand" "")
+ (match_operand:XF 3 "xfreg_or_fp01_operand" "")]))]
""
- "operands[1] = ia64_expand_compare (GE, DImode);")
+ "ia64_expand_compare (&operands[1], &operands[2], &operands[3]);")
-(define_expand "sltu"
- [(set (match_operand:DI 0 "gr_register_operand" "") (match_dup 1))]
- ""
- "operands[1] = ia64_expand_compare (LTU, DImode);")
-
-(define_expand "sleu"
- [(set (match_operand:DI 0 "gr_register_operand" "") (match_dup 1))]
- ""
- "operands[1] = ia64_expand_compare (LEU, DImode);")
-
-(define_expand "sgtu"
- [(set (match_operand:DI 0 "gr_register_operand" "") (match_dup 1))]
- ""
- "operands[1] = ia64_expand_compare (GTU, DImode);")
-
-(define_expand "sgeu"
- [(set (match_operand:DI 0 "gr_register_operand" "") (match_dup 1))]
- ""
- "operands[1] = ia64_expand_compare (GEU, DImode);")
-
-(define_expand "sunordered"
- [(set (match_operand:DI 0 "gr_register_operand" "") (match_dup 1))]
- ""
- "operands[1] = ia64_expand_compare (UNORDERED, DImode);")
-
-(define_expand "sordered"
- [(set (match_operand:DI 0 "gr_register_operand" "") (match_dup 1))]
- ""
- "operands[1] = ia64_expand_compare (ORDERED, DImode);")
+(define_expand "cstoretf4"
+ [(set (match_operand:DI 0 "gr_register_operand" "")
+ (match_operator:DI 1 "ia64_cbranch_operator"
+ [(match_operand:TF 2 "gr_register_operand" "")
+ (match_operand:TF 3 "gr_register_operand" "")]))]
+ "TARGET_HPUX"
+ "ia64_expand_compare (&operands[1], &operands[2], &operands[3]);")
;; Don't allow memory as destination here, because cmov/cmov/st is more
;; efficient than mov/mov/cst/cst.
@@ -6018,12 +5913,62 @@
"break %0"
[(set_attr "itanium_class" "chk_s_i")])
-(define_expand "conditional_trap"
- [(trap_if (match_operand 0 "" "") (match_operand 1 "" ""))]
+(define_expand "ctrapbi4"
+ [(trap_if (match_operator 0 "ia64_cbranch_operator"
+ [(match_operand:BI 1 "register_operand" "")
+ (match_operand:BI 2 "const_int_operand" "")])
+ (match_operand 3 "" ""))]
""
-{
- operands[0] = ia64_expand_compare (GET_CODE (operands[0]), VOIDmode);
-})
+ "ia64_expand_compare (&operands[0], &operands[1], &operands[2]);")
+
+(define_expand "ctrapsi4"
+ [(trap_if (match_operator 0 "ia64_cbranch_operator"
+ [(match_operand:SI 1 "gr_register_operand" "")
+ (match_operand:SI 2 "gr_reg_or_8bit_and_adjusted_operand" "")])
+ (match_operand 3 "" ""))]
+ ""
+ "ia64_expand_compare (&operands[0], &operands[1], &operands[2]);")
+
+(define_expand "ctrapdi4"
+ [(trap_if (match_operator 0 "ia64_cbranch_operator"
+ [(match_operand:DI 1 "gr_register_operand" "")
+ (match_operand:DI 2 "gr_reg_or_8bit_and_adjusted_operand" "")])
+ (match_operand 3 "" ""))]
+ ""
+ "ia64_expand_compare (&operands[0], &operands[1], &operands[2]);")
+
+(define_expand "ctrapsf4"
+ [(trap_if (match_operator 0 "ia64_cbranch_operator"
+ [(match_operand:SF 1 "fr_reg_or_fp01_operand" "")
+ (match_operand:SF 2 "fr_reg_or_fp01_operand" "")])
+ (match_operand 3 "" ""))]
+ ""
+ "ia64_expand_compare (&operands[0], &operands[1], &operands[2]);")
+
+(define_expand "ctrapdf4"
+ [(trap_if (match_operator 0 "ia64_cbranch_operator"
+ [(match_operand:DF 1 "fr_reg_or_fp01_operand" "")
+ (match_operand:DF 2 "fr_reg_or_fp01_operand" "")])
+ (match_operand 3 "" ""))]
+ ""
+ "ia64_expand_compare (&operands[0], &operands[1], &operands[2]);")
+
+(define_expand "ctrapxf4"
+ [(trap_if (match_operator 0 "ia64_cbranch_operator"
+ [(match_operand:XF 1 "xfreg_or_fp01_operand" "")
+ (match_operand:XF 2 "xfreg_or_fp01_operand" "")])
+ (match_operand 3 "" ""))]
+ ""
+ "ia64_expand_compare (&operands[0], &operands[1], &operands[2]);")
+
+(define_expand "ctraptf4"
+ [(trap_if (match_operator 0 "ia64_cbranch_operator"
+ [(match_operand:TF 1 "gr_register_operand" "")
+ (match_operand:TF 2 "gr_register_operand" "")])
+ (match_operand 3 "" ""))]
+ "TARGET_HPUX"
+ "ia64_expand_compare (&operands[0], &operands[1], &operands[2]);")
+
(define_insn "*conditional_trap"
[(trap_if (match_operator 0 "predicate_operator"
diff --git a/gcc/config/ia64/predicates.md b/gcc/config/ia64/predicates.md
index 5a957490390..1503a0520cb 100644
--- a/gcc/config/ia64/predicates.md
+++ b/gcc/config/ia64/predicates.md
@@ -536,6 +536,11 @@
(and (match_code "const_double,const_vector")
(match_test "op == CONST0_RTX (GET_MODE (op))"))))
+;; Return 1 if OP is a valid comparison operator for "cbranch" instructions.
+(define_predicate "ia64_cbranch_operator"
+ (ior (match_operand 0 "ordered_comparison_operator")
+ (match_code "ordered,unordered")))
+
;; True if this is a comparison operator, which accepts a normal 8-bit
;; signed immediate operand.
(define_predicate "normal_comparison_operator"
diff --git a/gcc/config/iq2000/iq2000-protos.h b/gcc/config/iq2000/iq2000-protos.h
index 094bcbf2f12..a927452d83c 100644
--- a/gcc/config/iq2000/iq2000-protos.h
+++ b/gcc/config/iq2000/iq2000-protos.h
@@ -41,7 +41,7 @@ extern void print_operand (FILE *, rtx, int);
#ifdef RTX_CODE
extern rtx gen_int_relational (enum rtx_code, rtx, rtx, rtx, int *);
-extern void gen_conditional_branch (rtx *, enum rtx_code);
+extern void gen_conditional_branch (rtx *, enum machine_mode);
#endif
#ifdef TREE_CODE
diff --git a/gcc/config/iq2000/iq2000.c b/gcc/config/iq2000/iq2000.c
index 3b9e1166b27..28bb7a831fe 100644
--- a/gcc/config/iq2000/iq2000.c
+++ b/gcc/config/iq2000/iq2000.c
@@ -118,13 +118,6 @@ enum processor_type iq2000_tune;
/* Which instruction set architecture to use. */
int iq2000_isa;
-/* Cached operands, and operator to compare for use in set/branch/trap
- on condition codes. */
-rtx branch_cmp[2];
-
-/* What type of branch to use. */
-enum cmp_type branch_type;
-
/* Local variables. */
/* The next branch instruction is a branch likely, not branch normal. */
@@ -1010,60 +1003,31 @@ gen_int_relational (enum rtx_code test_code, rtx result, rtx cmp0, rtx cmp1,
The comparison operands are saved away by cmp{si,di,sf,df}. */
void
-gen_conditional_branch (rtx operands[], enum rtx_code test_code)
+gen_conditional_branch (rtx operands[], enum machine_mode mode)
{
- enum cmp_type type = branch_type;
- rtx cmp0 = branch_cmp[0];
- rtx cmp1 = branch_cmp[1];
- enum machine_mode mode;
+ enum rtx_code test_code = GET_CODE (operands[0]);
+ rtx cmp0 = operands[1];
+ rtx cmp1 = operands[2];
rtx reg;
int invert;
rtx label1, label2;
- switch (type)
- {
- case CMP_SI:
- case CMP_DI:
- mode = type == CMP_SI ? SImode : DImode;
- invert = 0;
- reg = gen_int_relational (test_code, NULL_RTX, cmp0, cmp1, &invert);
-
- if (reg)
- {
- cmp0 = reg;
- cmp1 = const0_rtx;
- test_code = NE;
- }
- else if (GET_CODE (cmp1) == CONST_INT && INTVAL (cmp1) != 0)
- /* We don't want to build a comparison against a nonzero
- constant. */
- cmp1 = force_reg (mode, cmp1);
-
- break;
-
- case CMP_SF:
- case CMP_DF:
- reg = gen_reg_rtx (CCmode);
+ invert = 0;
+ reg = gen_int_relational (test_code, NULL_RTX, cmp0, cmp1, &invert);
- /* For cmp0 != cmp1, build cmp0 == cmp1, and test for result == 0. */
- emit_insn (gen_rtx_SET (VOIDmode, reg,
- gen_rtx_fmt_ee (test_code == NE ? EQ : test_code,
- CCmode, cmp0, cmp1)));
-
- test_code = test_code == NE ? EQ : NE;
- mode = CCmode;
+ if (reg)
+ {
cmp0 = reg;
cmp1 = const0_rtx;
- invert = 0;
- break;
-
- default:
- abort_with_insn (gen_rtx_fmt_ee (test_code, VOIDmode, cmp0, cmp1),
- "bad test");
+ test_code = NE;
}
+ else if (GET_CODE (cmp1) == CONST_INT && INTVAL (cmp1) != 0)
+ /* We don't want to build a comparison against a nonzero
+ constant. */
+ cmp1 = force_reg (mode, cmp1);
/* Generate the branch. */
- label1 = gen_rtx_LABEL_REF (VOIDmode, operands[0]);
+ label1 = gen_rtx_LABEL_REF (VOIDmode, operands[3]);
label2 = pc_rtx;
if (invert)
diff --git a/gcc/config/iq2000/iq2000.h b/gcc/config/iq2000/iq2000.h
index 30642b2a13f..0664f511bd3 100644
--- a/gcc/config/iq2000/iq2000.h
+++ b/gcc/config/iq2000/iq2000.h
@@ -1001,13 +1001,6 @@ extern enum processor_type iq2000_tune;
/* Which instruction set architecture to use. */
extern int iq2000_isa;
-/* Cached operands, and operator to compare for use in set/branch/trap
- on condition codes. */
-extern rtx branch_cmp[2];
-
-/* What type of branch to use. */
-extern enum cmp_type branch_type;
-
enum iq2000_builtins
{
IQ2000_BUILTIN_ADO16,
diff --git a/gcc/config/iq2000/iq2000.md b/gcc/config/iq2000/iq2000.md
index 919f6a20231..61275f2c671 100644
--- a/gcc/config/iq2000/iq2000.md
+++ b/gcc/config/iq2000/iq2000.md
@@ -989,63 +989,25 @@
;;
;; ....................
;;
-;; COMPARISONS
+;; CONDITIONAL BRANCHES
;;
;; ....................
-;; Flow here is rather complex:
-;;
-;; 1) The cmp{si,di,sf,df} routine is called. It deposits the
-;; arguments into the branch_cmp array, and the type into
-;; branch_type. No RTL is generated.
-;;
-;; 2) The appropriate branch define_expand is called, which then
-;; creates the appropriate RTL for the comparison and branch.
-;; Different CC modes are used, based on what type of branch is
-;; done, so that we can constrain things appropriately. There
-;; are assumptions in the rest of GCC that break if we fold the
-;; operands into the branches for integer operations, and use cc0
-;; for floating point, so we use the fp status register instead.
-;; If needed, an appropriate temporary is created to hold the
-;; of the integer compare.
-
-(define_expand "cmpsi"
- [(set (cc0)
- (compare:CC (match_operand:SI 0 "register_operand" "")
- (match_operand:SI 1 "arith_operand" "")))]
+(define_expand "cbranchsi4"
+ [(set (pc)
+ (if_then_else
+ (match_operator:SI 0 "ordered_comparison_operator"
+ [(match_operand:SI 1 "register_operand")
+ (match_operand:SI 2 "reg_or_const_operand")])
+ (label_ref (match_operand:SI 3 ""))
+ (pc)))]
""
"
{
- if (operands[0]) /* avoid unused code message */
- {
- branch_cmp[0] = operands[0];
- branch_cmp[1] = operands[1];
- branch_type = CMP_SI;
- DONE;
- }
+ gen_conditional_branch (operands, SImode);
+ DONE;
}")
-(define_expand "tstsi"
- [(set (cc0)
- (match_operand:SI 0 "register_operand" ""))]
- ""
- "
-{
- if (operands[0]) /* avoid unused code message */
- {
- branch_cmp[0] = operands[0];
- branch_cmp[1] = const0_rtx;
- branch_type = CMP_SI;
- DONE;
- }
-}")
-
-;;
-;; ....................
-;;
-;; CONDITIONAL BRANCHES
-;;
-;; ....................
;; Conditional branches on comparisons with zero.
@@ -1135,166 +1097,6 @@
[(set_attr "type" "branch")
(set_attr "mode" "none")])
-(define_expand "beq"
- [(set (pc)
- (if_then_else (eq:CC (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- if (operands[0]) /* avoid unused code warning */
- {
- gen_conditional_branch (operands, EQ);
- DONE;
- }
-}")
-
-(define_expand "bne"
- [(set (pc)
- (if_then_else (ne:CC (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- if (operands[0]) /* avoid unused code warning */
- {
- gen_conditional_branch (operands, NE);
- DONE;
- }
-}")
-
-(define_expand "bgt"
- [(set (pc)
- (if_then_else (gt:CC (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- if (operands[0]) /* avoid unused code warning */
- {
- gen_conditional_branch (operands, GT);
- DONE;
- }
-}")
-
-(define_expand "bge"
- [(set (pc)
- (if_then_else (ge:CC (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- if (operands[0]) /* avoid unused code warning */
- {
- gen_conditional_branch (operands, GE);
- DONE;
- }
-}")
-
-(define_expand "blt"
- [(set (pc)
- (if_then_else (lt:CC (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- if (operands[0]) /* avoid unused code warning */
- {
- gen_conditional_branch (operands, LT);
- DONE;
- }
-}")
-
-(define_expand "ble"
- [(set (pc)
- (if_then_else (le:CC (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- if (operands[0]) /* avoid unused code warning */
- {
- gen_conditional_branch (operands, LE);
- DONE;
- }
-}")
-
-(define_expand "bgtu"
- [(set (pc)
- (if_then_else (gtu:CC (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- if (operands[0]) /* avoid unused code warning */
- {
- gen_conditional_branch (operands, GTU);
- DONE;
- }
-}")
-
-(define_expand "bgeu"
- [(set (pc)
- (if_then_else (geu:CC (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- if (operands[0]) /* avoid unused code warning */
- {
- gen_conditional_branch (operands, GEU);
- DONE;
- }
-}")
-
-
-(define_expand "bltu"
- [(set (pc)
- (if_then_else (ltu:CC (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- if (operands[0]) /* avoid unused code warning */
- {
- gen_conditional_branch (operands, LTU);
- DONE;
- }
-}")
-
-(define_expand "bleu"
- [(set (pc)
- (if_then_else (leu:CC (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- if (operands[0]) /* avoid unused code warning */
- {
- gen_conditional_branch (operands, LEU);
- DONE;
- }
-}")
;; Recognize bbi and bbin instructions. These use two unusual template
;; patterns, %Ax and %Px. %Ax outputs an 'i' if operand `x' is a LABEL_REF
@@ -1390,25 +1192,19 @@
;;
;; ....................
-(define_expand "seq"
+(define_expand "cstoresi4"
[(set (match_operand:SI 0 "register_operand" "=d")
- (eq:SI (match_dup 1)
- (match_dup 2)))]
+ (match_operator:SI 1 "ordered_comparison_operator"
+ [(match_operand:SI 2 "register_operand")
+ (match_operand:SI 3 "reg_or_const_operand")]))]
""
"
{
- if (branch_type != CMP_SI && (branch_type != CMP_DI))
- FAIL;
-
- /* Set up operands from compare. */
- operands[1] = branch_cmp[0];
- operands[2] = branch_cmp[1];
-
- gen_int_relational (EQ, operands[0], operands[1], operands[2], (int *)0);
+ gen_int_relational (GET_CODE (operands[1]), operands[0],
+ operands[2], operands[3], (int *)0);
DONE;
}")
-
(define_insn "seq_si_zero"
[(set (match_operand:SI 0 "register_operand" "=d")
(eq:SI (match_operand:SI 1 "register_operand" "d")
@@ -1418,24 +1214,6 @@
[(set_attr "type" "arith")
(set_attr "mode" "SI")])
-(define_expand "sne"
- [(set (match_operand:SI 0 "register_operand" "=d")
- (ne:SI (match_dup 1)
- (match_dup 2)))]
- ""
- "
-{
- if (branch_type != CMP_SI && (branch_type != CMP_DI))
- FAIL;
-
- /* Set up operands from compare. */
- operands[1] = branch_cmp[0];
- operands[2] = branch_cmp[1];
-
- gen_int_relational (NE, operands[0], operands[1], operands[2], (int *)0);
- DONE;
-}")
-
(define_insn "sne_si_zero"
[(set (match_operand:SI 0 "register_operand" "=d")
(ne:SI (match_operand:SI 1 "register_operand" "d")
@@ -1445,24 +1223,6 @@
[(set_attr "type" "arith")
(set_attr "mode" "SI")])
-(define_expand "sgt"
- [(set (match_operand:SI 0 "register_operand" "=d")
- (gt:SI (match_dup 1)
- (match_dup 2)))]
- ""
- "
-{
- if (branch_type != CMP_SI && (branch_type != CMP_DI))
- FAIL;
-
- /* Set up operands from compare. */
- operands[1] = branch_cmp[0];
- operands[2] = branch_cmp[1];
-
- gen_int_relational (GT, operands[0], operands[1], operands[2], (int *)0);
- DONE;
-}")
-
(define_insn "sgt_si"
[(set (match_operand:SI 0 "register_operand" "=d,=d")
(gt:SI (match_operand:SI 1 "register_operand" "d,d")
@@ -1474,42 +1234,6 @@
[(set_attr "type" "arith,arith")
(set_attr "mode" "SI,SI")])
-(define_expand "sge"
- [(set (match_operand:SI 0 "register_operand" "=d")
- (ge:SI (match_dup 1)
- (match_dup 2)))]
- ""
- "
-{
- if (branch_type != CMP_SI && (branch_type != CMP_DI))
- FAIL;
-
- /* Set up operands from compare. */
- operands[1] = branch_cmp[0];
- operands[2] = branch_cmp[1];
-
- gen_int_relational (GE, operands[0], operands[1], operands[2], (int *)0);
- DONE;
-}")
-
-(define_expand "slt"
- [(set (match_operand:SI 0 "register_operand" "=d")
- (lt:SI (match_dup 1)
- (match_dup 2)))]
- ""
- "
-{
- if (branch_type != CMP_SI && (branch_type != CMP_DI))
- FAIL;
-
- /* Set up operands from compare. */
- operands[1] = branch_cmp[0];
- operands[2] = branch_cmp[1];
-
- gen_int_relational (LT, operands[0], operands[1], operands[2], (int *)0);
- DONE;
-}")
-
(define_insn "slt_si"
[(set (match_operand:SI 0 "register_operand" "=d,=d")
(lt:SI (match_operand:SI 1 "register_operand" "d,d")
@@ -1521,24 +1245,6 @@
[(set_attr "type" "arith,arith")
(set_attr "mode" "SI,SI")])
-(define_expand "sle"
- [(set (match_operand:SI 0 "register_operand" "=d")
- (le:SI (match_dup 1)
- (match_dup 2)))]
- ""
- "
-{
- if (branch_type != CMP_SI && (branch_type != CMP_DI))
- FAIL;
-
- /* Set up operands from compare. */
- operands[1] = branch_cmp[0];
- operands[2] = branch_cmp[1];
-
- gen_int_relational (LE, operands[0], operands[1], operands[2], (int *)0);
- DONE;
-}")
-
(define_insn "sle_si_const"
[(set (match_operand:SI 0 "register_operand" "=d")
(le:SI (match_operand:SI 1 "register_operand" "d")
@@ -1552,24 +1258,6 @@
[(set_attr "type" "arith")
(set_attr "mode" "SI")])
-(define_expand "sgtu"
- [(set (match_operand:SI 0 "register_operand" "=d")
- (gtu:SI (match_dup 1)
- (match_dup 2)))]
- ""
- "
-{
- if (branch_type != CMP_SI && (branch_type != CMP_DI))
- FAIL;
-
- /* Set up operands from compare. */
- operands[1] = branch_cmp[0];
- operands[2] = branch_cmp[1];
-
- gen_int_relational (GTU, operands[0], operands[1], operands[2], (int *)0);
- DONE;
-}")
-
(define_insn "sgtu_si"
[(set (match_operand:SI 0 "register_operand" "=d")
(gtu:SI (match_operand:SI 1 "register_operand" "d")
@@ -1588,42 +1276,6 @@
[(set_attr "type" "arith")
(set_attr "mode" "SI")])
-(define_expand "sgeu"
- [(set (match_operand:SI 0 "register_operand" "=d")
- (geu:SI (match_dup 1)
- (match_dup 2)))]
- ""
- "
-{
- if (branch_type != CMP_SI && (branch_type != CMP_DI))
- FAIL;
-
- /* Set up operands from compare. */
- operands[1] = branch_cmp[0];
- operands[2] = branch_cmp[1];
-
- gen_int_relational (GEU, operands[0], operands[1], operands[2], (int *)0);
- DONE;
-}")
-
-(define_expand "sltu"
- [(set (match_operand:SI 0 "register_operand" "=d")
- (ltu:SI (match_dup 1)
- (match_dup 2)))]
- ""
- "
-{
- if (branch_type != CMP_SI && (branch_type != CMP_DI))
- FAIL;
-
- /* Set up operands from compare. */
- operands[1] = branch_cmp[0];
- operands[2] = branch_cmp[1];
-
- gen_int_relational (LTU, operands[0], operands[1], operands[2], (int *)0);
- DONE;
-}")
-
(define_insn "sltu_si"
[(set (match_operand:SI 0 "register_operand" "=d,=d")
(ltu:SI (match_operand:SI 1 "register_operand" "d,d")
@@ -1635,24 +1287,6 @@
[(set_attr "type" "arith,arith")
(set_attr "mode" "SI,SI")])
-(define_expand "sleu"
- [(set (match_operand:SI 0 "register_operand" "=d")
- (leu:SI (match_dup 1)
- (match_dup 2)))]
- ""
- "
-{
- if (branch_type != CMP_SI && (branch_type != CMP_DI))
- FAIL;
-
- /* Set up operands from compare. */
- operands[1] = branch_cmp[0];
- operands[2] = branch_cmp[1];
-
- gen_int_relational (LEU, operands[0], operands[1], operands[2], (int *)0);
- DONE;
-}")
-
(define_insn "sleu_si_const"
[(set (match_operand:SI 0 "register_operand" "=d")
(leu:SI (match_operand:SI 1 "register_operand" "d")
diff --git a/gcc/config/iq2000/predicates.md b/gcc/config/iq2000/predicates.md
index 53471e455ad..f275090309b 100644
--- a/gcc/config/iq2000/predicates.md
+++ b/gcc/config/iq2000/predicates.md
@@ -41,6 +41,14 @@
return register_operand (op, mode);
})
+;; Return 1 if OP is a register or a constant. gen_int_relational
+;; takes care of forcing out-of-range constants into a register.
+
+(define_predicate "reg_or_const_operand"
+ (ior (match_code "const_int")
+ (and (match_code "reg,subreg")
+ (match_operand 0 "register_operand"))))
+
;; Return 1 if OP is a integer which fits in 16 bits.
(define_predicate "small_int"
diff --git a/gcc/config/m32c/cond.md b/gcc/config/m32c/cond.md
index 60d83eea6ca..c751070e716 100644
--- a/gcc/config/m32c/cond.md
+++ b/gcc/config/m32c/cond.md
@@ -58,12 +58,23 @@
[(set (reg:CC FLG_REGNO)
(compare (match_dup 1)
(match_dup 2)))
- (set (pc) (if_then_else (match_dup 4)
+ (set (pc) (if_then_else (match_op_dup 0 [(reg:CC FLG_REGNO) (const_int 0)])
(label_ref (match_dup 3))
(pc)))]
- "operands[4] = m32c_cmp_flg_0 (operands[0]);"
+ ""
)
+(define_insn "bcc_op"
+ [(set (pc)
+ (if_then_else (match_operator 0 "ordered_comparison_operator"
+ [(reg:CC FLG_REGNO) (const_int 0)])
+ (label_ref (match_operand 1 ""))
+ (pc)))]
+ ""
+ "j%c0\t%l1"
+ [(set_attr "flags" "n")]
+)
+
(define_insn "stzx_16"
[(set (match_operand:QI 0 "mrai_operand" "=R0w,R0w,R0w")
(if_then_else:QI (eq (reg:CC FLG_REGNO) (const_int 0))
@@ -113,34 +124,6 @@
"* return m32c_output_compare(insn, operands); "
[(set_attr "flags" "oszc")])
-(define_expand "cmp<mode>"
- [(set (reg:CC FLG_REGNO)
- (compare (match_operand:QHPSI 0 "mra_operand" "RraSd")
- (match_operand:QHPSI 1 "mrai_operand" "RraSdi")))]
- ""
- "m32c_pend_compare (operands); DONE;")
-
-(define_insn "b<code>_op"
- [(set (pc)
- (if_then_else (any_cond (reg:CC FLG_REGNO)
- (const_int 0))
- (label_ref (match_operand 0 ""))
- (pc)))]
- ""
- "j<code>\t%l0"
- [(set_attr "flags" "n")]
-)
-
-(define_expand "b<code>"
- [(set (pc)
- (if_then_else (any_cond (reg:CC FLG_REGNO)
- (const_int 0))
- (label_ref (match_operand 0 ""))
- (pc)))]
- ""
- "m32c_unpend_compare ();"
-)
-
;; m32c_conditional_register_usage changes the setcc_gen_code array to
;; point to the _24 variants if needed.
@@ -151,51 +134,54 @@
;; These are the post-split patterns for the conditional sets.
-(define_insn "s<code>_op"
+(define_insn "scc_op"
[(set (match_operand:QI 0 "register_operand" "=Rqi")
- (any_cond:QI (reg:CC FLG_REGNO) (const_int 0)))]
+ (match_operator:QI 1 "ordered_comparison_operator"
+ [(reg:CC FLG_REGNO) (const_int 0)]))]
"TARGET_A16 && reload_completed"
- "* return m32c_scc_pattern(operands, <CODE>);")
+ "* return m32c_scc_pattern(operands, GET_CODE (operands[1]));")
-(define_insn "s<code>_24_op"
+(define_insn "scc_24_op"
[(set (match_operand:HI 0 "mra_operand" "=RhiSd")
- (any_cond:HI (reg:CC FLG_REGNO) (const_int 0)))]
+ (match_operator:HI 1 "ordered_comparison_operator"
+ [(reg:CC FLG_REGNO) (const_int 0)]))]
"TARGET_A24 && reload_completed"
- "sc<code>\t%0"
+ "sc%c1\t%0"
[(set_attr "flags" "n")]
)
-;; These are the pre-split patterns for the conditional sets. Yes,
-;; there are a lot of permutations.
+;; These are the pre-split patterns for the conditional sets.
-(define_insn_and_split "s<code>_<mode>"
+(define_insn_and_split "cstore<mode>4"
[(set (match_operand:QI 0 "register_operand" "=Rqi")
- (any_cond:QI (match_operand:QHPSI 1 "mra_operand" "RraSd")
- (match_operand:QHPSI 2 "mrai_operand" "RraSdi")))]
+ (match_operator:QI 1 "ordered_comparison_operator"
+ [(match_operand:QHPSI 2 "mra_operand" "RraSd")
+ (match_operand:QHPSI 3 "mrai_operand" "RraSdi")]))]
"TARGET_A16"
"#"
"reload_completed"
[(set (reg:CC FLG_REGNO)
- (compare (match_dup 1)
- (match_dup 2)))
+ (compare (match_dup 2)
+ (match_dup 3)))
(set (match_dup 0)
- (any_cond:QI (reg:CC FLG_REGNO) (const_int 0)))]
+ (match_op_dup 1 [(reg:CC FLG_REGNO) (const_int 0)]))]
""
[(set_attr "flags" "x")]
)
-(define_insn_and_split "s<code>_<mode>_24"
+(define_insn_and_split "cstore<mode>4_24"
[(set (match_operand:HI 0 "mra_nopp_operand" "=RhiSd")
- (any_cond:HI (match_operand:QHPSI 1 "mra_operand" "RraSd")
- (match_operand:QHPSI 2 "mrai_operand" "RraSdi")))]
+ (match_operator:HI 1 "ordered_comparison_operator"
+ [(match_operand:QHPSI 2 "mra_operand" "RraSd")
+ (match_operand:QHPSI 3 "mrai_operand" "RraSdi")]))]
"TARGET_A24"
"#"
"reload_completed"
[(set (reg:CC FLG_REGNO)
- (compare (match_dup 1)
- (match_dup 2)))
+ (compare (match_dup 2)
+ (match_dup 3)))
(set (match_dup 0)
- (any_cond:HI (reg:CC FLG_REGNO) (const_int 0)))]
+ (match_op_dup 1 [(reg:CC FLG_REGNO) (const_int 0)]))]
""
[(set_attr "flags" "x")]
)
@@ -240,21 +226,7 @@
[(set_attr "flags" "x")]
)
-;; And these are the expanders, which read the pending compare
-;; operands to build a combined insn.
-
-(define_expand "s<code>"
- [(set (match_operand:QI 0 "register_operand" "=Rqi")
- (any_cond:QI (reg:CC FLG_REGNO) (const_int 0)))]
- "TARGET_A16"
- "m32c_expand_scc (<CODE>, operands); DONE;")
-
-(define_expand "s<code>_24"
- [(set (match_operand:HI 0 "mra_nopp_operand" "=RhiSd")
- (any_cond:HI (reg:CC FLG_REGNO) (const_int 0)))]
- "TARGET_A24"
- "m32c_expand_scc (<CODE>, operands); DONE;")
-
+;; And these are the expanders.
(define_expand "movqicc"
[(set (match_operand:QI 0 "register_operand" "")
diff --git a/gcc/config/m32c/m32c-protos.h b/gcc/config/m32c/m32c-protos.h
index 650c918b44a..ef857275c9d 100644
--- a/gcc/config/m32c/m32c-protos.h
+++ b/gcc/config/m32c/m32c-protos.h
@@ -45,7 +45,6 @@ void m32c_register_pragmas (void);
int m32c_regno_ok_for_base_p (int);
int m32c_trampoline_alignment (void);
int m32c_trampoline_size (void);
-void m32c_unpend_compare (void);
#if defined(RTX_CODE) && defined(TREE_CODE)
@@ -58,7 +57,6 @@ rtx m32c_function_value (const_tree, const_tree);
int m32c_cannot_change_mode_class (MM, MM, int);
int m32c_class_max_nregs (int, MM);
-rtx m32c_cmp_flg_0 (rtx);
rtx m32c_eh_return_stackadj_rtx (void);
void m32c_emit_eh_epilogue (rtx);
int m32c_expand_cmpstr (rtx *);
@@ -68,7 +66,6 @@ int m32c_expand_movmemhi (rtx *);
int m32c_expand_movstr (rtx *);
void m32c_expand_neg_mulpsi3 (rtx *);
int m32c_expand_setmemhi (rtx *);
-void m32c_expand_scc (int, rtx *);
int m32c_extra_constraint_p (rtx, char, const char *);
int m32c_extra_constraint_p2 (rtx, char, const char *);
int m32c_hard_regno_nregs (int, MM);
@@ -86,7 +83,6 @@ int m32c_memory_move_cost (MM, int, int);
int m32c_modes_tieable_p (MM, MM);
bool m32c_mov_ok (rtx *, MM);
char * m32c_output_compare (rtx, rtx *);
-void m32c_pend_compare (rtx *);
int m32c_preferred_output_reload_class (rtx, int);
int m32c_preferred_reload_class (rtx, int);
int m32c_prepare_move (rtx *, MM);
diff --git a/gcc/config/m32c/m32c.c b/gcc/config/m32c/m32c.c
index d0980dd63a6..17d5dd32ebc 100644
--- a/gcc/config/m32c/m32c.c
+++ b/gcc/config/m32c/m32c.c
@@ -1746,22 +1746,15 @@ m32c_initialize_trampoline (rtx tramp, rtx function, rtx chainval)
static void
m32c_init_libfuncs (void)
{
+ /* We do this because the M32C has an HImode operand, but the
+ M16C has an 8-bit operand. Since gcc looks at the match data
+ and not the expanded rtl, we have to reset the optab so that
+ the right modes are found. */
if (TARGET_A24)
{
- /* We do this because the M32C has an HImode operand, but the
- M16C has an 8-bit operand. Since gcc looks at the match data
- and not the expanded rtl, we have to reset the array so that
- the right modes are found. */
- setcc_gen_code[EQ] = CODE_FOR_seq_24;
- setcc_gen_code[NE] = CODE_FOR_sne_24;
- setcc_gen_code[GT] = CODE_FOR_sgt_24;
- setcc_gen_code[GE] = CODE_FOR_sge_24;
- setcc_gen_code[LT] = CODE_FOR_slt_24;
- setcc_gen_code[LE] = CODE_FOR_sle_24;
- setcc_gen_code[GTU] = CODE_FOR_sgtu_24;
- setcc_gen_code[GEU] = CODE_FOR_sgeu_24;
- setcc_gen_code[LTU] = CODE_FOR_sltu_24;
- setcc_gen_code[LEU] = CODE_FOR_sleu_24;
+ optab_handler (cstore_optab, QImode)->insn_code = CODE_FOR_cstoreqi4_24;
+ optab_handler (cstore_optab, HImode)->insn_code = CODE_FOR_cstorehi4_24;
+ optab_handler (cstore_optab, PSImode)->insn_code = CODE_FOR_cstorepsi4_24;
}
}
@@ -3691,57 +3684,8 @@ m32c_expand_neg_mulpsi3 (rtx * operands)
emit_insn (gen_truncsipsi2 (operands[0], temp2));
}
-static rtx compare_op0, compare_op1;
-
-void
-m32c_pend_compare (rtx *operands)
-{
- compare_op0 = operands[0];
- compare_op1 = operands[1];
-}
-
-void
-m32c_unpend_compare (void)
-{
- switch (GET_MODE (compare_op0))
- {
- case QImode:
- emit_insn (gen_cmpqi_op (compare_op0, compare_op1));
- case HImode:
- emit_insn (gen_cmphi_op (compare_op0, compare_op1));
- case PSImode:
- emit_insn (gen_cmppsi_op (compare_op0, compare_op1));
- default:
- /* Just to silence the "missing case" warnings. */ ;
- }
-}
-
-void
-m32c_expand_scc (int code, rtx *operands)
-{
- enum machine_mode mode = TARGET_A16 ? QImode : HImode;
-
- emit_insn (gen_rtx_SET (mode,
- operands[0],
- gen_rtx_fmt_ee (code,
- mode,
- compare_op0,
- compare_op1)));
-}
-
/* Pattern Output Functions */
-/* Returns a (OP (reg:CC FLG_REGNO) (const_int 0)) from some other
- match_operand rtx's OP. */
-rtx
-m32c_cmp_flg_0 (rtx cmp)
-{
- return gen_rtx_fmt_ee (GET_CODE (cmp),
- GET_MODE (cmp),
- gen_rtx_REG (CCmode, FLG_REGNO),
- GEN_INT (0));
-}
-
int
m32c_expand_movcc (rtx *operands)
{
@@ -3753,22 +3697,17 @@ m32c_expand_movcc (rtx *operands)
if (GET_CODE (operands[2]) != CONST_INT
|| GET_CODE (operands[3]) != CONST_INT)
return 1;
- emit_insn (gen_cmpqi(XEXP (rel, 0), XEXP (rel, 1)));
if (GET_CODE (rel) == NE)
{
rtx tmp = operands[2];
operands[2] = operands[3];
operands[3] = tmp;
+ rel = gen_rtx_EQ (GET_MODE (rel), XEXP (rel, 0), XEXP (rel, 1));
}
- cmp = gen_rtx_fmt_ee (GET_CODE (rel),
- GET_MODE (rel),
- compare_op0,
- compare_op1);
-
emit_move_insn (operands[0],
gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]),
- cmp,
+ rel,
operands[2],
operands[3]));
return 0;
diff --git a/gcc/config/m32c/m32c.md b/gcc/config/m32c/m32c.md
index 4bc4d05fbf1..da0f8dd23f9 100644
--- a/gcc/config/m32c/m32c.md
+++ b/gcc/config/m32c/m32c.md
@@ -60,10 +60,7 @@
(define_mode_iterator QHSI [QI HI (SI "TARGET_A24")])
(define_mode_attr bwl [(QI "b") (HI "w") (PSI "l") (SI "l")])
-(define_code_iterator any_cond [eq ne gt ge lt le gtu geu ltu leu])
(define_code_iterator eqne_cond [eq ne])
-(define_code_iterator gl_cond [gt ge lt le gtu geu ltu leu])
-
(define_insn "nop"
diff --git a/gcc/config/m32r/m32r-protos.h b/gcc/config/m32r/m32r-protos.h
index 33a9f9dd01f..04533b9b49e 100644
--- a/gcc/config/m32r/m32r-protos.h
+++ b/gcc/config/m32r/m32r-protos.h
@@ -38,6 +38,7 @@ extern enum m32r_function_type m32r_compute_function_type (tree);
extern int easy_di_const (rtx);
extern int easy_df_const (rtx);
extern rtx gen_compare (enum rtx_code, rtx, rtx, int);
+extern bool gen_cond_store (enum rtx_code, rtx, rtx, rtx);
extern rtx gen_split_move_double (rtx *);
extern int m32r_address_code (rtx);
extern void m32r_initialize_trampoline (rtx, rtx, rtx);
diff --git a/gcc/config/m32r/m32r.c b/gcc/config/m32r/m32r.c
index 656c0eae1be..0b5ff6bc6fd 100644
--- a/gcc/config/m32r/m32r.c
+++ b/gcc/config/m32r/m32r.c
@@ -43,10 +43,6 @@
#include "target-def.h"
#include "tm-constrs.h"
-/* Save the operands last given to a compare for use when we
- generate a scc or bcc insn. */
-rtx m32r_compare_op0, m32r_compare_op1;
-
/* Array of valid operand punctuation characters. */
char m32r_punct_chars[256];
@@ -864,6 +860,151 @@ gen_compare (enum rtx_code code, rtx x, rtx y, int need_compare)
return gen_rtx_fmt_ee (branch_code, VOIDmode, cc_reg, CONST0_RTX (CCmode));
}
+
+bool
+gen_cond_store (enum rtx_code code, rtx op0, rtx op1, rtx op2)
+{
+ enum machine_mode mode = GET_MODE (op0);
+
+ gcc_assert (mode == SImode);
+ switch (code)
+ {
+ case EQ:
+ if (!register_operand (op1, mode))
+ op1 = force_reg (mode, op1);
+
+ if (TARGET_M32RX || TARGET_M32R2)
+ {
+ if (!reg_or_zero_operand (op2, mode))
+ op2 = force_reg (mode, op2);
+
+ emit_insn (gen_seq_insn_m32rx (op0, op1, op2));
+ return true;
+ }
+ if (GET_CODE (op2) == CONST_INT && INTVAL (op2) == 0)
+ {
+ emit_insn (gen_seq_zero_insn (op0, op1));
+ return true;
+ }
+
+ if (!reg_or_eq_int16_operand (op2, mode))
+ op2 = force_reg (mode, op2);
+
+ emit_insn (gen_seq_insn (op0, op1, op2));
+ return true;
+
+ case NE:
+ if (GET_CODE (op2) != CONST_INT
+ || (INTVAL (op2) != 0 && satisfies_constraint_K (op2)))
+ {
+ rtx reg;
+
+ if (reload_completed || reload_in_progress)
+ return false;
+
+ reg = gen_reg_rtx (SImode);
+ emit_insn (gen_xorsi3 (reg, op1, op2));
+ op1 = reg;
+
+ if (!register_operand (op1, mode))
+ op1 = force_reg (mode, op1);
+
+ emit_insn (gen_sne_zero_insn (op0, op1));
+ return true;
+ }
+ return false;
+
+ case LT:
+ case GT:
+ if (code == GT)
+ {
+ rtx tmp = op2;
+ op2 = op1;
+ op1 = tmp;
+ code = LT;
+ }
+
+ if (!register_operand (op1, mode))
+ op1 = force_reg (mode, op1);
+
+ if (!reg_or_int16_operand (op2, mode))
+ op2 = force_reg (mode, op2);
+
+ emit_insn (gen_slt_insn (op0, op1, op2));
+ return true;
+
+ case LTU:
+ case GTU:
+ if (code == GTU)
+ {
+ rtx tmp = op2;
+ op2 = op1;
+ op1 = tmp;
+ code = LTU;
+ }
+
+ if (!register_operand (op1, mode))
+ op1 = force_reg (mode, op1);
+
+ if (!reg_or_int16_operand (op2, mode))
+ op2 = force_reg (mode, op2);
+
+ emit_insn (gen_sltu_insn (op0, op1, op2));
+ return true;
+
+ case GE:
+ case GEU:
+ if (!register_operand (op1, mode))
+ op1 = force_reg (mode, op1);
+
+ if (!reg_or_int16_operand (op2, mode))
+ op2 = force_reg (mode, op2);
+
+ if (code == GE)
+ emit_insn (gen_sge_insn (op0, op1, op2));
+ else
+ emit_insn (gen_sgeu_insn (op0, op1, op2));
+ return true;
+
+ case LE:
+ case LEU:
+ if (!register_operand (op1, mode))
+ op1 = force_reg (mode, op1);
+
+ if (GET_CODE (op2) == CONST_INT)
+ {
+ HOST_WIDE_INT value = INTVAL (op2);
+ if (value >= 2147483647)
+ {
+ emit_move_insn (op0, const1_rtx);
+ return true;
+ }
+
+ op2 = GEN_INT (value + 1);
+ if (value < -32768 || value >= 32767)
+ op2 = force_reg (mode, op2);
+
+ if (code == LEU)
+ emit_insn (gen_sltu_insn (op0, op1, op2));
+ else
+ emit_insn (gen_slt_insn (op0, op1, op2));
+ return true;
+ }
+
+ if (!register_operand (op2, mode))
+ op2 = force_reg (mode, op2);
+
+ if (code == LEU)
+ emit_insn (gen_sleu_insn (op0, op1, op2));
+ else
+ emit_insn (gen_sle_insn (op0, op1, op2));
+ return true;
+
+ default:
+ gcc_unreachable ();
+ }
+}
+
/* Split a 2 word move (DI or DF) into component parts. */
@@ -2291,8 +2432,8 @@ m32r_expand_block_move (rtx operands[])
if (bytes > MAX_MOVE_BYTES)
{
- emit_insn (gen_cmpsi (src_reg, final_src));
- emit_jump_insn (gen_bne (label));
+ rtx test = gen_rtx_NE (VOIDmode, src_reg, final_src);
+ emit_jump_insn (gen_cbranchsi4 (test, src_reg, final_src, label));
}
}
diff --git a/gcc/config/m32r/m32r.h b/gcc/config/m32r/m32r.h
index 9bc0fa98a0a..41dc07abad6 100644
--- a/gcc/config/m32r/m32r.h
+++ b/gcc/config/m32r/m32r.h
@@ -1495,12 +1495,6 @@ extern char m32r_punct_chars[256];
/* A function address in a call instruction. */
#define FUNCTION_MODE SImode
-/* Define the information needed to generate branch and scc insns. This is
- stored from the compare operation. Note that we can't use "rtx" here
- since it hasn't been defined! */
-extern struct rtx_def * m32r_compare_op0;
-extern struct rtx_def * m32r_compare_op1;
-
/* M32R function types. */
enum m32r_function_type
{
diff --git a/gcc/config/m32r/m32r.md b/gcc/config/m32r/m32r.md
index d117e1e6928..0c76a044ccc 100644
--- a/gcc/config/m32r/m32r.md
+++ b/gcc/config/m32r/m32r.md
@@ -1180,18 +1180,6 @@
;; thus merge the compare and branch into one instruction, so they are
;; preferred.
-(define_expand "cmpsi"
- [(set (reg:CC 17)
- (compare:CC (match_operand:SI 0 "register_operand" "")
- (match_operand:SI 1 "reg_or_cmp_int16_operand" "")))]
- ""
- "
-{
- m32r_compare_op0 = operands[0];
- m32r_compare_op1 = operands[1];
- DONE;
-}")
-
(define_insn "cmp_eqsi_zero_insn"
[(set (reg:CC 17)
(eq:CC (match_operand:SI 0 "register_operand" "r,r")
@@ -1256,114 +1244,20 @@
;; These control RTL generation for conditional jump insns.
-(define_expand "beq"
- [(set (pc)
- (if_then_else (match_dup 1)
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- operands[1] = gen_compare (EQ, m32r_compare_op0, m32r_compare_op1, FALSE);
-}")
-
-(define_expand "bne"
- [(set (pc)
- (if_then_else (match_dup 1)
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- operands[1] = gen_compare (NE, m32r_compare_op0, m32r_compare_op1, FALSE);
-}")
-
-(define_expand "bgt"
- [(set (pc)
- (if_then_else (match_dup 1)
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- operands[1] = gen_compare (GT, m32r_compare_op0, m32r_compare_op1, FALSE);
-}")
-
-(define_expand "ble"
- [(set (pc)
- (if_then_else (match_dup 1)
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- operands[1] = gen_compare (LE, m32r_compare_op0, m32r_compare_op1, FALSE);
-}")
-
-(define_expand "bge"
- [(set (pc)
- (if_then_else (match_dup 1)
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- operands[1] = gen_compare (GE, m32r_compare_op0, m32r_compare_op1, FALSE);
-}")
-
-(define_expand "blt"
- [(set (pc)
- (if_then_else (match_dup 1)
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- operands[1] = gen_compare (LT, m32r_compare_op0, m32r_compare_op1, FALSE);
-}")
-
-(define_expand "bgtu"
- [(set (pc)
- (if_then_else (match_dup 1)
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- operands[1] = gen_compare (GTU, m32r_compare_op0, m32r_compare_op1, FALSE);
-}")
-
-(define_expand "bleu"
- [(set (pc)
- (if_then_else (match_dup 1)
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- operands[1] = gen_compare (LEU, m32r_compare_op0, m32r_compare_op1, FALSE);
-}")
-
-(define_expand "bgeu"
- [(set (pc)
- (if_then_else (match_dup 1)
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- operands[1] = gen_compare (GEU, m32r_compare_op0, m32r_compare_op1, FALSE);
-}")
-
-(define_expand "bltu"
+(define_expand "cbranchsi4"
+ ; the comparison is emitted by gen_compare if needed.
[(set (pc)
- (if_then_else (match_dup 1)
- (label_ref (match_operand 0 "" ""))
+ (if_then_else (match_operator 0 "ordered_comparison_operator"
+ [(match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "reg_or_cmp_int16_operand" "")])
+ (label_ref (match_operand 3 "" ""))
(pc)))]
""
"
{
- operands[1] = gen_compare (LTU, m32r_compare_op0, m32r_compare_op1, FALSE);
+ operands[0] = gen_compare (GET_CODE (operands[0]), operands[1], operands[2], FALSE);
+ operands[1] = XEXP (operands[0], 0);
+ operands[2] = XEXP (operands[0], 1);
}")
;; Now match both normal and inverted jump.
@@ -1597,40 +1491,21 @@
;; S<cc> operations to set a register to 1/0 based on a comparison
-(define_expand "seq"
- [(match_operand:SI 0 "register_operand" "")]
+(define_expand "cstoresi4"
+ [(match_operand:SI 0 "register_operand" "")
+ (match_operator:SI 1 "ordered_comparison_operator"
+ [(match_operand:SI 2 "register_operand" "")
+ (match_operand:SI 3 "reg_or_cmp_int16_operand" "")])]
""
"
{
- rtx op0 = operands[0];
- rtx op1 = m32r_compare_op0;
- rtx op2 = m32r_compare_op1;
- enum machine_mode mode = GET_MODE (op0);
-
- if (mode != SImode)
+ if (GET_MODE (operands[0]) != SImode)
FAIL;
- if (! register_operand (op1, mode))
- op1 = force_reg (mode, op1);
-
- if (TARGET_M32RX || TARGET_M32R2)
- {
- if (! reg_or_zero_operand (op2, mode))
- op2 = force_reg (mode, op2);
-
- emit_insn (gen_seq_insn_m32rx (op0, op1, op2));
- DONE;
- }
- if (GET_CODE (op2) == CONST_INT && INTVAL (op2) == 0)
- {
- emit_insn (gen_seq_zero_insn (op0, op1));
- DONE;
- }
-
- if (! reg_or_eq_int16_operand (op2, mode))
- op2 = force_reg (mode, op2);
+ if (!gen_cond_store (GET_CODE (operands[1]),
+ operands[0], operands[2], operands[3]))
+ FAIL;
- emit_insn (gen_seq_insn (op0, op1, op2));
DONE;
}")
@@ -1739,41 +1614,6 @@
end_sequence ();
}")
-(define_expand "sne"
- [(match_operand:SI 0 "register_operand" "")]
- ""
- "
-{
- rtx op0 = operands[0];
- rtx op1 = m32r_compare_op0;
- rtx op2 = m32r_compare_op1;
- enum machine_mode mode = GET_MODE (op0);
-
- if (mode != SImode)
- FAIL;
-
- if (GET_CODE (op2) != CONST_INT
- || (INTVAL (op2) != 0 && satisfies_constraint_K (op2)))
- {
- rtx reg;
-
- if (reload_completed || reload_in_progress)
- FAIL;
-
- reg = gen_reg_rtx (SImode);
- emit_insn (gen_xorsi3 (reg, op1, op2));
- op1 = reg;
-
- if (! register_operand (op1, mode))
- op1 = force_reg (mode, op1);
-
- emit_insn (gen_sne_zero_insn (op0, op1));
- DONE;
- }
- else
- FAIL;
-}")
-
(define_insn "sne_zero_insn"
[(set (match_operand:SI 0 "register_operand" "=r")
(ne:SI (match_operand:SI 1 "register_operand" "r")
@@ -1801,29 +1641,6 @@
(ne:SI (reg:CC 17) (const_int 0)))]
"")
-(define_expand "slt"
- [(match_operand:SI 0 "register_operand" "")]
- ""
- "
-{
- rtx op0 = operands[0];
- rtx op1 = m32r_compare_op0;
- rtx op2 = m32r_compare_op1;
- enum machine_mode mode = GET_MODE (op0);
-
- if (mode != SImode)
- FAIL;
-
- if (! register_operand (op1, mode))
- op1 = force_reg (mode, op1);
-
- if (! reg_or_int16_operand (op2, mode))
- op2 = force_reg (mode, op2);
-
- emit_insn (gen_slt_insn (op0, op1, op2));
- DONE;
-}")
-
(define_insn "slt_insn"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(lt:SI (match_operand:SI 1 "register_operand" "r,r")
@@ -1847,46 +1664,6 @@
(ne:SI (reg:CC 17) (const_int 0)))]
"")
-(define_expand "sle"
- [(match_operand:SI 0 "register_operand" "")]
- ""
- "
-{
- rtx op0 = operands[0];
- rtx op1 = m32r_compare_op0;
- rtx op2 = m32r_compare_op1;
- enum machine_mode mode = GET_MODE (op0);
-
- if (mode != SImode)
- FAIL;
-
- if (! register_operand (op1, mode))
- op1 = force_reg (mode, op1);
-
- if (GET_CODE (op2) == CONST_INT)
- {
- HOST_WIDE_INT value = INTVAL (op2);
- if (value >= 2147483647)
- {
- emit_move_insn (op0, const1_rtx);
- DONE;
- }
-
- op2 = GEN_INT (value+1);
- if (value < -32768 || value >= 32767)
- op2 = force_reg (mode, op2);
-
- emit_insn (gen_slt_insn (op0, op1, op2));
- DONE;
- }
-
- if (! register_operand (op2, mode))
- op2 = force_reg (mode, op2);
-
- emit_insn (gen_sle_insn (op0, op1, op2));
- DONE;
-}")
-
(define_insn "sle_insn"
[(set (match_operand:SI 0 "register_operand" "=r")
(le:SI (match_operand:SI 1 "register_operand" "r")
@@ -1933,52 +1710,6 @@
(neg:SI (match_dup 0)))]
"")
-(define_expand "sgt"
- [(match_operand:SI 0 "register_operand" "")]
- ""
- "
-{
- rtx op0 = operands[0];
- rtx op1 = m32r_compare_op0;
- rtx op2 = m32r_compare_op1;
- enum machine_mode mode = GET_MODE (op0);
-
- if (mode != SImode)
- FAIL;
-
- if (! register_operand (op1, mode))
- op1 = force_reg (mode, op1);
-
- if (! register_operand (op2, mode))
- op2 = force_reg (mode, op2);
-
- emit_insn (gen_slt_insn (op0, op2, op1));
- DONE;
-}")
-
-(define_expand "sge"
- [(match_operand:SI 0 "register_operand" "")]
- ""
- "
-{
- rtx op0 = operands[0];
- rtx op1 = m32r_compare_op0;
- rtx op2 = m32r_compare_op1;
- enum machine_mode mode = GET_MODE (op0);
-
- if (mode != SImode)
- FAIL;
-
- if (! register_operand (op1, mode))
- op1 = force_reg (mode, op1);
-
- if (! reg_or_int16_operand (op2, mode))
- op2 = force_reg (mode, op2);
-
- emit_insn (gen_sge_insn (op0, op1, op2));
- DONE;
-}")
-
(define_insn "sge_insn"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(ge:SI (match_operand:SI 1 "register_operand" "r,r")
@@ -2025,29 +1756,6 @@
(neg:SI (match_dup 0)))]
"")
-(define_expand "sltu"
- [(match_operand:SI 0 "register_operand" "")]
- ""
- "
-{
- rtx op0 = operands[0];
- rtx op1 = m32r_compare_op0;
- rtx op2 = m32r_compare_op1;
- enum machine_mode mode = GET_MODE (op0);
-
- if (mode != SImode)
- FAIL;
-
- if (! register_operand (op1, mode))
- op1 = force_reg (mode, op1);
-
- if (! reg_or_int16_operand (op2, mode))
- op2 = force_reg (mode, op2);
-
- emit_insn (gen_sltu_insn (op0, op1, op2));
- DONE;
-}")
-
(define_insn "sltu_insn"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(ltu:SI (match_operand:SI 1 "register_operand" "r,r")
@@ -2071,43 +1779,6 @@
(ne:SI (reg:CC 17) (const_int 0)))]
"")
-(define_expand "sleu"
- [(match_operand:SI 0 "register_operand" "")]
- ""
- "
-{
- rtx op0 = operands[0];
- rtx op1 = m32r_compare_op0;
- rtx op2 = m32r_compare_op1;
- enum machine_mode mode = GET_MODE (op0);
-
- if (mode != SImode)
- FAIL;
-
- if (GET_CODE (op2) == CONST_INT)
- {
- HOST_WIDE_INT value = INTVAL (op2);
- if (value >= 2147483647)
- {
- emit_move_insn (op0, const1_rtx);
- DONE;
- }
-
- op2 = GEN_INT (value+1);
- if (value < 0 || value >= 32767)
- op2 = force_reg (mode, op2);
-
- emit_insn (gen_sltu_insn (op0, op1, op2));
- DONE;
- }
-
- if (! register_operand (op2, mode))
- op2 = force_reg (mode, op2);
-
- emit_insn (gen_sleu_insn (op0, op1, op2));
- DONE;
-}")
-
(define_insn "sleu_insn"
[(set (match_operand:SI 0 "register_operand" "=r")
(leu:SI (match_operand:SI 1 "register_operand" "r")
@@ -2154,52 +1825,6 @@
(neg:SI (match_dup 0)))]
"")
-(define_expand "sgtu"
- [(match_operand:SI 0 "register_operand" "")]
- ""
- "
-{
- rtx op0 = operands[0];
- rtx op1 = m32r_compare_op0;
- rtx op2 = m32r_compare_op1;
- enum machine_mode mode = GET_MODE (op0);
-
- if (mode != SImode)
- FAIL;
-
- if (! register_operand (op1, mode))
- op1 = force_reg (mode, op1);
-
- if (! register_operand (op2, mode))
- op2 = force_reg (mode, op2);
-
- emit_insn (gen_sltu_insn (op0, op2, op1));
- DONE;
-}")
-
-(define_expand "sgeu"
- [(match_operand:SI 0 "register_operand" "")]
- ""
- "
-{
- rtx op0 = operands[0];
- rtx op1 = m32r_compare_op0;
- rtx op2 = m32r_compare_op1;
- enum machine_mode mode = GET_MODE (op0);
-
- if (mode != SImode)
- FAIL;
-
- if (! register_operand (op1, mode))
- op1 = force_reg (mode, op1);
-
- if (! reg_or_int16_operand (op2, mode))
- op2 = force_reg (mode, op2);
-
- emit_insn (gen_sgeu_insn (op0, op1, op2));
- DONE;
-}")
-
(define_insn "sgeu_insn"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(geu:SI (match_operand:SI 1 "register_operand" "r,r")
@@ -2546,8 +2171,8 @@
FAIL;
/* Generate the comparison that will set the carry flag. */
- operands[1] = gen_compare (GET_CODE (operands[1]), m32r_compare_op0,
- m32r_compare_op1, TRUE);
+ operands[1] = gen_compare (GET_CODE (operands[1]), XEXP (operands[1], 0),
+ XEXP (operands[1], 1), TRUE);
/* See other movsicc pattern below for reason why. */
emit_insn (gen_blockage ());
diff --git a/gcc/config/m68hc11/m68hc11.c b/gcc/config/m68hc11/m68hc11.c
index 10bc7a0e66e..024e55de476 100644
--- a/gcc/config/m68hc11/m68hc11.c
+++ b/gcc/config/m68hc11/m68hc11.c
@@ -141,10 +141,6 @@ int m68hc11_sp_correction;
int m68hc11_addr_mode;
int m68hc11_mov_addr_mode;
-
-/* Comparison operands saved by the "tstxx" and "cmpxx" expand patterns. */
-rtx m68hc11_compare_op0;
-rtx m68hc11_compare_op1;
const struct processor_costs *m68hc11_cost;
@@ -3877,7 +3873,11 @@ m68hc11_notice_update_cc (rtx exp, rtx insn ATTRIBUTE_UNUSED)
{
cc_status.flags = 0;
cc_status.value1 = XEXP (exp, 0);
- cc_status.value2 = XEXP (exp, 1);
+ if (GET_CODE (XEXP (exp, 1)) == COMPARE
+ && XEXP (XEXP (exp, 1), 1) == CONST0_RTX (GET_MODE (XEXP (XEXP (exp, 1), 0))))
+ cc_status.value2 = XEXP (XEXP (exp, 1), 0);
+ else
+ cc_status.value2 = XEXP (exp, 1);
}
else
{
@@ -5355,6 +5355,7 @@ m68hc11_rtx_costs_1 (rtx x, enum rtx_code code,
case COMPARE:
case ABS:
case ZERO_EXTEND:
+ case ZERO_EXTRACT:
total = extra_cost + rtx_cost (XEXP (x, 0), code, !optimize_size);
if (mode == QImode)
{
@@ -5405,6 +5406,10 @@ m68hc11_rtx_costs (rtx x, int code, int outer_code, int *total,
*total = 0;
return true;
+ case ZERO_EXTRACT:
+ if (outer_code != COMPARE)
+ return false;
+
case ROTATE:
case ROTATERT:
case ASHIFT:
diff --git a/gcc/config/m68hc11/m68hc11.h b/gcc/config/m68hc11/m68hc11.h
index 35176592601..29d998dbf89 100644
--- a/gcc/config/m68hc11/m68hc11.h
+++ b/gcc/config/m68hc11/m68hc11.h
@@ -1498,8 +1498,6 @@ extern int current_function_interrupt;
extern int current_function_trap;
extern int current_function_far;
-extern GTY(()) rtx m68hc11_compare_op0;
-extern GTY(()) rtx m68hc11_compare_op1;
extern GTY(()) rtx m68hc11_soft_tmp_reg;
extern GTY(()) rtx ix_reg;
extern GTY(()) rtx iy_reg;
diff --git a/gcc/config/m68hc11/m68hc11.md b/gcc/config/m68hc11/m68hc11.md
index 0d40278cebb..f4ff3ebbb4c 100644
--- a/gcc/config/m68hc11/m68hc11.md
+++ b/gcc/config/m68hc11/m68hc11.md
@@ -162,31 +162,11 @@
;; An offsetable memory operand should be ok. The 'tst_operand' and
;; 'cmp_operand' predicates take care of this rule.
;;
-(define_expand "tstsi"
- [(set (cc0)
- (match_operand:SI 0 "tst_operand" ""))]
- ""
- "
-{
- m68hc11_compare_op0 = operands[0];
- m68hc11_compare_op1 = const0_rtx;
- DONE;
-}")
-
-(define_expand "tsthi"
- [(set (cc0)
- (match_operand:HI 0 "tst_operand" ""))]
- ""
- "
-{
- m68hc11_compare_op0 = operands[0];
- m68hc11_compare_op1 = const0_rtx;
- DONE;
-}")
(define_insn "tsthi_1"
[(set (cc0)
- (match_operand:HI 0 "tst_operand" "dx,*y"))]
+ (compare (match_operand:HI 0 "tst_operand" "dx,*y")
+ (const_int 0)))]
""
"*
{
@@ -196,34 +176,26 @@
return \"cp%0\\t#0\";
}")
-(define_expand "tstqi"
- [(set (cc0)
- (match_operand:QI 0 "tst_operand" ""))]
- ""
- "
-{
- m68hc11_compare_op0 = operands[0];
- m68hc11_compare_op1 = const0_rtx;
- DONE;
-}")
-
;;
;; Split pattern for (tst:QI) on an address register.
;;
(define_split
[(set (cc0)
- (match_operand:QI 0 "hard_addr_reg_operand" ""))]
+ (compare (match_operand:QI 0 "hard_addr_reg_operand" "")
+ (const_int 0)))]
"z_replacement_completed == 2 && GET_MODE (operands[0]) == QImode"
[(parallel [(set (reg:HI D_REGNUM) (match_dup 1))
(set (match_dup 1) (reg:HI D_REGNUM))])
- (set (cc0) (reg:QI D_REGNUM))
+ (set (cc0) (compare (reg:QI D_REGNUM)
+ (const_int 0)))
(parallel [(set (reg:HI D_REGNUM) (match_dup 1))
(set (match_dup 1) (reg:HI D_REGNUM))])]
"operands[1] = gen_rtx_REG (HImode, REGNO (operands[0]));")
(define_insn "tstqi_1"
[(set (cc0)
- (match_operand:QI 0 "tst_operand" "m,d,*A,!u"))]
+ (compare (match_operand:QI 0 "tst_operand" "m,d,*A,!u")
+ (const_int 0)))]
""
"*
{
@@ -252,8 +224,8 @@
;; after Z register replacement.
;;
(define_insn_and_split "tstqi_z_used"
- [(set (cc0)
- (match_operand:QI 0 "tst_operand" "m"))
+ [(set (cc0) (compare (match_operand:QI 0 "tst_operand" "m")
+ (const_int 0)))
(use (match_operand:HI 1 "hard_reg_operand" "dxy"))
(use (reg:HI SOFT_Z_REGNUM))]
""
@@ -261,7 +233,8 @@
"z_replacement_completed == 2"
[(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 1))
(set (match_dup 1) (match_dup 2))
- (set (cc0) (match_dup 0))
+ (set (cc0) (compare (match_dup 0)
+ (const_int 0)))
(set (match_dup 1) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
"operands[2] = gen_rtx_REG (HImode, SOFT_Z_REGNUM);")
@@ -270,21 +243,6 @@
;;- Compare
;;--------------------------------------------------------------------
-(define_expand "cmpsi"
- [(set (cc0)
- (compare (match_operand:SI 0 "tst_operand" "")
- (match_operand:SI 1 "cmp_operand" "")))]
- ""
- "
-{
- if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
- operands[0] = force_reg (SImode, operands[0]);
-
- m68hc11_compare_op0 = operands[0];
- m68hc11_compare_op1 = operands[1];
- DONE;
-}")
-
;;
;; Comparison of a hard register with another one is provided because
;; it helps GCC to avoid to spill a pseudo hard register.
@@ -316,21 +274,6 @@
(compare (match_dup 0) (mem:HI (post_inc:HI (reg:HI SP_REGNUM)))))]
"")
-(define_expand "cmphi"
- [(set (cc0)
- (compare (match_operand:HI 0 "tst_operand" "")
- (match_operand:HI 1 "cmp_operand" "")))]
- ""
- "
-{
- if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
- operands[0] = force_reg (HImode, operands[0]);
-
- m68hc11_compare_op0 = operands[0];
- m68hc11_compare_op1 = operands[1];
- DONE;
-}")
-
(define_insn "cmphi_1_hc12"
[(set (cc0)
(compare (match_operand:HI 0 "tst_operand"
@@ -419,25 +362,11 @@
operands[3] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
operands[4] = gen_rtx_REG (HImode, REGNO (operands[1]));")
-(define_expand "cmpqi"
- [(set (cc0)
- (compare (match_operand:QI 0 "tst_operand" "")
- (match_operand:QI 1 "cmp_operand" "")))]
- ""
- "
-{
- if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
- operands[0] = force_reg (QImode, operands[0]);
-
- m68hc11_compare_op0 = operands[0];
- m68hc11_compare_op1 = operands[1];
- DONE;
-}")
-
(define_insn "bitcmpqi"
[(set (cc0)
- (and:QI (match_operand:QI 0 "tst_operand" "d,d,d,m,!u")
- (match_operand:QI 1 "cmp_operand" "im,*B,u,d,d")))]
+ (compare (and:QI (match_operand:QI 0 "tst_operand" "d,d,d,m,!u")
+ (match_operand:QI 1 "cmp_operand" "im,*B,u,d,d"))
+ (const_int 0)))]
""
"@
bitb\\t%b1
@@ -448,8 +377,9 @@
(define_split /* "bitcmpqi" */
[(set (cc0)
- (and:QI (match_operand:QI 0 "tst_operand" "")
- (match_operand:QI 1 "hard_addr_reg_operand" "")))]
+ (compare (and:QI (match_operand:QI 0 "tst_operand" "")
+ (match_operand:QI 1 "hard_addr_reg_operand" ""))
+ (const_int 0)))]
"z_replacement_completed == 2"
[(set (match_dup 3) (match_dup 2))
(set (cc0) (and:QI (match_dup 0) (match_dup 4)))]
@@ -459,8 +389,9 @@
(define_insn_and_split "bitcmpqi_z_used"
[(set (cc0)
- (and:QI (match_operand:QI 0 "tst_operand" "d,m")
- (match_operand:QI 1 "cmp_operand" "m,d")))
+ (compare (and:QI (match_operand:QI 0 "tst_operand" "d,m")
+ (match_operand:QI 1 "cmp_operand" "m,d"))
+ (const_int 0)))
(use (match_operand:HI 2 "hard_reg_operand" "xy,xy"))
(use (reg:HI SOFT_Z_REGNUM))]
""
@@ -474,8 +405,9 @@
(define_insn "bitcmphi"
[(set (cc0)
- (and:HI (match_operand:HI 0 "tst_operand" "d")
- (match_operand:HI 1 "const_int_operand" "i")))]
+ (compare (and:HI (match_operand:HI 0 "tst_operand" "d")
+ (match_operand:HI 1 "const_int_operand" "i"))
+ (const_int 0)))]
"(INTVAL (operands[1]) & 0x0ff) == 0
|| (INTVAL (operands[1]) & 0x0ff00) == 0"
"*
@@ -488,9 +420,10 @@
(define_insn "bitcmpqi_12"
[(set (cc0)
- (zero_extract (match_operand:HI 0 "tst_operand" "d")
- (match_operand:HI 1 "const_int_operand" "i")
- (match_operand:HI 2 "const_int_operand" "i")))]
+ (compare (zero_extract:HI (match_operand:HI 0 "tst_operand" "d")
+ (match_operand:HI 1 "const_int_operand" "i")
+ (match_operand:HI 2 "const_int_operand" "i"))
+ (const_int 0)))]
"(unsigned) (INTVAL (operands[2]) + INTVAL (operands[1])) <= 8
|| (((unsigned) (INTVAL (operands[2]) + INTVAL (operands[1])) <= 16)
&& (unsigned) INTVAL (operands[2]) >= 8)"
@@ -6134,155 +6067,66 @@
""
"bra\\t%l0")
-(define_expand "beq"
- [(set (pc)
- (if_then_else (eq (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- m68hc11_expand_compare_and_branch (EQ, m68hc11_compare_op0,
- m68hc11_compare_op1,
- operands[0]);
- DONE;
-}")
-
-(define_expand "bne"
- [(set (pc)
- (if_then_else (ne (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- m68hc11_expand_compare_and_branch (NE, m68hc11_compare_op0,
- m68hc11_compare_op1,
- operands[0]);
- DONE;
-}")
-
-(define_expand "bgt"
- [(set (pc)
- (if_then_else (gt (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
+(define_expand "cbranchsi4"
+ [(set (cc0)
+ (compare (match_operand:SI 1 "tst_operand" "")
+ (match_operand:SI 2 "cmp_operand" "")))
+ (set (pc)
+ (if_then_else (match_operator 0 "ordered_comparison_operator"
+ [(cc0) (const_int 0)])
+ (label_ref (match_operand 3 "" ""))
(pc)))]
""
"
{
- m68hc11_expand_compare_and_branch (GT, m68hc11_compare_op0,
- m68hc11_compare_op1,
- operands[0]);
- DONE;
-}")
+ if (GET_CODE (operands[1]) == MEM && GET_CODE (operands[2]) == MEM)
+ operands[1] = force_reg (SImode, operands[1]);
-(define_expand "bgtu"
- [(set (pc)
- (if_then_else (gtu (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- m68hc11_expand_compare_and_branch (GTU, m68hc11_compare_op0,
- m68hc11_compare_op1,
- operands[0]);
+ m68hc11_expand_compare_and_branch (GET_CODE (operands[0]), operands[1],
+ operands[2], operands[3]);
DONE;
}")
-(define_expand "blt"
- [(set (pc)
- (if_then_else (lt (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- m68hc11_expand_compare_and_branch (LT, m68hc11_compare_op0,
- m68hc11_compare_op1,
- operands[0]);
- DONE;
-}")
-
-(define_expand "bltu"
- [(set (pc)
- (if_then_else (ltu (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
+(define_expand "cbranchhi4"
+ [(set (cc0)
+ (compare (match_operand:HI 1 "tst_operand" "")
+ (match_operand:HI 2 "cmp_operand" "")))
+ (set (pc)
+ (if_then_else (match_operator 0 "ordered_comparison_operator"
+ [(cc0) (const_int 0)])
+ (label_ref (match_operand 3 "" ""))
(pc)))]
""
"
{
- m68hc11_expand_compare_and_branch (LTU, m68hc11_compare_op0,
- m68hc11_compare_op1,
- operands[0]);
- DONE;
-}")
+ if (GET_CODE (operands[1]) == MEM && GET_CODE (operands[2]) == MEM)
+ operands[1] = force_reg (HImode, operands[1]);
-(define_expand "bge"
- [(set (pc)
- (if_then_else (ge (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- m68hc11_expand_compare_and_branch (GE, m68hc11_compare_op0,
- m68hc11_compare_op1,
- operands[0]);
+ m68hc11_expand_compare_and_branch (GET_CODE (operands[0]), operands[1],
+ operands[2], operands[3]);
DONE;
}")
-(define_expand "bgeu"
- [(set (pc)
- (if_then_else (geu (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
+(define_expand "cbranchqi4"
+ [(set (cc0)
+ (compare (match_operand:QI 1 "tst_operand" "")
+ (match_operand:QI 2 "cmp_operand" "")))
+ (set (pc)
+ (if_then_else (match_operator 0 "ordered_comparison_operator"
+ [(cc0) (const_int 0)])
+ (label_ref (match_operand 3 "" ""))
(pc)))]
""
"
{
- m68hc11_expand_compare_and_branch (GEU, m68hc11_compare_op0,
- m68hc11_compare_op1,
- operands[0]);
- DONE;
-}")
+ if (GET_CODE (operands[1]) == MEM && GET_CODE (operands[2]) == MEM)
+ operands[1] = force_reg (QImode, operands[1]);
-(define_expand "ble"
- [(set (pc)
- (if_then_else (le (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- m68hc11_expand_compare_and_branch (LE, m68hc11_compare_op0,
- m68hc11_compare_op1,
- operands[0]);
+ m68hc11_expand_compare_and_branch (GET_CODE (operands[0]), operands[1],
+ operands[2], operands[3]);
DONE;
}")
-(define_expand "bleu"
- [(set (pc)
- (if_then_else (leu (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- m68hc11_expand_compare_and_branch (LEU, m68hc11_compare_op0,
- m68hc11_compare_op1,
- operands[0]);
- DONE;
-}")
;;
;; Test and branch instructions for 68HC12 for EQ and NE.
@@ -7091,11 +6935,14 @@
(plus:HI (match_dup 0)
(match_operand:HI 1 "const_int_operand" "")))
(set (cc0)
- (match_operand:QI 2 "memory_operand" ""))]
+ (compare (match_operand:QI 2 "memory_operand" "")
+ (const_int 0)))]
"TARGET_AUTO_INC_DEC
&& (INTVAL (operands[1]) == -1 || INTVAL (operands[1]) == 1)
&& reg_mentioned_p (operands[0], operands[2])"
- [(set (cc0) (match_dup 3))]
+ [(set (cc0)
+ (compare (match_dup 3)
+ (const_int 0)))]
"if (INTVAL (operands[1]) == 1)
operands[3] = gen_rtx_MEM (QImode,
gen_rtx_PRE_INC (HImode, operands[0]));
@@ -7326,7 +7173,8 @@
(match_operand:HI 1 "hard_reg_operand" ""))
(set (match_dup 1) (plus:HI (match_dup 1)
(match_operand:HI 2 "const_int_operand" "")))
- (set (cc0) (match_dup 0))]
+ (set (cc0) (compare (match_dup 0)
+ (const_int 0)))]
"peep2_reg_dead_p (3, operands[0]) && !Z_REG_P (operands[1])"
[(set (match_dup 1) (plus:HI (match_dup 1) (match_dup 2)))
(set (cc0) (compare (match_dup 1) (match_dup 2)))]
@@ -7339,7 +7187,8 @@
(plus:HI (match_dup 2)
(match_operand:HI 3 "const_int_operand" "")))
(set (match_operand:HI 4 "memory_operand" "") (match_dup 2))
- (set (cc0) (match_operand:HI 5 "hard_reg_operand" ""))]
+ (set (cc0) (compare (match_operand:HI 5 "hard_reg_operand" "")
+ (const_int 0)))]
"peep2_reg_dead_p (4, operands[5]) && !Z_REG_P (operands[2])
&& !reg_mentioned_p (operands[2], operands[4])
diff --git a/gcc/config/m68k/constraints.md b/gcc/config/m68k/constraints.md
index 592112a155b..8be423788d6 100644
--- a/gcc/config/m68k/constraints.md
+++ b/gcc/config/m68k/constraints.md
@@ -78,6 +78,11 @@
(and (match_code "const_double")
(match_test "!(TARGET_68881 && standard_68881_constant_p (op))")))
+(define_constraint "H"
+ "Defines a real zero constant."
+ (and (match_code "const_double")
+ (match_test "op == CONST0_RTX (GET_MODE (op))")))
+
(define_constraint "S"
"Used for operands that satisfy 'm' when -mpcrel is in effect."
(and (match_code "mem")
diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c
index d3734efd9cf..1b5c83bb414 100644
--- a/gcc/config/m68k/m68k.c
+++ b/gcc/config/m68k/m68k.c
@@ -152,11 +152,6 @@ static bool m68k_return_in_memory (const_tree, const_tree);
/* Specify the identification number of the library being built */
const char *m68k_library_id_string = "_current_shared_library_a5_offset_";
-
-/* Nonzero if the last compare/test insn had FP operands. The
- sCC expanders peek at this to determine what to do for the
- 68060, which has no fsCC instructions. */
-int m68k_last_compare_had_fp_operands;
/* Initialize the GCC target structure. */
@@ -1024,10 +1019,10 @@ m68k_expand_prologue (void)
emit_move_insn (gen_rtx_REG (Pmode, D0_REG), limit);
limit = gen_rtx_REG (Pmode, D0_REG);
}
- emit_insn (gen_cmpsi (stack_pointer_rtx, limit));
- emit_insn (gen_conditional_trap (gen_rtx_LTU (VOIDmode,
- cc0_rtx, const0_rtx),
- const1_rtx));
+ emit_insn (gen_ctrapsi4 (gen_rtx_LTU (VOIDmode,
+ stack_pointer_rtx, limit),
+ stack_pointer_rtx, limit,
+ const1_rtx));
}
fsize_with_regs = current_frame.size;
@@ -1110,12 +1105,11 @@ m68k_expand_prologue (void)
if (crtl->limit_stack)
{
if (REG_P (stack_limit_rtx))
- {
- emit_insn (gen_cmpsi (stack_pointer_rtx, stack_limit_rtx));
- emit_insn (gen_conditional_trap (gen_rtx_LTU (VOIDmode,
- cc0_rtx, const0_rtx),
- const1_rtx));
- }
+ emit_insn (gen_ctrapsi4 (gen_rtx_LTU (VOIDmode, stack_pointer_rtx,
+ stack_limit_rtx),
+ stack_pointer_rtx, stack_limit_rtx,
+ const1_rtx));
+
else if (GET_CODE (stack_limit_rtx) != SYMBOL_REF)
warning (0, "stack limit expression is not supported");
}
@@ -2418,6 +2412,11 @@ m68k_rtx_costs (rtx x, int code, int outer_code, int *total,
*total = COSTS_N_INSNS (43); /* div.l */
return true;
+ case ZERO_EXTRACT:
+ if (outer_code == COMPARE)
+ *total = 0;
+ return false;
+
default:
return false;
}
diff --git a/gcc/config/m68k/m68k.h b/gcc/config/m68k/m68k.h
index 875667dc428..ec0b35bdc1b 100644
--- a/gcc/config/m68k/m68k.h
+++ b/gcc/config/m68k/m68k.h
@@ -1060,7 +1060,6 @@ enum m68k_function_kind
/* Variables in m68k.c; see there for details. */
extern const char *m68k_library_id_string;
-extern int m68k_last_compare_had_fp_operands;
extern enum target_device m68k_cpu;
extern enum uarch_type m68k_tune;
extern enum fpu_type m68k_fpu;
diff --git a/gcc/config/m68k/m68k.md b/gcc/config/m68k/m68k.md
index 68442fd5746..33058fa08b8 100644
--- a/gcc/config/m68k/m68k.md
+++ b/gcc/config/m68k/m68k.md
@@ -300,17 +300,10 @@
;; (set (cc0) (const_int foo)) has no mode information. Such insns will
;; be folded while optimizing anyway.
-(define_expand "tstdi"
- [(parallel [(set (cc0)
- (match_operand:DI 0 "nonimmediate_operand" ""))
- (clobber (match_scratch:SI 1 ""))
- (clobber (match_scratch:DI 2 ""))])]
- ""
- "m68k_last_compare_had_fp_operands = 0;")
-
-(define_insn ""
+(define_insn "tstdi"
[(set (cc0)
- (match_operand:DI 0 "nonimmediate_operand" "am,d"))
+ (compare (match_operand:DI 0 "nonimmediate_operand" "am,d")
+ (const_int 0)))
(clobber (match_scratch:SI 1 "=X,d"))
(clobber (match_scratch:DI 2 "=d,X"))]
""
@@ -339,17 +332,12 @@
return "sub%.l %1,%1\;tst%.l %R0\;subx%.l %1,%0";
})
-(define_expand "tstsi"
- [(set (cc0)
- (match_operand:SI 0 "nonimmediate_operand" ""))]
- ""
- "m68k_last_compare_had_fp_operands = 0;")
-
;; If you think that the 68020 does not support tstl a0,
;; reread page B-167 of the 68020 manual more carefully.
(define_insn "*tstsi_internal_68020_cf"
[(set (cc0)
- (match_operand:SI 0 "nonimmediate_operand" "rm"))]
+ (compare (match_operand:SI 0 "nonimmediate_operand" "rm")
+ (const_int 0)))]
"TARGET_68020 || TARGET_COLDFIRE"
"tst%.l %0"
[(set_attr "type" "tst_l")])
@@ -357,7 +345,8 @@
;; On an address reg, cmpw may replace cmpl.
(define_insn "*tstsi_internal"
[(set (cc0)
- (match_operand:SI 0 "nonimmediate_operand" "dm,r"))]
+ (compare (match_operand:SI 0 "nonimmediate_operand" "dm,r")
+ (const_int 0)))]
"!(TARGET_68020 || TARGET_COLDFIRE)"
"@
tst%.l %0
@@ -366,43 +355,26 @@
;; This can't use an address register, because comparisons
;; with address registers as second operand always test the whole word.
-(define_expand "tsthi"
- [(set (cc0)
- (match_operand:HI 0 "nonimmediate_operand" ""))]
- ""
- "m68k_last_compare_had_fp_operands = 0;")
-
(define_insn "*tsthi_internal"
[(set (cc0)
- (match_operand:HI 0 "nonimmediate_operand" "dm"))]
+ (compare (match_operand:HI 0 "nonimmediate_operand" "dm")
+ (const_int 0)))]
""
"tst%.w %0"
[(set_attr "type" "tst")])
-(define_expand "tstqi"
- [(set (cc0)
- (match_operand:QI 0 "nonimmediate_operand" ""))]
- ""
- "m68k_last_compare_had_fp_operands = 0;")
-
(define_insn "*tstqi_internal"
[(set (cc0)
- (match_operand:QI 0 "nonimmediate_operand" "dm"))]
+ (compare (match_operand:QI 0 "nonimmediate_operand" "dm")
+ (const_int 0)))]
""
"tst%.b %0"
[(set_attr "type" "tst")])
-(define_expand "tst<mode>"
- [(set (cc0)
- (match_operand:FP 0 "general_operand" ""))]
- "TARGET_HARD_FLOAT"
-{
- m68k_last_compare_had_fp_operands = 1;
-})
-
(define_insn "tst<mode>_68881"
[(set (cc0)
- (match_operand:FP 0 "general_operand" "f<FP:dreg>m"))]
+ (compare (match_operand:FP 0 "general_operand" "f<FP:dreg>m")
+ (match_operand:FP 1 "const0_operand" "H")))]
"TARGET_68881"
{
cc_status.flags = CC_IN_68881;
@@ -414,7 +386,8 @@
(define_insn "tst<mode>_cf"
[(set (cc0)
- (match_operand:FP 0 "general_operand" "f<FP:dreg><Q>U"))]
+ (compare (match_operand:FP 0 "general_operand" "f<FP:dreg><Q>U")
+ (match_operand:FP 1 "const0_operand" "H")))]
"TARGET_COLDFIRE_FPU"
{
cc_status.flags = CC_IN_68881;
@@ -427,20 +400,11 @@
;; compare instructions.
-(define_expand "cmpdi"
- [(parallel
- [(set (cc0)
- (compare (match_operand:DI 0 "nonimmediate_operand" "")
- (match_operand:DI 1 "general_operand" "")))
- (clobber (match_scratch:DI 2 ""))])]
- ""
- "m68k_last_compare_had_fp_operands = 0;")
-
-(define_insn ""
- [(set (cc0)
- (compare (match_operand:DI 1 "nonimmediate_operand" "0,d")
- (match_operand:DI 2 "general_operand" "d,0")))
- (clobber (match_scratch:DI 0 "=d,d"))]
+(define_insn "*cmpdi_internal"
+ [(set (cc0)
+ (compare (match_operand:DI 1 "nonimmediate_operand" "0,d")
+ (match_operand:DI 2 "general_operand" "d,0")))
+ (clobber (match_scratch:DI 0 "=d,d"))]
""
{
if (rtx_equal_p (operands[0], operands[1]))
@@ -452,15 +416,71 @@
}
})
-(define_expand "cmpsi"
- [(set (cc0)
- (compare (match_operand:SI 0 "nonimmediate_operand" "")
- (match_operand:SI 1 "general_operand" "")))]
+(define_insn "cmpdi"
+ [(set (cc0)
+ (compare (match_operand:DI 0 "nonimmediate_operand")
+ (match_operand:DI 1 "general_operand")))
+ (clobber (match_scratch:DI 2))]
+ ""
+ "")
+
+
+(define_expand "cbranchdi4"
+ [(set (pc)
+ (if_then_else (match_operator 0 "ordered_comparison_operator"
+ [(match_operand:DI 1 "nonimmediate_operand")
+ (match_operand:DI 2 "general_operand")])
+ (label_ref (match_operand 3 ""))
+ (pc)))]
""
{
- m68k_last_compare_had_fp_operands = 0;
+ if (operands[2] == const0_rtx)
+ emit_insn (gen_tstdi (operands[1]));
+ else
+ emit_insn (gen_cmpdi (operands[1], operands[2]));
+ operands[1] = cc0_rtx;
+ operands[2] = const0_rtx;
+})
+
+(define_expand "cstoredi4"
+ [(set (match_operand:QI 0 "register_operand")
+ (match_operator:QI 1 "ordered_comparison_operator"
+ [(match_operand:DI 2 "nonimmediate_operand")
+ (match_operand:DI 3 "general_operand")]))]
+ ""
+{
+ if (operands[3] == const0_rtx)
+ emit_insn (gen_tstdi (operands[2]));
+ else
+ emit_insn (gen_cmpdi (operands[2], operands[3]));
+ operands[2] = cc0_rtx;
+ operands[3] = const0_rtx;
})
+
+(define_expand "cbranchsi4"
+ [(set (cc0)
+ (compare (match_operand:SI 1 "nonimmediate_operand" "")
+ (match_operand:SI 2 "general_operand" "")))
+ (set (pc)
+ (if_then_else (match_operator 0 "ordered_comparison_operator"
+ [(cc0) (const_int 0)])
+ (label_ref (match_operand 3 ""))
+ (pc)))]
+ ""
+ "")
+
+(define_expand "cstoresi4"
+ [(set (cc0)
+ (compare (match_operand:SI 2 "nonimmediate_operand" "")
+ (match_operand:SI 3 "general_operand" "")))
+ (set (match_operand:QI 0 "register_operand")
+ (match_operator:QI 1 "ordered_comparison_operator"
+ [(cc0) (const_int 0)]))]
+ ""
+ "")
+
+
;; A composite of the cmp, cmpa, cmpi & cmpm m68000 op codes.
(define_insn ""
[(set (cc0)
@@ -500,12 +520,27 @@
}
[(set_attr "type" "cmp_l")])
-(define_expand "cmphi"
+(define_expand "cbranchhi4"
[(set (cc0)
- (compare (match_operand:HI 0 "nonimmediate_src_operand" "")
- (match_operand:HI 1 "general_src_operand" "")))]
- "!TARGET_COLDFIRE"
- "m68k_last_compare_had_fp_operands = 0;")
+ (compare (match_operand:HI 1 "nonimmediate_src_operand" "")
+ (match_operand:HI 2 "m68k_subword_comparison_operand" "")))
+ (set (pc)
+ (if_then_else (match_operator 0 "ordered_comparison_operator"
+ [(cc0) (const_int 0)])
+ (label_ref (match_operand 3 ""))
+ (pc)))]
+ ""
+ "")
+
+(define_expand "cstorehi4"
+ [(set (cc0)
+ (compare (match_operand:HI 2 "nonimmediate_operand" "")
+ (match_operand:HI 3 "m68k_subword_comparison_operand" "")))
+ (set (match_operand:QI 0 "register_operand")
+ (match_operator:QI 1 "ordered_comparison_operator"
+ [(cc0) (const_int 0)]))]
+ ""
+ "")
(define_insn ""
[(set (cc0)
@@ -524,12 +559,27 @@
return "cmp%.w %d1,%d0";
})
-(define_expand "cmpqi"
+(define_expand "cbranchqi4"
[(set (cc0)
- (compare (match_operand:QI 0 "nonimmediate_src_operand" "")
- (match_operand:QI 1 "general_src_operand" "")))]
- "!TARGET_COLDFIRE"
- "m68k_last_compare_had_fp_operands = 0;")
+ (compare (match_operand:QI 1 "nonimmediate_src_operand" "")
+ (match_operand:QI 2 "m68k_subword_comparison_operand" "")))
+ (set (pc)
+ (if_then_else (match_operator 0 "ordered_comparison_operator"
+ [(cc0) (const_int 0)])
+ (label_ref (match_operand 3 ""))
+ (pc)))]
+ ""
+ "")
+
+(define_expand "cstoreqi4"
+ [(set (cc0)
+ (compare (match_operand:QI 2 "nonimmediate_src_operand" "")
+ (match_operand:QI 3 "m68k_subword_comparison_operand" "")))
+ (set (match_operand:QI 0 "register_operand")
+ (match_operator:QI 1 "ordered_comparison_operator"
+ [(cc0) (const_int 0)]))]
+ ""
+ "")
(define_insn ""
[(set (cc0)
@@ -548,12 +598,28 @@
return "cmp%.b %d1,%d0";
})
-(define_expand "cmp<mode>"
+(define_expand "cbranch<mode>4"
[(set (cc0)
- (compare (match_operand:FP 0 "register_operand" "")
- (match_operand:FP 1 "fp_src_operand" "")))]
+ (compare (match_operand:FP 1 "register_operand" "")
+ (match_operand:FP 2 "fp_src_operand" "")))
+ (set (pc)
+ (if_then_else (match_operator 0 "comparison_operator"
+ [(cc0) (const_int 0)])
+ (label_ref (match_operand 3 ""))
+ (pc)))]
"TARGET_HARD_FLOAT"
- "m68k_last_compare_had_fp_operands = 1;")
+ "")
+
+(define_expand "cstore<mode>4"
+ [(set (cc0)
+ (compare (match_operand:FP 2 "register_operand" "")
+ (match_operand:FP 3 "fp_src_operand" "")))
+ (set (match_operand:QI 0 "register_operand")
+ (match_operator:QI 1 "m68k_cstore_comparison_operator"
+ [(cc0) (const_int 0)]))]
+ "TARGET_HARD_FLOAT && !(TUNE_68060 || TARGET_COLDFIRE_FPU)"
+ "if (TARGET_COLDFIRE && operands[2] != const0_rtx)
+ FAIL;")
(define_insn "*cmp<mode>_68881"
[(set (cc0)
@@ -588,10 +654,13 @@
;; from a MEM at a constant bit position if we can't use this as a constraint.
(define_insn ""
- [(set (cc0) (zero_extract (match_operand:QI 0 "memory_src_operand" "oS")
- (const_int 1)
- (minus:SI (const_int 7)
- (match_operand:SI 1 "general_operand" "di"))))]
+ [(set
+ (cc0)
+ (compare (zero_extract:SI (match_operand:QI 0 "memory_src_operand" "oS")
+ (const_int 1)
+ (minus:SI (const_int 7)
+ (match_operand:SI 1 "general_operand" "di")))
+ (const_int 0)))]
"!TARGET_COLDFIRE"
{
return output_btst (operands, operands[1], operands[0], insn, 7);
@@ -601,20 +670,26 @@
;; has been deleted.
(define_insn ""
- [(set (cc0) (zero_extract (match_operand:QI 0 "memory_operand" "o")
- (const_int 1)
- (minus:SI (const_int 7)
- (match_operand:SI 1 "general_operand" "d"))))]
+ [(set
+ (cc0)
+ (compare (zero_extract:SI (match_operand:QI 0 "memory_operand" "o")
+ (const_int 1)
+ (minus:SI (const_int 7)
+ (match_operand:SI 1 "general_operand" "d")))
+ (const_int 0)))]
"TARGET_COLDFIRE"
{
return output_btst (operands, operands[1], operands[0], insn, 7);
})
(define_insn ""
- [(set (cc0) (zero_extract (match_operand:SI 0 "register_operand" "d")
- (const_int 1)
- (minus:SI (const_int 31)
- (match_operand:SI 1 "general_operand" "di"))))]
+ [(set
+ (cc0)
+ (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "d")
+ (const_int 1)
+ (minus:SI (const_int 31)
+ (match_operand:SI 1 "general_operand" "di")))
+ (const_int 0)))]
""
{
return output_btst (operands, operands[1], operands[0], insn, 31);
@@ -625,24 +700,30 @@
;; are automatically masked to 3 or 5 bits.
(define_insn ""
- [(set (cc0) (zero_extract (match_operand:QI 0 "memory_operand" "o")
- (const_int 1)
- (minus:SI (const_int 7)
- (and:SI
- (match_operand:SI 1 "register_operand" "d")
- (const_int 7)))))]
+ [(set
+ (cc0)
+ (compare (zero_extract:SI (match_operand:QI 0 "memory_operand" "o")
+ (const_int 1)
+ (minus:SI (const_int 7)
+ (and:SI
+ (match_operand:SI 1 "register_operand" "d")
+ (const_int 7))))
+ (const_int 0)))]
""
{
return output_btst (operands, operands[1], operands[0], insn, 7);
})
(define_insn ""
- [(set (cc0) (zero_extract (match_operand:SI 0 "register_operand" "d")
- (const_int 1)
- (minus:SI (const_int 31)
- (and:SI
- (match_operand:SI 1 "register_operand" "d")
- (const_int 31)))))]
+ [(set
+ (cc0)
+ (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "d")
+ (const_int 1)
+ (minus:SI (const_int 31)
+ (and:SI
+ (match_operand:SI 1 "register_operand" "d")
+ (const_int 31))))
+ (const_int 0)))]
""
{
return output_btst (operands, operands[1], operands[0], insn, 31);
@@ -651,9 +732,12 @@
;; Nonoffsettable mem refs are ok in this one pattern
;; since we don't try to adjust them.
(define_insn ""
- [(set (cc0) (zero_extract (match_operand:QI 0 "memory_operand" "m")
- (const_int 1)
- (match_operand:SI 1 "const_int_operand" "n")))]
+ [(set
+ (cc0)
+ (compare (zero_extract:SI (match_operand:QI 0 "memory_operand" "m")
+ (const_int 1)
+ (match_operand:SI 1 "const_int_operand" "n"))
+ (const_int 0)))]
"(unsigned) INTVAL (operands[1]) < 8 && !TARGET_COLDFIRE"
{
operands[1] = GEN_INT (7 - INTVAL (operands[1]));
@@ -661,9 +745,12 @@
})
(define_insn ""
- [(set (cc0) (zero_extract (match_operand:SI 0 "register_operand" "do")
- (const_int 1)
- (match_operand:SI 1 "const_int_operand" "n")))]
+ [(set
+ (cc0)
+ (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "do")
+ (const_int 1)
+ (match_operand:SI 1 "const_int_operand" "n"))
+ (const_int 0)))]
"!TARGET_COLDFIRE"
{
if (GET_CODE (operands[0]) == MEM)
@@ -681,9 +768,12 @@
;; The 'o' has been replaced with 'Q'.
(define_insn ""
- [(set (cc0) (zero_extract (match_operand:SI 0 "register_operand" "dQ")
- (const_int 1)
- (match_operand:SI 1 "const_int_operand" "n")))]
+ [(set
+ (cc0)
+ (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "dQ")
+ (const_int 1)
+ (match_operand:SI 1 "const_int_operand" "n"))
+ (const_int 0)))]
"TARGET_COLDFIRE"
{
if (GET_CODE (operands[0]) == MEM)
@@ -5751,9 +5841,10 @@
(define_insn ""
[(set (cc0)
- (zero_extract:SI (match_operand:QI 0 "memory_operand" "o")
- (match_operand:SI 1 "const_int_operand" "n")
- (match_operand:SI 2 "general_operand" "dn")))]
+ (compare (zero_extract:SI (match_operand:QI 0 "memory_operand" "o")
+ (match_operand:SI 1 "const_int_operand" "n")
+ (match_operand:SI 2 "general_operand" "dn"))
+ (const_int 0)))]
"TARGET_68020 && TARGET_BITFIELD"
{
if (operands[1] == const1_rtx
@@ -5776,9 +5867,10 @@
;;; now handle the register cases
(define_insn ""
[(set (cc0)
- (zero_extract:SI (match_operand:SI 0 "register_operand" "d")
- (match_operand:SI 1 "const_int_operand" "n")
- (match_operand:SI 2 "general_operand" "dn")))]
+ (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "d")
+ (match_operand:SI 1 "const_int_operand" "n")
+ (match_operand:SI 2 "general_operand" "dn"))
+ (const_int 0)))]
"TARGET_68020 && TARGET_BITFIELD"
{
if (operands[1] == const1_rtx
@@ -5798,7 +5890,7 @@
(define_insn "scc0_di"
[(set (match_operand:QI 0 "nonimmediate_operand" "=dm")
- (match_operator 1 "valid_dbcc_comparison_p"
+ (match_operator 1 "ordered_comparison_operator"
[(match_operand:DI 2 "general_operand" "ro") (const_int 0)]))]
"! TARGET_COLDFIRE"
{
@@ -5807,7 +5899,7 @@
(define_insn "scc0_di_5200"
[(set (match_operand:QI 0 "nonimmediate_operand" "=d")
- (match_operator 1 "valid_dbcc_comparison_p"
+ (match_operator 1 "ordered_comparison_operator"
[(match_operand:DI 2 "general_operand" "ro") (const_int 0)]))]
"TARGET_COLDFIRE"
{
@@ -5816,7 +5908,7 @@
(define_insn "scc_di"
[(set (match_operand:QI 0 "nonimmediate_operand" "=dm,dm")
- (match_operator 1 "valid_dbcc_comparison_p"
+ (match_operator 1 "ordered_comparison_operator"
[(match_operand:DI 2 "general_operand" "ro,r")
(match_operand:DI 3 "general_operand" "r,ro")]))]
"! TARGET_COLDFIRE"
@@ -5826,7 +5918,7 @@
(define_insn "scc_di_5200"
[(set (match_operand:QI 0 "nonimmediate_operand" "=d,d")
- (match_operator 1 "valid_dbcc_comparison_p"
+ (match_operator 1 "ordered_comparison_operator"
[(match_operand:DI 2 "general_operand" "ro,r")
(match_operand:DI 3 "general_operand" "r,ro")]))]
"TARGET_COLDFIRE"
@@ -5838,19 +5930,6 @@
;; memory, but we cannot allow it to be in memory in case the address
;; needs to be reloaded.
-(define_expand "seq"
- [(set (match_operand:QI 0 "register_operand" "")
- (eq:QI (cc0) (const_int 0)))]
- ""
-{
- if ((TUNE_68060 || TARGET_COLDFIRE_FPU)
- && m68k_last_compare_had_fp_operands)
- {
- m68k_last_compare_had_fp_operands = 0;
- FAIL;
- }
-})
-
(define_insn ""
[(set (match_operand:QI 0 "register_operand" "=d")
(eq:QI (cc0) (const_int 0)))]
@@ -5860,19 +5939,6 @@
OUTPUT_JUMP ("seq %0", "fseq %0", "seq %0");
})
-(define_expand "sne"
- [(set (match_operand:QI 0 "register_operand" "")
- (ne:QI (cc0) (const_int 0)))]
- ""
-{
- if ((TUNE_68060 || TARGET_COLDFIRE_FPU)
- && m68k_last_compare_had_fp_operands)
- {
- m68k_last_compare_had_fp_operands = 0;
- FAIL;
- }
-})
-
(define_insn ""
[(set (match_operand:QI 0 "register_operand" "=d")
(ne:QI (cc0) (const_int 0)))]
@@ -5882,19 +5948,6 @@
OUTPUT_JUMP ("sne %0", "fsne %0", "sne %0");
})
-(define_expand "sgt"
- [(set (match_operand:QI 0 "register_operand" "")
- (gt:QI (cc0) (const_int 0)))]
- ""
-{
- if ((TUNE_68060 || TARGET_COLDFIRE_FPU)
- && m68k_last_compare_had_fp_operands)
- {
- m68k_last_compare_had_fp_operands = 0;
- FAIL;
- }
-})
-
(define_insn ""
[(set (match_operand:QI 0 "register_operand" "=d")
(gt:QI (cc0) (const_int 0)))]
@@ -5904,12 +5957,6 @@
OUTPUT_JUMP ("sgt %0", "fsgt %0", 0);
})
-(define_expand "sgtu"
- [(set (match_operand:QI 0 "register_operand" "")
- (gtu:QI (cc0) (const_int 0)))]
- ""
- "")
-
(define_insn ""
[(set (match_operand:QI 0 "register_operand" "=d")
(gtu:QI (cc0) (const_int 0)))]
@@ -5919,19 +5966,6 @@
return "shi %0";
})
-(define_expand "slt"
- [(set (match_operand:QI 0 "register_operand" "")
- (lt:QI (cc0) (const_int 0)))]
- ""
-{
- if ((TUNE_68060 || TARGET_COLDFIRE_FPU)
- && m68k_last_compare_had_fp_operands)
- {
- m68k_last_compare_had_fp_operands = 0;
- FAIL;
- }
-})
-
(define_insn ""
[(set (match_operand:QI 0 "register_operand" "=d")
(lt:QI (cc0) (const_int 0)))]
@@ -5941,12 +5975,6 @@
OUTPUT_JUMP ("slt %0", "fslt %0", "smi %0");
})
-(define_expand "sltu"
- [(set (match_operand:QI 0 "register_operand" "")
- (ltu:QI (cc0) (const_int 0)))]
- ""
- "")
-
(define_insn ""
[(set (match_operand:QI 0 "register_operand" "=d")
(ltu:QI (cc0) (const_int 0)))]
@@ -5956,19 +5984,6 @@
return "scs %0";
})
-(define_expand "sge"
- [(set (match_operand:QI 0 "register_operand" "")
- (ge:QI (cc0) (const_int 0)))]
- ""
-{
- if ((TUNE_68060 || TARGET_COLDFIRE_FPU)
- && m68k_last_compare_had_fp_operands)
- {
- m68k_last_compare_had_fp_operands = 0;
- FAIL;
- }
-})
-
(define_insn ""
[(set (match_operand:QI 0 "register_operand" "=d")
(ge:QI (cc0) (const_int 0)))]
@@ -5978,12 +5993,6 @@
OUTPUT_JUMP ("sge %0", "fsge %0", "spl %0");
})
-(define_expand "sgeu"
- [(set (match_operand:QI 0 "register_operand" "")
- (geu:QI (cc0) (const_int 0)))]
- ""
- "")
-
(define_insn "*scc"
[(set (match_operand:QI 0 "register_operand" "=d")
(geu:QI (cc0) (const_int 0)))]
@@ -5994,19 +6003,6 @@
}
[(set_attr "type" "scc")])
-(define_expand "sle"
- [(set (match_operand:QI 0 "register_operand" "")
- (le:QI (cc0) (const_int 0)))]
- ""
-{
- if ((TUNE_68060 || TARGET_COLDFIRE_FPU)
- && m68k_last_compare_had_fp_operands)
- {
- m68k_last_compare_had_fp_operands = 0;
- FAIL;
- }
-})
-
(define_insn ""
[(set (match_operand:QI 0 "register_operand" "=d")
(le:QI (cc0) (const_int 0)))]
@@ -6016,12 +6012,6 @@
OUTPUT_JUMP ("sle %0", "fsle %0", 0);
})
-(define_expand "sleu"
- [(set (match_operand:QI 0 "register_operand" "")
- (leu:QI (cc0) (const_int 0)))]
- ""
- "")
-
(define_insn "*sls"
[(set (match_operand:QI 0 "register_operand" "=d")
(leu:QI (cc0) (const_int 0)))]
@@ -6032,15 +6022,6 @@
}
[(set_attr "type" "scc")])
-(define_expand "sordered"
- [(set (match_operand:QI 0 "register_operand" "")
- (ordered:QI (cc0) (const_int 0)))]
- "TARGET_68881 && !TUNE_68060"
-{
- gcc_assert (m68k_last_compare_had_fp_operands);
- m68k_last_compare_had_fp_operands = 0;
-})
-
(define_insn "*sordered_1"
[(set (match_operand:QI 0 "register_operand" "=d")
(ordered:QI (cc0) (const_int 0)))]
@@ -6050,15 +6031,6 @@
return "fsor %0";
})
-(define_expand "sunordered"
- [(set (match_operand:QI 0 "register_operand" "")
- (unordered:QI (cc0) (const_int 0)))]
- "TARGET_68881 && !TUNE_68060"
-{
- gcc_assert (m68k_last_compare_had_fp_operands);
- m68k_last_compare_had_fp_operands = 0;
-})
-
(define_insn "*sunordered_1"
[(set (match_operand:QI 0 "register_operand" "=d")
(unordered:QI (cc0) (const_int 0)))]
@@ -6068,15 +6040,6 @@
return "fsun %0";
})
-(define_expand "suneq"
- [(set (match_operand:QI 0 "register_operand" "")
- (uneq:QI (cc0) (const_int 0)))]
- "TARGET_68881 && !TUNE_68060"
-{
- gcc_assert (m68k_last_compare_had_fp_operands);
- m68k_last_compare_had_fp_operands = 0;
-})
-
(define_insn "*suneq_1"
[(set (match_operand:QI 0 "register_operand" "=d")
(uneq:QI (cc0) (const_int 0)))]
@@ -6086,15 +6049,6 @@
return "fsueq %0";
})
-(define_expand "sunge"
- [(set (match_operand:QI 0 "register_operand" "")
- (unge:QI (cc0) (const_int 0)))]
- "TARGET_68881 && !TUNE_68060"
-{
- gcc_assert (m68k_last_compare_had_fp_operands);
- m68k_last_compare_had_fp_operands = 0;
-})
-
(define_insn "*sunge_1"
[(set (match_operand:QI 0 "register_operand" "=d")
(unge:QI (cc0) (const_int 0)))]
@@ -6104,15 +6058,6 @@
return "fsuge %0";
})
-(define_expand "sungt"
- [(set (match_operand:QI 0 "register_operand" "")
- (ungt:QI (cc0) (const_int 0)))]
- "TARGET_68881 && !TUNE_68060"
-{
- gcc_assert (m68k_last_compare_had_fp_operands);
- m68k_last_compare_had_fp_operands = 0;
-})
-
(define_insn "*sungt_1"
[(set (match_operand:QI 0 "register_operand" "=d")
(ungt:QI (cc0) (const_int 0)))]
@@ -6122,15 +6067,6 @@
return "fsugt %0";
})
-(define_expand "sunle"
- [(set (match_operand:QI 0 "register_operand" "")
- (unle:QI (cc0) (const_int 0)))]
- "TARGET_68881 && !TUNE_68060"
-{
- gcc_assert (m68k_last_compare_had_fp_operands);
- m68k_last_compare_had_fp_operands = 0;
-})
-
(define_insn "*sunle_1"
[(set (match_operand:QI 0 "register_operand" "=d")
(unle:QI (cc0) (const_int 0)))]
@@ -6140,15 +6076,6 @@
return "fsule %0";
})
-(define_expand "sunlt"
- [(set (match_operand:QI 0 "register_operand" "")
- (unlt:QI (cc0) (const_int 0)))]
- "TARGET_68881 && !TUNE_68060"
-{
- gcc_assert (m68k_last_compare_had_fp_operands);
- m68k_last_compare_had_fp_operands = 0;
-})
-
(define_insn "*sunlt_1"
[(set (match_operand:QI 0 "register_operand" "=d")
(unlt:QI (cc0) (const_int 0)))]
@@ -6158,15 +6085,6 @@
return "fsult %0";
})
-(define_expand "sltgt"
- [(set (match_operand:QI 0 "register_operand" "")
- (ltgt:QI (cc0) (const_int 0)))]
- "TARGET_68881 && !TUNE_68060"
-{
- gcc_assert (m68k_last_compare_had_fp_operands);
- m68k_last_compare_had_fp_operands = 0;
-})
-
(define_insn "*sltgt_1"
[(set (match_operand:QI 0 "register_operand" "=d")
(ltgt:QI (cc0) (const_int 0)))]
@@ -7758,23 +7676,54 @@
"trap #7"
[(set_attr "type" "trap")])
-(define_expand "conditional_trap"
- [(trap_if (match_operator 0 "valid_dbcc_comparison_p"
+(define_expand "ctrapdi4"
+ [(trap_if (match_operator 0 "ordered_comparison_operator"
[(cc0) (const_int 0)])
- (match_operand:SI 1 "const_int_operand" "I"))]
+ (match_operand:SI 3 "const1_operand" ""))]
"TARGET_68020"
{
- if (m68k_last_compare_had_fp_operands)
- {
- m68k_last_compare_had_fp_operands = 0;
- FAIL;
- }
+ if (operands[2] == const0_rtx)
+ emit_insn (gen_tstdi (operands[1]));
+ else
+ emit_insn (gen_cmpdi (operands[1], operands[2]));
+ operands[1] = cc0_rtx;
+ operands[2] = const0_rtx;
})
+(define_expand "ctrapsi4"
+ [(set (cc0)
+ (compare (match_operand:SI 1 "nonimmediate_operand" "")
+ (match_operand:SI 2 "general_operand" "")))
+ (trap_if (match_operator 0 "ordered_comparison_operator"
+ [(cc0) (const_int 0)])
+ (match_operand:SI 3 "const1_operand" ""))]
+ "TARGET_68020"
+ "")
+
+(define_expand "ctraphi4"
+ [(set (cc0)
+ (compare (match_operand:HI 1 "nonimmediate_src_operand" "")
+ (match_operand:HI 2 "general_src_operand" "")))
+ (trap_if (match_operator 0 "ordered_comparison_operator"
+ [(cc0) (const_int 0)])
+ (match_operand:SI 3 "const1_operand" ""))]
+ "TARGET_68020"
+ "")
+
+(define_expand "ctrapqi4"
+ [(set (cc0)
+ (compare (match_operand:QI 1 "nonimmediate_src_operand" "")
+ (match_operand:QI 2 "general_src_operand" "")))
+ (trap_if (match_operator 0 "ordered_comparison_operator"
+ [(cc0) (const_int 0)])
+ (match_operand:SI 3 "const1_operand" ""))]
+ "TARGET_68020"
+ "")
+
(define_insn "*conditional_trap"
- [(trap_if (match_operator 0 "valid_dbcc_comparison_p"
+ [(trap_if (match_operator 0 "ordered_comparison_operator"
[(cc0) (const_int 0)])
- (match_operand:SI 1 "const_int_operand" "I"))]
+ (match_operand:SI 1 "const1_operand" "I"))]
"TARGET_68020 && ! flags_in_68881 ()"
{
switch (GET_CODE (operands[0]))
diff --git a/gcc/config/m68k/predicates.md b/gcc/config/m68k/predicates.md
index b43e55b8972..417989f6d6c 100644
--- a/gcc/config/m68k/predicates.md
+++ b/gcc/config/m68k/predicates.md
@@ -124,6 +124,11 @@
(and (match_code "eq,ne,gtu,ltu,geu,leu,gt,lt,ge,le")
(match_test "valid_dbcc_comparison_p_2 (op, mode)")))
+(define_predicate "m68k_cstore_comparison_operator"
+ (if_then_else (match_test "TARGET_68881")
+ (match_operand 0 "comparison_operator")
+ (match_operand 0 "ordered_comparison_operator")))
+
;; Check for sign_extend or zero_extend. Used for bit-count operands.
(define_predicate "extend_operator"
@@ -193,6 +198,24 @@
(and (match_code "mem")
(match_test "GET_CODE (XEXP (op, 0)) == PRE_DEC")))
+;; A zero constant.
+(define_predicate "const0_operand"
+ (and (match_code "const_int,const_double,const_vector")
+ (match_test "op == CONST0_RTX (mode)")))
+
+;; A one constant (operand for conditional_trap).
+(define_predicate "const1_operand"
+ (and (match_code "const_int")
+ (match_test "op == const1_rtx")))
+
+;; A valid operand for a HImode or QImode conditional operation.
+;; ColdFire has tst patterns, but not cmp patterns.
+(define_predicate "m68k_subword_comparison_operand"
+ (if_then_else (match_test "TARGET_COLDFIRE")
+ (and (match_code "const_int")
+ (match_test "op == const0_rtx"))
+ (match_operand 0 "general_src_operand")))
+
;; An operand for movsi_const0 pattern.
(define_predicate "movsi_const0_operand"
(and (match_operand 0 "nonimmediate_operand")
diff --git a/gcc/config/mcore/mcore-protos.h b/gcc/config/mcore/mcore-protos.h
index 93c7c11e766..331cf7191d7 100644
--- a/gcc/config/mcore/mcore-protos.h
+++ b/gcc/config/mcore/mcore-protos.h
@@ -46,21 +46,17 @@ extern rtx mcore_function_value (const_tree, const_tree);
#ifdef RTX_CODE
-extern GTY(()) rtx arch_compare_op0;
-extern GTY(()) rtx arch_compare_op1;
-
extern const char * mcore_output_bclri (rtx, int);
extern const char * mcore_output_bseti (rtx, int);
extern const char * mcore_output_cmov (rtx *, int, const char *);
extern char * mcore_output_call (rtx *, int);
extern int mcore_is_dead (rtx, rtx);
extern int mcore_expand_insv (rtx *);
-extern int mcore_modify_comparison (RTX_CODE);
extern bool mcore_expand_block_move (rtx *);
extern const char * mcore_output_andn (rtx, rtx *);
extern void mcore_print_operand_address (FILE *, rtx);
extern void mcore_print_operand (FILE *, rtx, int);
-extern rtx mcore_gen_compare_reg (RTX_CODE);
+extern bool mcore_gen_compare (RTX_CODE, rtx, rtx);
extern int mcore_symbolic_address_p (rtx);
extern bool mcore_r15_operand_p (rtx);
extern enum reg_class mcore_secondary_reload_class (enum reg_class, enum machine_mode, rtx);
diff --git a/gcc/config/mcore/mcore.c b/gcc/config/mcore/mcore.c
index 24cc9406ed7..472bb75562a 100644
--- a/gcc/config/mcore/mcore.c
+++ b/gcc/config/mcore/mcore.c
@@ -57,11 +57,6 @@ long mcore_current_compilation_timestamp = 0;
/* Global variables for machine-dependent things. */
-/* Saved operands from the last compare to use when we generate an scc
- or bcc insn. */
-rtx arch_compare_op0;
-rtx arch_compare_op1;
-
/* Provides the class number of the smallest class containing
reg number. */
const int regno_reg_class[FIRST_PSEUDO_REGISTER] =
@@ -519,26 +514,36 @@ mcore_rtx_costs (rtx x, int code, int outer_code, int * total,
}
}
-/* Check to see if a comparison against a constant can be made more efficient
- by incrementing/decrementing the constant to get one that is more efficient
- to load. */
+/* Prepare the operands for a comparison. Return whether the branch/setcc
+ should reverse the operands. */
-int
-mcore_modify_comparison (enum rtx_code code)
+bool
+mcore_gen_compare (enum rtx_code code, rtx op0, rtx op1)
{
- rtx op1 = arch_compare_op1;
-
+ rtx cc_reg = gen_rtx_REG (CCmode, CC_REG);
+ bool invert;
+
if (GET_CODE (op1) == CONST_INT)
{
HOST_WIDE_INT val = INTVAL (op1);
switch (code)
{
+ case GTU:
+ /* Unsigned > 0 is the same as != 0; everything else is converted
+ below to LEU (reversed cmphs). */
+ if (val == 0)
+ code = NE;
+ break;
+
+ /* Check whether (LE A imm) can become (LT A imm + 1),
+ or (GT A imm) can become (GE A imm + 1). */
+ case GT:
case LE:
if (CONST_OK_FOR_J (val + 1))
{
- arch_compare_op1 = GEN_INT (val + 1);
- return 1;
+ op1 = GEN_INT (val + 1);
+ code = code == LE ? LT : GE;
}
break;
@@ -546,28 +551,18 @@ mcore_modify_comparison (enum rtx_code code)
break;
}
}
-
- return 0;
-}
-
-/* Prepare the operands for a comparison. */
-
-rtx
-mcore_gen_compare_reg (enum rtx_code code)
-{
- rtx op0 = arch_compare_op0;
- rtx op1 = arch_compare_op1;
- rtx cc_reg = gen_rtx_REG (CCmode, CC_REG);
-
+
if (CONSTANT_P (op1) && GET_CODE (op1) != CONST_INT)
op1 = force_reg (SImode, op1);
/* cmpnei: 0-31 (K immediate)
cmplti: 1-32 (J immediate, 0 using btsti x,31). */
+ invert = false;
switch (code)
{
case EQ: /* Use inverted condition, cmpne. */
code = NE;
+ invert = true;
/* Drop through. */
case NE: /* Use normal condition, cmpne. */
@@ -577,6 +572,7 @@ mcore_gen_compare_reg (enum rtx_code code)
case LE: /* Use inverted condition, reversed cmplt. */
code = GT;
+ invert = true;
/* Drop through. */
case GT: /* Use normal condition, reversed cmplt. */
@@ -586,6 +582,7 @@ mcore_gen_compare_reg (enum rtx_code code)
case GE: /* Use inverted condition, cmplt. */
code = LT;
+ invert = true;
/* Drop through. */
case LT: /* Use normal condition, cmplt. */
@@ -597,13 +594,10 @@ mcore_gen_compare_reg (enum rtx_code code)
break;
case GTU: /* Use inverted condition, cmple. */
- /* Unsigned > 0 is the same as != 0, but we need to invert the
- condition, so we want to set code = EQ. This cannot be done
- however, as the mcore does not support such a test. Instead
- we cope with this case in the "bgtu" pattern itself so we
- should never reach this point. */
+ /* We coped with unsigned > 0 above. */
gcc_assert (GET_CODE (op1) != CONST_INT || INTVAL (op1) != 0);
code = LEU;
+ invert = true;
/* Drop through. */
case LEU: /* Use normal condition, reversed cmphs. */
@@ -613,6 +607,7 @@ mcore_gen_compare_reg (enum rtx_code code)
case LTU: /* Use inverted condition, cmphs. */
code = GEU;
+ invert = true;
/* Drop through. */
case GEU: /* Use normal condition, cmphs. */
@@ -624,9 +619,10 @@ mcore_gen_compare_reg (enum rtx_code code)
break;
}
- emit_insn (gen_rtx_SET (VOIDmode, cc_reg, gen_rtx_fmt_ee (code, CCmode, op0, op1)));
-
- return cc_reg;
+ emit_insn (gen_rtx_SET (VOIDmode,
+ cc_reg,
+ gen_rtx_fmt_ee (code, CCmode, op0, op1)));
+ return invert;
}
int
diff --git a/gcc/config/mcore/mcore.md b/gcc/config/mcore/mcore.md
index 74906993e20..65b91588fc2 100644
--- a/gcc/config/mcore/mcore.md
+++ b/gcc/config/mcore/mcore.md
@@ -303,22 +303,6 @@
""
"cmphs %1,%0")
-;; We save the compare operands in the cmpxx patterns and use them when
-;; we generate the branch.
-
-;; We accept constants here, in case we can modify them to ones which
-;; are more efficient to load. E.g. change 'x <= 62' to 'x < 63'.
-
-(define_expand "cmpsi"
- [(set (reg:CC 17) (compare:CC (match_operand:SI 0 "mcore_compare_operand" "")
- (match_operand:SI 1 "nonmemory_operand" "")))]
- ""
- "
-{ arch_compare_op0 = operands[0];
- arch_compare_op1 = operands[1];
- DONE;
-}")
-
;; -------------------------------------------------------------------------
;; Logical operations
;; -------------------------------------------------------------------------
@@ -1479,6 +1463,10 @@
;; Define the real conditional branch instructions.
;; ------------------------------------------------------------------------
+;; At top-level, condition test are eq/ne, because we
+;; are comparing against the condition register (which
+;; has the result of the true relational test
+
(define_insn "branch_true"
[(set (pc) (if_then_else (ne (reg:CC 17) (const_int 0))
(label_ref (match_operand 0 "" ""))
@@ -1513,189 +1501,28 @@
;; Conditional branch insns
-;; At top-level, condition test are eq/ne, because we
-;; are comparing against the condition register (which
-;; has the result of the true relational test
-
-; There is no beq compare, so we reverse the branch arms.
-
-(define_expand "beq"
- [(set (pc) (if_then_else (ne (match_dup 1) (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "
-{
- operands[1] = mcore_gen_compare_reg (EQ);
-}")
-
-(define_expand "bne"
- [(set (pc) (if_then_else (ne (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- operands[1] = mcore_gen_compare_reg (NE);
-}")
-
-; check whether (GT A imm) can become (LE A imm) with the branch reversed.
-; if so, emit a (LT A imm + 1) in place of the (LE A imm). BRC
-
-(define_expand "bgt"
- [(set (pc) (if_then_else (ne (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- if (mcore_modify_comparison (LE))
- {
- emit_jump_insn (gen_reverse_blt (operands[0]));
- DONE;
- }
- operands[1] = mcore_gen_compare_reg (GT);
-}")
-
-; There is no ble compare, so we reverse the branch arms.
-; reversed the condition and branch arms for ble -- the check_dbra_loop()
-; transformation assumes that ble uses a branch-true with the label as
-; as the target. BRC
-
-; check whether (LE A imm) can become (LT A imm + 1).
-
-(define_expand "ble"
- [(set (pc) (if_then_else (eq (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- if (mcore_modify_comparison (LE))
- {
- emit_jump_insn (gen_blt (operands[0]));
- DONE;
- }
- operands[1] = mcore_gen_compare_reg (LE);
-}")
-
-; make generating a reversed blt simple
-(define_expand "reverse_blt"
- [(set (pc) (if_then_else (ne (match_dup 1) (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "
-{
- operands[1] = mcore_gen_compare_reg (LT);
-}")
-
-(define_expand "blt"
- [(set (pc) (if_then_else (ne (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- operands[1] = mcore_gen_compare_reg (LT);
-}")
-
-; There is no bge compare, so we reverse the branch arms.
-
-(define_expand "bge"
- [(set (pc) (if_then_else (ne (match_dup 1) (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "
-{
- operands[1] = mcore_gen_compare_reg (GE);
-}")
-
-; There is no gtu compare, so we reverse the branch arms
-
-;(define_expand "bgtu"
-; [(set (pc) (if_then_else (ne (match_dup 1) (const_int 0))
-; (pc)
-; (label_ref (match_operand 0 "" ""))))]
-; ""
-; "
-;{
-; if (GET_CODE (arch_compare_op1) == CONST_INT
-; && INTVAL (arch_compare_op1) == 0)
-; operands[1] = mcore_gen_compare_reg (NE);
-; else
-; { if (mcore_modify_comparison (GTU))
-; {
-; emit_jump_insn (gen_bgeu (operands[0]));
-; DONE;
-; }
-; operands[1] = mcore_gen_compare_reg (LEU);
-; }
-;}")
-
-(define_expand "bgtu"
- [(set (pc) (if_then_else (ne (match_dup 1) (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "
-{
- if (GET_CODE (arch_compare_op1) == CONST_INT
- && INTVAL (arch_compare_op1) == 0)
- {
- /* The inverse of '> 0' for an unsigned test is
- '== 0' but we do not have such an instruction available.
- Instead we must reverse the branch (back to the normal
- ordering) and test '!= 0'. */
-
- operands[1] = mcore_gen_compare_reg (NE);
-
- emit_jump_insn (gen_rtx_SET (VOIDmode,
- pc_rtx,
- gen_rtx_IF_THEN_ELSE (VOIDmode,
- gen_rtx_NE (VOIDmode,
- operands[1],
- const0_rtx),
- gen_rtx_LABEL_REF (VOIDmode,operands[0]),
- pc_rtx)));
- DONE;
- }
- operands[1] = mcore_gen_compare_reg (GTU);
-}")
-
-
-(define_expand "bleu"
- [(set (pc) (if_then_else (ne (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
+(define_expand "cbranchsi4"
+ [(set (pc)
+ (if_then_else (match_operator:SI 0 "ordered_comparison_operator"
+ [(match_operand:SI 1 "mcore_compare_operand")
+ (match_operand:SI 2 "nonmemory_operand")])
+ (label_ref (match_operand 3 ""))
+ (pc)))]
""
"
{
- operands[1] = mcore_gen_compare_reg (LEU);
-}")
+ bool invert;
+ invert = mcore_gen_compare (GET_CODE (operands[0]),
+ operands[1], operands[2]);
-; There is no bltu compare, so we reverse the branch arms
-(define_expand "bltu"
- [(set (pc) (if_then_else (ne (match_dup 1) (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "
-{
- operands[1] = mcore_gen_compare_reg (LTU);
+ if (invert)
+ emit_jump_insn (gen_branch_false (operands[3]));
+ else
+ emit_jump_insn (gen_branch_true (operands[3]));
+ DONE;
}")
-(define_expand "bgeu"
- [(set (pc) (if_then_else (ne (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- operands[1] = mcore_gen_compare_reg (GEU);
-}")
;; ------------------------------------------------------------------------
;; Jump and linkage insns
@@ -1853,118 +1680,23 @@
(set (match_dup 0) (eq:SI (reg:CC 17) (const_int 0)))])
-(define_expand "seq"
- [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
- (eq:SI (match_dup 1) (const_int 0)))]
- ""
- "
-{
- operands[1] = mcore_gen_compare_reg (NE);
-}")
-
-(define_expand "sne"
- [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
- (ne:SI (match_dup 1) (const_int 0)))]
- ""
- "
-{
- operands[1] = mcore_gen_compare_reg (NE);
-}")
-
-(define_expand "slt"
- [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
- (ne:SI (match_dup 1) (const_int 0)))]
- ""
- "
-{
- operands[1] = mcore_gen_compare_reg (LT);
-}")
-
-; make generating a LT with the comparison reversed easy. BRC
-(define_expand "reverse_slt"
- [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
- (eq:SI (match_dup 1) (const_int 0)))]
- ""
- "
-{
- operands[1] = mcore_gen_compare_reg (LT);
-}")
-
-(define_expand "sge"
- [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
- (eq:SI (match_dup 1) (const_int 0)))]
- ""
- "
-{
- operands[1] = mcore_gen_compare_reg (LT);
-}")
-
-; check whether (GT A imm) can become (LE A imm) with the comparison
-; reversed. if so, emit a (LT A imm + 1) in place of the (LE A imm). BRC
-
-(define_expand "sgt"
- [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
- (ne:SI (match_dup 1) (const_int 0)))]
- ""
- "
-{
- if (mcore_modify_comparison (LE))
- {
- emit_insn (gen_reverse_slt (operands[0]));
- DONE;
- }
-
- operands[1] = mcore_gen_compare_reg (GT);
-}")
-
-(define_expand "sle"
- [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
- (eq:SI (match_dup 1) (const_int 0)))]
- ""
- "
-{
- if (mcore_modify_comparison (LE))
- {
- emit_insn (gen_slt (operands[0]));
- DONE;
- }
- operands[1] = mcore_gen_compare_reg (GT);
-}")
-
-(define_expand "sltu"
- [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
- (eq:SI (match_dup 1) (const_int 0)))]
- ""
- "
-{
- operands[1] = mcore_gen_compare_reg (GEU);
-}")
-
-(define_expand "sgeu"
- [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
- (ne:SI (match_dup 1) (const_int 0)))]
- ""
- "
-{
- operands[1] = mcore_gen_compare_reg (GEU);
-}")
-
-(define_expand "sgtu"
+(define_expand "cstoresi4"
[(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
- (eq:SI (match_dup 1) (const_int 0)))]
+ (match_operator:SI 1 "ordered_comparison_operator"
+ [(match_operand:SI 2 "mcore_compare_operand" "")
+ (match_operand:SI 3 "nonmemory_operand" "")]))]
""
"
{
- operands[1] = mcore_gen_compare_reg (LEU);
-}")
+ bool invert;
+ invert = mcore_gen_compare (GET_CODE (operands[1]),
+ operands[2], operands[3]);
-(define_expand "sleu"
- [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
- (ne:SI (match_dup 1) (const_int 0)))]
- ""
- "
-{
- operands[1] = mcore_gen_compare_reg (LEU);
+ if (invert)
+ emit_insn (gen_mvcv (operands[0]));
+ else
+ emit_insn (gen_mvc (operands[0]));
+ DONE;
}")
(define_insn "incscc"
@@ -3308,7 +3040,7 @@
rtx loop_label = gen_label_rtx ();
rtx step = gen_reg_rtx (Pmode);
rtx tmp = gen_reg_rtx (Pmode);
- rtx memref;
+ rtx test, memref;
#if 1
emit_insn (gen_movsi (tmp, operands[1]));
@@ -3317,8 +3049,8 @@
if (GET_CODE (operands[1]) != CONST_INT)
{
out_label = gen_label_rtx ();
- emit_insn (gen_cmpsi (step, tmp)); /* quick out */
- emit_jump_insn (gen_bgeu (out_label));
+ test = gen_rtx_GEU (VOIDmode, step, tmp); /* quick out */
+ emit_jump_insn (gen_cbranchsi4 (test, step, tmp, out_label));
}
/* Run a loop that steps it incrementally. */
@@ -3332,8 +3064,8 @@
emit_insn(gen_subsi3(tmp, tmp, step));
/* Loop condition -- going back up. */
- emit_insn (gen_cmpsi (step, tmp));
- emit_jump_insn (gen_bltu (loop_label));
+ test = gen_rtx_LTU (VOIDmode, step, tmp);
+ emit_jump_insn (gen_cbranchsi4 (test, step, tmp, loop_label));
if (out_label)
emit_label (out_label);
diff --git a/gcc/config/mips/mips-protos.h b/gcc/config/mips/mips-protos.h
index b95461a4c4f..f2c67b84908 100644
--- a/gcc/config/mips/mips-protos.h
+++ b/gcc/config/mips/mips-protos.h
@@ -222,11 +222,11 @@ extern void mips_split_doubleword_move (rtx, rtx);
extern const char *mips_output_move (rtx, rtx);
extern void mips_restore_gp (rtx);
#ifdef RTX_CODE
-extern bool mips_expand_scc (enum rtx_code, rtx);
-extern void mips_expand_conditional_branch (rtx *, enum rtx_code);
+extern void mips_expand_scc (rtx *);
+extern void mips_expand_conditional_branch (rtx *);
extern void mips_expand_vcondv2sf (rtx, rtx, rtx, enum rtx_code, rtx, rtx);
extern void mips_expand_conditional_move (rtx *);
-extern void mips_expand_conditional_trap (enum rtx_code);
+extern void mips_expand_conditional_trap (rtx);
#endif
extern bool mips_use_pic_fn_addr_reg_p (const_rtx);
extern rtx mips_expand_call (enum mips_call_type, rtx, rtx, rtx, rtx, bool);
diff --git a/gcc/config/mips/mips-ps-3d.md b/gcc/config/mips/mips-ps-3d.md
index d4efe4cbf79..98932d85b11 100644
--- a/gcc/config/mips/mips-ps-3d.md
+++ b/gcc/config/mips/mips-ps-3d.md
@@ -58,7 +58,7 @@
MOVZ.PS. MOVT.PS and MOVF.PS depend on two CC values and move
each item independently. */
- if (GET_MODE_CLASS (GET_MODE (cmp_operands[0])) != MODE_INT)
+ if (GET_MODE_CLASS (GET_MODE (XEXP (operands[1], 0))) != MODE_INT)
FAIL;
mips_expand_conditional_move (operands);
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index 32c898bcf83..9d712d2f096 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -448,9 +448,6 @@ static int set_noat;
normal branch. */
static bool mips_branch_likely;
-/* The operands passed to the last cmpMM expander. */
-rtx cmp_operands[2];
-
/* The current instruction-set architecture. */
enum processor_type mips_arch;
const struct mips_cpu_info *mips_arch_info;
@@ -4221,8 +4218,8 @@ mips_reversed_fp_cond (enum rtx_code *code)
}
/* Convert a comparison into something that can be used in a branch or
- conditional move. cmp_operands[0] and cmp_operands[1] are the values
- being compared and *CODE is the code used to compare them.
+ conditional move. On entry, *OP0 and *OP1 are the values being
+ compared and *CODE is the code used to compare them.
Update *CODE, *OP0 and *OP1 so that they describe the final comparison.
If NEED_EQ_NE_P, then only EQ or NE comparisons against zero are possible,
@@ -4235,42 +4232,38 @@ mips_reversed_fp_cond (enum rtx_code *code)
static void
mips_emit_compare (enum rtx_code *code, rtx *op0, rtx *op1, bool need_eq_ne_p)
{
- if (GET_MODE_CLASS (GET_MODE (cmp_operands[0])) == MODE_INT)
+ rtx cmp_op0 = *op0;
+ rtx cmp_op1 = *op1;
+
+ if (GET_MODE_CLASS (GET_MODE (*op0)) == MODE_INT)
{
- if (!need_eq_ne_p && cmp_operands[1] == const0_rtx)
- {
- *op0 = cmp_operands[0];
- *op1 = cmp_operands[1];
- }
+ if (!need_eq_ne_p && *op1 == const0_rtx)
+ ;
else if (*code == EQ || *code == NE)
{
if (need_eq_ne_p)
{
- *op0 = mips_zero_if_equal (cmp_operands[0], cmp_operands[1]);
+ *op0 = mips_zero_if_equal (cmp_op0, cmp_op1);
*op1 = const0_rtx;
}
else
- {
- *op0 = cmp_operands[0];
- *op1 = force_reg (GET_MODE (*op0), cmp_operands[1]);
- }
+ *op1 = force_reg (GET_MODE (cmp_op0), cmp_op1);
}
else
{
/* The comparison needs a separate scc instruction. Store the
result of the scc in *OP0 and compare it against zero. */
bool invert = false;
- *op0 = gen_reg_rtx (GET_MODE (cmp_operands[0]));
- mips_emit_int_order_test (*code, &invert, *op0,
- cmp_operands[0], cmp_operands[1]);
+ *op0 = gen_reg_rtx (GET_MODE (cmp_op0));
+ mips_emit_int_order_test (*code, &invert, *op0, cmp_op0, cmp_op1);
*code = (invert ? EQ : NE);
*op1 = const0_rtx;
}
}
- else if (ALL_FIXED_POINT_MODE_P (GET_MODE (cmp_operands[0])))
+ else if (ALL_FIXED_POINT_MODE_P (GET_MODE (cmp_op0)))
{
*op0 = gen_rtx_REG (CCDSPmode, CCDSP_CC_REGNUM);
- mips_emit_binary (*code, *op0, cmp_operands[0], cmp_operands[1]);
+ mips_emit_binary (*code, *op0, cmp_op0, cmp_op1);
*code = NE;
*op1 = const0_rtx;
}
@@ -4290,49 +4283,55 @@ mips_emit_compare (enum rtx_code *code, rtx *op0, rtx *op1, bool need_eq_ne_p)
? gen_reg_rtx (CCmode)
: gen_rtx_REG (CCmode, FPSW_REGNUM));
*op1 = const0_rtx;
- mips_emit_binary (cmp_code, *op0, cmp_operands[0], cmp_operands[1]);
+ mips_emit_binary (cmp_code, *op0, cmp_op0, cmp_op1);
}
}
-/* Try comparing cmp_operands[0] and cmp_operands[1] using rtl code CODE.
- Store the result in TARGET and return true if successful.
+/* Try performing the comparison in OPERANDS[1], whose arms are OPERANDS[2]
+ and OPERAND[3]. Store the result in OPERANDS[0].
- On 64-bit targets, TARGET may be narrower than cmp_operands[0]. */
+ On 64-bit targets, the mode of the comparison and target will always be
+ SImode, thus possibly narrower than that of the comparison's operands. */
-bool
-mips_expand_scc (enum rtx_code code, rtx target)
+void
+mips_expand_scc (rtx operands[])
{
- if (GET_MODE_CLASS (GET_MODE (cmp_operands[0])) != MODE_INT)
- return false;
+ rtx target = operands[0];
+ enum rtx_code code = GET_CODE (operands[1]);
+ rtx op0 = operands[2];
+ rtx op1 = operands[3];
+
+ gcc_assert (GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT);
if (code == EQ || code == NE)
{
if (ISA_HAS_SEQ_SNE
- && reg_imm10_operand (cmp_operands[1], GET_MODE (cmp_operands[1])))
- mips_emit_binary (code, target, cmp_operands[0], cmp_operands[1]);
+ && reg_imm10_operand (op1, GET_MODE (op1)))
+ mips_emit_binary (code, target, op0, op1);
else
{
- rtx zie = mips_zero_if_equal (cmp_operands[0], cmp_operands[1]);
+ rtx zie = mips_zero_if_equal (op0, op1);
mips_emit_binary (code, target, zie, const0_rtx);
}
}
else
- mips_emit_int_order_test (code, 0, target,
- cmp_operands[0], cmp_operands[1]);
- return true;
+ mips_emit_int_order_test (code, 0, target, op0, op1);
}
-/* Compare cmp_operands[0] with cmp_operands[1] using comparison code
- CODE and jump to OPERANDS[0] if the condition holds. */
+/* Compare OPERANDS[1] with OPERANDS[2] using comparison code
+ CODE and jump to OPERANDS[3] if the condition holds. */
void
-mips_expand_conditional_branch (rtx *operands, enum rtx_code code)
+mips_expand_conditional_branch (rtx *operands)
{
- rtx op0, op1, condition;
+ enum rtx_code code = GET_CODE (operands[0]);
+ rtx op0 = operands[1];
+ rtx op1 = operands[2];
+ rtx condition;
mips_emit_compare (&code, &op0, &op1, TARGET_MIPS16);
condition = gen_rtx_fmt_ee (code, VOIDmode, op0, op1);
- emit_jump_insn (gen_condjump (condition, operands[0]));
+ emit_jump_insn (gen_condjump (condition, operands[3]));
}
/* Implement:
@@ -4359,35 +4358,36 @@ mips_expand_vcondv2sf (rtx dest, rtx true_src, rtx false_src,
cmp_result));
}
-/* Compare cmp_operands[0] with cmp_operands[1] using the code of
- OPERANDS[1]. Move OPERANDS[2] into OPERANDS[0] if the condition
- holds, otherwise move OPERANDS[3] into OPERANDS[0]. */
+/* Perform the comparison in OPERANDS[1]. Move OPERANDS[2] into OPERANDS[0]
+ if the condition holds, otherwise move OPERANDS[3] into OPERANDS[0]. */
void
mips_expand_conditional_move (rtx *operands)
{
- enum rtx_code code;
- rtx cond, op0, op1;
+ rtx cond;
+ enum rtx_code code = GET_CODE (operands[1]);
+ rtx op0 = XEXP (operands[1], 0);
+ rtx op1 = XEXP (operands[1], 1);
- code = GET_CODE (operands[1]);
mips_emit_compare (&code, &op0, &op1, true);
- cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1),
+ cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1);
emit_insn (gen_rtx_SET (VOIDmode, operands[0],
gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]), cond,
operands[2], operands[3])));
}
-/* Compare cmp_operands[0] with cmp_operands[1] using rtl code CODE,
- then trap if the condition holds. */
+/* Perform the comparison in COMPARISON, then trap if the condition holds. */
void
-mips_expand_conditional_trap (enum rtx_code code)
+mips_expand_conditional_trap (rtx comparison)
{
rtx op0, op1;
enum machine_mode mode;
+ enum rtx_code code;
/* MIPS conditional trap instructions don't have GT or LE flavors,
so we must swap the operands and convert to LT and GE respectively. */
+ code = GET_CODE (comparison);
switch (code)
{
case GT:
@@ -4395,17 +4395,17 @@ mips_expand_conditional_trap (enum rtx_code code)
case GTU:
case LEU:
code = swap_condition (code);
- op0 = cmp_operands[1];
- op1 = cmp_operands[0];
+ op0 = XEXP (comparison, 1);
+ op1 = XEXP (comparison, 0);
break;
default:
- op0 = cmp_operands[0];
- op1 = cmp_operands[1];
+ op0 = XEXP (comparison, 0);
+ op1 = XEXP (comparison, 1);
break;
}
- mode = GET_MODE (cmp_operands[0]);
+ mode = GET_MODE (XEXP (comparison, 0));
op0 = force_reg (mode, op0);
if (!arith_operand (op1, mode))
op1 = force_reg (mode, op1);
@@ -6396,7 +6396,7 @@ static void
mips_block_move_loop (rtx dest, rtx src, HOST_WIDE_INT length,
HOST_WIDE_INT bytes_per_iter)
{
- rtx label, src_reg, dest_reg, final_src;
+ rtx label, src_reg, dest_reg, final_src, test;
HOST_WIDE_INT leftover;
leftover = length % bytes_per_iter;
@@ -6423,11 +6423,11 @@ mips_block_move_loop (rtx dest, rtx src, HOST_WIDE_INT length,
mips_emit_move (dest_reg, plus_constant (dest_reg, bytes_per_iter));
/* Emit the loop condition. */
+ test = gen_rtx_NE (VOIDmode, src_reg, final_src);
if (Pmode == DImode)
- emit_insn (gen_cmpdi (src_reg, final_src));
+ emit_jump_insn (gen_cbranchdi4 (test, src_reg, final_src, label));
else
- emit_insn (gen_cmpsi (src_reg, final_src));
- emit_jump_insn (gen_bne (label));
+ emit_jump_insn (gen_cbranchsi4 (test, src_reg, final_src, label));
/* Mop up any left-over bytes. */
if (leftover)
diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h
index 5c68688ccce..301a26ec1ad 100644
--- a/gcc/config/mips/mips.h
+++ b/gcc/config/mips/mips.h
@@ -3432,7 +3432,6 @@ extern int mips_dbx_regno[];
extern int mips_dwarf_regno[];
extern bool mips_split_p[];
extern bool mips_split_hi_p[];
-extern GTY(()) rtx cmp_operands[2];
extern enum processor_type mips_arch; /* which cpu to codegen for */
extern enum processor_type mips_tune; /* which cpu to schedule for */
extern int mips_isa; /* architectural level */
diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md
index 95ba6ba2620..713bd834730 100644
--- a/gcc/config/mips/mips.md
+++ b/gcc/config/mips/mips.md
@@ -791,11 +791,6 @@
(DF "ISA_HAS_FP4 && TARGET_FLOAT64")
(V2SF "TARGET_SB1")])
-;; This code iterator allows all branch instructions to be generated from
-;; a single define_expand template.
-(define_code_iterator any_cond [unordered ordered unlt unge uneq ltgt unle ungt
- eq ne gt ge lt le gtu geu ltu leu])
-
;; This code iterator allows signed and unsigned widening multiplications
;; to use the same template.
(define_code_iterator any_extend [sign_extend zero_extend])
@@ -994,19 +989,15 @@
}
[(set_attr "type" "trap")])
-(define_expand "conditional_trap"
+(define_expand "ctrap<mode>4"
[(trap_if (match_operator 0 "comparison_operator"
- [(match_dup 2) (match_dup 3)])
- (match_operand 1 "const_int_operand"))]
+ [(match_operand:GPR 1 "reg_or_0_operand")
+ (match_operand:GPR 2 "arith_operand")])
+ (match_operand 3 "const_0_operand"))]
"ISA_HAS_COND_TRAP"
{
- if (GET_MODE_CLASS (GET_MODE (cmp_operands[0])) == MODE_INT
- && operands[1] == const0_rtx)
- {
- mips_expand_conditional_trap (GET_CODE (operands[0]));
- DONE;
- }
- FAIL;
+ mips_expand_conditional_trap (operands[0]);
+ DONE;
})
(define_insn "*conditional_trap<mode>"
@@ -3243,6 +3234,7 @@
rtx reg3 = gen_reg_rtx (SImode);
rtx label1 = gen_label_rtx ();
rtx label2 = gen_label_rtx ();
+ rtx test;
REAL_VALUE_TYPE offset;
real_2expN (&offset, 31, DFmode);
@@ -3252,8 +3244,8 @@
mips_emit_move (reg1, CONST_DOUBLE_FROM_REAL_VALUE (offset, DFmode));
do_pending_stack_adjust ();
- emit_insn (gen_cmpdf (operands[1], reg1));
- emit_jump_insn (gen_bge (label1));
+ test = gen_rtx_GE (VOIDmode, operands[1], reg1);
+ emit_jump_insn (gen_cbranchdf4 (test, operands[1], reg1, label1));
emit_insn (gen_fix_truncdfsi2 (operands[0], operands[1]));
emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
@@ -3288,6 +3280,7 @@
rtx reg3 = gen_reg_rtx (DImode);
rtx label1 = gen_label_rtx ();
rtx label2 = gen_label_rtx ();
+ rtx test;
REAL_VALUE_TYPE offset;
real_2expN (&offset, 63, DFmode);
@@ -3295,8 +3288,8 @@
mips_emit_move (reg1, CONST_DOUBLE_FROM_REAL_VALUE (offset, DFmode));
do_pending_stack_adjust ();
- emit_insn (gen_cmpdf (operands[1], reg1));
- emit_jump_insn (gen_bge (label1));
+ test = gen_rtx_GE (VOIDmode, operands[1], reg1);
+ emit_jump_insn (gen_cbranchdf4 (test, operands[1], reg1, label1));
emit_insn (gen_fix_truncdfdi2 (operands[0], operands[1]));
emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
@@ -3330,6 +3323,7 @@
rtx reg3 = gen_reg_rtx (SImode);
rtx label1 = gen_label_rtx ();
rtx label2 = gen_label_rtx ();
+ rtx test;
REAL_VALUE_TYPE offset;
real_2expN (&offset, 31, SFmode);
@@ -3337,8 +3331,8 @@
mips_emit_move (reg1, CONST_DOUBLE_FROM_REAL_VALUE (offset, SFmode));
do_pending_stack_adjust ();
- emit_insn (gen_cmpsf (operands[1], reg1));
- emit_jump_insn (gen_bge (label1));
+ test = gen_rtx_GE (VOIDmode, operands[1], reg1);
+ emit_jump_insn (gen_cbranchsf4 (test, operands[1], reg1, label1));
emit_insn (gen_fix_truncsfsi2 (operands[0], operands[1]));
emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
@@ -3372,6 +3366,7 @@
rtx reg3 = gen_reg_rtx (DImode);
rtx label1 = gen_label_rtx ();
rtx label2 = gen_label_rtx ();
+ rtx test;
REAL_VALUE_TYPE offset;
real_2expN (&offset, 63, SFmode);
@@ -3379,8 +3374,8 @@
mips_emit_move (reg1, CONST_DOUBLE_FROM_REAL_VALUE (offset, SFmode));
do_pending_stack_adjust ();
- emit_insn (gen_cmpsf (operands[1], reg1));
- emit_jump_insn (gen_bge (label1));
+ test = gen_rtx_GE (VOIDmode, operands[1], reg1);
+ emit_jump_insn (gen_cbranchsf4 (test, operands[1], reg1, label1));
emit_insn (gen_fix_truncsfdi2 (operands[0], operands[1]));
emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
@@ -5011,50 +5006,6 @@
;;
;; ....................
;;
-;; COMPARISONS
-;;
-;; ....................
-
-;; Flow here is rather complex:
-;;
-;; 1) The cmp{si,di,sf,df} routine is called. It deposits the arguments
-;; into cmp_operands[] but generates no RTL.
-;;
-;; 2) The appropriate branch define_expand is called, which then
-;; creates the appropriate RTL for the comparison and branch.
-;; Different CC modes are used, based on what type of branch is
-;; done, so that we can constrain things appropriately. There
-;; are assumptions in the rest of GCC that break if we fold the
-;; operands into the branches for integer operations, and use cc0
-;; for floating point, so we use the fp status register instead.
-;; If needed, an appropriate temporary is created to hold the
-;; of the integer compare.
-
-(define_expand "cmp<mode>"
- [(set (cc0)
- (compare:CC (match_operand:GPR 0 "register_operand")
- (match_operand:GPR 1 "nonmemory_operand")))]
- ""
-{
- cmp_operands[0] = operands[0];
- cmp_operands[1] = operands[1];
- DONE;
-})
-
-(define_expand "cmp<mode>"
- [(set (cc0)
- (compare:CC (match_operand:SCALARF 0 "register_operand")
- (match_operand:SCALARF 1 "register_operand")))]
- ""
-{
- cmp_operands[0] = operands[0];
- cmp_operands[1] = operands[1];
- DONE;
-})
-
-;;
-;; ....................
-;;
;; CONDITIONAL BRANCHES
;;
;; ....................
@@ -5189,15 +5140,29 @@
[(set_attr "type" "branch")
(set_attr "mode" "none")])
-(define_expand "b<code>"
+(define_expand "cbranch<mode>4"
[(set (pc)
- (if_then_else (any_cond:CC (cc0)
- (const_int 0))
- (label_ref (match_operand 0 ""))
+ (if_then_else (match_operator 0 "comparison_operator"
+ [(match_operand:GPR 1 "register_operand")
+ (match_operand:GPR 2 "nonmemory_operand")])
+ (label_ref (match_operand 3 ""))
(pc)))]
""
{
- mips_expand_conditional_branch (operands, <CODE>);
+ mips_expand_conditional_branch (operands);
+ DONE;
+})
+
+(define_expand "cbranch<mode>4"
+ [(set (pc)
+ (if_then_else (match_operator 0 "comparison_operator"
+ [(match_operand:SCALARF 1 "register_operand")
+ (match_operand:SCALARF 2 "register_operand")])
+ (label_ref (match_operand 3 ""))
+ (pc)))]
+ ""
+{
+ mips_expand_conditional_branch (operands);
DONE;
})
@@ -5261,12 +5226,16 @@
;; Destination is always set in SI mode.
-(define_expand "seq"
+(define_expand "cstore<mode>4"
[(set (match_operand:SI 0 "register_operand")
- (eq:SI (match_dup 1)
- (match_dup 2)))]
+ (match_operator:SI 1 "mips_cstore_operator"
+ [(match_operand:GPR 2 "register_operand")
+ (match_operand:GPR 3 "nonmemory_operand")]))]
""
- { if (mips_expand_scc (EQ, operands[0])) DONE; else FAIL; })
+{
+ mips_expand_scc (operands);
+ DONE;
+})
(define_insn "*seq_zero_<GPR:mode><GPR2:mode>"
[(set (match_operand:GPR2 0 "register_operand" "=d")
@@ -5299,16 +5268,6 @@
[(set_attr "type" "slt")
(set_attr "mode" "<GPR:MODE>")])
-;; "sne" uses sltu instructions in which the first operand is $0.
-;; This isn't possible in mips16 code.
-
-(define_expand "sne"
- [(set (match_operand:SI 0 "register_operand")
- (ne:SI (match_dup 1)
- (match_dup 2)))]
- "!TARGET_MIPS16"
- { if (mips_expand_scc (NE, operands[0])) DONE; else FAIL; })
-
(define_insn "*sne_zero_<GPR:mode><GPR2:mode>"
[(set (match_operand:GPR2 0 "register_operand" "=d")
(ne:GPR2 (match_operand:GPR 1 "register_operand" "d")
@@ -5331,13 +5290,6 @@
[(set_attr "type" "slt")
(set_attr "mode" "<GPR:MODE>")])
-(define_expand "sgt<u>"
- [(set (match_operand:SI 0 "register_operand")
- (any_gt:SI (match_dup 1)
- (match_dup 2)))]
- ""
- { if (mips_expand_scc (<CODE>, operands[0])) DONE; else FAIL; })
-
(define_insn "*sgt<u>_<GPR:mode><GPR2:mode>"
[(set (match_operand:GPR2 0 "register_operand" "=d")
(any_gt:GPR2 (match_operand:GPR 1 "register_operand" "d")
@@ -5356,13 +5308,6 @@
[(set_attr "type" "slt")
(set_attr "mode" "<GPR:MODE>")])
-(define_expand "sge<u>"
- [(set (match_operand:SI 0 "register_operand")
- (any_ge:SI (match_dup 1)
- (match_dup 2)))]
- ""
- { if (mips_expand_scc (<CODE>, operands[0])) DONE; else FAIL; })
-
(define_insn "*sge<u>_<GPR:mode><GPR2:mode>"
[(set (match_operand:GPR2 0 "register_operand" "=d")
(any_ge:GPR2 (match_operand:GPR 1 "register_operand" "d")
@@ -5372,13 +5317,6 @@
[(set_attr "type" "slt")
(set_attr "mode" "<GPR:MODE>")])
-(define_expand "slt<u>"
- [(set (match_operand:SI 0 "register_operand")
- (any_lt:SI (match_dup 1)
- (match_dup 2)))]
- ""
- { if (mips_expand_scc (<CODE>, operands[0])) DONE; else FAIL; })
-
(define_insn "*slt<u>_<GPR:mode><GPR2:mode>"
[(set (match_operand:GPR2 0 "register_operand" "=d")
(any_lt:GPR2 (match_operand:GPR 1 "register_operand" "d")
@@ -5402,13 +5340,6 @@
(const_int 4)
(const_int 8))])])
-(define_expand "sle<u>"
- [(set (match_operand:SI 0 "register_operand")
- (any_le:SI (match_dup 1)
- (match_dup 2)))]
- ""
- { if (mips_expand_scc (<CODE>, operands[0])) DONE; else FAIL; })
-
(define_insn "*sle<u>_<GPR:mode><GPR2:mode>"
[(set (match_operand:GPR2 0 "register_operand" "=d")
(any_le:GPR2 (match_operand:GPR 1 "register_operand" "d")
diff --git a/gcc/config/mips/predicates.md b/gcc/config/mips/predicates.md
index aaebdded674..d32eaf13f8e 100644
--- a/gcc/config/mips/predicates.md
+++ b/gcc/config/mips/predicates.md
@@ -285,6 +285,12 @@
(define_predicate "order_operator"
(match_code "lt,ltu,le,leu,ge,geu,gt,gtu"))
+;; For NE, cstore uses sltu instructions in which the first operand is $0.
+;; This isn't possible in mips16 code.
+
+(define_predicate "mips_cstore_operator"
+ (ior (match_code "eq,gt,gtu,ge,geu,lt,ltu,le,leu")
+ (and (match_code "ne") (match_test "!TARGET_MIPS16"))))
(define_predicate "small_data_pattern"
(and (match_code "set,parallel,unspec,unspec_volatile,prefetch")
diff --git a/gcc/config/mmix/mmix-protos.h b/gcc/config/mmix/mmix-protos.h
index d71064aa6d7..d294d8ff0ed 100644
--- a/gcc/config/mmix/mmix-protos.h
+++ b/gcc/config/mmix/mmix-protos.h
@@ -96,7 +96,6 @@ extern void mmix_setup_frame_addresses (void);
/* Needs to be ifdef:d for sake of enum rtx_code. */
extern enum machine_mode mmix_select_cc_mode (enum rtx_code, rtx, rtx);
extern void mmix_canonicalize_comparison (enum rtx_code *, rtx *, rtx *);
-extern int mmix_valid_comparison (enum rtx_code, enum machine_mode, rtx);
extern rtx mmix_gen_compare_reg (enum rtx_code, rtx, rtx);
#endif
diff --git a/gcc/config/mmix/mmix.c b/gcc/config/mmix/mmix.c
index ceed8dbb6db..6ced05c04dc 100644
--- a/gcc/config/mmix/mmix.c
+++ b/gcc/config/mmix/mmix.c
@@ -2359,70 +2359,14 @@ mmix_shiftable_wyde_value (unsigned HOST_WIDEST_INT value)
return 1;
}
-/* Returns zero if code and mode is not a valid condition from a
- compare-type insn. Nonzero if it is. The parameter op, if non-NULL,
- is the comparison of mode is CC-somethingmode. */
-
-int
-mmix_valid_comparison (RTX_CODE code, enum machine_mode mode, rtx op)
-{
- if (mode == VOIDmode && op != NULL_RTX)
- mode = GET_MODE (op);
-
- /* We don't care to look at these, they should always be valid. */
- if (mode == CCmode || mode == CC_UNSmode || mode == DImode)
- return 1;
-
- if ((mode == CC_FPmode || mode == DFmode)
- && (code == GT || code == LT))
- return 1;
-
- if ((mode == CC_FPEQmode || mode == DFmode)
- && (code == EQ || code == NE))
- return 1;
-
- if ((mode == CC_FUNmode || mode == DFmode)
- && (code == ORDERED || code == UNORDERED))
- return 1;
-
- return 0;
-}
-
-/* X and Y are two things to compare using CODE. Emit a compare insn if
- possible and return the rtx for the cc-reg in the proper mode, or
- NULL_RTX if this is not a valid comparison. */
+/* X and Y are two things to compare using CODE. Return the rtx for
+ the cc-reg in the proper mode. */
rtx
mmix_gen_compare_reg (RTX_CODE code, rtx x, rtx y)
{
enum machine_mode ccmode = SELECT_CC_MODE (code, x, y);
- rtx cc_reg;
-
- /* FIXME: Do we get constants here? Of double mode? */
- enum machine_mode mode
- = GET_MODE (x) == VOIDmode
- ? GET_MODE (y)
- : GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT ? DFmode : DImode;
-
- if (! mmix_valid_comparison (code, mode, x))
- return NULL_RTX;
-
- cc_reg = gen_reg_rtx (ccmode);
-
- /* FIXME: Can we avoid emitting a compare insn here? */
- if (! REG_P (x) && ! REG_P (y))
- x = force_reg (mode, x);
-
- /* If it's not quite right yet, put y in a register. */
- if (! REG_P (y)
- && (GET_CODE (y) != CONST_INT
- || ! CONST_OK_FOR_LETTER_P (INTVAL (y), 'I')))
- y = force_reg (mode, y);
-
- emit_insn (gen_rtx_SET (VOIDmode, cc_reg,
- gen_rtx_COMPARE (ccmode, x, y)));
-
- return cc_reg;
+ return gen_reg_rtx (ccmode);
}
/* Local (static) helper functions. */
diff --git a/gcc/config/mmix/mmix.h b/gcc/config/mmix/mmix.h
index a7fb6e5884e..5a0582df26b 100644
--- a/gcc/config/mmix/mmix.h
+++ b/gcc/config/mmix/mmix.h
@@ -81,11 +81,6 @@ along with GCC; see the file COPYING3. If not see
#define MMIX_FUNCTION_ARG_SIZE(MODE, TYPE) \
((MODE) != BLKmode ? GET_MODE_SIZE (MODE) : int_size_in_bytes (TYPE))
-/* Declarations for helper variables that are not tied to a particular
- target macro. */
-extern GTY(()) rtx mmix_compare_op0;
-extern GTY(()) rtx mmix_compare_op1;
-
/* Per-function machine data. This is normally an opaque type just
defined and used in the tm.c file, but we need to see the definition in
mmix.md too. */
diff --git a/gcc/config/mmix/mmix.md b/gcc/config/mmix/mmix.md
index aa878af0f82..44263e47f64 100644
--- a/gcc/config/mmix/mmix.md
+++ b/gcc/config/mmix/mmix.md
@@ -440,30 +440,6 @@ DIVU %1,%1,%2\;GET %0,:rR\;NEGU %2,0,%0\;CSNN %0,$255,%2")
""
"NOR %0,%1,0")
-;; Since we don't have cc0, we do what is recommended in the manual;
-;; store away the operands for use in the branch, scc or movcc insn.
-(define_expand "cmpdi"
- [(match_operand:DI 0 "register_operand" "")
- (match_operand:DI 1 "mmix_reg_or_8bit_operand" "")]
- ""
- "
-{
- mmix_compare_op0 = operands[0];
- mmix_compare_op1 = operands[1];
- DONE;
-}")
-
-(define_expand "cmpdf"
- [(match_operand:DF 0 "register_operand" "")
- (match_operand:DF 1 "register_operand" "")]
- ""
- "
-{
- mmix_compare_op0 = operands[0];
- mmix_compare_op1 = operands[1];
- DONE;
-}")
-
;; When the user-patterns expand, the resulting insns will match the
;; patterns below.
@@ -474,7 +450,7 @@ DIVU %1,%1,%2\;GET %0,:rR\;NEGU %2,0,%0\;CSNN %0,$255,%2")
;; unsigned, so that has to be done another way.
;; FIXME: Perhaps a peep2 changing CCcode to a new code, that
;; gets folded here.
-(define_insn "*cmpcc_folded"
+(define_insn "*cmpdi_folded"
[(set (match_operand:CC 0 "register_operand" "=r")
(compare:CC
(match_operand:DI 1 "register_operand" "r")
@@ -485,7 +461,7 @@ DIVU %1,%1,%2\;GET %0,:rR\;NEGU %2,0,%0\;CSNN %0,$255,%2")
&& REGNO (operands[1]) == REGNO (operands[0])"
"%% folded: cmp %0,%1,0")
-(define_insn "*cmpcc"
+(define_insn "*cmps"
[(set (match_operand:CC 0 "register_operand" "=r")
(compare:CC
(match_operand:DI 1 "register_operand" "r")
@@ -724,7 +700,8 @@ DIVU %1,%1,%2\;GET %0,:rR\;NEGU %2,0,%0\;CSNN %0,$255,%2")
;; 0 to use in movdfcc.
(define_expand "movdfcc"
- [(set (match_operand:DF 0 "register_operand" "")
+ [(set (match_dup 4) (match_dup 5))
+ (set (match_operand:DF 0 "register_operand" "")
(if_then_else:DF
(match_operand 1 "comparison_operator" "")
(match_operand:DF 2 "mmix_reg_or_0_operand" "")
@@ -733,15 +710,20 @@ DIVU %1,%1,%2\;GET %0,:rR\;NEGU %2,0,%0\;CSNN %0,$255,%2")
"
{
enum rtx_code code = GET_CODE (operands[1]);
- rtx cc_reg = mmix_gen_compare_reg (code, mmix_compare_op0,
- mmix_compare_op1);
- if (cc_reg == NULL_RTX)
+ if (code == LE || code == GE)
FAIL;
- operands[1] = gen_rtx_fmt_ee (code, VOIDmode, cc_reg, const0_rtx);
+
+ operands[4] = mmix_gen_compare_reg (code, XEXP (operands[1], 0),
+ XEXP (operands[1], 1));
+ operands[5] = gen_rtx_COMPARE (GET_MODE (operands[4]),
+ XEXP (operands[1], 0),
+ XEXP (operands[1], 1));
+ operands[1] = gen_rtx_fmt_ee (code, VOIDmode, operands[4], const0_rtx);
}")
(define_expand "movdicc"
- [(set (match_operand:DI 0 "register_operand" "")
+ [(set (match_dup 4) (match_dup 5))
+ (set (match_operand:DI 0 "register_operand" "")
(if_then_else:DI
(match_operand 1 "comparison_operator" "")
(match_operand:DI 2 "mmix_reg_or_8bit_operand" "")
@@ -750,11 +732,15 @@ DIVU %1,%1,%2\;GET %0,:rR\;NEGU %2,0,%0\;CSNN %0,$255,%2")
"
{
enum rtx_code code = GET_CODE (operands[1]);
- rtx cc_reg = mmix_gen_compare_reg (code, mmix_compare_op0,
- mmix_compare_op1);
- if (cc_reg == NULL_RTX)
+ if (code == LE || code == GE)
FAIL;
- operands[1] = gen_rtx_fmt_ee (code, VOIDmode, cc_reg, const0_rtx);
+
+ operands[4] = mmix_gen_compare_reg (code, XEXP (operands[1], 0),
+ XEXP (operands[1], 1));
+ operands[5] = gen_rtx_COMPARE (GET_MODE (operands[4]),
+ XEXP (operands[1], 0),
+ XEXP (operands[1], 1));
+ operands[1] = gen_rtx_fmt_ee (code, VOIDmode, operands[4], const0_rtx);
}")
;; FIXME: Is this the right way to do "folding" of CCmode -> DImode?
@@ -854,175 +840,65 @@ DIVU %1,%1,%2\;GET %0,:rR\;NEGU %2,0,%0\;CSNN %0,$255,%2")
CS%d2 %0,%3,%1
ZS%d2 %0,%3,%1")
-;; FIXME: scc patterns will probably help, I just skip them
+;; FIXME: scc insns will probably help, I just skip them
;; right now. Revisit.
-(define_expand "beq"
- [(set (pc)
- (if_then_else (eq (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- operands[1]
- = mmix_gen_compare_reg (EQ, mmix_compare_op0, mmix_compare_op1);
-}")
-
-(define_expand "bne"
- [(set (pc)
- (if_then_else (ne (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
+(define_expand "cbranchdi4"
+ [(set (match_dup 4)
+ (match_op_dup 5
+ [(match_operand:DI 1 "register_operand" "")
+ (match_operand:DI 2 "mmix_reg_or_8bit_operand" "")]))
+ (set (pc)
+ (if_then_else
+ (match_operator 0 "ordered_comparison_operator"
+ [(match_dup 4)
+ (const_int 0)])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
""
"
{
- operands[1]
- = mmix_gen_compare_reg (NE, mmix_compare_op0, mmix_compare_op1);
+ operands[4] = mmix_gen_compare_reg (GET_CODE (operands[0]),
+ operands[1], operands[2]);
+ operands[5] = gen_rtx_fmt_ee (COMPARE,
+ GET_MODE (operands[4]),
+ operands[1], operands[2]);
}")
-(define_expand "bgt"
- [(set (pc)
- (if_then_else (gt (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
+(define_expand "cbranchdf4"
+ [(set (match_dup 4)
+ (match_op_dup 5
+ [(match_operand:DF 1 "register_operand" "")
+ (match_operand:DF 2 "register_operand" "")]))
+ (set (pc)
+ (if_then_else
+ (match_operator 0 "float_comparison_operator"
+ [(match_dup 4)
+ (const_int 0)])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
""
"
{
- operands[1]
- = mmix_gen_compare_reg (GT, mmix_compare_op0, mmix_compare_op1);
-}")
-
-(define_expand "ble"
- [(set (pc)
- (if_then_else (le (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- operands[1]
- = mmix_gen_compare_reg (LE, mmix_compare_op0, mmix_compare_op1);
-
/* The head comment of optabs.c:can_compare_p says we're required to
implement this, so we have to clean up the mess here. */
- if (operands[1] == NULL_RTX)
+ if (GET_CODE (operands[0]) == LE || GET_CODE (operands[0]) == GE)
{
- /* FIXME: Watch out for sharing/unsharing of rtx:es. */
- emit_jump_insn ((*bcc_gen_fctn[(int) LT]) (operands[0]));
- emit_jump_insn ((*bcc_gen_fctn[(int) EQ]) (operands[0]));
+ enum rtx_code ltgt_code = GET_CODE (operands[0]) == LE ? LT : GT;
+ emit_cmp_and_jump_insns (operands[1], operands[2], ltgt_code, NULL_RTX,
+ DFmode, 0, operands[3]);
+ emit_cmp_and_jump_insns (operands[1], operands[2], EQ, NULL_RTX,
+ DFmode, 0, operands[3]);
DONE;
}
-}")
-
-(define_expand "bge"
- [(set (pc)
- (if_then_else (ge (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- operands[1]
- = mmix_gen_compare_reg (GE, mmix_compare_op0, mmix_compare_op1);
- /* The head comment of optabs.c:can_compare_p says we're required to
- implement this, so we have to clean up the mess here. */
- if (operands[1] == NULL_RTX)
- {
- /* FIXME: Watch out for sharing/unsharing of rtx:es. */
- emit_jump_insn ((*bcc_gen_fctn[(int) GT]) (operands[0]));
- emit_jump_insn ((*bcc_gen_fctn[(int) EQ]) (operands[0]));
- DONE;
- }
+ operands[4] = mmix_gen_compare_reg (GET_CODE (operands[0]),
+ operands[1], operands[2]);
+ operands[5] = gen_rtx_fmt_ee (COMPARE,
+ GET_MODE (operands[4]),
+ operands[1], operands[2]);
}")
-(define_expand "blt"
- [(set (pc)
- (if_then_else (lt (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- operands[1]
- = mmix_gen_compare_reg (LT, mmix_compare_op0, mmix_compare_op1);
-}")
-
-(define_expand "bgtu"
- [(set (pc)
- (if_then_else (gtu (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- operands[1]
- = mmix_gen_compare_reg (GTU, mmix_compare_op0, mmix_compare_op1);
-}")
-
-(define_expand "bleu"
- [(set (pc)
- (if_then_else (leu (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- operands[1]
- = mmix_gen_compare_reg (LEU, mmix_compare_op0, mmix_compare_op1);
-}")
-
-(define_expand "bgeu"
- [(set (pc)
- (if_then_else (geu (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- operands[1]
- = mmix_gen_compare_reg (GEU, mmix_compare_op0, mmix_compare_op1);
-}")
-
-(define_expand "bltu"
- [(set (pc)
- (if_then_else (ltu (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- operands[1]
- = mmix_gen_compare_reg (LTU, mmix_compare_op0, mmix_compare_op1);
-}")
-
-(define_expand "bunordered"
- [(set (pc)
- (if_then_else (unordered (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- operands[1]
- = mmix_gen_compare_reg (UNORDERED, mmix_compare_op0, mmix_compare_op1);
-
- if (operands[1] == NULL_RTX)
- FAIL;
-}")
-
-(define_expand "bordered"
- [(set (pc)
- (if_then_else (ordered (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- operands[1]
- = mmix_gen_compare_reg (ORDERED, mmix_compare_op0, mmix_compare_op1);
-}")
;; FIXME: we can emit an unordered-or-*not*-equal compare in one insn, but
;; there's no RTL code for it. Maybe revisit in future.
diff --git a/gcc/config/mmix/predicates.md b/gcc/config/mmix/predicates.md
index 5c5792e1f6b..b5773b87aee 100644
--- a/gcc/config/mmix/predicates.md
+++ b/gcc/config/mmix/predicates.md
@@ -17,6 +17,11 @@
;; along with GCC; see the file COPYING3. If not see
;; <http://www.gnu.org/licenses/>.
+;; Return 1 if OP is a valid comparison operator for "cbranch" instructions.
+;; LE and GE are further lowered by the cbranchdf4 pattern.
+(define_predicate "float_comparison_operator"
+ (match_code "ne, eq, le, ge, lt, gt, ordered, unordered"))
+
;; True if this is a foldable comparison operator
;; - one where a the result of (compare:CC (reg) (const_int 0)) can be
;; replaced by (reg). */
diff --git a/gcc/config/mn10300/mn10300.c b/gcc/config/mn10300/mn10300.c
index ceb77e862c2..47fd5cbf933 100644
--- a/gcc/config/mn10300/mn10300.c
+++ b/gcc/config/mn10300/mn10300.c
@@ -2030,7 +2030,7 @@ mn10300_rtx_costs (rtx x, int code, int outer_code, int *total, bool speed ATTRI
{
case CONST_INT:
/* Zeros are extremely cheap. */
- if (INTVAL (x) == 0 && outer_code == SET)
+ if (INTVAL (x) == 0 && (outer_code == SET || outer_code == COMPARE))
*total = 0;
/* If it fits in 8 bits, then it's still relatively cheap. */
else if (INT_8_BITS (INTVAL (x)))
@@ -2059,6 +2059,12 @@ mn10300_rtx_costs (rtx x, int code, int outer_code, int *total, bool speed ATTRI
*total = 8;
return true;
+ case ZERO_EXTRACT:
+ /* This is cheap, we can use btst. */
+ if (outer_code == COMPARE)
+ *total = 0;
+ return false;
+
/* ??? This probably needs more work. */
case MOD:
case DIV:
diff --git a/gcc/config/mn10300/mn10300.md b/gcc/config/mn10300/mn10300.md
index 35b0e589cb5..a2b6296912f 100644
--- a/gcc/config/mn10300/mn10300.md
+++ b/gcc/config/mn10300/mn10300.md
@@ -826,34 +826,34 @@
;; TEST INSTRUCTIONS
;; ----------------------------------------------------------------------
-;; Go ahead and define tstsi so we can eliminate redundant tst insns
-;; when we start trying to optimize this port.
-(define_insn "tstsi"
- [(set (cc0) (match_operand:SI 0 "register_operand" "dax"))]
- ""
- "* return output_tst (operands[0], insn);"
- [(set_attr "cc" "set_znv")])
-
-(define_insn ""
- [(set (cc0) (zero_extend:SI (match_operand:QI 0 "memory_operand" "dx,!a")))]
+(define_insn "*tst_extqisi_am33"
+ [(set (cc0) (compare
+ (zero_extend:SI (match_operand:QI 0 "memory_operand" "dx,!a"))
+ (const_int 0)))]
"TARGET_AM33"
"* return output_tst (operands[0], insn);"
[(set_attr "cc" "set_znv")])
-(define_insn ""
- [(set (cc0) (zero_extend:SI (match_operand:QI 0 "memory_operand" "dx")))]
+(define_insn "*tst_extqisi"
+ [(set (cc0) (compare
+ (zero_extend:SI (match_operand:QI 0 "memory_operand" "dx"))
+ (const_int 0)))]
""
"* return output_tst (operands[0], insn);"
[(set_attr "cc" "set_znv")])
-(define_insn ""
- [(set (cc0) (zero_extend:SI (match_operand:HI 0 "memory_operand" "dx,!a")))]
+(define_insn "*tst_exthisi_am33"
+ [(set (cc0) (compare
+ (zero_extend:SI (match_operand:HI 0 "memory_operand" "dx,!a"))
+ (const_int 0)))]
"TARGET_AM33"
"* return output_tst (operands[0], insn);"
[(set_attr "cc" "set_znv")])
-(define_insn ""
- [(set (cc0) (zero_extend:SI (match_operand:HI 0 "memory_operand" "dx")))]
+(define_insn "*tst_exthisi"
+ [(set (cc0) (compare
+ (zero_extend:SI (match_operand:HI 0 "memory_operand" "dx"))
+ (const_int 0)))]
""
"* return output_tst (operands[0], insn);"
[(set_attr "cc" "set_znv")])
@@ -874,17 +874,22 @@
;; possibly satisfied, so just mark the alternative with a `!', so
;; that it is not considered by reload.
-(define_insn "cmpsi"
+(define_insn "*cmpsi"
[(set (cc0)
- (compare (match_operand:SI 0 "register_operand" "!*d*a*x,dax")
- (match_operand:SI 1 "nonmemory_operand" "*0,daxi")))]
+ (compare (match_operand:SI 0 "register_operand" "!*d*a*x,dax,dax")
+ (match_operand:SI 1 "nonmemory_operand" "*0,I,daxi")))]
""
- "@
- btst 0,d0
- cmp %1,%0"
- [(set_attr "cc" "compare,compare")])
+ "*
+{
+ if (which_alternative == 0)
+ return \"btst 0,d0\";
+ if (which_alternative == 1)
+ return output_tst (operands[0], insn);
+ return \"cmp %1,%0\";
+}"
+ [(set_attr "cc" "compare,set_znv,compare")])
-(define_insn "cmpsf"
+(define_insn "*cmpsf"
[(set (cc0)
(compare (match_operand:SF 0 "register_operand" "f,f")
(match_operand:SF 1 "nonmemory_operand" "f,F")))]
@@ -1510,9 +1515,10 @@
(define_insn ""
[(set (cc0)
- (zero_extract:SI (match_operand:SI 0 "register_operand" "dx")
- (match_operand 1 "const_int_operand" "")
- (match_operand 2 "const_int_operand" "")))]
+ (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "dx")
+ (match_operand 1 "const_int_operand" "")
+ (match_operand 2 "const_int_operand" ""))
+ (const_int 0)))]
""
"*
{
@@ -1537,9 +1543,10 @@
(define_insn ""
[(set (cc0)
- (zero_extract:SI (match_operand:QI 0 "general_operand" "R,dx")
- (match_operand 1 "const_int_operand" "")
- (match_operand 2 "const_int_operand" "")))]
+ (compare (zero_extract:SI (match_operand:QI 0 "general_operand" "R,dx")
+ (match_operand 1 "const_int_operand" "")
+ (match_operand 2 "const_int_operand" ""))
+ (const_int 0)))]
"mask_ok_for_mem_btst (INTVAL (operands[1]), INTVAL (operands[2]))"
"*
{
@@ -1581,17 +1588,19 @@
[(set_attr "cc" "clobber")])
(define_insn ""
- [(set (cc0) (and:SI (match_operand:SI 0 "register_operand" "dx")
- (match_operand:SI 1 "const_int_operand" "")))]
+ [(set (cc0) (compare (and:SI (match_operand:SI 0 "register_operand" "dx")
+ (match_operand:SI 1 "const_int_operand" ""))
+ (const_int 0)))]
""
"btst %1,%0"
[(set_attr "cc" "clobber")])
(define_insn ""
[(set (cc0)
- (and:SI
- (subreg:SI (match_operand:QI 0 "general_operand" "R,dx") 0)
- (match_operand:SI 1 "const_8bit_operand" "")))]
+ (compare (and:SI
+ (subreg:SI (match_operand:QI 0 "general_operand" "R,dx") 0)
+ (match_operand:SI 1 "const_8bit_operand" ""))
+ (const_int 0)))]
""
"@
btst %U1,%A0
@@ -1603,97 +1612,34 @@
;; JUMP INSTRUCTIONS
;; ----------------------------------------------------------------------
-;; Conditional jump instructions
-
-(define_expand "ble"
- [(set (pc)
- (if_then_else (le (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "bleu"
- [(set (pc)
- (if_then_else (leu (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "bge"
- [(set (pc)
- (if_then_else (ge (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "bgeu"
- [(set (pc)
- (if_then_else (geu (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "blt"
- [(set (pc)
- (if_then_else (lt (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "bltu"
- [(set (pc)
- (if_then_else (ltu (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "bgt"
- [(set (pc)
- (if_then_else (gt (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
+(define_expand "cbranchsi4"
+ [(set (cc0)
+ (compare (match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "nonmemory_operand" "")))
+ (set (pc)
+ (if_then_else
+ (match_operator 0 "ordered_comparison_operator" [(cc0)
+ (const_int 0)])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
""
"")
-(define_expand "bgtu"
- [(set (pc)
- (if_then_else (gtu (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
+(define_expand "cbranchsf4"
+ [(set (cc0)
+ (compare (match_operand:SF 1 "register_operand" "")
+ (match_operand:SF 2 "nonmemory_operand" "")))
+ (set (pc)
+ (if_then_else
+ (match_operator 0 "ordered_comparison_operator" [(cc0)
+ (const_int 0)])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
+ "TARGET_AM33_2"
"")
-(define_expand "beq"
- [(set (pc)
- (if_then_else (eq (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-(define_expand "bne"
- [(set (pc)
- (if_then_else (ne (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
+;; Conditional jump instructions
(define_insn ""
[(set (pc)
@@ -1774,11 +1720,13 @@
rtx table = gen_reg_rtx (SImode);
rtx index = gen_reg_rtx (SImode);
rtx addr = gen_reg_rtx (Pmode);
+ rtx test;
emit_move_insn (table, gen_rtx_LABEL_REF (VOIDmode, operands[3]));
emit_move_insn (index, plus_constant (operands[0], - INTVAL (operands[1])));
- emit_insn (gen_cmpsi (index, operands[2]));
- emit_jump_insn (gen_bgtu (operands[4]));
+ test = gen_rtx_fmt_ee (GTU, VOIDmode, index, operands[2]);
+ emit_jump_insn (gen_cbranchsi4 (test, index, operands[2], operands[4]));
+
emit_move_insn (index, gen_rtx_ASHIFT (SImode, index, const2_rtx));
emit_move_insn (addr, gen_rtx_MEM (SImode,
gen_rtx_PLUS (SImode, table, index)));
@@ -2518,7 +2466,8 @@
;; This will work on the mn10200 because we can check the ZX flag
;; if the comparison is in HImode.
(define_peephole
- [(set (cc0) (match_operand:SI 0 "register_operand" "dx"))
+ [(set (cc0) (compare (match_operand:SI 0 "register_operand" "dx")
+ (const_int 0)))
(set (pc) (if_then_else (ge (cc0) (const_int 0))
(match_operand 1 "" "")
(pc)))]
@@ -2527,7 +2476,8 @@
[(set_attr "cc" "clobber")])
(define_peephole
- [(set (cc0) (match_operand:SI 0 "register_operand" "dx"))
+ [(set (cc0) (compare (match_operand:SI 0 "register_operand" "dx")
+ (const_int 0)))
(set (pc) (if_then_else (lt (cc0) (const_int 0))
(match_operand 1 "" "")
(pc)))]
@@ -2536,7 +2486,8 @@
[(set_attr "cc" "clobber")])
(define_peephole
- [(set (cc0) (match_operand:SI 0 "register_operand" "dx"))
+ [(set (cc0) (compare (match_operand:SI 0 "register_operand" "dx")
+ (const_int 0)))
(set (pc) (if_then_else (ge (cc0) (const_int 0))
(pc)
(match_operand 1 "" "")))]
@@ -2545,7 +2496,8 @@
[(set_attr "cc" "clobber")])
(define_peephole
- [(set (cc0) (match_operand:SI 0 "register_operand" "dx"))
+ [(set (cc0) (compare (match_operand:SI 0 "register_operand" "dx")
+ (const_int 0)))
(set (pc) (if_then_else (lt (cc0) (const_int 0))
(pc)
(match_operand 1 "" "")))]
diff --git a/gcc/config/pa/pa-protos.h b/gcc/config/pa/pa-protos.h
index 3cd1f8580bc..526081acd52 100644
--- a/gcc/config/pa/pa-protos.h
+++ b/gcc/config/pa/pa-protos.h
@@ -56,7 +56,6 @@ extern void output_arg_descriptor (rtx);
extern void output_global_address (FILE *, rtx, int);
extern void print_operand (FILE *, rtx, int);
extern rtx legitimize_pic_address (rtx, enum machine_mode, rtx);
-extern struct rtx_def *gen_cmp_fp (enum rtx_code, rtx, rtx);
extern void hppa_encode_label (rtx);
extern int arith11_operand (rtx, enum machine_mode);
extern int adddi3_operand (rtx, enum machine_mode);
@@ -96,7 +95,7 @@ extern int fmpyaddoperands (rtx *);
extern int fmpysuboperands (rtx *);
extern int call_operand_address (rtx, enum machine_mode);
extern int ior_operand (rtx, enum machine_mode);
-extern void emit_bcond_fp (enum rtx_code, rtx);
+extern void emit_bcond_fp (rtx[]);
extern int emit_move_sequence (rtx *, enum machine_mode, rtx);
extern int emit_hpdiv_const (rtx *, int);
extern int is_function_label_plus_const (rtx);
diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c
index 80f5fe90bc2..882fac1aad4 100644
--- a/gcc/config/pa/pa.c
+++ b/gcc/config/pa/pa.c
@@ -165,11 +165,6 @@ static GTY(()) section *som_readonly_data_section;
static GTY(()) section *som_one_only_readonly_data_section;
static GTY(()) section *som_one_only_data_section;
-/* Save the operands last given to a compare for use when we
- generate a scc or bcc insn. */
-rtx hppa_compare_op0, hppa_compare_op1;
-enum cmp_type hppa_branch_type;
-
/* Which cpu we are scheduling for. */
enum processor_type pa_cpu = TARGET_SCHED_DEFAULT;
@@ -4383,6 +4378,19 @@ return_addr_rtx (int count, rtx frameaddr)
rtx saved_rp;
rtx ins;
+ /* Instruction stream at the normal return address for the export stub:
+
+ 0x4bc23fd1 | stub+8: ldw -18(sr0,sp),rp
+ 0x004010a1 | stub+12: ldsid (sr0,rp),r1
+ 0x00011820 | stub+16: mtsp r1,sr0
+ 0xe0400002 | stub+20: be,n 0(sr0,rp)
+
+ 0xe0400002 must be specified as -532676606 so that it won't be
+ rejected as an invalid immediate operand on 64-bit hosts. */
+
+ HOST_WIDE_INT insns[4] = {0x4bc23fd1, 0x004010a1, 0x00011820, -532676606};
+ int i;
+
if (count != 0)
return NULL_RTX;
@@ -4391,6 +4399,9 @@ return_addr_rtx (int count, rtx frameaddr)
if (TARGET_64BIT || TARGET_NO_SPACE_REGS)
return rp;
+ /* If there is no export stub then just use the value saved from
+ the return pointer register. */
+
saved_rp = gen_reg_rtx (Pmode);
emit_move_insn (saved_rp, rp);
@@ -4402,37 +4413,15 @@ return_addr_rtx (int count, rtx frameaddr)
label = gen_label_rtx ();
/* Check the instruction stream at the normal return address for the
- export stub:
-
- 0x4bc23fd1 | stub+8: ldw -18(sr0,sp),rp
- 0x004010a1 | stub+12: ldsid (sr0,rp),r1
- 0x00011820 | stub+16: mtsp r1,sr0
- 0xe0400002 | stub+20: be,n 0(sr0,rp)
+ export stub. If it is an export stub, than our return address is
+ really in -24[frameaddr]. */
- If it is an export stub, than our return address is really in
- -24[frameaddr]. */
-
- emit_cmp_insn (gen_rtx_MEM (SImode, ins), GEN_INT (0x4bc23fd1), NE,
- NULL_RTX, SImode, 1);
- emit_jump_insn (gen_bne (label));
-
- emit_cmp_insn (gen_rtx_MEM (SImode, plus_constant (ins, 4)),
- GEN_INT (0x004010a1), NE, NULL_RTX, SImode, 1);
- emit_jump_insn (gen_bne (label));
-
- emit_cmp_insn (gen_rtx_MEM (SImode, plus_constant (ins, 8)),
- GEN_INT (0x00011820), NE, NULL_RTX, SImode, 1);
- emit_jump_insn (gen_bne (label));
-
- /* 0xe0400002 must be specified as -532676606 so that it won't be
- rejected as an invalid immediate operand on 64-bit hosts. */
- emit_cmp_insn (gen_rtx_MEM (SImode, plus_constant (ins, 12)),
- GEN_INT (-532676606), NE, NULL_RTX, SImode, 1);
-
- /* If there is no export stub then just use the value saved from
- the return pointer register. */
-
- emit_jump_insn (gen_bne (label));
+ for (i = 0; i < 3; i++)
+ {
+ rtx op0 = gen_rtx_MEM (SImode, plus_constant (ins, i * 4));
+ rtx op1 = GEN_INT (insns[i]);
+ emit_cmp_and_jump_insns (op0, op1, NE, NULL, SImode, 0, label);
+ }
/* Here we know that our return address points to an export
stub. We don't want to return the address of the export stub,
@@ -4446,30 +4435,32 @@ return_addr_rtx (int count, rtx frameaddr)
-24))));
emit_label (label);
+
return saved_rp;
}
void
-emit_bcond_fp (enum rtx_code code, rtx operand0)
+emit_bcond_fp (rtx operands[])
{
+ enum rtx_code code = GET_CODE (operands[0]);
+ rtx operand0 = operands[1];
+ rtx operand1 = operands[2];
+ rtx label = operands[3];
+
+ emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_REG (CCFPmode, 0),
+ gen_rtx_fmt_ee (code, CCFPmode, operand0, operand1)));
+
emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
gen_rtx_IF_THEN_ELSE (VOIDmode,
- gen_rtx_fmt_ee (code,
+ gen_rtx_fmt_ee (NE,
VOIDmode,
gen_rtx_REG (CCFPmode, 0),
const0_rtx),
- gen_rtx_LABEL_REF (VOIDmode, operand0),
+ gen_rtx_LABEL_REF (VOIDmode, label),
pc_rtx)));
}
-rtx
-gen_cmp_fp (enum rtx_code code, rtx operand0, rtx operand1)
-{
- return gen_rtx_SET (VOIDmode, gen_rtx_REG (CCFPmode, 0),
- gen_rtx_fmt_ee (code, CCFPmode, operand0, operand1));
-}
-
/* Adjust the cost of a scheduling dependency. Return the new cost of
a dependency LINK or INSN on DEP_INSN. COST is the current cost. */
diff --git a/gcc/config/pa/pa.h b/gcc/config/pa/pa.h
index 303bdd341df..576916f5b7b 100644
--- a/gcc/config/pa/pa.h
+++ b/gcc/config/pa/pa.h
@@ -21,14 +21,6 @@ You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
-enum cmp_type /* comparison type */
-{
- CMP_SI, /* compare integers */
- CMP_SF, /* compare single precision floats */
- CMP_DF, /* compare double precision floats */
- CMP_MAX /* max comparison type */
-};
-
/* For long call handling. */
extern unsigned long total_code_bytes;
@@ -755,10 +747,6 @@ struct hppa_args {int words, nargs_prototype, incoming, indirect; };
? PARM_BOUNDARY : MAX_PARM_BOUNDARY)
-extern GTY(()) rtx hppa_compare_op0;
-extern GTY(()) rtx hppa_compare_op1;
-extern enum cmp_type hppa_branch_type;
-
/* On HPPA, we emit profiling code as rtl via PROFILE_HOOK rather than
as assembly via FUNCTION_PROFILER. Just output a local label.
We can't use the function label because the GAS SOM target can't
diff --git a/gcc/config/pa/pa.md b/gcc/config/pa/pa.md
index b845182d592..1f5a69b9352 100644
--- a/gcc/config/pa/pa.md
+++ b/gcc/config/pa/pa.md
@@ -653,64 +653,6 @@
;; Compare instructions.
;; This controls RTL generation and register allocation.
-;; We generate RTL for comparisons and branches by having the cmpxx
-;; patterns store away the operands. Then, the scc and bcc patterns
-;; emit RTL for both the compare and the branch.
-;;
-
-(define_expand "cmpdi"
- [(set (reg:CC 0)
- (compare:CC (match_operand:DI 0 "reg_or_0_operand" "")
- (match_operand:DI 1 "register_operand" "")))]
- "TARGET_64BIT"
-
- "
-{
- hppa_compare_op0 = operands[0];
- hppa_compare_op1 = operands[1];
- hppa_branch_type = CMP_SI;
- DONE;
-}")
-
-(define_expand "cmpsi"
- [(set (reg:CC 0)
- (compare:CC (match_operand:SI 0 "reg_or_0_operand" "")
- (match_operand:SI 1 "arith5_operand" "")))]
- ""
- "
-{
- hppa_compare_op0 = operands[0];
- hppa_compare_op1 = operands[1];
- hppa_branch_type = CMP_SI;
- DONE;
-}")
-
-(define_expand "cmpsf"
- [(set (reg:CCFP 0)
- (compare:CCFP (match_operand:SF 0 "reg_or_0_operand" "")
- (match_operand:SF 1 "reg_or_0_operand" "")))]
- "! TARGET_SOFT_FLOAT"
- "
-{
- hppa_compare_op0 = operands[0];
- hppa_compare_op1 = operands[1];
- hppa_branch_type = CMP_SF;
- DONE;
-}")
-
-(define_expand "cmpdf"
- [(set (reg:CCFP 0)
- (compare:CCFP (match_operand:DF 0 "reg_or_0_operand" "")
- (match_operand:DF 1 "reg_or_0_operand" "")))]
- "! TARGET_SOFT_FLOAT"
- "
-{
- hppa_compare_op0 = operands[0];
- hppa_compare_op1 = operands[1];
- hppa_branch_type = CMP_DF;
- DONE;
-}")
-
(define_insn ""
[(set (reg:CCFP 0)
(match_operator:CCFP 2 "comparison_operator"
@@ -767,143 +709,13 @@
;; scc insns.
-(define_expand "seq"
- [(set (match_operand:SI 0 "register_operand" "")
- (eq:SI (match_dup 1)
- (match_dup 2)))]
- "!TARGET_64BIT"
- "
-{
- /* fp scc patterns rarely match, and are not a win on the PA. */
- if (hppa_branch_type != CMP_SI)
- FAIL;
- /* set up operands from compare. */
- operands[1] = hppa_compare_op0;
- operands[2] = hppa_compare_op1;
- /* fall through and generate default code */
-}")
-
-(define_expand "sne"
- [(set (match_operand:SI 0 "register_operand" "")
- (ne:SI (match_dup 1)
- (match_dup 2)))]
- "!TARGET_64BIT"
- "
-{
- /* fp scc patterns rarely match, and are not a win on the PA. */
- if (hppa_branch_type != CMP_SI)
- FAIL;
- operands[1] = hppa_compare_op0;
- operands[2] = hppa_compare_op1;
-}")
-
-(define_expand "slt"
- [(set (match_operand:SI 0 "register_operand" "")
- (lt:SI (match_dup 1)
- (match_dup 2)))]
- "!TARGET_64BIT"
- "
-{
- /* fp scc patterns rarely match, and are not a win on the PA. */
- if (hppa_branch_type != CMP_SI)
- FAIL;
- operands[1] = hppa_compare_op0;
- operands[2] = hppa_compare_op1;
-}")
-
-(define_expand "sgt"
- [(set (match_operand:SI 0 "register_operand" "")
- (gt:SI (match_dup 1)
- (match_dup 2)))]
- "!TARGET_64BIT"
- "
-{
- /* fp scc patterns rarely match, and are not a win on the PA. */
- if (hppa_branch_type != CMP_SI)
- FAIL;
- operands[1] = hppa_compare_op0;
- operands[2] = hppa_compare_op1;
-}")
-
-(define_expand "sle"
- [(set (match_operand:SI 0 "register_operand" "")
- (le:SI (match_dup 1)
- (match_dup 2)))]
- "!TARGET_64BIT"
- "
-{
- /* fp scc patterns rarely match, and are not a win on the PA. */
- if (hppa_branch_type != CMP_SI)
- FAIL;
- operands[1] = hppa_compare_op0;
- operands[2] = hppa_compare_op1;
-}")
-
-(define_expand "sge"
- [(set (match_operand:SI 0 "register_operand" "")
- (ge:SI (match_dup 1)
- (match_dup 2)))]
- "!TARGET_64BIT"
- "
-{
- /* fp scc patterns rarely match, and are not a win on the PA. */
- if (hppa_branch_type != CMP_SI)
- FAIL;
- operands[1] = hppa_compare_op0;
- operands[2] = hppa_compare_op1;
-}")
-
-(define_expand "sltu"
- [(set (match_operand:SI 0 "register_operand" "")
- (ltu:SI (match_dup 1)
- (match_dup 2)))]
+(define_expand "cstoresi4"
+ [(set (match_operand:SI 0 "register_operand")
+ (match_operator:SI 1 "ordered_comparison_operator"
+ [(match_operand:SI 2 "reg_or_0_operand" "")
+ (match_operand:SI 3 "arith5_operand" "")]))]
"!TARGET_64BIT"
- "
-{
- if (hppa_branch_type != CMP_SI)
- FAIL;
- operands[1] = hppa_compare_op0;
- operands[2] = hppa_compare_op1;
-}")
-
-(define_expand "sgtu"
- [(set (match_operand:SI 0 "register_operand" "")
- (gtu:SI (match_dup 1)
- (match_dup 2)))]
- "!TARGET_64BIT"
- "
-{
- if (hppa_branch_type != CMP_SI)
- FAIL;
- operands[1] = hppa_compare_op0;
- operands[2] = hppa_compare_op1;
-}")
-
-(define_expand "sleu"
- [(set (match_operand:SI 0 "register_operand" "")
- (leu:SI (match_dup 1)
- (match_dup 2)))]
- "!TARGET_64BIT"
- "
-{
- if (hppa_branch_type != CMP_SI)
- FAIL;
- operands[1] = hppa_compare_op0;
- operands[2] = hppa_compare_op1;
-}")
-
-(define_expand "sgeu"
- [(set (match_operand:SI 0 "register_operand" "")
- (geu:SI (match_dup 1)
- (match_dup 2)))]
- "!TARGET_64BIT"
- "
-{
- if (hppa_branch_type != CMP_SI)
- FAIL;
- operands[1] = hppa_compare_op0;
- operands[2] = hppa_compare_op1;
-}")
+ "")
;; Instruction canonicalization puts immediate operands second, which
;; is the reverse of what we want.
@@ -1346,28 +1158,15 @@
(define_expand "movsicc"
[(set (match_operand:SI 0 "register_operand" "")
(if_then_else:SI
- (match_operator 1 "comparison_operator"
- [(match_dup 4)
- (match_dup 5)])
+ (match_operand 1 "comparison_operator" "")
(match_operand:SI 2 "reg_or_cint_move_operand" "")
(match_operand:SI 3 "reg_or_cint_move_operand" "")))]
""
"
{
- enum rtx_code code = GET_CODE (operands[1]);
-
- if (hppa_branch_type != CMP_SI)
+ if (GET_MODE (XEXP (operands[1], 0)) != SImode
+ || GET_MODE (XEXP (operands[1], 0)) != GET_MODE (XEXP (operands[1], 1)))
FAIL;
-
- if (GET_MODE (hppa_compare_op0) != GET_MODE (hppa_compare_op1)
- || GET_MODE (hppa_compare_op0) != GET_MODE (operands[0]))
- FAIL;
-
- /* operands[1] is currently the result of compare_from_rtx. We want to
- emit a compare of the original operands. */
- operands[1] = gen_rtx_fmt_ee (code, SImode, hppa_compare_op0, hppa_compare_op1);
- operands[4] = hppa_compare_op0;
- operands[5] = hppa_compare_op1;
}")
;; We used to accept any register for op1.
@@ -1419,28 +1218,15 @@
(define_expand "movdicc"
[(set (match_operand:DI 0 "register_operand" "")
(if_then_else:DI
- (match_operator 1 "comparison_operator"
- [(match_dup 4)
- (match_dup 5)])
+ (match_operand 1 "comparison_operator" "")
(match_operand:DI 2 "reg_or_cint_move_operand" "")
(match_operand:DI 3 "reg_or_cint_move_operand" "")))]
"TARGET_64BIT"
"
{
- enum rtx_code code = GET_CODE (operands[1]);
-
- if (hppa_branch_type != CMP_SI)
+ if (GET_MODE (XEXP (operands[1], 0)) != DImode
+ || GET_MODE (XEXP (operands[1], 0)) != GET_MODE (XEXP (operands[1], 1)))
FAIL;
-
- if (GET_MODE (hppa_compare_op0) != GET_MODE (hppa_compare_op1)
- || GET_MODE (hppa_compare_op0) != GET_MODE (operands[0]))
- FAIL;
-
- /* operands[1] is currently the result of compare_from_rtx. We want to
- emit a compare of the original operands. */
- operands[1] = gen_rtx_fmt_ee (code, DImode, hppa_compare_op0, hppa_compare_op1);
- operands[4] = hppa_compare_op0;
- operands[5] = hppa_compare_op1;
}")
; We need the first constraint alternative in order to avoid
@@ -1486,289 +1272,52 @@
;; Conditional Branches
-(define_expand "beq"
- [(set (pc)
- (if_then_else (eq (match_dup 1) (match_dup 2))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- if (hppa_branch_type != CMP_SI)
- {
- emit_insn (gen_cmp_fp (EQ, hppa_compare_op0, hppa_compare_op1));
- emit_bcond_fp (NE, operands[0]);
- DONE;
- }
- /* set up operands from compare. */
- operands[1] = hppa_compare_op0;
- operands[2] = hppa_compare_op1;
- /* fall through and generate default code */
-}")
-
-(define_expand "bne"
- [(set (pc)
- (if_then_else (ne (match_dup 1) (match_dup 2))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- if (hppa_branch_type != CMP_SI)
- {
- emit_insn (gen_cmp_fp (NE, hppa_compare_op0, hppa_compare_op1));
- emit_bcond_fp (NE, operands[0]);
- DONE;
- }
- operands[1] = hppa_compare_op0;
- operands[2] = hppa_compare_op1;
-}")
-
-(define_expand "bgt"
+(define_expand "cbranchdi4"
[(set (pc)
- (if_then_else (gt (match_dup 1) (match_dup 2))
- (label_ref (match_operand 0 "" ""))
+ (if_then_else (match_operator 0 "ordered_comparison_operator"
+ [(match_operand:DI 1 "reg_or_0_operand" "")
+ (match_operand:DI 2 "register_operand" "")])
+ (label_ref (match_operand 3 "" ""))
(pc)))]
- ""
- "
-{
- if (hppa_branch_type != CMP_SI)
- {
- emit_insn (gen_cmp_fp (GT, hppa_compare_op0, hppa_compare_op1));
- emit_bcond_fp (NE, operands[0]);
- DONE;
- }
- operands[1] = hppa_compare_op0;
- operands[2] = hppa_compare_op1;
-}")
-
-(define_expand "blt"
- [(set (pc)
- (if_then_else (lt (match_dup 1) (match_dup 2))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- if (hppa_branch_type != CMP_SI)
- {
- emit_insn (gen_cmp_fp (LT, hppa_compare_op0, hppa_compare_op1));
- emit_bcond_fp (NE, operands[0]);
- DONE;
- }
- operands[1] = hppa_compare_op0;
- operands[2] = hppa_compare_op1;
-}")
-
-(define_expand "bge"
- [(set (pc)
- (if_then_else (ge (match_dup 1) (match_dup 2))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- if (hppa_branch_type != CMP_SI)
- {
- emit_insn (gen_cmp_fp (GE, hppa_compare_op0, hppa_compare_op1));
- emit_bcond_fp (NE, operands[0]);
- DONE;
- }
- operands[1] = hppa_compare_op0;
- operands[2] = hppa_compare_op1;
-}")
-
-(define_expand "ble"
- [(set (pc)
- (if_then_else (le (match_dup 1) (match_dup 2))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- if (hppa_branch_type != CMP_SI)
- {
- emit_insn (gen_cmp_fp (LE, hppa_compare_op0, hppa_compare_op1));
- emit_bcond_fp (NE, operands[0]);
- DONE;
- }
- operands[1] = hppa_compare_op0;
- operands[2] = hppa_compare_op1;
-}")
-
-(define_expand "bgtu"
- [(set (pc)
- (if_then_else (gtu (match_dup 1) (match_dup 2))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- if (hppa_branch_type != CMP_SI)
- FAIL;
- operands[1] = hppa_compare_op0;
- operands[2] = hppa_compare_op1;
-}")
-
-(define_expand "bltu"
- [(set (pc)
- (if_then_else (ltu (match_dup 1) (match_dup 2))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- if (hppa_branch_type != CMP_SI)
- FAIL;
- operands[1] = hppa_compare_op0;
- operands[2] = hppa_compare_op1;
-}")
-
-(define_expand "bgeu"
- [(set (pc)
- (if_then_else (geu (match_dup 1) (match_dup 2))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- if (hppa_branch_type != CMP_SI)
- FAIL;
- operands[1] = hppa_compare_op0;
- operands[2] = hppa_compare_op1;
-}")
-
-(define_expand "bleu"
- [(set (pc)
- (if_then_else (leu (match_dup 1) (match_dup 2))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- if (hppa_branch_type != CMP_SI)
- FAIL;
- operands[1] = hppa_compare_op0;
- operands[2] = hppa_compare_op1;
-}")
-
-(define_expand "bltgt"
- [(set (pc)
- (if_then_else (ltgt (match_dup 1) (match_dup 2))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- if (hppa_branch_type == CMP_SI)
- FAIL;
- emit_insn (gen_cmp_fp (LTGT, hppa_compare_op0, hppa_compare_op1));
- emit_bcond_fp (NE, operands[0]);
- DONE;
-}")
-
-(define_expand "bunle"
- [(set (pc)
- (if_then_else (unle (match_dup 1) (match_dup 2))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- if (hppa_branch_type == CMP_SI)
- FAIL;
- emit_insn (gen_cmp_fp (UNLE, hppa_compare_op0, hppa_compare_op1));
- emit_bcond_fp (NE, operands[0]);
- DONE;
-}")
-
-(define_expand "bunlt"
- [(set (pc)
- (if_then_else (unlt (match_dup 1) (match_dup 2))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- if (hppa_branch_type == CMP_SI)
- FAIL;
- emit_insn (gen_cmp_fp (UNLT, hppa_compare_op0, hppa_compare_op1));
- emit_bcond_fp (NE, operands[0]);
- DONE;
-}")
-
-(define_expand "bunge"
- [(set (pc)
- (if_then_else (unge (match_dup 1) (match_dup 2))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- if (hppa_branch_type == CMP_SI)
- FAIL;
- emit_insn (gen_cmp_fp (UNGE, hppa_compare_op0, hppa_compare_op1));
- emit_bcond_fp (NE, operands[0]);
- DONE;
-}")
+ "TARGET_64BIT"
+ "")
-(define_expand "bungt"
+(define_expand "cbranchsi4"
[(set (pc)
- (if_then_else (ungt (match_dup 1) (match_dup 2))
- (label_ref (match_operand 0 "" ""))
+ (if_then_else (match_operator 0 "ordered_comparison_operator"
+ [(match_operand:SI 1 "reg_or_0_operand" "")
+ (match_operand:SI 2 "arith5_operand" "")])
+ (label_ref (match_operand 3 "" ""))
(pc)))]
""
- "
-{
- if (hppa_branch_type == CMP_SI)
- FAIL;
- emit_insn (gen_cmp_fp (UNGT, hppa_compare_op0, hppa_compare_op1));
- emit_bcond_fp (NE, operands[0]);
- DONE;
-}")
+ "")
-(define_expand "buneq"
+(define_expand "cbranchsf4"
[(set (pc)
- (if_then_else (uneq (match_dup 1) (match_dup 2))
- (label_ref (match_operand 0 "" ""))
+ (if_then_else (match_operator 0 "comparison_operator"
+ [(match_operand:SF 1 "reg_or_0_operand" "")
+ (match_operand:SF 2 "reg_or_0_operand" "")])
+ (label_ref (match_operand 3 "" ""))
(pc)))]
""
"
{
- if (hppa_branch_type == CMP_SI)
- FAIL;
- emit_insn (gen_cmp_fp (UNEQ, hppa_compare_op0, hppa_compare_op1));
- emit_bcond_fp (NE, operands[0]);
+ emit_bcond_fp (operands);
DONE;
}")
-(define_expand "bunordered"
- [(set (pc)
- (if_then_else (unordered (match_dup 1) (match_dup 2))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- if (hppa_branch_type == CMP_SI)
- FAIL;
- emit_insn (gen_cmp_fp (UNORDERED, hppa_compare_op0, hppa_compare_op1));
- emit_bcond_fp (NE, operands[0]);
- DONE;
-}")
-(define_expand "bordered"
+(define_expand "cbranchdf4"
[(set (pc)
- (if_then_else (ordered (match_dup 1) (match_dup 2))
- (label_ref (match_operand 0 "" ""))
+ (if_then_else (match_operator 0 "comparison_operator"
+ [(match_operand:DF 1 "reg_or_0_operand" "")
+ (match_operand:DF 2 "reg_or_0_operand" "")])
+ (label_ref (match_operand 3 "" ""))
(pc)))]
""
"
{
- if (hppa_branch_type == CMP_SI)
- FAIL;
- emit_insn (gen_cmp_fp (ORDERED, hppa_compare_op0, hppa_compare_op1));
- emit_bcond_fp (NE, operands[0]);
+ emit_bcond_fp (operands);
DONE;
}")
@@ -7527,8 +7076,10 @@
then be worthwhile to split the casesi patterns to improve scheduling.
However, it's not clear that all this extra complexity is worth
the effort. */
- emit_insn (gen_cmpsi (operands[0], operands[2]));
- emit_jump_insn (gen_bgtu (operands[4]));
+ {
+ rtx test = gen_rtx_GTU (VOIDmode, operands[0], operands[2]);
+ emit_jump_insn (gen_cbranchsi4 (test, operands[0], operands[2], operands[4]));
+ }
if (TARGET_BIG_SWITCH)
{
diff --git a/gcc/config/pdp11/pdp11-protos.h b/gcc/config/pdp11/pdp11-protos.h
index f493fbc8ab1..1ed272e5081 100644
--- a/gcc/config/pdp11/pdp11-protos.h
+++ b/gcc/config/pdp11/pdp11-protos.h
@@ -33,9 +33,9 @@ extern void output_addr_const_pdp11 (FILE *, rtx);
extern const char *output_move_double (rtx *);
extern const char *output_move_quad (rtx *);
extern const char *output_block_move (rtx *);
+extern const char *output_jump (enum rtx_code, int, int);
extern void print_operand_address (FILE *, rtx);
extern int register_move_cost (enum reg_class, enum reg_class);
#endif /* RTX_CODE */
extern void output_ascii (FILE *, const char *, int);
-extern const char *output_jump (const char *, const char *, int);
diff --git a/gcc/config/pdp11/pdp11.c b/gcc/config/pdp11/pdp11.c
index 6e8941d75e9..8f2d78fe555 100644
--- a/gcc/config/pdp11/pdp11.c
+++ b/gcc/config/pdp11/pdp11.c
@@ -1170,11 +1170,27 @@ pdp11_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED, int *total,
}
const char *
-output_jump (const char *pos, const char *neg, int length)
+output_jump (enum rtx_code code, int inv, int length)
{
static int x = 0;
static char buf[1000];
+ const char *pos, *neg;
+
+ switch (code)
+ {
+ case EQ: pos = "beq", neg = "bne"; break;
+ case NE: pos = "bne", neg = "beq"; break;
+ case GT: pos = "bgt", neg = "ble"; break;
+ case GTU: pos = "bhi", neg = "blos"; break;
+ case LT: pos = "blt", neg = "bge"; break;
+ case LTU: pos = "blo", neg = "bhis"; break;
+ case GE: pos = "bge", neg = "blt"; break;
+ case GEU: pos = "bhis", neg = "blo"; break;
+ case LE: pos = "ble", neg = "bgt"; break;
+ case LEU: pos = "blos", neg = "bhi"; break;
+ default: gcc_unreachable ();
+ }
#if 0
/* currently we don't need this, because the tstdf and cmpdf
@@ -1190,14 +1206,13 @@ output_jump (const char *pos, const char *neg, int length)
{
case 1:
- strcpy(buf, pos);
- strcat(buf, " %l0");
+ sprintf(buf, "%s %%l1", inv ? neg : pos);
return buf;
case 3:
- sprintf(buf, "%s JMP_%d\n\tjmp %%l0\nJMP_%d:", neg, x, x);
+ sprintf(buf, "%s JMP_%d\n\tjmp %%l1\nJMP_%d:", inv ? pos : neg, x, x);
x++;
diff --git a/gcc/config/pdp11/pdp11.h b/gcc/config/pdp11/pdp11.h
index 9dbb41eb7c1..437e2b81e2e 100644
--- a/gcc/config/pdp11/pdp11.h
+++ b/gcc/config/pdp11/pdp11.h
@@ -1031,6 +1031,9 @@ JMP FUNCTION 0x0058 0x0000 <- FUNCTION
#define OPTIMIZATION_OPTIONS(LEVEL,SIZE) \
{ \
+ flag_finite_math_only = 0; \
+ flag_trapping_math = 0; \
+ flag_signaling_nans = 0; \
if (LEVEL >= 3) \
{ \
flag_omit_frame_pointer = 1; \
diff --git a/gcc/config/pdp11/pdp11.md b/gcc/config/pdp11/pdp11.md
index d5d4396b1c6..64d57e056b3 100644
--- a/gcc/config/pdp11/pdp11.md
+++ b/gcc/config/pdp11/pdp11.md
@@ -19,6 +19,11 @@
;; along with GCC; see the file COPYING3. If not see
;; <http://www.gnu.org/licenses/>.
+;; Match CONST_DOUBLE zero for tstd/tstf.
+(define_predicate "register_or_const0_operand"
+ (ior (match_operand 0 "register_operand")
+ (match_test "op == CONST0_RTX (GET_MODE (op))")))
+
;; HI is 16 bit
;; QI is 8 bit
@@ -81,141 +86,50 @@
;(define_function_unit "fpu" 1 1 (eq_attr "type" "fp") 0 0)
;; compare
-(define_insn "cmpdf"
+(define_insn "*cmpdf"
[(set (cc0)
- (compare (match_operand:DF 0 "general_operand" "fR,Q,F")
- (match_operand:DF 1 "register_operand" "a,a,a")))]
+ (compare (match_operand:DF 0 "general_operand" "fR,fR,Q,Q,F")
+ (match_operand:DF 1 "register_or_const0_operand" "G,a,G,a,a")))]
"TARGET_FPU"
"*
{
cc_status.flags = CC_IN_FPU;
- return \"{cmpd|cmpf} %0, %1\;cfcc\";
-}"
- [(set_attr "length" "2,3,6")])
-
-;; a bit of brain damage, maybe inline later -
-;; problem is - gcc seems to NEED SImode because
-;; of the cmp weirdness - maybe change gcc to handle this?
-
-(define_expand "cmpsi"
- [(set (reg:SI 0)
- (match_operand:SI 0 "general_operand" "g"))
- (set (reg:SI 2)
- (match_operand:SI 1 "general_operand" "g"))
- (parallel [(set (cc0)
- (compare (reg:SI 0)
- (reg:SI 2)))
- (clobber (reg:SI 0))])]
- "0" ;; disable for test
- "")
-
-;; check for next insn for branch code - does this still
-;; work in gcc 2.* ?
-
-(define_insn ""
- [(set (cc0)
- (compare (reg:SI 0)
- (reg:SI 2)))
- (clobber (reg:SI 0))]
- ""
- "*
-{
- rtx br_insn = NEXT_INSN (insn);
- RTX_CODE br_code;
-
- gcc_assert (GET_CODE (br_insn) == JUMP_INSN);
- br_code = GET_CODE (XEXP (XEXP (PATTERN (br_insn), 1), 0));
-
- switch(br_code)
- {
- case GEU:
- case LTU:
- case GTU:
- case LEU:
-
- return \"jsr pc, ___ucmpsi\;cmp $1,r0\";
-
- case GE:
- case LT:
- case GT:
- case LE:
- case EQ:
- case NE:
-
- return \"jsr pc, ___cmpsi\;tst r0\";
-
- default:
-
- gcc_unreachable ();
- }
+ if (which_alternative == 0 || which_alternative == 2)
+ return \"{tstd|tstf} %0, %1\;cfcc\";
+ else
+ return \"{cmpd|cmpf} %0, %1\;cfcc\";
}"
- [(set_attr "length" "4")])
+ [(set_attr "length" "2,2,3,3,6")])
-
-(define_insn "cmphi"
+(define_insn "*cmphi"
[(set (cc0)
- (compare (match_operand:HI 0 "general_operand" "rR,rR,Qi,Qi")
- (match_operand:HI 1 "general_operand" "rR,Qi,rR,Qi")))]
+ (compare (match_operand:HI 0 "general_operand" "rR,rR,rR,Q,Qi,Qi")
+ (match_operand:HI 1 "general_operand" "N,rR,Qi,N,rR,Qi")))]
""
- "cmp %0,%1"
- [(set_attr "length" "1,2,2,3")])
-
-(define_insn "cmpqi"
+ "@
+ tst %0
+ cmp %0,%1
+ cmp %0,%1
+ tst %0
+ cmp %0,%1
+ cmp %0,%1"
+ [(set_attr "length" "1,1,2,2,2,3")])
+
+(define_insn "*cmpqi"
[(set (cc0)
- (compare (match_operand:QI 0 "general_operand" "rR,rR,Qi,Qi")
- (match_operand:QI 1 "general_operand" "rR,Qi,rR,Qi")))]
+ (compare (match_operand:QI 0 "general_operand" "rR,rR,rR,Q,Qi,Qi")
+ (match_operand:QI 1 "general_operand" "N,rR,Qi,N,rR,Qi")))]
""
- "cmpb %0,%1"
- [(set_attr "length" "1,2,2,3")])
+ "@
+ tstb %0
+ cmpb %0,%1
+ cmpb %0,%1
+ tstb %0
+ cmpb %0,%1
+ cmpb %0,%1"
+ [(set_attr "length" "1,1,2,2,2,3")])
-;; We have to have this because cse can optimize the previous pattern
-;; into this one.
-
-(define_insn "tstdf"
- [(set (cc0)
- (match_operand:DF 0 "general_operand" "fR,Q"))]
- "TARGET_FPU"
- "*
-{
- cc_status.flags = CC_IN_FPU;
- return \"{tstd|tstf} %0\;cfcc\";
-}"
- [(set_attr "length" "2,3")])
-
-
-(define_expand "tstsi"
- [(set (reg:SI 0)
- (match_operand:SI 0 "general_operand" "g"))
- (parallel [(set (cc0)
- (reg:SI 0))
- (clobber (reg:SI 0))])]
- "0" ;; disable for test
- "")
-
-(define_insn ""
- [(set (cc0)
- (reg:SI 0))
- (clobber (reg:SI 0))]
- ""
- "jsr pc, ___tstsi\;tst r0"
- [(set_attr "length" "3")])
-
-
-(define_insn "tsthi"
- [(set (cc0)
- (match_operand:HI 0 "general_operand" "rR,Q"))]
- ""
- "tst %0"
- [(set_attr "length" "1,2")])
-
-(define_insn "tstqi"
- [(set (cc0)
- (match_operand:QI 0 "general_operand" "rR,Q"))]
- ""
- "tstb %0"
- [(set_attr "length" "1,2")])
-
;; sob instruction - we need an assembler which can make this instruction
;; valid under _all_ circumstances!
@@ -264,353 +178,81 @@
;; These control RTL generation for conditional jump insns
;; and match them for register allocation.
-;; problem with too short jump distance! we need an assembler which can
-;; make this valid for all jump distances!
-;; e.g. gas!
-
-;; these must be changed to check for CC_IN_FCCR if float is to be
-;; enabled
-
-(define_insn "beq"
- [(set (pc)
- (if_then_else (eq (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "* return output_jump(\"beq\", \"bne\", get_attr_length(insn));"
- [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
- (pc))
- (const_int -128))
- (ge (minus (match_dup 0)
- (pc))
- (const_int 128)))
- (const_int 3)
- (const_int 1)))])
-
-
-(define_insn "bne"
- [(set (pc)
- (if_then_else (ne (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "* return output_jump(\"bne\", \"beq\", get_attr_length(insn));"
- [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
- (pc))
- (const_int -128))
- (ge (minus (match_dup 0)
- (pc))
- (const_int 128)))
- (const_int 3)
- (const_int 1)))])
-
-(define_insn "bgt"
- [(set (pc)
- (if_then_else (gt (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "* return output_jump(\"bgt\", \"ble\", get_attr_length(insn));"
- [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
- (pc))
- (const_int -128))
- (ge (minus (match_dup 0)
- (pc))
- (const_int 128)))
- (const_int 3)
- (const_int 1)))])
-
-(define_insn "bgtu"
- [(set (pc)
- (if_then_else (gtu (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
+(define_expand "cbranchdf4"
+ [(set (cc0)
+ (compare (match_operand:DF 1 "general_operand")
+ (match_operand:DF 2 "general_operand")))
+ (set (pc)
+ (if_then_else (match_operator 0 "ordered_comparison_operator"
+ [(cc0) (const_int 0)])
+ (label_ref (match_operand 3 "" ""))
(pc)))]
""
- "* return output_jump(\"bhi\", \"blos\", get_attr_length(insn));"
- [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
- (pc))
- (const_int -128))
- (ge (minus (match_dup 0)
- (pc))
- (const_int 128)))
- (const_int 3)
- (const_int 1)))])
+ "")
-(define_insn "blt"
- [(set (pc)
- (if_then_else (lt (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
+(define_expand "cbranchhi4"
+ [(set (cc0)
+ (compare (match_operand:HI 1 "general_operand")
+ (match_operand:HI 2 "general_operand")))
+ (set (pc)
+ (if_then_else (match_operator 0 "ordered_comparison_operator"
+ [(cc0) (const_int 0)])
+ (label_ref (match_operand 3 "" ""))
(pc)))]
""
- "* return output_jump(\"blt\", \"bge\", get_attr_length(insn));"
- [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
- (pc))
- (const_int -128))
- (ge (minus (match_dup 0)
- (pc))
- (const_int 128)))
- (const_int 3)
- (const_int 1)))])
-
+ "")
-(define_insn "bltu"
- [(set (pc)
- (if_then_else (ltu (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
+(define_expand "cbranchqi4"
+ [(set (cc0)
+ (compare (match_operand:QI 1 "general_operand")
+ (match_operand:QI 2 "general_operand")))
+ (set (pc)
+ (if_then_else (match_operator 0 "ordered_comparison_operator"
+ [(cc0) (const_int 0)])
+ (label_ref (match_operand 3 "" ""))
(pc)))]
""
- "* return output_jump(\"blo\", \"bhis\", get_attr_length(insn));"
- [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
- (pc))
- (const_int -128))
- (ge (minus (match_dup 0)
- (pc))
- (const_int 128)))
- (const_int 3)
- (const_int 1)))])
+ "")
-(define_insn "bge"
- [(set (pc)
- (if_then_else (ge (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "* return output_jump(\"bge\", \"blt\", get_attr_length(insn));"
- [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
- (pc))
- (const_int -128))
- (ge (minus (match_dup 0)
- (pc))
- (const_int 128)))
- (const_int 3)
- (const_int 1)))])
+;; problem with too short jump distance! we need an assembler which can
+;; make this valid for all jump distances!
+;; e.g. gas!
-(define_insn "bgeu"
- [(set (pc)
- (if_then_else (geu (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "* return output_jump(\"bhis\", \"blo\", get_attr_length(insn));"
- [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
- (pc))
- (const_int -128))
- (ge (minus (match_dup 0)
- (pc))
- (const_int 128)))
- (const_int 3)
- (const_int 1)))])
+;; these must be changed to check for CC_IN_FCCR if float is to be
+;; enabled
-(define_insn "ble"
+(define_insn "*branch"
[(set (pc)
- (if_then_else (le (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
+ (if_then_else (match_operator 0 "ordered_comparison_operator"
+ [(cc0) (const_int 0)])
+ (label_ref (match_operand 1 "" ""))
(pc)))]
""
- "* return output_jump(\"ble\", \"bgt\", get_attr_length(insn));"
- [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
+ "* return output_jump(GET_CODE (operands[0]), 0, get_attr_length(insn));"
+ [(set (attr "length") (if_then_else (ior (le (minus (match_dup 1)
(pc))
(const_int -128))
- (ge (minus (match_dup 0)
+ (ge (minus (match_dup 1)
(pc))
(const_int 128)))
(const_int 3)
(const_int 1)))])
-(define_insn "bleu"
- [(set (pc)
- (if_then_else (leu (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "* return output_jump(\"blos\", \"bhi\", get_attr_length(insn));"
- [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
- (pc))
- (const_int -128))
- (ge (minus (match_dup 0)
- (pc))
- (const_int 128)))
- (const_int 3)
- (const_int 1)))])
-
;; These match inverted jump insns for register allocation.
-(define_insn ""
+(define_insn "*branch_inverted"
[(set (pc)
- (if_then_else (eq (cc0)
- (const_int 0))
+ (if_then_else (match_operator 0 "ordered_comparison_operator"
+ [(cc0) (const_int 0)])
(pc)
- (label_ref (match_operand 0 "" ""))))]
+ (label_ref (match_operand 1 "" ""))))]
""
- "* return output_jump(\"bne\", \"beq\", get_attr_length(insn));"
- [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
+ "* return output_jump(GET_CODE (operands[0]), 1, get_attr_length(insn));"
+ [(set (attr "length") (if_then_else (ior (le (minus (match_dup 1)
(pc))
(const_int -128))
- (ge (minus (match_dup 0)
- (pc))
- (const_int 128)))
- (const_int 3)
- (const_int 1)))])
-
-(define_insn ""
- [(set (pc)
- (if_then_else (ne (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "* return output_jump(\"beq\", \"bne\", get_attr_length(insn));"
- [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
- (pc))
- (const_int -128))
- (ge (minus (match_dup 0)
- (pc))
- (const_int 128)))
- (const_int 3)
- (const_int 1)))])
-
-(define_insn ""
- [(set (pc)
- (if_then_else (gt (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "* return output_jump(\"ble\", \"bgt\", get_attr_length(insn));"
- [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
- (pc))
- (const_int -128))
- (ge (minus (match_dup 0)
- (pc))
- (const_int 128)))
- (const_int 3)
- (const_int 1)))])
-
-(define_insn ""
- [(set (pc)
- (if_then_else (gtu (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "* return output_jump(\"blos\", \"bhi\", get_attr_length(insn));"
- [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
- (pc))
- (const_int -128))
- (ge (minus (match_dup 0)
- (pc))
- (const_int 128)))
- (const_int 3)
- (const_int 1)))])
-
-(define_insn ""
- [(set (pc)
- (if_then_else (lt (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "* return output_jump(\"bge\", \"blt\", get_attr_length(insn));"
- [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
- (pc))
- (const_int -128))
- (ge (minus (match_dup 0)
- (pc))
- (const_int 128)))
- (const_int 3)
- (const_int 1)))])
-
-(define_insn ""
- [(set (pc)
- (if_then_else (ltu (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "* return output_jump(\"bhis\", \"blo\", get_attr_length(insn));"
- [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
- (pc))
- (const_int -128))
- (ge (minus (match_dup 0)
- (pc))
- (const_int 128)))
- (const_int 3)
- (const_int 1)))])
-
-(define_insn ""
- [(set (pc)
- (if_then_else (ge (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "* return output_jump(\"blt\", \"bge\", get_attr_length(insn));"
- [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
- (pc))
- (const_int -128))
- (ge (minus (match_dup 0)
- (pc))
- (const_int 128)))
- (const_int 3)
- (const_int 1)))])
-
-(define_insn ""
- [(set (pc)
- (if_then_else (geu (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "* return output_jump(\"blo\", \"bhis\", get_attr_length(insn));"
- [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
- (pc))
- (const_int -128))
- (ge (minus (match_dup 0)
- (pc))
- (const_int 128)))
- (const_int 3)
- (const_int 1)))])
-
-(define_insn ""
- [(set (pc)
- (if_then_else (le (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "* return output_jump(\"bgt\", \"ble\", get_attr_length(insn));"
- [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
- (pc))
- (const_int -128))
- (ge (minus (match_dup 0)
- (pc))
- (const_int 128)))
- (const_int 3)
- (const_int 1)))])
-
-(define_insn ""
- [(set (pc)
- (if_then_else (leu (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "* return output_jump(\"bhi\", \"blos\", get_attr_length(insn));"
- [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
- (pc))
- (const_int -128))
- (ge (minus (match_dup 0)
+ (ge (minus (match_dup 1)
(pc))
(const_int 128)))
(const_int 3)
diff --git a/gcc/config/picochip/picochip.md b/gcc/config/picochip/picochip.md
index 657629c96fa..02f0f14850d 100644
--- a/gcc/config/picochip/picochip.md
+++ b/gcc/config/picochip/picochip.md
@@ -551,7 +551,7 @@
(define_insn_and_split "cbranchhi4"
[(set (pc)
(if_then_else
- (match_operator:CC 0 "comparison_operator"
+ (match_operator:CC 0 "ordered_comparison_operator"
[(match_operand:HI 1 "register_operand" "r")
(match_operand:HI 2 "picochip_comparison_operand" "ri")])
(label_ref (match_operand 3 "" ""))
@@ -2524,117 +2524,6 @@
(set_attr "type" "picoAlu,picoAlu")
(set_attr "longConstant" "false,true")])
-;; cmphi - This needs to be defined, to ensure that the conditional
-;; move works properly (because the if-cvt code uses this pattern to
-;; build the conditional move, even though normally we use cbranch to
-;; directly generate the instructions).
-
-(define_expand "cmphi"
- [(match_operand:HI 0 "general_operand" "g")
- (match_operand:HI 1 "general_operand" "g")]
- ""
- "DONE;")
-
-;;============================================================================
-;; Branch patterns - needed for conditional moves. This is because
-;; they result in the bcc_gen_fctn array being initialised with the
-;; code to define_expand the following, and this in turn means that
-;; when noce_emit_cmove is called, the correct pattern can be
-;; generated, based upon the assumed presence of the following. The
-;; following are never actually used, because the earlier cbranch
-;; patterns take precendence.
-;;============================================================================
-
-(define_expand "bne"
- [(set (pc)
- (if_then_else
- (ne (reg:CC CC_REGNUM) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "gcc_unreachable();")
-
-(define_expand "beq"
- [(set (pc)
- (if_then_else
- (eq (reg:CC CC_REGNUM) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "gcc_unreachable();")
-
-(define_expand "blt"
- [(set (pc)
- (if_then_else
- (lt (reg:CC CC_REGNUM) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "gcc_unreachable();")
-
-(define_expand "bge"
- [(set (pc)
- (if_then_else
- (ge (reg:CC CC_REGNUM) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "gcc_unreachable();")
-
-(define_expand "bgeu"
- [(set (pc)
- (if_then_else
- (geu (reg:CC CC_REGNUM) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "gcc_unreachable();")
-
-(define_expand "bltu"
- [(set (pc)
- (if_then_else
- (ltu (reg:CC CC_REGNUM) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "gcc_unreachable();")
-
-(define_expand "ble"
- [(set (pc)
- (if_then_else
- (le (reg:CC CC_REGNUM) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "gcc_unreachable();")
-
-(define_expand "bgt"
- [(set (pc)
- (if_then_else
- (gt (reg:CC CC_REGNUM) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "gcc_unreachable();")
-
-(define_expand "bleu"
- [(set (pc)
- (if_then_else
- (leu (reg:CC CC_REGNUM) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "gcc_unreachable();")
-
-(define_expand "bgtu"
- [(set (pc)
- (if_then_else
- (gtu (reg:CC CC_REGNUM) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "gcc_unreachable();")
-
;;============================================================================
;; Scheduling, including delay slot scheduling.
;;============================================================================
diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md
index af80ef46b6f..dbf78734b17 100644
--- a/gcc/config/rs6000/predicates.md
+++ b/gcc/config/rs6000/predicates.md
@@ -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")
diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h
index 4b8f5220a51..f40adabd00a 100644
--- a/gcc/config/rs6000/rs6000-protos.h
+++ b/gcc/config/rs6000/rs6000-protos.h
@@ -81,8 +81,8 @@ extern void print_operand_address (FILE *, rtx);
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);
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 8e24769816d..2d34b14f63f 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -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);
@@ -12788,21 +12783,24 @@ rs6000_reverse_condition (enum machine_mode mode, enum rtx_code code)
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
@@ -12816,13 +12814,13 @@ rs6000_generate_compare (enum rtx_code code)
/* 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. */
@@ -12834,26 +12832,20 @@ rs6000_generate_compare (enum rtx_code code)
{
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:
@@ -12866,26 +12858,20 @@ rs6000_generate_compare (enum rtx_code code)
{
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:
@@ -12898,26 +12884,20 @@ rs6000_generate_compare (enum rtx_code code)
{
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:
@@ -12949,26 +12929,20 @@ rs6000_generate_compare (enum rtx_code code)
{
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:
@@ -12998,16 +12972,14 @@ rs6000_generate_compare (enum rtx_code code)
/* 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)),
@@ -13016,29 +12988,25 @@ rs6000_generate_compare (enum rtx_code code)
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
@@ -13081,16 +13049,17 @@ rs6000_generate_compare (enum rtx_code code)
/* 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;
@@ -13125,11 +13094,11 @@ rs6000_emit_sCOND (enum rtx_code code, rtx result)
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);
@@ -13144,12 +13113,12 @@ rs6000_emit_sCOND (enum rtx_code code, rtx result)
/* 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)));
@@ -13595,8 +13564,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);
@@ -13616,7 +13585,7 @@ rs6000_emit_cmove (rtx dest, rtx op, rtx true_cond, rtx false_cond)
/* 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);
@@ -13781,13 +13750,13 @@ rs6000_emit_int_cmove (rtx dest, rtx op, rtx true_cond, rtx false_cond)
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)
diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h
index f11ea1fe249..e65bf5d95df 100644
--- a/gcc/config/rs6000/rs6000.h
+++ b/gcc/config/rs6000/rs6000.h
@@ -1986,12 +1986,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. */
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index cc37d911dbb..9d4a96051b7 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -11897,262 +11897,90 @@
;; 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" "")))]
+;; insns, and branches.
+
+(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 ""))]
""
"
{
- /* Take care of the possibility that operands[1] might be negative but
+ /* 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[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;
-}")
+ if (GET_CODE (operands[2]) == CONST_INT
+ && INTVAL (operands[2]) < 0)
+ {
+ operands[2] = force_reg (<MODE>mode, operands[2]);
+ operands[0] = gen_rtx_fmt_ee (GET_CODE (operands[0]),
+ GET_MODE (operands[0]),
+ operands[1], operands[2]);
+ }
-(define_expand "cmp<mode>"
- [(set (cc0) (compare (match_operand:FP 0 "gpc_reg_operand" "")
- (match_operand:FP 1 "gpc_reg_operand" "")))]
- ""
- "
-{
- rs6000_compare_op0 = operands[0];
- rs6000_compare_op1 = operands[1];
- rs6000_compare_fp_p = 1;
+ rs6000_emit_cbranch (<MODE>mode, operands);
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" ""))]
+(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)
- FAIL;
-
- 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 "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)
- FAIL;
-
- rs6000_emit_sCOND (GE, operands[0]);
- DONE;
-}")
+ /* 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]);
+ operands[1] = gen_rtx_fmt_ee (GET_CODE (operands[1]),
+ GET_MODE (operands[1]),
+ operands[2], operands[3]);
+ }
-;; 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" ""))]
- ""
- "
-{
- if (! rs6000_compare_fp_p && rs6000_compare_op1 == const0_rtx)
+ /* 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" "")
@@ -12195,16 +12023,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;
})
@@ -14775,17 +14603,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))]
diff --git a/gcc/config/s390/predicates.md b/gcc/config/s390/predicates.md
index bb8fdf261d5..d09c9b3e161 100644
--- a/gcc/config/s390/predicates.md
+++ b/gcc/config/s390/predicates.md
@@ -189,6 +189,14 @@
return (s390_compare_and_branch_condition_mask (op) >= 0);
})
+;; Return nonzero if OP is a valid comparison operator for the
+;; cstore expanders -- respectively cstorecc4 and integer cstore.
+(define_predicate "s390_eqne_operator"
+ (match_code "eq, ne"))
+
+(define_predicate "s390_scond_operator"
+ (match_code "ltu, gtu, leu, geu"))
+
;; Return nonzero if OP is a valid comparison operator
;; for an ALC condition.
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index e2ed4a0d407..17891c6492f 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -223,11 +223,6 @@ struct processor_costs z10_cost =
extern int reload_completed;
-/* Save information from a "cmpxx" operation until the branch or scc is
- emitted. A pair of a MODE_CC register and a const0_rtx if a compare
- has been emitted already. */
-rtx s390_compare_op0, s390_compare_op1;
-
/* Structure used to hold the components of a S/390 memory
address. A legitimate address on S/390 is of the general
form
@@ -7747,15 +7742,11 @@ s390_emit_prologue (void)
rtx t = gen_rtx_AND (Pmode, stack_pointer_rtx,
GEN_INT (stack_check_mask));
if (TARGET_64BIT)
- gen_cmpdi (t, const0_rtx);
+ emit_insn (gen_ctrapdi4 (gen_rtx_EQ (VOIDmode, t, const0_rtx),
+ t, const0_rtx, const0_rtx));
else
- gen_cmpsi (t, const0_rtx);
-
- emit_insn (gen_conditional_trap (gen_rtx_EQ (CCmode,
- gen_rtx_REG (CCmode,
- CC_REGNUM),
- const0_rtx),
- const0_rtx));
+ emit_insn (gen_ctrapsi4 (gen_rtx_EQ (VOIDmode, t, const0_rtx),
+ t, const0_rtx, const0_rtx));
}
}
diff --git a/gcc/config/s390/s390.h b/gcc/config/s390/s390.h
index 2b4d7ce72ca..b2541857170 100644
--- a/gcc/config/s390/s390.h
+++ b/gcc/config/s390/s390.h
@@ -803,12 +803,6 @@ do { \
#define CANONICALIZE_COMPARISON(CODE, OP0, OP1) \
s390_canonicalize_comparison (&(CODE), &(OP0), &(OP1))
-/* Define the information needed to generate branch and scc insns. This is
- stored from the compare operation. Note that we can't use "rtx" here
- since it hasn't been defined! */
-extern struct rtx_def *s390_compare_op0, *s390_compare_op1;
-
-
/* Relative costs of operations. */
/* On s390, copy between fprs and gprs is expensive. */
diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md
index c3d181f0aac..7c9a2b28100 100644
--- a/gcc/config/s390/s390.md
+++ b/gcc/config/s390/s390.md
@@ -354,13 +354,6 @@
(define_mode_iterator INT [(DI "TARGET_64BIT") SI HI QI])
(define_mode_iterator INTALL [TI DI SI HI QI])
-;; This iterator allows to unify all 'bCOND' expander patterns.
-(define_code_iterator COMPARE [eq ne gt gtu lt ltu ge geu le leu unordered
- ordered uneq unlt ungt unle unge ltgt])
-
-;; This iterator allows to unify all 'sCOND' patterns.
-(define_code_iterator SCOND [ltu gtu leu geu])
-
;; This iterator allows some 'ashift' and 'lshiftrt' pattern to be defined from
;; the same template.
(define_code_iterator SHIFT [ashift lshiftrt])
@@ -493,39 +486,6 @@
;;- Compare instructions.
;;
-(define_expand "cmp<mode>"
- [(set (reg:CC CC_REGNUM)
- (compare:CC (match_operand:GPR 0 "register_operand" "")
- (match_operand:GPR 1 "general_operand" "")))]
- ""
-{
- s390_compare_op0 = operands[0];
- s390_compare_op1 = operands[1];
- DONE;
-})
-
-(define_expand "cmp<mode>"
- [(set (reg:CC CC_REGNUM)
- (compare:CC (match_operand:FP 0 "register_operand" "")
- (match_operand:FP 1 "general_operand" "")))]
- "TARGET_HARD_FLOAT"
-{
- s390_compare_op0 = operands[0];
- s390_compare_op1 = operands[1];
- DONE;
-})
-
-(define_expand "cmpcc"
- [(set (reg:CC CC_REGNUM)
- (compare:CC (match_operand 0 "cc_reg_operand" "")
- (match_operand 1 "general_operand" "")))]
- ""
-{
- s390_compare_op0 = operands[0];
- s390_compare_op1 = operands[1];
- DONE;
-})
-
; Test-under-Mask instructions
(define_insn "*tmqi_mem"
@@ -3812,9 +3772,9 @@
TD -> DI convert afterwards. */
emit_insn (gen_extendddtd2 (temp, operands[1]));
temp = force_reg (TDmode, temp);
- emit_insn (gen_cmptd (temp,
- CONST_DOUBLE_FROM_REAL_VALUE (cmp, TDmode)));
- emit_jump_insn (gen_blt (label1));
+ emit_cmp_and_jump_insns (temp,
+ CONST_DOUBLE_FROM_REAL_VALUE (cmp, TDmode),
+ LT, NULL_RTX, VOIDmode, 0, label1);
emit_insn (gen_subtd3 (temp, temp,
CONST_DOUBLE_FROM_REAL_VALUE (sub, TDmode)));
emit_insn (gen_fix_trunctddi2_dfp (operands[0], temp, GEN_INT (11)));
@@ -3840,9 +3800,9 @@
decimal_real_from_string (&cmp, "9223372036854775808.0"); /* 2^63 */
decimal_real_from_string (&sub, "18446744073709551616.0"); /* 2^64 */
- emit_insn (gen_cmptd (operands[1],
- CONST_DOUBLE_FROM_REAL_VALUE (cmp, TDmode)));
- emit_jump_insn (gen_blt (label1));
+ emit_cmp_and_jump_insns (operands[1],
+ CONST_DOUBLE_FROM_REAL_VALUE (cmp, TDmode),
+ LT, NULL_RTX, VOIDmode, 0, label1);
emit_insn (gen_subtd3 (temp, operands[1],
CONST_DOUBLE_FROM_REAL_VALUE (sub, TDmode)));
emit_insn (gen_fix_trunctddi2_dfp (operands[0], temp, GEN_INT (11)));
@@ -3873,9 +3833,9 @@
real_2expN (&cmp, GET_MODE_BITSIZE(<GPR:MODE>mode) - 1, <BFP:MODE>mode);
real_2expN (&sub, GET_MODE_BITSIZE(<GPR:MODE>mode), <BFP:MODE>mode);
- emit_insn (gen_cmp<BFP:mode> (operands[1],
- CONST_DOUBLE_FROM_REAL_VALUE (cmp, <BFP:MODE>mode)));
- emit_jump_insn (gen_blt (label1));
+ emit_cmp_and_jump_insns (operands[1],
+ CONST_DOUBLE_FROM_REAL_VALUE (cmp, <BFP:MODE>mode),
+ LT, NULL_RTX, VOIDmode, 0, label1);
emit_insn (gen_sub<BFP:mode>3 (temp, operands[1],
CONST_DOUBLE_FROM_REAL_VALUE (sub, <BFP:MODE>mode)));
emit_insn (gen_fix_trunc<BFP:mode><GPR:mode>2_bfp (operands[0], temp,
@@ -5074,7 +5034,7 @@
(match_operand:GPR 3 "const_int_operand" "")]
"TARGET_CPU_ZARCH"
"if (!s390_expand_addcc (GET_CODE (operands[1]),
- s390_compare_op0, s390_compare_op1,
+ XEXP (operands[1], 0), XEXP (operands[1], 1),
operands[0], operands[2],
operands[3])) FAIL; DONE;")
@@ -5114,31 +5074,29 @@
"")
-(define_expand "s<code>"
+(define_expand "cstore<mode>4"
[(set (match_operand:SI 0 "register_operand" "")
- (SCOND (match_dup 0)
- (match_dup 0)))]
+ (match_operator:SI 1 "s390_scond_operator"
+ [(match_operand:GPR 2 "register_operand" "")
+ (match_operand:GPR 3 "general_operand" "")]))]
"TARGET_CPU_ZARCH"
- "if (!s390_expand_addcc (<CODE>, s390_compare_op0, s390_compare_op1,
+ "if (!s390_expand_addcc (GET_CODE (operands[1]), operands[2], operands[3],
operands[0], const0_rtx, const1_rtx)) FAIL; DONE;")
-(define_expand "seq"
+(define_expand "cstorecc4"
[(parallel
- [(set (match_operand:SI 0 "register_operand" "=d")
- (match_dup 1))
- (clobber (reg:CC CC_REGNUM))])
- (parallel
- [(set (match_dup 0) (xor:SI (match_dup 0) (const_int 1)))
+ [(set (match_operand:SI 0 "register_operand" "")
+ (match_operator:SI 1 "s390_eqne_operator"
+ [(match_operand:CCZ1 2 "register_operand")
+ (match_operand 3 "const0_operand")]))
(clobber (reg:CC CC_REGNUM))])]
""
-{
- if (GET_MODE (s390_compare_op0) != CCZ1mode)
- FAIL;
- operands[1] = s390_emit_compare (NE, s390_compare_op0, s390_compare_op1);
- PUT_MODE (operands[1], SImode);
-})
+ "emit_insn (gen_sne (operands[0], operands[2]));
+ if (GET_CODE (operands[1]) == EQ)
+ emit_insn (gen_xorsi3 (operands[0], operands[0], const1_rtx));
+ DONE;")
-(define_insn_and_split "*sne"
+(define_insn_and_split "sne"
[(set (match_operand:SI 0 "register_operand" "=d")
(ne:SI (match_operand:CCZ1 1 "register_operand" "0")
(const_int 0)))
@@ -5566,8 +5524,8 @@
operands[1] = make_safe_from (operands[1], operands[0]);
emit_move_insn (operands[0], const0_rtx);
- emit_insn (gen_cmpsi (operands[1], operands[2]));
- emit_jump_insn (gen_bltu (label1));
+ emit_cmp_and_jump_insns (operands[1], operands[2], LT, NULL_RTX,
+ SImode, 1, label1);
emit_move_insn (operands[0], const1_rtx);
emit_label (label1);
}
@@ -5598,12 +5556,12 @@
operands[2] = make_safe_from (operands[2], operands[0]);
emit_move_insn (operands[0], const0_rtx);
- emit_insn (gen_cmpsi (operands[2], operands[1]));
- emit_jump_insn (gen_bgtu (label3));
- emit_insn (gen_cmpsi (operands[2], const0_rtx));
- emit_jump_insn (gen_blt (label2));
- emit_insn (gen_cmpsi (operands[2], const1_rtx));
- emit_jump_insn (gen_beq (label1));
+ emit_cmp_and_jump_insns (operands[2], operands[1], GT, NULL_RTX,
+ SImode, 1, label3);
+ emit_cmp_and_jump_insns (operands[2], const0_rtx, LT, NULL_RTX,
+ SImode, 0, label2);
+ emit_cmp_and_jump_insns (operands[2], const1_rtx, EQ, NULL_RTX,
+ SImode, 0, label1);
emit_insn (gen_zero_extendsidi2 (operands[3], operands[1]));
insn = emit_insn (gen_divmoddisi3 (operands[3], operands[3],
operands[2]));
@@ -5652,8 +5610,8 @@
operands[1] = make_safe_from (operands[1], operands[0]);
emit_move_insn (operands[0], operands[1]);
- emit_insn (gen_cmpsi (operands[0], operands[2]));
- emit_jump_insn (gen_bltu (label1));
+ emit_cmp_and_jump_insns (operands[0], operands[2], LT, NULL_RTX,
+ SImode, 1, label1);
emit_insn (gen_abssi2 (operands[0], operands[2]));
emit_insn (gen_addsi3 (operands[0], operands[0], operands[1]));
emit_label (label1);
@@ -5685,12 +5643,12 @@
operands[2] = make_safe_from (operands[2], operands[0]);
emit_move_insn(operands[0], operands[1]);
- emit_insn (gen_cmpsi (operands[2], operands[1]));
- emit_jump_insn (gen_bgtu (label3));
- emit_insn (gen_cmpsi (operands[2], const0_rtx));
- emit_jump_insn (gen_blt (label2));
- emit_insn (gen_cmpsi (operands[2], const1_rtx));
- emit_jump_insn (gen_beq (label1));
+ emit_cmp_and_jump_insns (operands[2], operands[1], GT, NULL_RTX,
+ SImode, 1, label3);
+ emit_cmp_and_jump_insns (operands[2], const0_rtx, LT, NULL_RTX,
+ SImode, 0, label2);
+ emit_cmp_and_jump_insns (operands[2], const1_rtx, EQ, NULL_RTX,
+ SImode, 0, label1);
emit_insn (gen_zero_extendsidi2 (operands[3], operands[1]));
insn = emit_insn (gen_divmoddisi3 (operands[3], operands[3],
operands[2]));
@@ -7359,15 +7317,42 @@
;; Branch instruction patterns.
;;
-(define_expand "b<code>"
+(define_expand "cbranch<mode>4"
[(set (pc)
- (if_then_else (COMPARE (match_operand 0 "" "")
- (const_int 0))
- (match_dup 0)
+ (if_then_else (match_operator 0 "comparison_operator"
+ [(match_operand:GPR 1 "register_operand" "")
+ (match_operand:GPR 2 "general_operand" "")])
+ (label_ref (match_operand 3 "" ""))
(pc)))]
""
- "s390_emit_jump (operands[0],
- s390_emit_compare (<CODE>, s390_compare_op0, s390_compare_op1)); DONE;")
+ "s390_emit_jump (operands[3],
+ s390_emit_compare (GET_CODE (operands[0]), operands[1], operands[2]));
+ DONE;")
+
+(define_expand "cbranch<mode>4"
+ [(set (pc)
+ (if_then_else (match_operator 0 "comparison_operator"
+ [(match_operand:FP 1 "register_operand" "")
+ (match_operand:FP 2 "general_operand" "")])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
+ "TARGET_HARD_FLOAT"
+ "s390_emit_jump (operands[3],
+ s390_emit_compare (GET_CODE (operands[0]), operands[1], operands[2]));
+ DONE;")
+
+(define_expand "cbranchcc4"
+ [(set (pc)
+ (if_then_else (match_operator 0 "s390_eqne_operator"
+ [(match_operand 1 "cc_reg_operand" "")
+ (match_operand 2 "const0_operand" "")])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
+ "TARGET_HARD_FLOAT"
+ "s390_emit_jump (operands[3],
+ s390_emit_compare (GET_CODE (operands[0]), operands[1], operands[2]));
+ DONE;")
+
;;
@@ -7506,18 +7491,36 @@
[(set_attr "op_type" "RI")
(set_attr "type" "branch")])
-(define_expand "conditional_trap"
- [(trap_if (match_operand 0 "comparison_operator" "")
- (match_operand 1 "general_operand" ""))]
+(define_expand "ctrap<mode>4"
+ [(trap_if (match_operator 0 "comparison_operator"
+ [(match_operand:GPR 1 "register_operand" "")
+ (match_operand:GPR 2 "general_operand" "")])
+ (match_operand 3 "const0_operand" ""))]
""
-{
- if (operands[1] != const0_rtx) FAIL;
- operands[0] = s390_emit_compare (GET_CODE (operands[0]),
- s390_compare_op0, s390_compare_op1);
-})
+ {
+ rtx cond = s390_emit_compare (GET_CODE (operands[0]),
+ operands[1], operands[2]);
+ emit_insn (gen_condtrap (cond, XEXP (cond, 0)));
+ DONE;
+ })
+
+(define_expand "ctrap<mode>4"
+ [(trap_if (match_operator 0 "comparison_operator"
+ [(match_operand:FP 1 "register_operand" "")
+ (match_operand:FP 2 "general_operand" "")])
+ (match_operand 3 "const0_operand" ""))]
+ ""
+ {
+ rtx cond = s390_emit_compare (GET_CODE (operands[0]),
+ operands[1], operands[2]);
+ emit_insn (gen_condtrap (cond, XEXP (cond, 0)));
+ DONE;
+ })
-(define_insn "*trap"
- [(trap_if (match_operator 0 "s390_comparison" [(reg CC_REGNUM) (const_int 0)])
+(define_insn "condtrap"
+ [(trap_if (match_operator 0 "s390_comparison"
+ [(match_operand 1 "cc_reg_operand" "c")
+ (const_int 0)])
(const_int 0))]
""
"j%C0\t.+2";
@@ -8665,6 +8668,7 @@
(match_operand 2 "" "")]
""
{
+ rtx cc_reg, test;
#ifdef TARGET_THREAD_SSP_OFFSET
operands[1]
= gen_rtx_MEM (Pmode, gen_rtx_PLUS (Pmode, s390_get_thread_pointer (),
@@ -8675,9 +8679,9 @@
else
emit_insn (gen_stack_protect_testsi (operands[0], operands[1]));
- s390_compare_op0 = gen_rtx_REG (CCZmode, CC_REGNUM);
- s390_compare_op1 = const0_rtx;
- emit_jump_insn (gen_beq (operands[2]));
+ cc_reg = gen_rtx_REG (CCZmode, CC_REGNUM);
+ test = gen_rtx_EQ (VOIDmode, cc_reg, const0_rtx);
+ emit_jump_insn (gen_cbranchcc4 (test, cc_reg, const0_rtx, operands[2]));
DONE;
})
diff --git a/gcc/config/score/score-conv.h b/gcc/config/score/score-conv.h
index 67855da895e..e042dc1b7d3 100644
--- a/gcc/config/score/score-conv.h
+++ b/gcc/config/score/score-conv.h
@@ -22,11 +22,6 @@
extern int target_flags;
-/* Define the information needed to generate branch insns. This is
- stored from the compare operation. */
-extern GTY(()) rtx cmp_op0;
-extern GTY(()) rtx cmp_op1;
-
#define GP_REG_FIRST 0U
#define GP_REG_LAST 31U
#define GP_REG_NUM (GP_REG_LAST - GP_REG_FIRST + 1U)
diff --git a/gcc/config/score/score-protos.h b/gcc/config/score/score-protos.h
index d6739b8cf4c..204dc1876a4 100644
--- a/gcc/config/score/score-protos.h
+++ b/gcc/config/score/score-protos.h
@@ -25,7 +25,6 @@ enum score_mem_unit {SCORE_BYTE = 0, SCORE_HWORD = 1, SCORE_WORD = 2};
#define SCORE_ALIGN_UNIT(V, UNIT) !(V & ((1 << UNIT) - 1))
-extern void score_gen_cmp (enum machine_mode mode);
extern void score_prologue (void);
extern void score_epilogue (int sibcall_p);
extern void score_call (rtx *ops, bool sib);
diff --git a/gcc/config/score/score.c b/gcc/config/score/score.c
index 2ac3021bf5e..e517eeb6608 100644
--- a/gcc/config/score/score.c
+++ b/gcc/config/score/score.c
@@ -117,7 +117,6 @@
#define TARGET_ADDRESS_COST score_address_cost
struct extern_list *extern_head = 0;
-rtx cmp_op0, cmp_op1;
/* default 0 = NO_REGS */
enum reg_class score_char_to_class[256];
@@ -698,17 +697,6 @@ score_epilogue (int sibcall_p)
gcc_unreachable ();
}
-void
-score_gen_cmp (enum machine_mode mode)
-{
- if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
- return score7_gen_cmp (mode);
- else if (TARGET_SCORE3)
- return score3_gen_cmp (mode);
-
- gcc_unreachable ();
-}
-
/* Call and sibcall pattern all need call this function. */
void
score_call (rtx *ops, bool sib)
@@ -1118,7 +1106,7 @@ score_block_move_loop (rtx dst, rtx src, HOST_WIDE_INT length)
HOST_WIDE_INT loop_mov_bytes;
HOST_WIDE_INT iteration = 0;
HOST_WIDE_INT head_length = 0, leftover;
- rtx label, src_reg, dst_reg, final_dst;
+ rtx label, src_reg, dst_reg, final_dst, test;
bool gen_loop_head = (src_align < BITS_PER_WORD
|| dst_align < BITS_PER_WORD);
@@ -1158,8 +1146,8 @@ score_block_move_loop (rtx dst, rtx src, HOST_WIDE_INT length)
score_block_move_loop_body (dst_reg, dst_align,
src_reg, src_align, loop_mov_bytes);
- emit_insn (gen_cmpsi (dst_reg, final_dst));
- emit_jump_insn (gen_bne (label));
+ test = gen_rtx_NE (VOIDmode, dst_reg, final_dst);
+ emit_jump_insn (gen_cbranchsi4 (test, dst_reg, final_dst, label));
score_block_move_loop_foot (dst_reg, dst_align,
src_reg, src_align, leftover);
diff --git a/gcc/config/score/score.md b/gcc/config/score/score.md
index e616c57aa7e..b426e14e0ac 100644
--- a/gcc/config/score/score.md
+++ b/gcc/config/score/score.md
@@ -2175,6 +2175,20 @@
(set_attr "length" "4,4")
(set_attr "mode" "SI")])
+(define_expand "cbranchsi4"
+ [(set (reg:CC CC_REGNUM)
+ (compare:CC (match_operand:SI 1 "score_register_operand" "")
+ (match_operand:SI 2 "arith_operand" "")))
+ (set (pc)
+ (if_then_else
+ (match_operator 0 "ordered_comparison_operator"
+ [(reg:CC CC_REGNUM)
+ (const_int 0)])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
+ ""
+ "")
+
(define_insn "cbrancheqz"
[(set (pc) (if_then_else
(eq (match_operand:SI 0 "score_register_operand" "d")
@@ -2259,16 +2273,6 @@
(const_int 4)
(const_int 6)))])
-(define_expand "cmpsi"
- [(match_operand:SI 0 "score_register_operand")
- (match_operand:SI 1 "arith_operand")]
- ""
-{
- cmp_op0 = operands[0];
- cmp_op1 = operands[1];
- DONE;
-})
-
(define_insn "cmpsi_nz_score7"
[(set (reg:CC_NZ CC_REGNUM)
(compare:CC_NZ (match_operand:SI 0 "register_operand" "d,e,d")
@@ -2375,106 +2379,6 @@
(set_attr "up_c" "yes")
(set_attr "mode" "SI")])
-(define_expand "beq"
- [(set (pc)
- (if_then_else (eq (reg:CC CC_REGNUM) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- score_gen_cmp (CCmode);
-})
-
-(define_expand "bne"
- [(set (pc)
- (if_then_else (ne (reg:CC CC_REGNUM) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- score_gen_cmp (CCmode);
-})
-
-(define_expand "bgt"
- [(set (pc)
- (if_then_else (gt (reg:CC CC_REGNUM) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- score_gen_cmp (CCmode);
-})
-
-(define_expand "ble"
- [(set (pc)
- (if_then_else (le (reg:CC CC_REGNUM) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- score_gen_cmp (CCmode);
-})
-
-(define_expand "bge"
- [(set (pc)
- (if_then_else (ge (reg:CC CC_REGNUM) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- score_gen_cmp (CCmode);
-})
-
-(define_expand "blt"
- [(set (pc)
- (if_then_else (lt (reg:CC CC_REGNUM) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- score_gen_cmp (CCmode);
-})
-
-(define_expand "bgtu"
- [(set (pc)
- (if_then_else (gtu (reg:CC CC_REGNUM) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- score_gen_cmp (CCmode);
-})
-
-(define_expand "bleu"
- [(set (pc)
- (if_then_else (leu (reg:CC CC_REGNUM) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- score_gen_cmp (CCmode);
-})
-
-(define_expand "bgeu"
- [(set (pc)
- (if_then_else (geu (reg:CC CC_REGNUM) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- score_gen_cmp (CCmode);
-})
-
-(define_expand "bltu"
- [(set (pc)
- (if_then_else (ltu (reg:CC CC_REGNUM) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- score_gen_cmp (CCmode);
-})
-
(define_insn "*branch_n_score7"
[(set (pc)
(if_then_else
diff --git a/gcc/config/score/score3.c b/gcc/config/score/score3.c
index 9e41452c03d..3ddc3b8c798 100644
--- a/gcc/config/score/score3.c
+++ b/gcc/config/score/score3.c
@@ -54,9 +54,6 @@
#define BITSET_P(VALUE, BIT) (((VALUE) & (1L << (BIT))) != 0)
#define INS_BUF_SZ 128
-/* Define the information needed to generate branch insns. This is
- stored from the compare operation. */
-extern rtx cmp_op0, cmp_op1;
extern enum reg_class score_char_to_class[256];
static int score3_sdata_max;
@@ -1647,13 +1644,6 @@ score3_epilogue (int sibcall_p)
emit_jump_insn (gen_return_internal_score3 (gen_rtx_REG (Pmode, RA_REGNUM)));
}
-void
-score3_gen_cmp (enum machine_mode mode)
-{
- emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_REG (mode, CC_REGNUM),
- gen_rtx_COMPARE (mode, cmp_op0, cmp_op1)));
-}
-
/* Return true if X is a symbolic constant that can be calculated in
the same way as a bare symbol. If it is, store the type of the
symbol in *SYMBOL_TYPE. */
@@ -1692,7 +1682,8 @@ score3_movsicc (rtx *ops)
mode = score3_select_cc_mode (GET_CODE (ops[1]), ops[2], ops[3]);
emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_REG (mode, CC_REGNUM),
- gen_rtx_COMPARE (mode, cmp_op0, cmp_op1)));
+ gen_rtx_COMPARE (mode, XEXP (ops[1], 0),
+ XEXP (ops[1], 1))));
}
/* Call and sibcall pattern all need call this function. */
diff --git a/gcc/config/score/score3.h b/gcc/config/score/score3.h
index c46a8e694d9..d718d12e8d9 100644
--- a/gcc/config/score/score3.h
+++ b/gcc/config/score/score3.h
@@ -138,7 +138,6 @@ extern enum machine_mode
score3_select_cc_mode (enum rtx_code op, rtx x, rtx y);
extern void score3_prologue (void);
extern void score3_epilogue (int sibcall_p);
-extern void score3_gen_cmp (enum machine_mode mode);
extern void score3_call (rtx *ops, bool sib);
extern void score3_call_value (rtx *ops, bool sib);
extern void score3_movsicc (rtx *ops);
diff --git a/gcc/config/score/score7.c b/gcc/config/score/score7.c
index dc532764edd..661cae73bd3 100644
--- a/gcc/config/score/score7.c
+++ b/gcc/config/score/score7.c
@@ -54,9 +54,6 @@
#define BITSET_P(VALUE, BIT) (((VALUE) & (1L << (BIT))) != 0)
#define INS_BUF_SZ 128
-/* Define the information needed to generate branch insns. This is
- stored from the compare operation. */
-extern rtx cmp_op0, cmp_op1;
extern enum reg_class score_char_to_class[256];
static int score7_sdata_max;
@@ -1531,13 +1528,6 @@ score7_epilogue (int sibcall_p)
emit_jump_insn (gen_return_internal_score7 (gen_rtx_REG (Pmode, RA_REGNUM)));
}
-void
-score7_gen_cmp (enum machine_mode mode)
-{
- emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_REG (mode, CC_REGNUM),
- gen_rtx_COMPARE (mode, cmp_op0, cmp_op1)));
-}
-
/* Return true if X is a symbolic constant that can be calculated in
the same way as a bare symbol. If it is, store the type of the
symbol in *SYMBOL_TYPE. */
@@ -1576,7 +1566,8 @@ score7_movsicc (rtx *ops)
mode = score7_select_cc_mode (GET_CODE (ops[1]), ops[2], ops[3]);
emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_REG (mode, CC_REGNUM),
- gen_rtx_COMPARE (mode, cmp_op0, cmp_op1)));
+ gen_rtx_COMPARE (mode, XEXP (ops[1], 0),
+ XEXP (ops[1], 1))));
}
/* Call and sibcall pattern all need call this function. */
diff --git a/gcc/config/score/score7.h b/gcc/config/score/score7.h
index e2033c74498..0c0a3b20f8e 100644
--- a/gcc/config/score/score7.h
+++ b/gcc/config/score/score7.h
@@ -139,7 +139,6 @@ extern enum machine_mode score7_select_cc_mode (enum rtx_code op,
rtx y);
extern void score7_prologue (void);
extern void score7_epilogue (int sibcall_p);
-extern void score7_gen_cmp (enum machine_mode mode);
extern void score7_call (rtx *ops, bool sib);
extern void score7_call_value (rtx *ops, bool sib);
extern void score7_movsicc (rtx *ops);
diff --git a/gcc/config/sh/predicates.md b/gcc/config/sh/predicates.md
index da9962c9984..ea924d830f5 100644
--- a/gcc/config/sh/predicates.md
+++ b/gcc/config/sh/predicates.md
@@ -552,6 +552,17 @@
(and (match_code "minus,div")
(match_test "GET_MODE (op) == mode")))
+;; UNORDERED is only supported on SHMEDIA.
+
+(define_predicate "sh_float_comparison_operator"
+ (ior (match_operand 0 "ordered_comparison_operator")
+ (and (match_test "TARGET_SHMEDIA")
+ (match_code "unordered"))))
+
+(define_predicate "shmedia_cbranch_comparison_operator"
+ (ior (match_operand 0 "equality_comparison_operator")
+ (match_operand 0 "greater_comparison_operator")))
+
;; TODO: Add a comment here.
(define_predicate "sh_const_vec"
diff --git a/gcc/config/sh/sh-protos.h b/gcc/config/sh/sh-protos.h
index a484b9c5d05..0c89f17b15d 100644
--- a/gcc/config/sh/sh-protos.h
+++ b/gcc/config/sh/sh-protos.h
@@ -41,7 +41,6 @@ enum sh_function_kind {
extern rtx sh_fsca_sf2int (void);
extern rtx sh_fsca_df2int (void);
extern rtx sh_fsca_int2sf (void);
-extern struct rtx_def *prepare_scc_operands (enum rtx_code);
/* Declare functions defined in sh.c and used in templates. */
@@ -72,7 +71,10 @@ extern enum rtx_code prepare_cbranch_operands (rtx *, enum machine_mode mode,
enum rtx_code comparison);
extern void expand_cbranchsi4 (rtx *operands, enum rtx_code comparison, int);
extern bool expand_cbranchdi4 (rtx *operands, enum rtx_code comparison);
-extern void from_compare (rtx *, int);
+extern void sh_emit_scc_to_t (enum rtx_code, rtx, rtx);
+extern rtx sh_emit_cheap_store_flag (enum machine_mode, enum rtx_code, rtx, rtx);
+extern void sh_emit_compare_and_branch (rtx *, enum machine_mode);
+extern void sh_emit_compare_and_set (rtx *, enum machine_mode);
extern int shift_insns_rtx (rtx);
extern void gen_ashift (int, int, rtx);
extern void gen_ashift_hi (int, int, rtx);
@@ -117,7 +119,7 @@ extern int sh_insn_length_adjustment (rtx);
extern int sh_can_redirect_branch (rtx, rtx);
extern void sh_expand_unop_v2sf (enum rtx_code, rtx, rtx);
extern void sh_expand_binop_v2sf (enum rtx_code, rtx, rtx, rtx);
-extern int sh_expand_t_scc (enum rtx_code code, rtx target);
+extern int sh_expand_t_scc (rtx *);
extern rtx sh_gen_truncate (enum machine_mode, rtx, int);
extern bool sh_vector_mode_supported_p (enum machine_mode);
#endif /* RTX_CODE */
diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c
index d23a45a2289..e25cd42e871 100644
--- a/gcc/config/sh/sh.c
+++ b/gcc/config/sh/sh.c
@@ -105,12 +105,6 @@ static int skip_cycles = 0;
and returned from sh_reorder2. */
static short cached_can_issue_more;
-/* Saved operands from the last compare to use when we generate an scc
- or bcc insn. */
-
-rtx sh_compare_op0;
-rtx sh_compare_op1;
-
/* Provides the class number of the smallest class containing
reg number. */
@@ -1677,10 +1671,26 @@ expand_cbranchdi4 (rtx *operands, enum rtx_code comparison)
return true;
}
+/* Emit INSN, possibly in a PARALLEL with an USE of fpscr for SH4. */
+
+static void
+sh_emit_set_t_insn (rtx insn, enum machine_mode mode)
+{
+ if ((TARGET_SH4 || TARGET_SH2A) && GET_MODE_CLASS (mode) == MODE_FLOAT)
+ {
+ insn = gen_rtx_PARALLEL (VOIDmode,
+ gen_rtvec (2, insn,
+ gen_rtx_USE (VOIDmode, get_fpscr_rtx ())));
+ (mode == SFmode ? emit_sf_insn : emit_df_insn) (insn);
+ }
+ else
+ emit_insn (insn);
+}
+
/* Prepare the operands for an scc instruction; make sure that the
- compare has been done. */
-rtx
-prepare_scc_operands (enum rtx_code code)
+ compare has been done and the result is in T_REG. */
+void
+sh_emit_scc_to_t (enum rtx_code code, rtx op0, rtx op1)
{
rtx t_reg = gen_rtx_REG (SImode, T_REG);
enum rtx_code oldcode = code;
@@ -1709,77 +1719,222 @@ prepare_scc_operands (enum rtx_code code)
}
if (code != oldcode)
{
- rtx tmp = sh_compare_op0;
- sh_compare_op0 = sh_compare_op1;
- sh_compare_op1 = tmp;
+ rtx tmp = op0;
+ op0 = op1;
+ op1 = tmp;
}
- mode = GET_MODE (sh_compare_op0);
+ mode = GET_MODE (op0);
if (mode == VOIDmode)
- mode = GET_MODE (sh_compare_op1);
+ mode = GET_MODE (op1);
- sh_compare_op0 = force_reg (mode, sh_compare_op0);
+ op0 = force_reg (mode, op0);
if ((code != EQ && code != NE
- && (sh_compare_op1 != const0_rtx
+ && (op1 != const0_rtx
|| code == GTU || code == GEU || code == LTU || code == LEU))
- || (mode == DImode && sh_compare_op1 != const0_rtx)
+ || (mode == DImode && op1 != const0_rtx)
|| (TARGET_SH2E && GET_MODE_CLASS (mode) == MODE_FLOAT))
- sh_compare_op1 = force_reg (mode, sh_compare_op1);
+ op1 = force_reg (mode, op1);
- if ((TARGET_SH4 || TARGET_SH2A) && GET_MODE_CLASS (mode) == MODE_FLOAT)
- (mode == SFmode ? emit_sf_insn : emit_df_insn)
- (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2,
- gen_rtx_SET (VOIDmode, t_reg,
- gen_rtx_fmt_ee (code, SImode,
- sh_compare_op0, sh_compare_op1)),
- gen_rtx_USE (VOIDmode, get_fpscr_rtx ()))));
- else
- emit_insn (gen_rtx_SET (VOIDmode, t_reg,
- gen_rtx_fmt_ee (code, SImode,
- sh_compare_op0, sh_compare_op1)));
+ sh_emit_set_t_insn (gen_rtx_SET (VOIDmode, t_reg,
+ gen_rtx_fmt_ee (code, SImode, op0, op1)),
+ mode);
+}
- return t_reg;
+rtx
+sh_emit_cheap_store_flag (enum machine_mode mode, enum rtx_code code,
+ rtx op0, rtx op1)
+{
+ rtx target = gen_reg_rtx (SImode);
+ rtx tmp;
+
+ gcc_assert (TARGET_SHMEDIA);
+ switch (code)
+ {
+ case EQ:
+ case GT:
+ case LT:
+ case UNORDERED:
+ case GTU:
+ case LTU:
+ tmp = gen_rtx_fmt_ee (code, SImode, op0, op1);
+ emit_insn (gen_cstore4_media (target, tmp, op0, op1));
+ code = NE;
+ break;
+
+ case NE:
+ case GE:
+ case LE:
+ case ORDERED:
+ case GEU:
+ case LEU:
+ tmp = gen_rtx_fmt_ee (reverse_condition (code), mode, op0, op1);
+ emit_insn (gen_cstore4_media (target, tmp, op0, op1));
+ code = EQ;
+ break;
+
+ case UNEQ:
+ case UNGE:
+ case UNGT:
+ case UNLE:
+ case UNLT:
+ case LTGT:
+ return NULL_RTX;
+
+ default:
+ gcc_unreachable ();
+ }
+
+ if (mode == DImode)
+ {
+ rtx t2 = gen_reg_rtx (DImode);
+ emit_insn (gen_extendsidi2 (t2, target));
+ target = t2;
+ }
+
+ return gen_rtx_fmt_ee (code, VOIDmode, target, const0_rtx);
}
/* Called from the md file, set up the operands of a compare instruction. */
void
-from_compare (rtx *operands, int code)
+sh_emit_compare_and_branch (rtx *operands, enum machine_mode mode)
{
- enum machine_mode mode = GET_MODE (sh_compare_op0);
- rtx insn;
- if (mode == VOIDmode)
- mode = GET_MODE (sh_compare_op1);
- if (code != EQ
- || mode == DImode
- || (TARGET_SH2E && GET_MODE_CLASS (mode) == MODE_FLOAT))
+ enum rtx_code code = GET_CODE (operands[0]);
+ enum rtx_code branch_code;
+ rtx op0 = operands[1];
+ rtx op1 = operands[2];
+ rtx insn, tem;
+ bool need_ccmpeq = false;
+
+ if (TARGET_SH2E && GET_MODE_CLASS (mode) == MODE_FLOAT)
{
- /* Force args into regs, since we can't use constants here. */
- sh_compare_op0 = force_reg (mode, sh_compare_op0);
- if (sh_compare_op1 != const0_rtx
- || code == GTU || code == GEU
- || (TARGET_SH2E && GET_MODE_CLASS (mode) == MODE_FLOAT))
- sh_compare_op1 = force_reg (mode, sh_compare_op1);
+ op0 = force_reg (mode, op0);
+ op1 = force_reg (mode, op1);
}
- if (TARGET_SH2E && GET_MODE_CLASS (mode) == MODE_FLOAT && code == GE)
+ else
{
- from_compare (operands, GT);
- insn = gen_ieee_ccmpeqsf_t (sh_compare_op0, sh_compare_op1);
+ if (code != EQ || mode == DImode)
+ {
+ /* Force args into regs, since we can't use constants here. */
+ op0 = force_reg (mode, op0);
+ if (op1 != const0_rtx || code == GTU || code == GEU)
+ op1 = force_reg (mode, op1);
+ }
}
+
+ if (GET_MODE_CLASS (mode) == MODE_FLOAT)
+ {
+ if (code == LT
+ || (code == LE && TARGET_IEEE && TARGET_SH2E)
+ || (code == GE && !(TARGET_IEEE && TARGET_SH2E)))
+ {
+ tem = op0, op0 = op1, op1 = tem;
+ code = swap_condition (code);
+ }
+
+ /* GE becomes fcmp/gt+fcmp/eq, for SH2E and TARGET_IEEE only. */
+ if (code == GE)
+ {
+ gcc_assert (TARGET_IEEE && TARGET_SH2E);
+ need_ccmpeq = true;
+ code = GT;
+ }
+
+ /* Now we can have EQ, NE, GT, LE. NE and LE are then transformed
+ to EQ/GT respectively. */
+ gcc_assert (code == EQ || code == GT || code == NE || code == LE);
+ }
+
+ switch (code)
+ {
+ case EQ:
+ case GT:
+ case GE:
+ case GTU:
+ case GEU:
+ branch_code = code;
+ break;
+ case NE:
+ case LT:
+ case LE:
+ case LTU:
+ case LEU:
+ branch_code = reverse_condition (code);
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+ insn = gen_rtx_SET (VOIDmode,
+ gen_rtx_REG (SImode, T_REG),
+ gen_rtx_fmt_ee (branch_code, SImode, op0, op1));
+
+ sh_emit_set_t_insn (insn, mode);
+ if (need_ccmpeq)
+ sh_emit_set_t_insn (gen_ieee_ccmpeqsf_t (op0, op1), mode);
+
+ if (branch_code == code)
+ emit_jump_insn (gen_branch_true (operands[3]));
else
- insn = gen_rtx_SET (VOIDmode,
- gen_rtx_REG (SImode, T_REG),
- gen_rtx_fmt_ee ((enum rtx_code) code, SImode,
- sh_compare_op0, sh_compare_op1));
- if ((TARGET_SH4 || TARGET_SH2A) && GET_MODE_CLASS (mode) == MODE_FLOAT)
+ emit_jump_insn (gen_branch_false (operands[3]));
+}
+
+void
+sh_emit_compare_and_set (rtx *operands, enum machine_mode mode)
+{
+ enum rtx_code code = GET_CODE (operands[1]);
+ rtx op0 = operands[2];
+ rtx op1 = operands[3];
+ rtx lab = NULL_RTX;
+ bool invert = false;
+ rtx tem;
+
+ op0 = force_reg (mode, op0);
+ if ((code != EQ && code != NE
+ && (op1 != const0_rtx
+ || code == GTU || code == GEU || code == LTU || code == LEU))
+ || (mode == DImode && op1 != const0_rtx)
+ || (TARGET_SH2E && GET_MODE_CLASS (mode) == MODE_FLOAT))
+ op1 = force_reg (mode, op1);
+
+ if (GET_MODE_CLASS (mode) == MODE_FLOAT)
{
- insn = gen_rtx_PARALLEL (VOIDmode,
- gen_rtvec (2, insn,
- gen_rtx_USE (VOIDmode, get_fpscr_rtx ())));
- (mode == SFmode ? emit_sf_insn : emit_df_insn) (insn);
+ if (code == LT || code == LE)
+ {
+ code = swap_condition (code);
+ tem = op0, op0 = op1, op1 = tem;
+ }
+ if (code == GE)
+ {
+ if (TARGET_IEEE)
+ {
+ lab = gen_label_rtx ();
+ sh_emit_scc_to_t (EQ, op0, op1);
+ emit_jump_insn (gen_branch_true (lab));
+ code = GT;
+ }
+ else
+ {
+ code = LT;
+ invert = true;
+ }
+ }
}
+
+ if (code == NE)
+ {
+ code = EQ;
+ invert = true;
+ }
+
+ sh_emit_scc_to_t (code, op0, op1);
+ if (lab)
+ emit_label (lab);
+ if (invert)
+ emit_insn (gen_movnegt (operands[0]));
else
- emit_insn (insn);
+ emit_move_insn (operands[0], gen_rtx_REG (SImode, T_REG));
}
/* Functions to output assembly code. */
@@ -10782,17 +10937,21 @@ sh_get_pr_initial_val (void)
}
int
-sh_expand_t_scc (enum rtx_code code, rtx target)
+sh_expand_t_scc (rtx operands[])
{
+ enum rtx_code code = GET_CODE (operands[1]);
+ rtx target = operands[0];
+ rtx op0 = operands[2];
+ rtx op1 = operands[3];
rtx result = target;
HOST_WIDE_INT val;
- if (GET_CODE (sh_compare_op0) != REG || REGNO (sh_compare_op0) != T_REG
- || GET_CODE (sh_compare_op1) != CONST_INT)
+ if (GET_CODE (op0) != REG || REGNO (op0) != T_REG
+ || GET_CODE (op1) != CONST_INT)
return 0;
if (GET_CODE (result) != REG)
result = gen_reg_rtx (SImode);
- val = INTVAL (sh_compare_op1);
+ val = INTVAL (op1);
if ((code == EQ && val == 1) || (code == NE && val == 0))
emit_insn (gen_movt (result));
else if (TARGET_SH2A && ((code == EQ && val == 0)
diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md
index dc6a7ab6b82..ffd0db08225 100644
--- a/gcc/config/sh/sh.md
+++ b/gcc/config/sh/sh.md
@@ -646,8 +646,15 @@
(label_ref (match_operand 3 "" ""))
(pc)))
(clobber (reg:SI T_REG))]
- "TARGET_CBRANCHDI4"
- "expand_cbranchsi4 (operands, LAST_AND_UNUSED_RTX_CODE, -1); DONE;")
+ ""
+ "if (TARGET_SHMEDIA)
+ emit_jump_insn (gen_cbranchint4_media (operands[0], operands[1],
+ operands[2], operands[3]));
+ else if (TARGET_CBRANCHDI4)
+ expand_cbranchsi4 (operands, LAST_AND_UNUSED_RTX_CODE, -1);
+ else
+ sh_emit_compare_and_branch (operands, SImode);
+ DONE;")
;; -------------------------------------------------------------------------
;; SImode unsigned integer comparisons
@@ -676,23 +683,6 @@
"cmp/hi %1,%0"
[(set_attr "type" "mt_group")])
-;; We save the compare operands in the cmpxx patterns and use them when
-;; we generate the branch.
-
-(define_expand "cmpsi"
- [(set (reg:SI T_REG)
- (compare (match_operand:SI 0 "cmpsi_operand" "")
- (match_operand:SI 1 "arith_operand" "")))]
- "TARGET_SH1 || TARGET_SHMEDIA"
- "
-{
- if (GET_CODE (operands[0]) == REG && REGNO (operands[0]) == T_REG
- && GET_CODE (operands[1]) != CONST_INT)
- operands[0] = copy_to_mode_reg (SImode, operands[0]);
- sh_compare_op0 = operands[0];
- sh_compare_op1 = operands[1];
- DONE;
-}")
;; -------------------------------------------------------------------------
;; DImode compare and branch
@@ -713,29 +703,45 @@
(pc)))
(clobber (match_dup 4))
(clobber (reg:SI T_REG))]
- "TARGET_CBRANCHDI4"
+ "TARGET_CBRANCHDI4 || TARGET_SH2 || TARGET_SHMEDIA"
"
{
enum rtx_code comparison;
- if (TARGET_EXPAND_CBRANCHDI4)
+ if (TARGET_SHMEDIA)
+ {
+ emit_jump_insn (gen_cbranchint4_media (operands[0], operands[1],
+ operands[2], operands[3]));
+ DONE;
+ }
+
+ else if (!TARGET_CBRANCHDI4)
+ {
+ sh_emit_compare_and_branch (operands, DImode);
+ DONE;
+ }
+
+ else
{
- if (expand_cbranchdi4 (operands, LAST_AND_UNUSED_RTX_CODE))
- DONE;
+ if (TARGET_EXPAND_CBRANCHDI4)
+ {
+ if (expand_cbranchdi4 (operands, LAST_AND_UNUSED_RTX_CODE))
+ DONE;
+ }
+ comparison = prepare_cbranch_operands (operands, DImode,
+ LAST_AND_UNUSED_RTX_CODE);
+ if (comparison != GET_CODE (operands[0]))
+ operands[0]
+ = gen_rtx_fmt_ee (comparison, VOIDmode, operands[1], operands[2]);
+ operands[4] = gen_rtx_SCRATCH (SImode);
}
- comparison = prepare_cbranch_operands (operands, DImode,
- LAST_AND_UNUSED_RTX_CODE);
- if (comparison != GET_CODE (operands[0]))
- operands[0]
- = gen_rtx_fmt_ee (comparison, VOIDmode, operands[1], operands[2]);
- operands[4] = gen_rtx_SCRATCH (SImode);
}")
(define_insn_and_split "cbranchdi4_i"
[(set (pc)
(if_then_else (match_operator 0 "comparison_operator"
[(match_operand:DI 1 "arith_operand" "r,r")
- (match_operand:DI 2 "arith_operand" "rN,i")])
+ (match_operand:DI 2 "arith_operand" "rN,I08")])
(label_ref (match_operand 3 "" ""))
(pc)))
(clobber (match_scratch:SI 4 "=X,&r"))
@@ -907,20 +913,6 @@
"cmpgtu %1,r63,%0"
[(set_attr "type" "cmp_media")])
-;; We save the compare operands in the cmpxx patterns and use them when
-;; we generate the branch.
-
-(define_expand "cmpdi"
- [(set (reg:SI T_REG)
- (compare (match_operand:DI 0 "arith_operand" "")
- (match_operand:DI 1 "arith_operand" "")))]
- "TARGET_SH2 || TARGET_SHMEDIA"
- "
-{
- sh_compare_op0 = operands[0];
- sh_compare_op1 = operands[1];
- DONE;
-}")
;; -------------------------------------------------------------------------
;; Conditional move instructions
;; -------------------------------------------------------------------------
@@ -988,92 +980,20 @@
"
{
if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
- && GET_MODE (sh_compare_op0) == DImode
- && sh_compare_op1 == const0_rtx)
- operands[1] = gen_rtx_fmt_ee (GET_CODE (operands[1]), VOIDmode,
- sh_compare_op0, sh_compare_op1);
+ && GET_MODE (XEXP (operands[1], 0)) == DImode
+ && XEXP (operands[1], 1) == const0_rtx)
+ ;
else
{
- rtx tmp;
-
if (!can_create_pseudo_p ())
FAIL;
- tmp = gen_reg_rtx (DImode);
-
- switch (GET_CODE (operands[1]))
- {
- case EQ:
- emit_insn (gen_seq (tmp));
- operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
- break;
-
- case NE:
- emit_insn (gen_seq (tmp));
- operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
- break;
-
- case GT:
- emit_insn (gen_sgt (tmp));
- operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
- break;
-
- case LT:
- emit_insn (gen_slt (tmp));
- operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
- break;
-
- case GE:
- emit_insn (gen_slt (tmp));
- operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
- break;
-
- case LE:
- emit_insn (gen_sgt (tmp));
- operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
- break;
-
- case GTU:
- emit_insn (gen_sgtu (tmp));
- operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
- break;
-
- case LTU:
- emit_insn (gen_sltu (tmp));
- operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
- break;
-
- case GEU:
- emit_insn (gen_sltu (tmp));
- operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
- break;
-
- case LEU:
- emit_insn (gen_sgtu (tmp));
- operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
- break;
-
- case UNORDERED:
- emit_insn (gen_sunordered (tmp));
- operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
- break;
-
- case ORDERED:
- emit_insn (gen_sunordered (tmp));
- operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
- break;
-
- case UNEQ:
- case UNGE:
- case UNGT:
- case UNLE:
- case UNLT:
- case LTGT:
- FAIL;
-
- default:
- gcc_unreachable ();
- }
+ operands[1] = sh_emit_cheap_store_flag (GET_MODE (operands[0]),
+ GET_CODE (operands[1]),
+ XEXP (operands[1], 0),
+ XEXP (operands[1], 1));
+ if (!operands[1])
+ FAIL;
}
}")
@@ -1268,24 +1188,26 @@
"
{
if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
- && GET_MODE (sh_compare_op0) == SImode
+ && GET_MODE (XEXP (operands[1], 0)) == SImode
&& (TARGET_SHMEDIA
- || (REG_P (sh_compare_op0) && REGNO (sh_compare_op0) == T_REG))
- && sh_compare_op1 == const0_rtx)
- operands[1] = gen_rtx_fmt_ee (GET_CODE (operands[1]), VOIDmode,
- sh_compare_op0, sh_compare_op1);
+ || (REG_P (XEXP (operands[1], 0))
+ && REGNO (XEXP (operands[1], 0)) == T_REG))
+ && XEXP (operands[1], 1) == const0_rtx)
+ ;
+
else if (TARGET_PRETEND_CMOVE)
{
enum rtx_code code = GET_CODE (operands[1]);
enum rtx_code new_code = code;
- rtx tmp;
+ rtx op0 = XEXP (operands[1], 0);
+ rtx op1 = XEXP (operands[1], 1);
if (! currently_expanding_to_rtl)
FAIL;
switch (code)
{
case LT: case LE: case LEU: case LTU:
- if (GET_MODE_CLASS (GET_MODE (sh_compare_op0)) != MODE_INT)
+ if (GET_MODE_CLASS (GET_MODE (op0)) != MODE_INT)
break;
case NE:
new_code = reverse_condition (code);
@@ -1295,92 +1217,21 @@
default:
FAIL;
}
- tmp = prepare_scc_operands (new_code);
+ sh_emit_scc_to_t (new_code, op0, op1);
operands[1] = gen_rtx_fmt_ee (new_code == code ? NE : EQ, VOIDmode,
- tmp, const0_rtx);
+ gen_rtx_REG (SImode, T_REG), const0_rtx);
}
else
{
- rtx tmp;
-
if (!can_create_pseudo_p ())
FAIL;
- tmp = gen_reg_rtx (SImode);
-
- switch (GET_CODE (operands[1]))
- {
- case EQ:
- emit_insn (gen_seq (tmp));
- operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
- break;
-
- case NE:
- emit_insn (gen_seq (tmp));
- operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
- break;
-
- case GT:
- emit_insn (gen_sgt (tmp));
- operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
- break;
-
- case LT:
- emit_insn (gen_slt (tmp));
- operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
- break;
-
- case GE:
- emit_insn (gen_slt (tmp));
- operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
- break;
-
- case LE:
- emit_insn (gen_sgt (tmp));
- operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
- break;
-
- case GTU:
- emit_insn (gen_sgtu (tmp));
- operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
- break;
-
- case LTU:
- emit_insn (gen_sltu (tmp));
- operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
- break;
-
- case GEU:
- emit_insn (gen_sltu (tmp));
- operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
- break;
-
- case LEU:
- emit_insn (gen_sgtu (tmp));
- operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
- break;
-
- case UNORDERED:
- emit_insn (gen_sunordered (tmp));
- operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
- break;
-
- case ORDERED:
- emit_insn (gen_sunordered (tmp));
- operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
- break;
-
- case UNEQ:
- case UNGE:
- case UNGT:
- case UNLE:
- case UNLT:
- case LTGT:
- FAIL;
-
- default:
- abort ();
- }
+ operands[1] = sh_emit_cheap_store_flag (GET_MODE (operands[0]),
+ GET_CODE (operands[1]),
+ XEXP (operands[1], 0),
+ XEXP (operands[1], 1));
+ if (!operands[1])
+ FAIL;
}
}")
@@ -1887,8 +1738,9 @@
implemented by comparing with the divisor. */
if (operands[1] == const1_rtx && currently_expanding_to_rtl)
{
- emit_insn (gen_cmpsi (operands[1], operands[2]));
- emit_insn (gen_sgeu (operands[0]));
+ rtx test = gen_rtx_GEU (VOIDmode, operands[1], operands[2]);
+ emit_insn (gen_cstoresi4 (operands[0], test,
+ operands[1], operands[2]));
DONE;
}
else if (operands[2] == const0_rtx)
@@ -6877,14 +6729,83 @@ label:
;; Conditional branch insns
-(define_expand "beq_media"
+(define_expand "cbranchint4_media"
[(set (pc)
- (if_then_else (eq (match_operand:DI 1 "arith_reg_operand" "r,r")
- (match_operand:DI 2 "arith_operand" "r,I06"))
- (match_operand 0 "" "")
+ (if_then_else (match_operator 0 "shmedia_cbranch_comparison_operator"
+ [(match_operand 1 "" "")
+ (match_operand 2 "" "")])
+ (match_operand 3 "" "")
(pc)))]
"TARGET_SHMEDIA"
- "operands[0] = gen_rtx_LABEL_REF (Pmode, operands[0]);")
+ "
+{
+ enum machine_mode mode = GET_MODE (operands[1]);
+ if (mode == VOIDmode)
+ mode = GET_MODE (operands[2]);
+ if (GET_CODE (operands[0]) == EQ || GET_CODE (operands[0]) == NE)
+ {
+ operands[1] = force_reg (mode, operands[1]);
+ if (CONSTANT_P (operands[2])
+ && (! satisfies_constraint_I06 (operands[2])))
+ operands[2] = force_reg (mode, operands[2]);
+ }
+ else
+ {
+ if (operands[1] != const0_rtx)
+ operands[1] = force_reg (mode, operands[1]);
+ if (operands[2] != const0_rtx)
+ operands[2] = force_reg (mode, operands[2]);
+ }
+ switch (GET_CODE (operands[0]))
+ {
+ case LEU:
+ case LE:
+ case LTU:
+ case LT:
+ operands[0] = gen_rtx_fmt_ee (swap_condition (GET_CODE (operands[0])),
+ VOIDmode, operands[2], operands[1]);
+ operands[1] = XEXP (operands[0], 0);
+ operands[2] = XEXP (operands[0], 1);
+ break;
+ default:
+ operands[0] = gen_rtx_fmt_ee (GET_CODE (operands[0]),
+ VOIDmode, operands[1], operands[2]);
+ break;
+ }
+ operands[3] = gen_rtx_LABEL_REF (Pmode, operands[3]);
+}")
+
+(define_expand "cbranchfp4_media"
+ [(set (pc)
+ (if_then_else (match_operator 0 "sh_float_comparison_operator"
+ [(match_operand 1 "" "")
+ (match_operand 2 "" "")])
+ (match_operand 3 "" "")
+ (pc)))]
+ "TARGET_SHMEDIA"
+ "
+{
+ /* hack to generate same code. */
+ rtx tmp_di = GET_CODE (operands[0]) == UNORDERED ? NULL : gen_reg_rtx (DImode);
+ rtx tmp = gen_reg_rtx (SImode);
+ rtx cmp;
+ if (GET_CODE (operands[0]) == NE)
+ cmp = gen_rtx_EQ (SImode, operands[1], operands[2]);
+ else
+ cmp = gen_rtx_fmt_ee (GET_CODE (operands[0]), SImode,
+ operands[1], operands[2]);
+
+ emit_insn (gen_cstore4_media (tmp, cmp, operands[1], operands[2]));
+ if (tmp_di) emit_insn (gen_extendsidi2 (tmp_di, tmp)); else tmp_di = tmp;
+
+ if (GET_CODE (cmp) == GET_CODE (operands[0]))
+ operands[0] = gen_rtx_NE (VOIDmode, tmp_di, const0_rtx);
+ else
+ operands[0] = gen_rtx_EQ (VOIDmode, tmp_di, const0_rtx);
+ operands[1] = tmp_di;
+ operands[2] = const0_rtx;
+ operands[3] = gen_rtx_LABEL_REF (Pmode, operands[3]);
+}")
(define_insn "*beq_media_i"
[(set (pc)
@@ -6912,51 +6833,6 @@ label:
b%o3i%' %1, %2, %0%>"
[(set_attr "type" "cbranch_media")])
-(define_expand "bne_media"
- [(set (pc)
- (if_then_else (ne (match_operand:DI 1 "arith_reg_operand" "r,r")
- (match_operand:DI 2 "arith_operand" "r,I06"))
- (match_operand 0 "" "")
- (pc)))]
- "TARGET_SHMEDIA"
- "operands[0] = gen_rtx_LABEL_REF (Pmode, operands[0]);")
-
-(define_expand "bgt_media"
- [(set (pc)
- (if_then_else (gt (match_operand:DI 1 "arith_reg_or_0_operand" "")
- (match_operand:DI 2 "arith_reg_or_0_operand" ""))
- (match_operand 0 "" "")
- (pc)))]
- "TARGET_SHMEDIA"
- "operands[0] = gen_rtx_LABEL_REF (Pmode, operands[0]);")
-
-(define_expand "bge_media"
- [(set (pc)
- (if_then_else (ge (match_operand:DI 1 "arith_reg_or_0_operand" "")
- (match_operand:DI 2 "arith_reg_or_0_operand" ""))
- (match_operand 0 "" "")
- (pc)))]
- "TARGET_SHMEDIA"
- "operands[0] = gen_rtx_LABEL_REF (Pmode, operands[0]);")
-
-(define_expand "bgtu_media"
- [(set (pc)
- (if_then_else (gtu (match_operand:DI 1 "arith_reg_or_0_operand" "")
- (match_operand:DI 2 "arith_reg_or_0_operand" ""))
- (match_operand 0 "" "")
- (pc)))]
- "TARGET_SHMEDIA"
- "operands[0] = gen_rtx_LABEL_REF (Pmode, operands[0]);")
-
-(define_expand "bgeu_media"
- [(set (pc)
- (if_then_else (geu (match_operand:DI 1 "arith_reg_or_0_operand" "")
- (match_operand:DI 2 "arith_reg_or_0_operand" ""))
- (match_operand 0 "" "")
- (pc)))]
- "TARGET_SHMEDIA"
- "operands[0] = gen_rtx_LABEL_REF (Pmode, operands[0]);")
-
(define_insn "*bgt_media_i"
[(set (pc)
(if_then_else (match_operator 3 "greater_comparison_operator"
@@ -7003,343 +6879,6 @@ label:
"b%o3%' %N2, %N1, %0%>"
[(set_attr "type" "cbranch_media")])
-(define_expand "beq"
- [(set (pc)
- (if_then_else (ne (reg:SI T_REG) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- if (TARGET_SHMEDIA)
- {
- enum machine_mode mode = GET_MODE (sh_compare_op0);
-
- if (mode != DImode && mode != SImode)
- {
- rtx tmp = gen_reg_rtx (DImode);
-
- emit_insn (gen_seq (tmp));
- emit_jump_insn (gen_bne_media (operands[0], tmp, const0_rtx));
- DONE;
- }
-
- sh_compare_op0 = force_reg (mode, sh_compare_op0);
- if (CONSTANT_P (sh_compare_op1)
- && (! satisfies_constraint_I06 (sh_compare_op1)))
- sh_compare_op1 = force_reg (mode, sh_compare_op1);
- emit_jump_insn (gen_beq_media (operands[0],
- sh_compare_op0, sh_compare_op1));
- DONE;
- }
-
- from_compare (operands, EQ);
-}")
-
-(define_expand "bne"
- [(set (pc)
- (if_then_else (eq (reg:SI T_REG) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- if (TARGET_SHMEDIA)
- {
- enum machine_mode mode = GET_MODE (sh_compare_op0);
-
- if (mode != DImode && mode != SImode)
- {
- rtx tmp = gen_reg_rtx (DImode);
-
- emit_insn (gen_seq (tmp));
- emit_jump_insn (gen_beq_media (operands[0], tmp, const0_rtx));
- DONE;
- }
-
- sh_compare_op0 = force_reg (mode, sh_compare_op0);
- if (CONSTANT_P (sh_compare_op1)
- && (! satisfies_constraint_I06 (sh_compare_op1)))
- sh_compare_op1 = force_reg (mode, sh_compare_op1);
- emit_jump_insn (gen_bne_media (operands[0],
- sh_compare_op0, sh_compare_op1));
- DONE;
- }
-
- from_compare (operands, EQ);
-}")
-
-(define_expand "bgt"
- [(set (pc)
- (if_then_else (ne (reg:SI T_REG) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- if (TARGET_SHMEDIA)
- {
- enum machine_mode mode = GET_MODE (sh_compare_op0);
-
- if (mode != DImode && mode != SImode)
- {
- rtx tmp = gen_reg_rtx (DImode);
-
- emit_insn (gen_sgt (tmp));
- emit_jump_insn (gen_bne_media (operands[0], tmp, const0_rtx));
- DONE;
- }
-
- if (sh_compare_op0 != const0_rtx)
- sh_compare_op0 = force_reg (mode, sh_compare_op0);
- if (sh_compare_op1 != const0_rtx)
- sh_compare_op1 = force_reg (mode, sh_compare_op1);
- emit_jump_insn (gen_bgt_media (operands[0],
- sh_compare_op0, sh_compare_op1));
- DONE;
- }
-
- from_compare (operands, GT);
-}")
-
-(define_expand "blt"
- [(set (pc)
- (if_then_else (eq (reg:SI T_REG) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- if (TARGET_SHMEDIA)
- {
- enum machine_mode mode = GET_MODE (sh_compare_op0);
-
- if (mode != DImode && mode != SImode)
- {
- rtx tmp = gen_reg_rtx (DImode);
-
- emit_insn (gen_slt (tmp));
- emit_jump_insn (gen_bne_media (operands[0], tmp, const0_rtx));
- DONE;
- }
-
- if (sh_compare_op0 != const0_rtx)
- sh_compare_op0 = force_reg (mode, sh_compare_op0);
- if (sh_compare_op1 != const0_rtx)
- sh_compare_op1 = force_reg (mode, sh_compare_op1);
- emit_jump_insn (gen_bgt_media (operands[0],
- sh_compare_op1, sh_compare_op0));
- DONE;
- }
-
- if (GET_MODE_CLASS (GET_MODE (sh_compare_op0)) == MODE_FLOAT)
- {
- rtx tmp = sh_compare_op0;
- sh_compare_op0 = sh_compare_op1;
- sh_compare_op1 = tmp;
- emit_insn (gen_bgt (operands[0]));
- DONE;
- }
- from_compare (operands, GE);
-}")
-
-(define_expand "ble"
- [(set (pc)
- (if_then_else (eq (reg:SI T_REG) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- if (TARGET_SHMEDIA)
- {
- enum machine_mode mode = GET_MODE (sh_compare_op0);
-
- if (mode != DImode && mode != SImode)
- {
- rtx tmp = gen_reg_rtx (DImode);
-
- emit_insn (gen_sle (tmp));
- emit_jump_insn (gen_bne_media (operands[0], tmp, const0_rtx));
- DONE;
- }
-
- if (sh_compare_op0 != const0_rtx)
- sh_compare_op0 = force_reg (mode, sh_compare_op0);
- if (sh_compare_op1 != const0_rtx)
- sh_compare_op1 = force_reg (mode, sh_compare_op1);
- emit_jump_insn (gen_bge_media (operands[0],
- sh_compare_op1, sh_compare_op0));
- DONE;
- }
-
- if (TARGET_SH2E
- && TARGET_IEEE
- && GET_MODE_CLASS (GET_MODE (sh_compare_op0)) == MODE_FLOAT)
- {
- rtx tmp = sh_compare_op0;
- sh_compare_op0 = sh_compare_op1;
- sh_compare_op1 = tmp;
- emit_insn (gen_bge (operands[0]));
- DONE;
- }
- from_compare (operands, GT);
-}")
-
-(define_expand "bge"
- [(set (pc)
- (if_then_else (ne (reg:SI T_REG) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- if (TARGET_SHMEDIA)
- {
- enum machine_mode mode = GET_MODE (sh_compare_op0);
-
- if (mode != DImode && mode != SImode)
- {
- rtx tmp = gen_reg_rtx (DImode);
-
- emit_insn (gen_sge (tmp));
- emit_jump_insn (gen_bne_media (operands[0], tmp, const0_rtx));
- DONE;
- }
-
- if (sh_compare_op0 != const0_rtx)
- sh_compare_op0 = force_reg (mode, sh_compare_op0);
- if (sh_compare_op1 != const0_rtx)
- sh_compare_op1 = force_reg (mode, sh_compare_op1);
- emit_jump_insn (gen_bge_media (operands[0],
- sh_compare_op0, sh_compare_op1));
- DONE;
- }
-
- if (TARGET_SH2E
- && ! TARGET_IEEE
- && GET_MODE_CLASS (GET_MODE (sh_compare_op0)) == MODE_FLOAT)
- {
- rtx tmp = sh_compare_op0;
- sh_compare_op0 = sh_compare_op1;
- sh_compare_op1 = tmp;
- emit_insn (gen_ble (operands[0]));
- DONE;
- }
- from_compare (operands, GE);
-}")
-
-(define_expand "bgtu"
- [(set (pc)
- (if_then_else (ne (reg:SI T_REG) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- if (TARGET_SHMEDIA)
- {
- enum machine_mode mode = GET_MODE (sh_compare_op0);
-
- if (sh_compare_op0 != const0_rtx)
- sh_compare_op0 = force_reg (mode, sh_compare_op0);
- if (sh_compare_op1 != const0_rtx)
- sh_compare_op1 = force_reg (mode, sh_compare_op1);
- emit_jump_insn (gen_bgtu_media (operands[0],
- sh_compare_op0, sh_compare_op1));
- DONE;
- }
-
- from_compare (operands, GTU);
-}")
-
-(define_expand "bltu"
- [(set (pc)
- (if_then_else (eq (reg:SI T_REG) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- if (TARGET_SHMEDIA)
- {
- enum machine_mode mode = GET_MODE (sh_compare_op0);
-
- if (sh_compare_op0 != const0_rtx)
- sh_compare_op0 = force_reg (mode, sh_compare_op0);
- if (sh_compare_op1 != const0_rtx)
- sh_compare_op1 = force_reg (mode, sh_compare_op1);
- emit_jump_insn (gen_bgtu_media (operands[0],
- sh_compare_op1, sh_compare_op0));
- DONE;
- }
-
- from_compare (operands, GEU);
-}")
-
-(define_expand "bgeu"
- [(set (pc)
- (if_then_else (ne (reg:SI T_REG) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- if (TARGET_SHMEDIA)
- {
- enum machine_mode mode = GET_MODE (sh_compare_op0);
-
- if (sh_compare_op0 != const0_rtx)
- sh_compare_op0 = force_reg (mode, sh_compare_op0);
- if (sh_compare_op1 != const0_rtx)
- sh_compare_op1 = force_reg (mode, sh_compare_op1);
- emit_jump_insn (gen_bgeu_media (operands[0],
- sh_compare_op0, sh_compare_op1));
- DONE;
- }
-
- from_compare (operands, GEU);
-}")
-
-(define_expand "bleu"
- [(set (pc)
- (if_then_else (eq (reg:SI T_REG) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "
-{
- if (TARGET_SHMEDIA)
- {
- enum machine_mode mode = GET_MODE (sh_compare_op0);
-
- if (sh_compare_op0 != const0_rtx)
- sh_compare_op0 = force_reg (mode, sh_compare_op0);
- if (sh_compare_op1 != const0_rtx)
- sh_compare_op1 = force_reg (mode, sh_compare_op1);
- emit_jump_insn (gen_bgeu_media (operands[0],
- sh_compare_op1, sh_compare_op0));
- DONE;
- }
-
- from_compare (operands, GTU);
-}")
-
-(define_expand "bunordered"
- [(set (match_dup 1) (unordered:SI (match_dup 2) (match_dup 3)))
- (set (pc)
- (if_then_else (ne (match_dup 1) (const_int 0))
- (match_operand 0 "" "")
- (pc)))]
- "TARGET_SHMEDIA"
- "
-{
- operands[0] = gen_rtx_LABEL_REF (Pmode, operands[0]);
- operands[1] = gen_reg_rtx (SImode);
- operands[2] = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
- operands[3] = force_reg (GET_MODE (sh_compare_op1), sh_compare_op1);
-}")
-
;; combiner splitter for test-and-branch on single bit in register. This
;; is endian dependent because the non-paradoxical subreg looks different
;; on big endian.
@@ -9120,15 +8659,17 @@ mov.l\\t1f,r0\\n\\
rtx reg3 = gen_reg_rtx (Pmode);
rtx reg4 = gen_reg_rtx (Pmode);
rtx reg5 = gen_reg_rtx (Pmode);
- rtx load;
+ rtx load, test;
operands[0] = convert_modes (DImode, SImode, operands[0], 0);
operands[1] = convert_modes (DImode, SImode, operands[1], 0);
operands[2] = convert_modes (DImode, SImode, operands[2], 1);
- emit_jump_insn (gen_bgt_media (operands[4], operands[1], operands[0]));
+ test = gen_rtx_GT (VOIDmode, operands[1], operands[0]);
+ emit_jump_insn (gen_cbranchdi4 (test, operands[1], operands[0], operands[4]));
emit_move_insn (reg, gen_rtx_MINUS (DImode, operands[0], operands[1]));
- emit_jump_insn (gen_bgtu_media (operands[4], reg, operands[2]));
+ test = gen_rtx_GTU (VOIDmode, reg, operands[2]);
+ emit_jump_insn (gen_cbranchdi4 (test, reg, operands[2], operands[4]));
emit_insn (gen_casesi_shift_media (reg2, reg, operands[3]));
emit_move_insn (reg3, gen_datalabel_ref (gen_rtx_LABEL_REF
(Pmode, operands[3])));
@@ -9580,536 +9121,133 @@ mov.l\\t1f,r0\\n\\
"movrt\\t%0"
[(set_attr "type" "arith")])
-(define_expand "seq"
- [(set (match_operand:SI 0 "arith_reg_dest" "")
- (match_dup 1))]
- ""
- "
-{
- if (TARGET_SHMEDIA)
- {
- rtx reg;
-
- sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
- if (sh_compare_op1 != const0_rtx)
- sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
- ? GET_MODE (sh_compare_op0)
- : GET_MODE (sh_compare_op1),
- sh_compare_op1);
- if (GET_MODE_SIZE (GET_MODE (operands[0])) <= 4)
- {
- if (GET_MODE (operands[0]) != SImode)
- operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
-
- switch (GET_MODE (sh_compare_op0))
- {
- case SImode:
- emit_insn (gen_cmpeqsi_media (operands[0],
- sh_compare_op0, sh_compare_op1));
- break;
-
- case DImode:
- emit_insn (gen_cmpeqdi_media (operands[0],
- sh_compare_op0, sh_compare_op1));
- break;
-
- case SFmode:
- if (! TARGET_SHMEDIA_FPU)
- FAIL;
- emit_insn (gen_cmpeqsf_media (operands[0],
- sh_compare_op0, sh_compare_op1));
- break;
-
- case DFmode:
- if (! TARGET_SHMEDIA_FPU)
- FAIL;
- emit_insn (gen_cmpeqdf_media (operands[0],
- sh_compare_op0, sh_compare_op1));
- break;
-
- default:
- FAIL;
- }
- DONE;
- }
-
- reg = operands[0];
- if (GET_MODE (operands[0]) != SImode)
- reg = (!can_create_pseudo_p ()
- ? gen_rtx_SUBREG (SImode, operands[0], 0)
- : gen_reg_rtx (SImode));
-
- switch (GET_MODE (sh_compare_op0))
- {
- case SImode:
- emit_insn (gen_cmpeqsi_media (reg,
- sh_compare_op0, sh_compare_op1));
- break;
-
- case DImode:
- emit_insn (gen_cmpeqdi_media (reg,
- sh_compare_op0, sh_compare_op1));
- break;
-
- case SFmode:
- if (! TARGET_SHMEDIA_FPU)
- FAIL;
- emit_insn (gen_cmpeqsf_media (reg,
- sh_compare_op0, sh_compare_op1));
- break;
-
- case DFmode:
- if (! TARGET_SHMEDIA_FPU)
- FAIL;
- emit_insn (gen_cmpeqdf_media (reg,
- sh_compare_op0, sh_compare_op1));
- break;
-
- default:
- FAIL;
- }
-
- if (GET_MODE (operands[0]) == DImode)
- emit_insn (gen_extendsidi2 (operands[0], reg));
-
- DONE;
- }
- if (sh_expand_t_scc (EQ, operands[0]))
- DONE;
- if (! currently_expanding_to_rtl)
- FAIL;
- operands[1] = prepare_scc_operands (EQ);
-}")
-
-(define_expand "slt"
- [(set (match_operand:SI 0 "arith_reg_operand" "")
- (match_dup 1))]
- ""
+(define_expand "cstore4_media"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (match_operator:SI 1 "sh_float_comparison_operator"
+ [(match_operand 2 "logical_operand" "")
+ (match_operand 3 "cmp_operand" "")]))]
+ "TARGET_SHMEDIA"
"
{
- if (TARGET_SHMEDIA)
+ enum machine_mode mode = GET_MODE (operands[2]);
+ enum rtx_code code = GET_CODE (operands[1]);
+ bool invert, swap;
+ if (mode == VOIDmode)
+ mode = GET_MODE (operands[3]);
+ if (operands[2] == const0_rtx)
{
- rtx reg;
-
- sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
- if (sh_compare_op1 != const0_rtx)
- sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
- ? GET_MODE (sh_compare_op0)
- : GET_MODE (sh_compare_op1),
- sh_compare_op1);
-
- reg = operands[0];
- if (GET_MODE (operands[0]) != SImode)
- reg = (!can_create_pseudo_p ()
- ? gen_rtx_SUBREG (SImode, operands[0], 0)
- : gen_reg_rtx (SImode));
-
- switch (GET_MODE (sh_compare_op0))
- {
- case SImode:
- emit_insn (gen_cmpgtsi_media (reg,
- sh_compare_op1, sh_compare_op0));
- break;
-
- case DImode:
- emit_insn (gen_cmpgtdi_media (reg,
- sh_compare_op1, sh_compare_op0));
- break;
-
- case SFmode:
- if (! TARGET_SHMEDIA_FPU)
- FAIL;
- emit_insn (gen_cmpgtsf_media (reg,
- sh_compare_op1, sh_compare_op0));
- break;
-
- case DFmode:
- if (! TARGET_SHMEDIA_FPU)
- FAIL;
- emit_insn (gen_cmpgtdf_media (reg,
- sh_compare_op1, sh_compare_op0));
- break;
-
- default:
- FAIL;
- }
-
- if (GET_MODE (operands[0]) == DImode)
- emit_insn (gen_extendsidi2 (operands[0], reg));
-
- DONE;
+ if (code == EQ || code == NE)
+ operands[2] = operands[3], operands[3] = const0_rtx;
}
- if (! currently_expanding_to_rtl)
- FAIL;
- operands[1] = prepare_scc_operands (LT);
-}")
-
-(define_expand "sle"
- [(match_operand:SI 0 "arith_reg_operand" "")]
- ""
- "
-{
- rtx tmp = sh_compare_op0;
+ else
+ operands[2] = force_reg (mode, operands[2]);
+ if (operands[3] != const0_rtx)
+ operands[3] = force_reg (mode, operands[3]);
- if (TARGET_SHMEDIA)
+ switch (code)
{
- rtx reg;
-
- sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
- if (sh_compare_op1 != const0_rtx)
- sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
- ? GET_MODE (sh_compare_op0)
- : GET_MODE (sh_compare_op1),
- sh_compare_op1);
-
- reg = operands[0];
- if (GET_MODE (operands[0]) != SImode)
- reg = (!can_create_pseudo_p ()
- ? gen_rtx_SUBREG (SImode, operands[0], 0)
- : gen_reg_rtx (SImode));
-
- switch (GET_MODE (sh_compare_op0))
- {
- case SImode:
- {
- tmp = !can_create_pseudo_p () ? reg : gen_reg_rtx (SImode);
-
- emit_insn (gen_cmpgtsi_media (tmp,
- sh_compare_op0, sh_compare_op1));
- emit_insn (gen_cmpeqdi_media (reg, tmp, const0_rtx));
- break;
- }
-
- case DImode:
- {
- tmp = !can_create_pseudo_p () ? reg : gen_reg_rtx (SImode);
-
- emit_insn (gen_cmpgtdi_media (tmp,
- sh_compare_op0, sh_compare_op1));
- emit_insn (gen_cmpeqdi_media (reg, tmp, const0_rtx));
- break;
- }
-
- case SFmode:
- if (! TARGET_SHMEDIA_FPU)
- FAIL;
- emit_insn (gen_cmpgesf_media (reg,
- sh_compare_op1, sh_compare_op0));
- break;
+ case GEU:
+ case GE:
+ swap = invert = !FLOAT_MODE_P (mode);
+ break;
- case DFmode:
- if (! TARGET_SHMEDIA_FPU)
- FAIL;
- emit_insn (gen_cmpgedf_media (reg,
- sh_compare_op1, sh_compare_op0));
- break;
+ case LEU:
+ case LE:
+ swap = FLOAT_MODE_P (mode), invert = !swap;
+ break;
- default:
- FAIL;
- }
+ case LTU:
+ case LT:
+ swap = true, invert = false;
+ break;
- if (GET_MODE (operands[0]) == DImode)
- emit_insn (gen_extendsidi2 (operands[0], reg));
+ case GTU:
+ case GT:
+ case EQ:
+ case UNORDERED:
+ swap = invert = false;
+ break;
- DONE;
- }
+ case NE:
+ swap = invert = true;
+ break;
- sh_compare_op0 = sh_compare_op1;
- sh_compare_op1 = tmp;
- emit_insn (gen_sge (operands[0]));
- DONE;
-}")
+ default:
+ gcc_unreachable ();
+ }
-(define_expand "sgt"
- [(set (match_operand:SI 0 "arith_reg_operand" "")
- (match_dup 1))]
- ""
- "
-{
- if (TARGET_SHMEDIA)
+ if (swap)
{
- rtx reg;
-
- reg = operands[0];
- if (GET_MODE (operands[0]) != SImode)
- reg = (!can_create_pseudo_p () ?
- gen_rtx_SUBREG (SImode, operands[0], 0)
- : gen_reg_rtx (SImode));
- sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
- if (sh_compare_op1 != const0_rtx)
- sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
- ? GET_MODE (sh_compare_op0)
- : GET_MODE (sh_compare_op1),
- sh_compare_op1);
-
- switch (GET_MODE (sh_compare_op0))
- {
- case SImode:
- emit_insn (gen_cmpgtsi_media (reg,
- sh_compare_op0, sh_compare_op1));
- break;
-
- case DImode:
- emit_insn (gen_cmpgtdi_media (reg,
- sh_compare_op0, sh_compare_op1));
- break;
-
- case SFmode:
- if (! TARGET_SHMEDIA_FPU)
- FAIL;
- emit_insn (gen_cmpgtsf_media (reg,
- sh_compare_op0, sh_compare_op1));
- break;
-
- case DFmode:
- if (! TARGET_SHMEDIA_FPU)
- FAIL;
- emit_insn (gen_cmpgtdf_media (reg,
- sh_compare_op0, sh_compare_op1));
- break;
-
- default:
- FAIL;
- }
-
- if (GET_MODE (operands[0]) == DImode)
- emit_insn (gen_extendsidi2 (operands[0], reg));
-
- DONE;
+ rtx tem = operands[2];
+ operands[2] = operands[3];
+ operands[3] = tem;
+ code = swap_condition (code);
}
- if (! currently_expanding_to_rtl)
- FAIL;
- operands[1] = prepare_scc_operands (GT);
-}")
-(define_expand "sge"
- [(set (match_operand:SI 0 "arith_reg_operand" "")
- (match_dup 1))]
- ""
- "
-{
- if (TARGET_SHMEDIA)
+ if (invert)
{
- rtx reg;
- enum machine_mode mode = GET_MODE (sh_compare_op0);
-
- if ((mode) == VOIDmode)
- mode = GET_MODE (sh_compare_op1);
- reg = operands[0];
- if (GET_MODE (operands[0]) != SImode)
- reg = (!can_create_pseudo_p ()
- ? gen_rtx_SUBREG (SImode, operands[0], 0)
- : gen_reg_rtx (SImode));
- sh_compare_op0 = force_reg (mode, sh_compare_op0);
- if (sh_compare_op1 != const0_rtx)
- sh_compare_op1 = force_reg (mode, sh_compare_op1);
-
- switch (mode)
- {
- case SImode:
- {
- rtx tmp = !can_create_pseudo_p () ? reg : gen_reg_rtx (SImode);
-
- emit_insn (gen_cmpgtsi_media (tmp,
- sh_compare_op1, sh_compare_op0));
- emit_insn (gen_cmpeqdi_media (reg, tmp, const0_rtx));
- break;
- }
-
- case DImode:
- {
- rtx tmp = !can_create_pseudo_p () ? reg : gen_reg_rtx (SImode);
-
- emit_insn (gen_cmpgtdi_media (tmp,
- sh_compare_op1, sh_compare_op0));
- emit_insn (gen_cmpeqdi_media (reg, tmp, const0_rtx));
- break;
- }
-
- case SFmode:
- if (! TARGET_SHMEDIA_FPU)
- FAIL;
- emit_insn (gen_cmpgesf_media (reg,
- sh_compare_op0, sh_compare_op1));
- break;
-
- case DFmode:
- if (! TARGET_SHMEDIA_FPU)
- FAIL;
- emit_insn (gen_cmpgedf_media (reg,
- sh_compare_op0, sh_compare_op1));
- break;
-
- default:
- FAIL;
- }
-
- if (GET_MODE (operands[0]) == DImode)
- emit_insn (gen_extendsidi2 (operands[0], reg));
-
- DONE;
+ rtx tem = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
+ code = reverse_condition (code);
+ operands[1] = gen_rtx_fmt_ee (code, VOIDmode, operands[2], operands[3]);
+ emit_insn (gen_cstore4_media (tem, operands[1],
+ operands[2], operands[3]));
+ code = EQ;
+ operands[2] = tem;
+ operands[3] = const0_rtx;
}
- if (! currently_expanding_to_rtl)
- FAIL;
- if (GET_MODE_CLASS (GET_MODE (sh_compare_op0)) == MODE_FLOAT)
- {
- if (TARGET_IEEE)
- {
- rtx lab = gen_label_rtx ();
- prepare_scc_operands (EQ);
- emit_jump_insn (gen_branch_true (lab));
- prepare_scc_operands (GT);
- emit_label (lab);
- emit_insn (gen_movt (operands[0]));
- }
- else
- emit_insn (gen_movnegt (operands[0], prepare_scc_operands (LT)));
- DONE;
- }
- operands[1] = prepare_scc_operands (GE);
+ operands[1] = gen_rtx_fmt_ee (code, VOIDmode, operands[2], operands[3]);
}")
-(define_expand "sgtu"
- [(set (match_operand:SI 0 "arith_reg_operand" "")
- (match_dup 1))]
- ""
- "
-{
- if (TARGET_SHMEDIA)
+(define_expand "cstoresi4"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (match_operator:SI 1 "comparison_operator"
+ [(match_operand:SI 2 "cmpsi_operand" "")
+ (match_operand:SI 3 "arith_operand" "")]))]
+ "TARGET_SH1 || TARGET_SHMEDIA"
+ "if (TARGET_SHMEDIA)
{
- rtx reg;
-
- reg = operands[0];
- if (GET_MODE (operands[0]) == DImode)
- reg = (!can_create_pseudo_p ()
- ? gen_rtx_SUBREG (SImode, operands[0], 0)
- : gen_reg_rtx (SImode));
- sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
- if (sh_compare_op1 != const0_rtx)
- sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
- ? GET_MODE (sh_compare_op0)
- : GET_MODE (sh_compare_op1),
- sh_compare_op1);
-
- emit_insn (gen_cmpgtudi_media (reg,
- sh_compare_op0, sh_compare_op1));
- if (GET_MODE (operands[0]) == DImode)
- emit_insn (gen_extendsidi2 (operands[0], reg));
-
+ emit_insn (gen_cstore4_media (operands[0], operands[1],
+ operands[2], operands[3]));
DONE;
}
- if (! currently_expanding_to_rtl)
- FAIL;
- operands[1] = prepare_scc_operands (GTU);
-}")
-(define_expand "sltu"
- [(set (match_operand:SI 0 "arith_reg_operand" "")
- (match_dup 1))]
- ""
- "
-{
- if (TARGET_SHMEDIA)
- {
- rtx reg;
-
- reg = operands[0];
- if (GET_MODE (operands[0]) == DImode)
- reg = (!can_create_pseudo_p ()
- ? gen_rtx_SUBREG (SImode, operands[0], 0)
- : gen_reg_rtx (SImode));
- sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
- if (sh_compare_op1 != const0_rtx)
- sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
- ? GET_MODE (sh_compare_op0)
- : GET_MODE (sh_compare_op1),
- sh_compare_op1);
-
- emit_insn (gen_cmpgtudi_media (reg,
- sh_compare_op1, sh_compare_op0));
- if (GET_MODE (operands[0]) == DImode)
- emit_insn (gen_extendsidi2 (operands[0], reg));
+ if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
+ && sh_expand_t_scc (operands))
+ DONE;
- DONE;
- }
- if (! currently_expanding_to_rtl)
- FAIL;
- operands[1] = prepare_scc_operands (LTU);
-}")
+ if (! currently_expanding_to_rtl)
+ FAIL;
+
+ sh_emit_compare_and_set (operands, SImode);
+ DONE;
+")
-(define_expand "sleu"
- [(set (match_operand:SI 0 "arith_reg_operand" "")
- (match_dup 1))]
- ""
- "
-{
- if (TARGET_SHMEDIA)
+(define_expand "cstoredi4"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (match_operator:SI 1 "comparison_operator"
+ [(match_operand:DI 2 "arith_operand" "")
+ (match_operand:DI 3 "arith_operand" "")]))]
+ "TARGET_SH2 || TARGET_SHMEDIA"
+ "if (TARGET_SHMEDIA)
{
- rtx tmp, reg;
-
- reg = operands[0];
- if (GET_MODE (operands[0]) != SImode)
- reg = (!can_create_pseudo_p ()
- ? gen_rtx_SUBREG (SImode, operands[0], 0)
- : gen_reg_rtx (SImode));
- sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
- if (sh_compare_op1 != const0_rtx)
- sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
- ? GET_MODE (sh_compare_op0)
- : GET_MODE (sh_compare_op1),
- sh_compare_op1);
-
- tmp = !can_create_pseudo_p () ? reg : gen_reg_rtx (SImode);
-
- emit_insn (gen_cmpgtudi_media (tmp, sh_compare_op0, sh_compare_op1));
- emit_insn (gen_cmpeqdi_media (reg, tmp, const0_rtx));
- if (GET_MODE (operands[0]) == DImode)
- emit_insn (gen_extendsidi2 (operands[0], reg));
-
+ emit_insn (gen_cstore4_media (operands[0], operands[1],
+ operands[2], operands[3]));
DONE;
}
- if (! currently_expanding_to_rtl)
- FAIL;
- operands[1] = prepare_scc_operands (LEU);
-}")
-(define_expand "sgeu"
- [(set (match_operand:SI 0 "arith_reg_operand" "")
- (match_dup 1))]
- ""
- "
-{
- if (TARGET_SHMEDIA)
- {
- rtx tmp, reg;
-
- reg = operands[0];
- if (GET_MODE (operands[0]) != SImode)
- reg = (!can_create_pseudo_p ()
- ? gen_rtx_SUBREG (SImode, operands[0], 0)
- : gen_reg_rtx (SImode));
- sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
- if (sh_compare_op1 != const0_rtx)
- sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
- ? GET_MODE (sh_compare_op0)
- : GET_MODE (sh_compare_op1),
- sh_compare_op1);
+ if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
+ && sh_expand_t_scc (operands))
+ DONE;
- tmp = !can_create_pseudo_p () ? operands[0] : gen_reg_rtx (SImode);
+ if (! currently_expanding_to_rtl)
+ FAIL;
+
+ sh_emit_compare_and_set (operands, DImode);
+ DONE;
+")
- emit_insn (gen_cmpgtudi_media (tmp, sh_compare_op1, sh_compare_op0));
- emit_insn (gen_cmpeqdi_media (reg, tmp, const0_rtx));
- if (GET_MODE (operands[0]) == DImode)
- emit_insn (gen_extendsidi2 (operands[0], reg));
- DONE;
- }
-
- if (! currently_expanding_to_rtl)
- FAIL;
- operands[1] = prepare_scc_operands (GEU);
-}")
;; sne moves the complement of the T reg to DEST like this:
;; cmp/eq ...
@@ -10119,81 +9257,20 @@ mov.l\\t1f,r0\\n\\
;; not require r0 and further, the -1 may be CSE-ed or lifted out of a
;; loop.
-(define_expand "sne"
- [(set (match_dup 2) (const_int -1))
- (parallel [(set (match_operand:SI 0 "arith_reg_operand" "")
- (neg:SI (plus:SI (match_dup 1)
- (match_dup 2))))
+(define_expand "movnegt"
+ [(set (match_dup 1) (const_int -1))
+ (parallel [(set (match_operand:SI 0 "" "")
+ (neg:SI (plus:SI (reg:SI T_REG)
+ (match_dup 1))))
(set (reg:SI T_REG)
- (ne:SI (ior:SI (match_dup 1) (match_dup 2))
+ (ne:SI (ior:SI (reg:SI T_REG) (match_dup 1))
(const_int 0)))])]
""
"
{
- if (TARGET_SHMEDIA)
- {
- rtx tmp, reg;
-
- reg = operands[0];
- if (GET_MODE (operands[0]) != SImode)
- reg = (!can_create_pseudo_p ()
- ? gen_rtx_SUBREG (SImode, operands[0], 0)
- : gen_reg_rtx (SImode));
- if (! TARGET_SHMEDIA_FPU
- && GET_MODE (sh_compare_op0) != DImode
- && GET_MODE (sh_compare_op0) != SImode)
- FAIL;
-
- sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
- if (sh_compare_op1 != const0_rtx)
- sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
- ? GET_MODE (sh_compare_op0)
- : GET_MODE (sh_compare_op1),
- sh_compare_op1);
-
- tmp = !can_create_pseudo_p () ? reg : gen_reg_rtx (SImode);
-
- emit_insn (gen_seq (tmp));
- emit_insn (gen_cmpeqdi_media (reg, tmp, const0_rtx));
- if (GET_MODE (operands[0]) == DImode)
- emit_insn (gen_extendsidi2 (operands[0], reg));
-
- DONE;
- }
-
- if (sh_expand_t_scc (NE, operands[0]))
- DONE;
- if (! currently_expanding_to_rtl)
- FAIL;
- operands[1] = prepare_scc_operands (EQ);
- operands[2] = gen_reg_rtx (SImode);
-}")
-
-(define_expand "sunordered"
- [(set (match_operand:SI 0 "arith_reg_operand" "")
- (unordered:SI (match_dup 1) (match_dup 2)))]
- "TARGET_SHMEDIA_FPU"
- "
-{
- operands[1] = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
- operands[2] = force_reg (GET_MODE (sh_compare_op1), sh_compare_op1);
+ operands[1] = gen_reg_rtx (SImode);
}")
-;; Use the same trick for FP sle / sge
-
-;; Apart from the constant use and the T setting, this is like movt,
-;; except that it uses the logically negated value of T, i.e.
-;; operand[0] := T ? 0 : 1.
-(define_expand "movnegt"
- [(set (match_dup 2) (const_int -1))
- (parallel [(set (match_operand 0 "" "")
- (neg:SI (plus:SI (match_dup 1)
- (match_dup 2))))
- (set (reg:SI T_REG)
- (ne:SI (ior:SI (match_operand 1 "" "") (match_dup 2))
- (const_int 0)))])]
- "TARGET_SH1"
- "operands[2] = gen_reg_rtx (SImode);")
;; Recognize mov #-1/negc/neg sequence, and change it to movt/add #-1.
;; This prevents a regression that occurred when we switched from xor to
@@ -10208,6 +9285,47 @@ mov.l\\t1f,r0\\n\\
(set (match_dup 0) (plus:SI (match_dup 0) (const_int -1)))]
"")
+(define_expand "cstoresf4"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (match_operator:SI 1 "sh_float_comparison_operator"
+ [(match_operand:SF 2 "arith_operand" "")
+ (match_operand:SF 3 "arith_operand" "")]))]
+ "TARGET_SH2E || TARGET_SHMEDIA_FPU"
+ "if (TARGET_SHMEDIA)
+ {
+ emit_insn (gen_cstore4_media (operands[0], operands[1],
+ operands[2], operands[3]));
+ DONE;
+ }
+
+ if (! currently_expanding_to_rtl)
+ FAIL;
+
+ sh_emit_compare_and_set (operands, SFmode);
+ DONE;
+")
+
+(define_expand "cstoredf4"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (match_operator:SI 1 "sh_float_comparison_operator"
+ [(match_operand:DF 2 "arith_operand" "")
+ (match_operand:DF 3 "arith_operand" "")]))]
+ "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
+ "if (TARGET_SHMEDIA)
+ {
+ emit_insn (gen_cstore4_media (operands[0], operands[1],
+ operands[2], operands[3]));
+ DONE;
+ }
+
+ if (! currently_expanding_to_rtl)
+ FAIL;
+
+ sh_emit_compare_and_set (operands, DFmode);
+ DONE;
+")
+
+
;; -------------------------------------------------------------------------
;; Instructions to cope with inline literal tables
;; -------------------------------------------------------------------------
@@ -10986,15 +10104,21 @@ mov.l\\t1f,r0\\n\\
"fcmpun.s %1, %2, %0"
[(set_attr "type" "fcmp_media")])
-(define_expand "cmpsf"
- [(set (reg:SI T_REG)
- (compare (match_operand:SF 0 "arith_operand" "")
- (match_operand:SF 1 "arith_operand" "")))]
+(define_expand "cbranchsf4"
+ [(set (pc)
+ (if_then_else (match_operator 0 "sh_float_comparison_operator"
+ [(match_operand:SF 1 "arith_operand" "")
+ (match_operand:SF 2 "arith_operand" "")])
+ (match_operand 3 "" "")
+ (pc)))]
"TARGET_SH2E || TARGET_SHMEDIA_FPU"
"
{
- sh_compare_op0 = operands[0];
- sh_compare_op1 = operands[1];
+ if (TARGET_SHMEDIA)
+ emit_jump_insn (gen_cbranchfp4_media (operands[0], operands[1], operands[2],
+ operands[3]));
+ else
+ sh_emit_compare_and_branch (operands, SFmode);
DONE;
}")
@@ -11484,18 +10608,25 @@ mov.l\\t1f,r0\\n\\
"fcmpun.d %1,%2,%0"
[(set_attr "type" "fcmp_media")])
-(define_expand "cmpdf"
- [(set (reg:SI T_REG)
- (compare (match_operand:DF 0 "arith_operand" "")
- (match_operand:DF 1 "arith_operand" "")))]
+(define_expand "cbranchdf4"
+ [(set (pc)
+ (if_then_else (match_operator 0 "sh_float_comparison_operator"
+ [(match_operand:DF 1 "arith_operand" "")
+ (match_operand:DF 2 "arith_operand" "")])
+ (match_operand 3 "" "")
+ (pc)))]
"(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
"
{
- sh_compare_op0 = operands[0];
- sh_compare_op1 = operands[1];
+ if (TARGET_SHMEDIA)
+ emit_jump_insn (gen_cbranchfp4_media (operands[0], operands[1], operands[2],
+ operands[3]));
+ else
+ sh_emit_compare_and_branch (operands, DFmode);
DONE;
}")
+
(define_expand "negdf2"
[(set (match_operand:DF 0 "arith_reg_operand" "")
(neg:DF (match_operand:DF 1 "arith_reg_operand" "")))]
@@ -14144,15 +13275,21 @@ mov.l\\t1f,r0\\n\\
if (TARGET_SHMEDIA)
{
rtx tmp = gen_reg_rtx (GET_MODE (operands[0]));
+ rtx test;
+ test = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
if (TARGET_SHMEDIA64)
- emit_insn (gen_stack_protect_test_di_media (tmp, operands[0],
- operands[1]));
+ {
+ emit_insn (gen_stack_protect_test_di_media (tmp, operands[0],
+ operands[1]));
+ emit_jump_insn (gen_cbranchdi4 (test, tmp, const0_rtx, operands[2]));
+ }
else
- emit_insn (gen_stack_protect_test_si_media (tmp, operands[0],
- operands[1]));
-
- emit_jump_insn (gen_bne_media (operands[2], tmp, const0_rtx));
+ {
+ emit_insn (gen_stack_protect_test_si_media (tmp, operands[0],
+ operands[1]));
+ emit_jump_insn (gen_cbranchsi4 (test, tmp, const0_rtx, operands[2]));
+ }
}
else
{
diff --git a/gcc/config/sparc/sparc-protos.h b/gcc/config/sparc/sparc-protos.h
index 40ac75e130c..fd388dd8139 100644
--- a/gcc/config/sparc/sparc-protos.h
+++ b/gcc/config/sparc/sparc-protos.h
@@ -54,16 +54,14 @@ extern void sparc_output_scratch_registers (FILE *);
#ifdef RTX_CODE
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 rtx gen_compare_operator (enum rtx_code code);
-extern enum rtx_code sparc_emit_float_lib_cmp (rtx, rtx, enum rtx_code);
+extern rtx gen_compare_reg (rtx cmp);
+extern rtx 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 *);
extern void emit_tfmode_unop (enum rtx_code, rtx *);
extern void emit_tfmode_cvt (enum rtx_code, rtx *);
/* This function handles all v9 scc insns */
-extern int gen_v9_scc (enum rtx_code, rtx *);
extern void sparc_initialize_trampoline (rtx, rtx, rtx);
extern void sparc64_initialize_trampoline (rtx, rtx, rtx);
extern bool legitimate_constant_p (rtx);
@@ -86,7 +84,8 @@ extern const char *output_return (rtx);
extern const char *output_sibcall (rtx, rtx);
extern const char *output_v8plus_shift (rtx *, rtx, const char *);
extern const char *output_v9branch (rtx, rtx, int, int, int, int, rtx);
-extern void emit_v9_brxx_insn (enum rtx_code, rtx, rtx);
+extern bool emit_scc_insn (rtx []);
+extern void emit_conditional_branch_insn (rtx []);
extern void print_operand (FILE *, rtx, int);
extern int mems_ok_for_ldd_peep (rtx, rtx, rtx);
extern int arith_double_4096_operand (rtx, enum machine_mode);
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index ab2b57bbcd9..330c2c06981 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -280,10 +280,6 @@ static GTY(()) alias_set_type sparc_sr_alias_set;
/* The alias set for the structure return value. */
static GTY(()) alias_set_type struct_value_alias_set;
-/* Save the operands last given to a compare for use when we
- generate a scc or bcc insn. */
-rtx sparc_compare_op0, sparc_compare_op1;
-
/* Vector to say how input registers are mapped to output registers.
HARD_FRAME_POINTER_REGNUM cannot be remapped by this function to
eliminate it. You must use -fomit-frame-pointer to get that. */
@@ -2005,19 +2001,18 @@ select_cc_mode (enum rtx_code op, rtx x, rtx y ATTRIBUTE_UNUSED)
}
}
-/* Emit the compare insn and return the CC reg for a CODE comparison. */
+/* Emit the compare insn and return the CC reg for a CODE comparison
+ with operands X and Y. */
-rtx
-gen_compare_reg (enum rtx_code code)
+static rtx
+gen_compare_reg_1 (enum rtx_code code, rtx x, rtx y)
{
enum machine_mode mode;
- rtx x, y, cc_reg;
+ rtx cc_reg;
- if (GET_MODE_CLASS (GET_MODE (sparc_compare_op0)) == MODE_CC)
- return sparc_compare_op0;
+ if (GET_MODE_CLASS (GET_MODE (x)) == MODE_CC)
+ return x;
- x = sparc_compare_op0;
- y = sparc_compare_op1;
mode = SELECT_CC_MODE (code, x, y);
/* ??? We don't have movcc patterns so we cannot generate pseudo regs for the
@@ -2073,26 +2068,19 @@ gen_compare_reg (enum rtx_code code)
return cc_reg;
}
-/* Same as above but return the whole compare operator. */
+
+/* Emit the compare insn and return the CC reg for the comparison in CMP. */
rtx
-gen_compare_operator (enum rtx_code code)
+gen_compare_reg (rtx cmp)
{
- 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);
+ return gen_compare_reg_1 (GET_CODE (cmp), XEXP (cmp, 0), XEXP (cmp, 1));
}
/* This function is used for v9 only.
+ DEST is the target of the Scc insn.
CODE is the code for an Scc's comparison.
- OPERANDS[0] is the target of the Scc insn.
- OPERANDS[1] is the value we compare against const0_rtx (which hasn't
- been generated yet).
+ X and Y are the values we compare.
This function is needed to turn
@@ -2106,53 +2094,50 @@ gen_compare_operator (enum rtx_code code)
IE: The instruction recognizer needs to see the mode of the comparison to
find the right instruction. We could use "gt:DI" right in the
- define_expand, but leaving it out allows us to handle DI, SI, etc.
+ define_expand, but leaving it out allows us to handle DI, SI, etc. */
- We refer to the global sparc compare operands sparc_compare_op0 and
- sparc_compare_op1. */
-
-int
-gen_v9_scc (enum rtx_code compare_code, register rtx *operands)
+static int
+gen_v9_scc (rtx dest, enum rtx_code compare_code, rtx x, rtx y)
{
if (! TARGET_ARCH64
- && (GET_MODE (sparc_compare_op0) == DImode
- || GET_MODE (operands[0]) == DImode))
+ && (GET_MODE (x) == DImode
+ || GET_MODE (dest) == DImode))
return 0;
/* Try to use the movrCC insns. */
if (TARGET_ARCH64
- && GET_MODE_CLASS (GET_MODE (sparc_compare_op0)) == MODE_INT
- && sparc_compare_op1 == const0_rtx
+ && GET_MODE_CLASS (GET_MODE (x)) == MODE_INT
+ && y == const0_rtx
&& v9_regcmp_p (compare_code))
{
- rtx op0 = sparc_compare_op0;
+ rtx op0 = x;
rtx temp;
/* Special case for op0 != 0. This can be done with one instruction if
- operands[0] == sparc_compare_op0. */
+ dest == x. */
if (compare_code == NE
- && GET_MODE (operands[0]) == DImode
- && rtx_equal_p (op0, operands[0]))
+ && GET_MODE (dest) == DImode
+ && rtx_equal_p (op0, dest))
{
- emit_insn (gen_rtx_SET (VOIDmode, operands[0],
+ emit_insn (gen_rtx_SET (VOIDmode, dest,
gen_rtx_IF_THEN_ELSE (DImode,
gen_rtx_fmt_ee (compare_code, DImode,
op0, const0_rtx),
const1_rtx,
- operands[0])));
+ dest)));
return 1;
}
- if (reg_overlap_mentioned_p (operands[0], op0))
+ if (reg_overlap_mentioned_p (dest, op0))
{
- /* Handle the case where operands[0] == sparc_compare_op0.
+ /* Handle the case where dest == x.
We "early clobber" the result. */
- op0 = gen_reg_rtx (GET_MODE (sparc_compare_op0));
- emit_move_insn (op0, sparc_compare_op0);
+ op0 = gen_reg_rtx (GET_MODE (x));
+ emit_move_insn (op0, x);
}
- emit_insn (gen_rtx_SET (VOIDmode, operands[0], const0_rtx));
+ emit_insn (gen_rtx_SET (VOIDmode, dest, const0_rtx));
if (GET_MODE (op0) != DImode)
{
temp = gen_reg_rtx (DImode);
@@ -2160,47 +2145,137 @@ gen_v9_scc (enum rtx_code compare_code, register rtx *operands)
}
else
temp = op0;
- emit_insn (gen_rtx_SET (VOIDmode, operands[0],
- gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]),
+ emit_insn (gen_rtx_SET (VOIDmode, dest,
+ gen_rtx_IF_THEN_ELSE (GET_MODE (dest),
gen_rtx_fmt_ee (compare_code, DImode,
temp, const0_rtx),
const1_rtx,
- operands[0])));
+ dest)));
return 1;
}
else
{
- operands[1] = gen_compare_reg (compare_code);
+ x = gen_compare_reg_1 (compare_code, x, y);
+ y = const0_rtx;
- switch (GET_MODE (operands[1]))
- {
- case CCmode :
- case CCXmode :
- case CCFPEmode :
- case CCFPmode :
- break;
- default :
- gcc_unreachable ();
- }
- emit_insn (gen_rtx_SET (VOIDmode, operands[0], const0_rtx));
- emit_insn (gen_rtx_SET (VOIDmode, operands[0],
- gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]),
+ gcc_assert (GET_MODE (x) != CC_NOOVmode
+ && GET_MODE (x) != CCX_NOOVmode);
+
+ emit_insn (gen_rtx_SET (VOIDmode, dest, const0_rtx));
+ emit_insn (gen_rtx_SET (VOIDmode, dest,
+ gen_rtx_IF_THEN_ELSE (GET_MODE (dest),
gen_rtx_fmt_ee (compare_code,
- GET_MODE (operands[1]),
- operands[1], const0_rtx),
- const1_rtx, operands[0])));
+ GET_MODE (x), x, y),
+ const1_rtx, dest)));
return 1;
}
}
+
+/* Emit an scc insn. For seq, sne, sgeu, and sltu, we can do this
+ without jumps using the addx/subx instructions. */
+
+bool
+emit_scc_insn (rtx operands[])
+{
+ rtx tem;
+ rtx x;
+ rtx y;
+ enum rtx_code code;
+
+ /* The quad-word fp compare library routines all return nonzero to indicate
+ true, which is different from the equivalent libgcc routines, so we must
+ handle them specially here. */
+ if (GET_MODE (operands[2]) == TFmode && ! TARGET_HARD_QUAD)
+ {
+ operands[1] = sparc_emit_float_lib_cmp (operands[2], operands[3],
+ GET_CODE (operands[1]));
+ operands[2] = XEXP (operands[1], 0);
+ operands[3] = XEXP (operands[1], 1);
+ }
+
+ code = GET_CODE (operands[1]);
+ x = operands[2];
+ y = operands[3];
+
+ /* For seq/sne on v9 we use the same code as v8 (the addx/subx method has
+ more applications). The exception to this is "reg != 0" which can
+ be done in one instruction on v9 (so we do it). */
+ if (code == EQ)
+ {
+ if (GET_MODE (x) == SImode)
+ {
+ rtx pat = gen_seqsi_special (operands[0], x, y);
+ emit_insn (pat);
+ return true;
+ }
+ else if (GET_MODE (x) == DImode)
+ {
+ rtx pat = gen_seqdi_special (operands[0], x, y);
+ emit_insn (pat);
+ return true;
+ }
+ }
+
+ if (code == NE)
+ {
+ if (GET_MODE (x) == SImode)
+ {
+ rtx pat = gen_snesi_special (operands[0], x, y);
+ emit_insn (pat);
+ return true;
+ }
+ else if (GET_MODE (x) == DImode)
+ {
+ rtx pat = gen_snedi_special (operands[0], x, y);
+ emit_insn (pat);
+ return true;
+ }
+ }
+
+ /* For the rest, on v9 we can use conditional moves. */
+
+ if (TARGET_V9)
+ {
+ if (gen_v9_scc (operands[0], code, x, y))
+ return true;
+ }
+
+ /* We can do LTU and GEU using the addx/subx instructions too. And
+ for GTU/LEU, if both operands are registers swap them and fall
+ back to the easy case. */
+ if (code == GTU || code == LEU)
+ {
+ if ((GET_CODE (x) == REG || GET_CODE (x) == SUBREG)
+ && (GET_CODE (y) == REG || GET_CODE (y) == SUBREG))
+ {
+ tem = x;
+ x = y;
+ y = tem;
+ code = swap_condition (code);
+ }
+ }
+
+ if (code == LTU || code == GEU)
+ {
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0],
+ gen_rtx_fmt_ee (code, SImode,
+ gen_compare_reg_1 (code, x, y),
+ const0_rtx)));
+ return true;
+ }
+
+ /* Nope, do branches. */
+ return false;
+}
+
/* Emit a conditional jump insn for the v9 architecture using comparison code
CODE and jump target LABEL.
This function exists to take advantage of the v9 brxx insns. */
-void
+static void
emit_v9_brxx_insn (enum rtx_code code, rtx op0, rtx label)
{
- gcc_assert (GET_MODE_CLASS (GET_MODE (sparc_compare_op0)) != MODE_CC);
emit_jump_insn (gen_rtx_SET (VOIDmode,
pc_rtx,
gen_rtx_IF_THEN_ELSE (VOIDmode,
@@ -2210,6 +2285,37 @@ emit_v9_brxx_insn (enum rtx_code code, rtx op0, rtx label)
pc_rtx)));
}
+void
+emit_conditional_branch_insn (rtx operands[])
+{
+ /* The quad-word fp compare library routines all return nonzero to indicate
+ true, which is different from the equivalent libgcc routines, so we must
+ handle them specially here. */
+ if (GET_MODE (operands[1]) == TFmode && ! TARGET_HARD_QUAD)
+ {
+ operands[0] = sparc_emit_float_lib_cmp (operands[1], operands[2],
+ GET_CODE (operands[0]));
+ operands[1] = XEXP (operands[0], 0);
+ operands[2] = XEXP (operands[0], 1);
+ }
+
+ if (TARGET_ARCH64 && operands[2] == const0_rtx
+ && GET_CODE (operands[1]) == REG
+ && GET_MODE (operands[1]) == DImode)
+ {
+ emit_v9_brxx_insn (GET_CODE (operands[0]), operands[1], operands[3]);
+ return;
+ }
+
+ operands[1] = gen_compare_reg (operands[0]);
+ operands[2] = const0_rtx;
+ operands[0] = gen_rtx_fmt_ee (GET_CODE (operands[0]), VOIDmode,
+ operands[1], operands[2]);
+ emit_jump_insn (gen_cbranchcc4 (operands[0], operands[1], operands[2],
+ operands[3]));
+}
+
+
/* Generate a DFmode part of a hard TFmode register.
REG is the TFmode hard register, LOW is 1 for the
low 64bit of the register and 0 otherwise.
@@ -6116,7 +6222,7 @@ output_cbranch (rtx op, rtx dest, int label, int reversed, int annul,
values as arguments instead of the TFmode registers themselves,
that's why we cannot call emit_float_lib_cmp. */
-enum rtx_code
+rtx
sparc_emit_float_lib_cmp (rtx x, rtx y, enum rtx_code comparison)
{
const char *qpfunc;
@@ -6207,32 +6313,24 @@ sparc_emit_float_lib_cmp (rtx x, rtx y, enum rtx_code comparison)
switch (comparison)
{
default:
- new_comparison = NE;
- emit_cmp_insn (result, const0_rtx, new_comparison, NULL_RTX, mode, 0);
- break;
+ return gen_rtx_NE (VOIDmode, result, const0_rtx);
case ORDERED:
case UNORDERED:
new_comparison = (comparison == UNORDERED ? EQ : NE);
- emit_cmp_insn (result, GEN_INT(3), new_comparison, NULL_RTX, mode, 0);
- break;
+ return gen_rtx_fmt_ee (new_comparison, VOIDmode, result, GEN_INT(3));
case UNGT:
case UNGE:
new_comparison = (comparison == UNGT ? GT : NE);
- emit_cmp_insn (result, const1_rtx, new_comparison, NULL_RTX, mode, 0);
- break;
+ return gen_rtx_fmt_ee (new_comparison, VOIDmode, result, const1_rtx);
case UNLE:
- new_comparison = NE;
- emit_cmp_insn (result, const2_rtx, new_comparison, NULL_RTX, mode, 0);
- break;
+ return gen_rtx_NE (VOIDmode, result, const2_rtx);
case UNLT:
tem = gen_reg_rtx (mode);
if (TARGET_ARCH32)
emit_insn (gen_andsi3 (tem, result, const1_rtx));
else
emit_insn (gen_anddi3 (tem, result, const1_rtx));
- new_comparison = NE;
- emit_cmp_insn (tem, const0_rtx, new_comparison, NULL_RTX, mode, 0);
- break;
+ return gen_rtx_NE (VOIDmode, tem, const0_rtx);
case UNEQ:
case LTGT:
tem = gen_reg_rtx (mode);
@@ -6246,11 +6344,10 @@ sparc_emit_float_lib_cmp (rtx x, rtx y, enum rtx_code comparison)
else
emit_insn (gen_anddi3 (tem2, tem, const2_rtx));
new_comparison = (comparison == UNEQ ? EQ : NE);
- emit_cmp_insn (tem2, const0_rtx, new_comparison, NULL_RTX, mode, 0);
- break;
+ return gen_rtx_fmt_ee (new_comparison, VOIDmode, tem2, const0_rtx);
}
- return new_comparison;
+ gcc_unreachable ();
}
/* Generate an unsigned DImode to FP conversion. This is the same code
@@ -9021,15 +9118,12 @@ sparc_expand_compare_and_swap_12 (rtx result, rtx mem, rtx oldval, rtx newval)
gen_rtx_AND (SImode, gen_rtx_NOT (SImode, mask),
res)));
- sparc_compare_op0 = resv;
- sparc_compare_op1 = val;
- cc = gen_compare_reg (NE);
-
+ cc = gen_compare_reg_1 (NE, resv, val);
emit_insn (gen_rtx_SET (VOIDmode, val, resv));
- sparc_compare_op0 = cc;
- sparc_compare_op1 = const0_rtx;
- emit_jump_insn (gen_bne (loop_label));
+ /* Use cbranchcc4 to separate the compare and branch! */
+ emit_jump_insn (gen_cbranchcc4 (gen_rtx_NE (VOIDmode, cc, const0_rtx),
+ cc, const0_rtx, loop_label));
emit_label (end_label);
diff --git a/gcc/config/sparc/sparc.h b/gcc/config/sparc/sparc.h
index d21900135e2..280036224be 100644
--- a/gcc/config/sparc/sparc.h
+++ b/gcc/config/sparc/sparc.h
@@ -1558,12 +1558,6 @@ function_arg_padding ((MODE), (TYPE))
&& (GET_MODE_ALIGNMENT (MODE) == 128 \
|| ((TYPE) && TYPE_ALIGN (TYPE) == 128))) \
? 128 : PARM_BOUNDARY)
-
-/* Define the information needed to generate branch and scc insns. This is
- stored from the compare operation. */
-
-extern GTY(()) rtx sparc_compare_op0;
-extern GTY(()) rtx sparc_compare_op1;
/* Generate the special assembly code needed to tell the assembler whatever
diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md
index 4fae329cd9a..9e35910f4db 100644
--- a/gcc/config/sparc/sparc.md
+++ b/gcc/config/sparc/sparc.md
@@ -76,6 +76,18 @@
(UNSPECV_LDSTUB 10)
])
+
+(define_mode_iterator P [(SI "Pmode == SImode") (DI "Pmode == DImode")])
+(define_mode_iterator I [QI HI SI DI])
+(define_mode_iterator F [SF DF TF])
+
+;; We don't define V1SI because SI should work just fine.
+(define_mode_iterator V32 [SF V2HI V4QI])
+(define_mode_iterator V32I [SI V2HI V4QI])
+
+(define_mode_iterator V64 [DF V2SI V4HI V8QI])
+(define_mode_iterator V64I [DI V2SI V4HI V8QI])
+
;; The upper 32 fp regs on the v9 can't hold SFmode values. To deal with this
;; a second register class, EXTRA_FP_REGS, exists for the v9 chip. The name
;; is a bit of a misnomer as it covers all 64 fp regs. The corresponding
@@ -340,84 +352,11 @@
;; Compare instructions.
-;; We generate RTL for comparisons and branches by having the cmpxx
-;; patterns store away the operands. Then, the scc and bcc patterns
-;; emit RTL for both the compare and the branch.
-;;
-;; We do this because we want to generate different code for an sne and
-;; seq insn. In those cases, if the second operand of the compare is not
-;; const0_rtx, we want to compute the xor of the two operands and test
-;; it against zero.
-;;
-;; We start with the DEFINE_EXPANDs, then the DEFINE_INSNs to match
-;; the patterns. Finally, we have the DEFINE_SPLITs for some of the scc
-;; insns that actually require more than one machine instruction.
-
-(define_expand "cmpsi"
- [(set (reg:CC 100)
- (compare:CC (match_operand:SI 0 "compare_operand" "")
- (match_operand:SI 1 "arith_operand" "")))]
- ""
-{
- if (GET_CODE (operands[0]) == ZERO_EXTRACT && operands[1] != const0_rtx)
- operands[0] = force_reg (SImode, operands[0]);
-
- sparc_compare_op0 = operands[0];
- sparc_compare_op1 = operands[1];
- DONE;
-})
-
-(define_expand "cmpdi"
- [(set (reg:CCX 100)
- (compare:CCX (match_operand:DI 0 "compare_operand" "")
- (match_operand:DI 1 "arith_operand" "")))]
- "TARGET_ARCH64"
-{
- if (GET_CODE (operands[0]) == ZERO_EXTRACT && operands[1] != const0_rtx)
- operands[0] = force_reg (DImode, operands[0]);
-
- sparc_compare_op0 = operands[0];
- sparc_compare_op1 = operands[1];
- DONE;
-})
-
-(define_expand "cmpsf"
- ;; The 96 here isn't ever used by anyone.
- [(set (reg:CCFP 96)
- (compare:CCFP (match_operand:SF 0 "register_operand" "")
- (match_operand:SF 1 "register_operand" "")))]
- "TARGET_FPU"
-{
- sparc_compare_op0 = operands[0];
- sparc_compare_op1 = operands[1];
- DONE;
-})
-
-(define_expand "cmpdf"
- ;; The 96 here isn't ever used by anyone.
- [(set (reg:CCFP 96)
- (compare:CCFP (match_operand:DF 0 "register_operand" "")
- (match_operand:DF 1 "register_operand" "")))]
- "TARGET_FPU"
-{
- sparc_compare_op0 = operands[0];
- sparc_compare_op1 = operands[1];
- DONE;
-})
-
-(define_expand "cmptf"
- ;; The 96 here isn't ever used by anyone.
- [(set (reg:CCFP 96)
- (compare:CCFP (match_operand:TF 0 "register_operand" "")
- (match_operand:TF 1 "register_operand" "")))]
- "TARGET_FPU"
-{
- sparc_compare_op0 = operands[0];
- sparc_compare_op1 = operands[1];
- DONE;
-})
+;; These are just the DEFINE_INSNs to match the patterns and the
+;; DEFINE_SPLITs for some of the scc insns that actually require
+;; more than one machine instruction. DEFINE_EXPANDs are further down.
-;; Now the compare DEFINE_INSNs.
+;; The compare DEFINE_INSNs.
(define_insn "*cmpsi_insn"
[(set (reg:CC 100)
@@ -509,12 +448,41 @@
}
[(set_attr "type" "fpcmp")])
-;; Next come the scc insns. For seq, sne, sgeu, and sltu, we can do this
-;; without jumps using the addx/subx instructions. For seq/sne on v9 we use
-;; the same code as v8 (the addx/subx method has more applications). The
-;; exception to this is "reg != 0" which can be done in one instruction on v9
-;; (so we do it). For the rest, on v9 we use conditional moves; on v8, we do
-;; branches.
+;; Next come the scc insns.
+
+(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"))]
+ ""
+{
+ if (GET_CODE (operands[2]) == ZERO_EXTRACT && operands[3] != const0_rtx)
+ operands[2] = force_reg (SImode, operands[2]);
+ if (emit_scc_insn (operands)) DONE; else FAIL;
+})
+
+(define_expand "cstoredi4"
+ [(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"))]
+ "TARGET_ARCH64"
+{
+ if (GET_CODE (operands[2]) == ZERO_EXTRACT && operands[3] != const0_rtx)
+ operands[2] = force_reg (DImode, operands[2]);
+ if (emit_scc_insn (operands)) DONE; else FAIL;
+})
+
+(define_expand "cstore<F:mode>4"
+ [(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"))]
+ "TARGET_FPU"
+ { if (emit_scc_insn (operands)) DONE; else FAIL; })
+
+
;; Seq_special[_xxx] and sne_special[_xxx] clobber the CC reg, because they
;; generate addcc/subcc instructions.
@@ -533,8 +501,8 @@
[(set (match_dup 3)
(xor:DI (match_operand:DI 1 "register_operand" "")
(match_operand:DI 2 "register_operand" "")))
- (set (match_operand:DI 0 "register_operand" "")
- (eq:DI (match_dup 3) (const_int 0)))]
+ (set (match_operand:SI 0 "register_operand" "")
+ (eq:SI (match_dup 3) (const_int 0)))]
"TARGET_ARCH64"
{ operands[3] = gen_reg_rtx (DImode); })
@@ -552,338 +520,11 @@
[(set (match_dup 3)
(xor:DI (match_operand:DI 1 "register_operand" "")
(match_operand:DI 2 "register_operand" "")))
- (set (match_operand:DI 0 "register_operand" "")
- (ne:DI (match_dup 3) (const_int 0)))]
- "TARGET_ARCH64"
- { operands[3] = gen_reg_rtx (DImode); })
-
-(define_expand "seqdi_special_trunc"
- [(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)))]
- "TARGET_ARCH64"
- { operands[3] = gen_reg_rtx (DImode); })
-
-(define_expand "snedi_special_trunc"
- [(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)))]
"TARGET_ARCH64"
{ operands[3] = gen_reg_rtx (DImode); })
-(define_expand "seqsi_special_extend"
- [(set (match_dup 3)
- (xor:SI (match_operand:SI 1 "register_operand" "")
- (match_operand:SI 2 "register_operand" "")))
- (parallel [(set (match_operand:DI 0 "register_operand" "")
- (eq:DI (match_dup 3) (const_int 0)))
- (clobber (reg:CC 100))])]
- "TARGET_ARCH64"
- { operands[3] = gen_reg_rtx (SImode); })
-
-(define_expand "snesi_special_extend"
- [(set (match_dup 3)
- (xor:SI (match_operand:SI 1 "register_operand" "")
- (match_operand:SI 2 "register_operand" "")))
- (parallel [(set (match_operand:DI 0 "register_operand" "")
- (ne:DI (match_dup 3) (const_int 0)))
- (clobber (reg:CC 100))])]
- "TARGET_ARCH64"
- { operands[3] = gen_reg_rtx (SImode); })
-
-;; ??? v9: Operand 0 needs a mode, so SImode was chosen.
-;; However, the code handles both SImode and DImode.
-(define_expand "seq"
- [(set (match_operand:SI 0 "int_register_operand" "")
- (eq:SI (match_dup 1) (const_int 0)))]
- ""
-{
- if (GET_MODE (sparc_compare_op0) == SImode)
- {
- rtx pat;
-
- if (GET_MODE (operands[0]) == SImode)
- pat = gen_seqsi_special (operands[0], sparc_compare_op0,
- sparc_compare_op1);
- else if (! TARGET_ARCH64)
- FAIL;
- else
- pat = gen_seqsi_special_extend (operands[0], sparc_compare_op0,
- sparc_compare_op1);
- emit_insn (pat);
- DONE;
- }
- else if (GET_MODE (sparc_compare_op0) == DImode)
- {
- rtx pat;
-
- if (! TARGET_ARCH64)
- FAIL;
- else if (GET_MODE (operands[0]) == SImode)
- pat = gen_seqdi_special_trunc (operands[0], sparc_compare_op0,
- sparc_compare_op1);
- else
- pat = gen_seqdi_special (operands[0], sparc_compare_op0,
- sparc_compare_op1);
- emit_insn (pat);
- DONE;
- }
- else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
- {
- 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)
- {
- if (gen_v9_scc (EQ, operands))
- DONE;
- /* fall through */
- }
- FAIL;
-})
-
-;; ??? v9: Operand 0 needs a mode, so SImode was chosen.
-;; However, the code handles both SImode and DImode.
-(define_expand "sne"
- [(set (match_operand:SI 0 "int_register_operand" "")
- (ne:SI (match_dup 1) (const_int 0)))]
- ""
-{
- if (GET_MODE (sparc_compare_op0) == SImode)
- {
- rtx pat;
-
- if (GET_MODE (operands[0]) == SImode)
- pat = gen_snesi_special (operands[0], sparc_compare_op0,
- sparc_compare_op1);
- else if (! TARGET_ARCH64)
- FAIL;
- else
- pat = gen_snesi_special_extend (operands[0], sparc_compare_op0,
- sparc_compare_op1);
- emit_insn (pat);
- DONE;
- }
- else if (GET_MODE (sparc_compare_op0) == DImode)
- {
- rtx pat;
-
- if (! TARGET_ARCH64)
- FAIL;
- else if (GET_MODE (operands[0]) == SImode)
- pat = gen_snedi_special_trunc (operands[0], sparc_compare_op0,
- sparc_compare_op1);
- else
- pat = gen_snedi_special (operands[0], sparc_compare_op0,
- sparc_compare_op1);
- emit_insn (pat);
- DONE;
- }
- else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
- {
- 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)
- {
- if (gen_v9_scc (NE, operands))
- DONE;
- /* fall through */
- }
- FAIL;
-})
-
-(define_expand "sgt"
- [(set (match_operand:SI 0 "int_register_operand" "")
- (gt:SI (match_dup 1) (const_int 0)))]
- ""
-{
- if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
- {
- 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)
- {
- if (gen_v9_scc (GT, operands))
- DONE;
- /* fall through */
- }
- FAIL;
-})
-
-(define_expand "slt"
- [(set (match_operand:SI 0 "int_register_operand" "")
- (lt:SI (match_dup 1) (const_int 0)))]
- ""
-{
- if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
- {
- 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)
- {
- if (gen_v9_scc (LT, operands))
- DONE;
- /* fall through */
- }
- FAIL;
-})
-
-(define_expand "sge"
- [(set (match_operand:SI 0 "int_register_operand" "")
- (ge:SI (match_dup 1) (const_int 0)))]
- ""
-{
- if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
- {
- 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)
- {
- if (gen_v9_scc (GE, operands))
- DONE;
- /* fall through */
- }
- FAIL;
-})
-
-(define_expand "sle"
- [(set (match_operand:SI 0 "int_register_operand" "")
- (le:SI (match_dup 1) (const_int 0)))]
- ""
-{
- if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
- {
- 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)
- {
- if (gen_v9_scc (LE, operands))
- DONE;
- /* fall through */
- }
- FAIL;
-})
-
-(define_expand "sgtu"
- [(set (match_operand:SI 0 "int_register_operand" "")
- (gtu:SI (match_dup 1) (const_int 0)))]
- ""
-{
- if (! TARGET_V9)
- {
- rtx tem, pat;
-
- /* We can do ltu easily, so if both operands are registers, swap them and
- do a LTU. */
- if ((GET_CODE (sparc_compare_op0) == REG
- || GET_CODE (sparc_compare_op0) == SUBREG)
- && (GET_CODE (sparc_compare_op1) == REG
- || GET_CODE (sparc_compare_op1) == SUBREG))
- {
- tem = sparc_compare_op0;
- sparc_compare_op0 = sparc_compare_op1;
- sparc_compare_op1 = tem;
- pat = gen_sltu (operands[0]);
- if (pat == NULL_RTX)
- FAIL;
- emit_insn (pat);
- DONE;
- }
- }
- else
- {
- if (gen_v9_scc (GTU, operands))
- DONE;
- }
- FAIL;
-})
-
-(define_expand "sltu"
- [(set (match_operand:SI 0 "int_register_operand" "")
- (ltu:SI (match_dup 1) (const_int 0)))]
- ""
-{
- if (TARGET_V9)
- {
- if (gen_v9_scc (LTU, operands))
- DONE;
- }
- operands[1] = gen_compare_reg (LTU);
-})
-
-(define_expand "sgeu"
- [(set (match_operand:SI 0 "int_register_operand" "")
- (geu:SI (match_dup 1) (const_int 0)))]
- ""
-{
- if (TARGET_V9)
- {
- if (gen_v9_scc (GEU, operands))
- DONE;
- }
- operands[1] = gen_compare_reg (GEU);
-})
-
-(define_expand "sleu"
- [(set (match_operand:SI 0 "int_register_operand" "")
- (leu:SI (match_dup 1) (const_int 0)))]
- ""
-{
- if (! TARGET_V9)
- {
- rtx tem, pat;
-
- /* We can do geu easily, so if both operands are registers, swap them and
- do a GEU. */
- if ((GET_CODE (sparc_compare_op0) == REG
- || GET_CODE (sparc_compare_op0) == SUBREG)
- && (GET_CODE (sparc_compare_op1) == REG
- || GET_CODE (sparc_compare_op1) == SUBREG))
- {
- tem = sparc_compare_op0;
- sparc_compare_op0 = sparc_compare_op1;
- sparc_compare_op1 = tem;
- pat = gen_sgeu (operands[0]);
- if (pat == NULL_RTX)
- FAIL;
- emit_insn (pat);
- DONE;
- }
- }
- else
- {
- if (gen_v9_scc (LEU, operands))
- DONE;
- }
- FAIL;
-})
;; Now the DEFINE_INSNs for the scc cases.
@@ -1275,344 +916,51 @@
;; These control RTL generation for conditional jump insns
-;; The quad-word fp compare library routines all return nonzero to indicate
-;; true, which is different from the equivalent libgcc routines, so we must
-;; handle them specially here.
-
-(define_expand "beq"
- [(set (pc)
- (if_then_else (eq (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx
- && GET_CODE (sparc_compare_op0) == REG
- && GET_MODE (sparc_compare_op0) == DImode)
- {
- emit_v9_brxx_insn (EQ, sparc_compare_op0, operands[0]);
- DONE;
- }
- else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
- {
- 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;
- }
- operands[1] = gen_compare_reg (EQ);
-})
-
-(define_expand "bne"
- [(set (pc)
- (if_then_else (ne (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx
- && GET_CODE (sparc_compare_op0) == REG
- && GET_MODE (sparc_compare_op0) == DImode)
- {
- emit_v9_brxx_insn (NE, sparc_compare_op0, operands[0]);
- DONE;
- }
- else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
- {
- 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;
- }
- operands[1] = gen_compare_reg (NE);
-})
-
-(define_expand "bgt"
- [(set (pc)
- (if_then_else (gt (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx
- && GET_CODE (sparc_compare_op0) == REG
- && GET_MODE (sparc_compare_op0) == DImode)
- {
- emit_v9_brxx_insn (GT, sparc_compare_op0, operands[0]);
- DONE;
- }
- else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
- {
- 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;
- }
- operands[1] = gen_compare_reg (GT);
-})
-
-(define_expand "bgtu"
- [(set (pc)
- (if_then_else (gtu (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- operands[1] = gen_compare_reg (GTU);
-})
-
-(define_expand "blt"
- [(set (pc)
- (if_then_else (lt (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx
- && GET_CODE (sparc_compare_op0) == REG
- && GET_MODE (sparc_compare_op0) == DImode)
- {
- emit_v9_brxx_insn (LT, sparc_compare_op0, operands[0]);
- DONE;
- }
- else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
- {
- 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;
- }
- operands[1] = gen_compare_reg (LT);
-})
-
-(define_expand "bltu"
- [(set (pc)
- (if_then_else (ltu (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- operands[1] = gen_compare_reg (LTU);
-})
-
-(define_expand "bge"
- [(set (pc)
- (if_then_else (ge (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx
- && GET_CODE (sparc_compare_op0) == REG
- && GET_MODE (sparc_compare_op0) == DImode)
- {
- emit_v9_brxx_insn (GE, sparc_compare_op0, operands[0]);
- DONE;
- }
- else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
- {
- 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;
- }
- operands[1] = gen_compare_reg (GE);
-})
-
-(define_expand "bgeu"
- [(set (pc)
- (if_then_else (geu (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- operands[1] = gen_compare_reg (GEU);
-})
-
-(define_expand "ble"
+(define_expand "cbranchcc4"
[(set (pc)
- (if_then_else (le (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
+ (if_then_else (match_operator 0 "comparison_operator"
+ [(match_operand 1 "compare_operand" "")
+ (match_operand 2 "const_zero_operand" "")])
+ (label_ref (match_operand 3 "" ""))
(pc)))]
""
-{
- if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx
- && GET_CODE (sparc_compare_op0) == REG
- && GET_MODE (sparc_compare_op0) == DImode)
- {
- emit_v9_brxx_insn (LE, sparc_compare_op0, operands[0]);
- DONE;
- }
- else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
- {
- 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;
- }
- operands[1] = gen_compare_reg (LE);
-})
-
-(define_expand "bleu"
- [(set (pc)
- (if_then_else (leu (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- operands[1] = gen_compare_reg (LEU);
-})
-
-(define_expand "bunordered"
- [(set (pc)
- (if_then_else (unordered (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
- {
- 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;
- }
- operands[1] = gen_compare_reg (UNORDERED);
-})
-
-(define_expand "bordered"
- [(set (pc)
- (if_then_else (ordered (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
- {
- 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;
- }
- operands[1] = gen_compare_reg (ORDERED);
-})
-
-(define_expand "bungt"
- [(set (pc)
- (if_then_else (ungt (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
- {
- 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;
- }
- operands[1] = gen_compare_reg (UNGT);
-})
+ "")
-(define_expand "bunlt"
- [(set (pc)
- (if_then_else (unlt (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
+(define_expand "cbranchsi4"
+ [(use (match_operator 0 "comparison_operator"
+ [(match_operand:SI 1 "compare_operand" "")
+ (match_operand:SI 2 "arith_operand" "")]))
+ (use (match_operand 3 ""))]
""
{
- if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
- {
- 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;
- }
- operands[1] = gen_compare_reg (UNLT);
+ if (GET_CODE (operands[1]) == ZERO_EXTRACT && operands[2] != const0_rtx)
+ operands[1] = force_reg (SImode, operands[1]);
+ emit_conditional_branch_insn (operands);
+ DONE;
})
-(define_expand "buneq"
- [(set (pc)
- (if_then_else (uneq (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
+(define_expand "cbranchdi4"
+ [(use (match_operator 0 "comparison_operator"
+ [(match_operand:DI 1 "compare_operand" "")
+ (match_operand:DI 2 "arith_operand" "")]))
+ (use (match_operand 3 ""))]
+ "TARGET_ARCH64"
{
- if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
- {
- 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;
- }
- operands[1] = gen_compare_reg (UNEQ);
+ if (GET_CODE (operands[1]) == ZERO_EXTRACT && operands[2] != const0_rtx)
+ operands[1] = force_reg (DImode, operands[1]);
+ emit_conditional_branch_insn (operands);
+ DONE;
})
-(define_expand "bunge"
- [(set (pc)
- (if_then_else (unge (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
- {
- 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;
- }
- operands[1] = gen_compare_reg (UNGE);
-})
+(define_expand "cbranch<F:mode>4"
+ [(use (match_operator 0 "comparison_operator"
+ [(match_operand:F 1 "register_operand" "")
+ (match_operand:F 2 "register_operand" "")]))
+ (use (match_operand 3 ""))]
+ "TARGET_FPU"
+ { emit_conditional_branch_insn (operands); DONE; })
-(define_expand "bunle"
- [(set (pc)
- (if_then_else (unle (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
- {
- 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;
- }
- operands[1] = gen_compare_reg (UNLE);
-})
-(define_expand "bltgt"
- [(set (pc)
- (if_then_else (ltgt (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
- {
- 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;
- }
- operands[1] = gen_compare_reg (LTGT);
-})
-
;; Now match both normal and inverted jump.
;; XXX fpcmp nop braindamage
@@ -1755,8 +1103,6 @@
(set_attr "branch_type" "reg")])
-(define_mode_iterator P [(SI "Pmode == SImode") (DI "Pmode == DImode")])
-
;; Load in operand 0 the (absolute) address of operand 1, which is a symbolic
;; value subject to a PC-relative relocation. Operand 2 is a helper function
;; that adds the PC value at the call point to operand 0.
@@ -2393,9 +1739,6 @@
;; Floating point and vector move instructions
-;; We don't define V1SI because SI should work just fine.
-(define_mode_iterator V32 [SF V2HI V4QI])
-
;; Yes, you guessed it right, the former movsf expander.
(define_expand "mov<V32:mode>"
[(set (match_operand:V32 0 "nonimmediate_operand" "")
@@ -2530,8 +1873,6 @@
[(set (match_dup 0) (high:SF (match_dup 1)))
(set (match_dup 0) (lo_sum:SF (match_dup 0) (match_dup 1)))])
-(define_mode_iterator V64 [DF V2SI V4HI V8QI])
-
;; Yes, you again guessed it right, the former movdf expander.
(define_expand "mov<V64:mode>"
[(set (match_operand:V64 0 "nonimmediate_operand" "")
@@ -3073,8 +2414,6 @@
;; 3 contains the constant if one is present, but we handle either for
;; generality (sparc.c puts a constant in operand 2).
-(define_mode_iterator I [QI HI SI DI])
-
(define_expand "mov<I:mode>cc"
[(set (match_operand:I 0 "register_operand" "")
(if_then_else:I (match_operand 1 "comparison_operator" "")
@@ -3083,21 +2422,27 @@
"TARGET_V9 && !(<I:MODE>mode == DImode && TARGET_ARCH32)"
{
enum rtx_code code = GET_CODE (operands[1]);
+ rtx cc_reg;
- if (GET_MODE (sparc_compare_op0) == DImode
+ if (GET_MODE (XEXP (operands[1], 0)) == DImode
&& ! TARGET_ARCH64)
FAIL;
- if (sparc_compare_op1 == const0_rtx
- && GET_CODE (sparc_compare_op0) == REG
- && GET_MODE (sparc_compare_op0) == DImode
+ if (GET_MODE (XEXP (operands[1], 0)) == TFmode && !TARGET_HARD_QUAD)
+ operands[1]
+ = sparc_emit_float_lib_cmp (XEXP (operands[1], 0), XEXP (operands[1], 1),
+ GET_CODE (operands[1]));
+
+ if (XEXP (operands[1], 1) == const0_rtx
+ && GET_CODE (XEXP (operands[1], 0)) == REG
+ && GET_MODE (XEXP (operands[1], 0)) == DImode
&& v9_regcmp_p (code))
- operands[1] = gen_rtx_fmt_ee (code, DImode, sparc_compare_op0, const0_rtx);
+ cc_reg = XEXP (operands[1], 0);
else
- operands[1] = gen_compare_operator (code);
-})
+ cc_reg = gen_compare_reg (operands[1]);
-(define_mode_iterator F [SF DF TF])
+ operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
+})
(define_expand "mov<F:mode>cc"
[(set (match_operand:F 0 "register_operand" "")
@@ -3107,18 +2452,26 @@
"TARGET_V9 && TARGET_FPU"
{
enum rtx_code code = GET_CODE (operands[1]);
+ rtx cc_reg;
- if (GET_MODE (sparc_compare_op0) == DImode
+ if (GET_MODE (XEXP (operands[1], 0)) == DImode
&& ! TARGET_ARCH64)
FAIL;
- if (sparc_compare_op1 == const0_rtx
- && GET_CODE (sparc_compare_op0) == REG
- && GET_MODE (sparc_compare_op0) == DImode
+ if (GET_MODE (XEXP (operands[1], 0)) == TFmode && !TARGET_HARD_QUAD)
+ operands[1]
+ = sparc_emit_float_lib_cmp (XEXP (operands[1], 0), XEXP (operands[1], 1),
+ GET_CODE (operands[1]));
+
+ if (XEXP (operands[1], 1) == const0_rtx
+ && GET_CODE (XEXP (operands[1], 0)) == REG
+ && GET_MODE (XEXP (operands[1], 0)) == DImode
&& v9_regcmp_p (code))
- operands[1] = gen_rtx_fmt_ee (code, DImode, sparc_compare_op0, const0_rtx);
+ cc_reg = XEXP (operands[1], 0);
else
- operands[1] = gen_compare_operator (code);
+ cc_reg = gen_compare_reg (operands[1]);
+
+ operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
})
;; Conditional move define_insns
@@ -5133,9 +4486,6 @@
;; We define DImode `and' so with DImode `not' we can get
;; DImode `andn'. Other combinations are possible.
-(define_mode_iterator V64I [DI V2SI V4HI V8QI])
-(define_mode_iterator V32I [SI V2HI V4QI])
-
(define_expand "and<V64I:mode>3"
[(set (match_operand:V64I 0 "register_operand" "")
(and:V64I (match_operand:V64I 1 "arith_double_operand" "")
@@ -7434,14 +6784,28 @@
"ta\t5"
[(set_attr "type" "trap")])
-(define_expand "conditional_trap"
- [(trap_if (match_operator 0 "noov_compare_operator" [(match_dup 2) (match_dup 3)])
- (match_operand:SI 1 "arith_operand" ""))]
+(define_expand "ctrapsi4"
+ [(trap_if (match_operator 0 "noov_compare_operator"
+ [(match_operand:SI 1 "compare_operand" "")
+ (match_operand:SI 2 "arith_operand" "")])
+ (match_operand 3 ""))]
""
- "operands[2] = gen_compare_reg (GET_CODE (operands[0]));
- if (GET_MODE (operands[2]) != CCmode && GET_MODE (operands[2]) != CCXmode)
+ "operands[1] = gen_compare_reg (operands[0]);
+ if (GET_MODE (operands[1]) != CCmode && GET_MODE (operands[1]) != CCXmode)
FAIL;
- operands[3] = const0_rtx;")
+ operands[2] = const0_rtx;")
+
+(define_expand "ctrapdi4"
+ [(trap_if (match_operator 0 "noov_compare_operator"
+ [(match_operand:DI 1 "compare_operand" "")
+ (match_operand:DI 2 "arith_operand" "")])
+ (match_operand 3 ""))]
+ "TARGET_ARCH64"
+ "operands[1] = gen_compare_reg (operands[0]);
+ if (GET_MODE (operands[1]) != CCmode && GET_MODE (operands[1]) != CCXmode)
+ FAIL;
+ operands[2] = const0_rtx;")
+
(define_insn ""
[(trap_if (match_operator 0 "noov_compare_operator" [(reg:CC 100) (const_int 0)])
@@ -8071,6 +7435,7 @@
(match_operand 2 "" "")]
""
{
+ rtx result, test;
#ifdef TARGET_THREAD_SSP_OFFSET
rtx tlsreg = gen_rtx_REG (Pmode, 7);
rtx addr = gen_rtx_PLUS (Pmode, tlsreg, GEN_INT (TARGET_THREAD_SSP_OFFSET));
@@ -8078,18 +7443,18 @@
#endif
if (TARGET_ARCH64)
{
- rtx temp = gen_reg_rtx (Pmode);
- emit_insn (gen_stack_protect_testdi (temp, operands[0], operands[1]));
- sparc_compare_op0 = temp;
- sparc_compare_op1 = const0_rtx;
+ result = gen_reg_rtx (Pmode);
+ emit_insn (gen_stack_protect_testdi (result, operands[0], operands[1]));
+ test = gen_rtx_EQ (VOIDmode, result, const0_rtx);
+ emit_jump_insn (gen_cbranchdi4 (test, result, const0_rtx, operands[2]));
}
else
{
emit_insn (gen_stack_protect_testsi (operands[0], operands[1]));
- sparc_compare_op0 = gen_rtx_REG (CCmode, SPARC_ICC_REG);
- sparc_compare_op1 = const0_rtx;
+ result = gen_rtx_REG (CCmode, SPARC_ICC_REG);
+ test = gen_rtx_EQ (VOIDmode, result, const0_rtx);
+ emit_jump_insn (gen_cbranchcc4 (test, result, const0_rtx, operands[2]));
}
- emit_jump_insn (gen_beq (operands[2]));
DONE;
})
diff --git a/gcc/config/spu/spu-protos.h b/gcc/config/spu/spu-protos.h
index 06e02ba0b48..3e2600b996b 100644
--- a/gcc/config/spu/spu-protos.h
+++ b/gcc/config/spu/spu-protos.h
@@ -28,8 +28,7 @@ extern int valid_subreg (rtx op);
extern void spu_expand_extv (rtx * ops, int unsignedp);
extern void spu_expand_insv (rtx * ops);
extern int spu_expand_block_move (rtx * ops);
-extern void spu_emit_branch_or_set (int is_set, enum rtx_code code,
- rtx * operands);
+extern void spu_emit_branch_or_set (int is_set, rtx cmp, rtx * operands);
extern int spu_emit_vector_cond_expr (rtx, rtx, rtx, rtx, rtx, rtx);
extern HOST_WIDE_INT const_double_to_hwint (rtx x);
extern rtx hwint_to_const_double (enum machine_mode mode, HOST_WIDE_INT v);
diff --git a/gcc/config/spu/spu.c b/gcc/config/spu/spu.c
index bb73622f9d5..f73bb217605 100644
--- a/gcc/config/spu/spu.c
+++ b/gcc/config/spu/spu.c
@@ -212,7 +212,6 @@ static void asm_file_start (void);
static unsigned int spu_section_type_flags (tree, const char *, int);
extern const char *reg_names[];
-rtx spu_compare_op0, spu_compare_op1;
/* Which instruction set architecture to use. */
int spu_arch;
@@ -844,42 +843,44 @@ int spu_comp_icode[12][3] = {
WORD_MODE, we can generate better code in most cases if we do it
ourselves. */
void
-spu_emit_branch_or_set (int is_set, enum rtx_code code, rtx operands[])
+spu_emit_branch_or_set (int is_set, rtx cmp, rtx operands[])
{
int reverse_compare = 0;
int reverse_test = 0;
rtx compare_result, eq_result;
rtx comp_rtx, eq_rtx;
- rtx target = operands[0];
enum machine_mode comp_mode;
enum machine_mode op_mode;
enum spu_comp_code scode, eq_code;
enum insn_code ior_code;
+ enum rtx_code code = GET_CODE (cmp);
+ rtx op0 = XEXP (cmp, 0);
+ rtx op1 = XEXP (cmp, 1);
int index;
int eq_test = 0;
- /* When spu_compare_op1 is a CONST_INT change (X >= C) to (X > C-1),
+ /* When op1 is a CONST_INT change (X >= C) to (X > C-1),
and so on, to keep the constant in operand 1. */
- if (GET_CODE (spu_compare_op1) == CONST_INT)
+ if (GET_CODE (op1) == CONST_INT)
{
- HOST_WIDE_INT val = INTVAL (spu_compare_op1) - 1;
- if (trunc_int_for_mode (val, GET_MODE (spu_compare_op0)) == val)
+ HOST_WIDE_INT val = INTVAL (op1) - 1;
+ if (trunc_int_for_mode (val, GET_MODE (op0)) == val)
switch (code)
{
case GE:
- spu_compare_op1 = GEN_INT (val);
+ op1 = GEN_INT (val);
code = GT;
break;
case LT:
- spu_compare_op1 = GEN_INT (val);
+ op1 = GEN_INT (val);
code = LE;
break;
case GEU:
- spu_compare_op1 = GEN_INT (val);
+ op1 = GEN_INT (val);
code = GTU;
break;
case LTU:
- spu_compare_op1 = GEN_INT (val);
+ op1 = GEN_INT (val);
code = LEU;
break;
default:
@@ -888,7 +889,7 @@ spu_emit_branch_or_set (int is_set, enum rtx_code code, rtx operands[])
}
comp_mode = SImode;
- op_mode = GET_MODE (spu_compare_op0);
+ op_mode = GET_MODE (op0);
switch (code)
{
@@ -1012,18 +1013,18 @@ spu_emit_branch_or_set (int is_set, enum rtx_code code, rtx operands[])
abort ();
}
- if (GET_MODE (spu_compare_op1) == DFmode
+ if (GET_MODE (op1) == DFmode
&& (scode != SPU_GT && scode != SPU_EQ))
abort ();
- if (is_set == 0 && spu_compare_op1 == const0_rtx
- && (GET_MODE (spu_compare_op0) == SImode
- || GET_MODE (spu_compare_op0) == HImode) && scode == SPU_EQ)
+ if (is_set == 0 && op1 == const0_rtx
+ && (GET_MODE (op0) == SImode
+ || GET_MODE (op0) == HImode) && scode == SPU_EQ)
{
/* Don't need to set a register with the result when we are
comparing against zero and branching. */
reverse_test = !reverse_test;
- compare_result = spu_compare_op0;
+ compare_result = op0;
}
else
{
@@ -1031,23 +1032,22 @@ spu_emit_branch_or_set (int is_set, enum rtx_code code, rtx operands[])
if (reverse_compare)
{
- rtx t = spu_compare_op1;
- spu_compare_op1 = spu_compare_op0;
- spu_compare_op0 = t;
+ rtx t = op1;
+ op1 = op0;
+ op0 = t;
}
if (spu_comp_icode[index][scode] == 0)
abort ();
if (!(*insn_data[spu_comp_icode[index][scode]].operand[1].predicate)
- (spu_compare_op0, op_mode))
- spu_compare_op0 = force_reg (op_mode, spu_compare_op0);
+ (op0, op_mode))
+ op0 = force_reg (op_mode, op0);
if (!(*insn_data[spu_comp_icode[index][scode]].operand[2].predicate)
- (spu_compare_op1, op_mode))
- spu_compare_op1 = force_reg (op_mode, spu_compare_op1);
+ (op1, op_mode))
+ op1 = force_reg (op_mode, op1);
comp_rtx = GEN_FCN (spu_comp_icode[index][scode]) (compare_result,
- spu_compare_op0,
- spu_compare_op1);
+ op0, op1);
if (comp_rtx == 0)
abort ();
emit_insn (comp_rtx);
@@ -1056,8 +1056,7 @@ spu_emit_branch_or_set (int is_set, enum rtx_code code, rtx operands[])
{
eq_result = gen_reg_rtx (comp_mode);
eq_rtx = GEN_FCN (spu_comp_icode[index][eq_code]) (eq_result,
- spu_compare_op0,
- spu_compare_op1);
+ op0, op1);
if (eq_rtx == 0)
abort ();
emit_insn (eq_rtx);
@@ -1088,13 +1087,14 @@ spu_emit_branch_or_set (int is_set, enum rtx_code code, rtx operands[])
else
bcomp = gen_rtx_NE (comp_mode, compare_result, const0_rtx);
- loc_ref = gen_rtx_LABEL_REF (VOIDmode, target);
+ loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands[3]);
emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp,
loc_ref, pc_rtx)));
}
else if (is_set == 2)
{
+ rtx target = operands[0];
int compare_size = GET_MODE_BITSIZE (comp_mode);
int target_size = GET_MODE_BITSIZE (GET_MODE (target));
enum machine_mode mode = mode_for_size (target_size, MODE_INT, 0);
@@ -1129,6 +1129,7 @@ spu_emit_branch_or_set (int is_set, enum rtx_code code, rtx operands[])
}
else
{
+ rtx target = operands[0];
if (reverse_test)
emit_insn (gen_rtx_SET (VOIDmode, compare_result,
gen_rtx_NOT (comp_mode, compare_result)));
diff --git a/gcc/config/spu/spu.h b/gcc/config/spu/spu.h
index ed92715cd01..ddd464ac579 100644
--- a/gcc/config/spu/spu.h
+++ b/gcc/config/spu/spu.h
@@ -606,11 +606,6 @@ targetm.resolve_overloaded_builtin = spu_resolve_overloaded_builtin; \
} \
} while (0)
-/* These are set by the cmp patterns and used while expanding
- conditional branches. */
-extern GTY(()) rtx spu_compare_op0;
-extern GTY(()) rtx spu_compare_op1;
-
/* Builtins. */
diff --git a/gcc/config/spu/spu.md b/gcc/config/spu/spu.md
index bd6936fd9e3..db42db16111 100644
--- a/gcc/config/spu/spu.md
+++ b/gcc/config/spu/spu.md
@@ -3657,57 +3657,6 @@ selb\t%0,%4,%0,%3"
[(set_attr "type" "br")])
-;; Compare insns are next. Note that the spu has two types of compares,
-;; 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:VQHSI 0 "spu_reg_operand" "")
- (match_operand:VQHSI 1 "spu_nonmem_operand" "")))]
- ""
- {
- spu_compare_op0 = operands[0];
- spu_compare_op1 = operands[1];
- DONE;
- })
-
-(define_expand "cmp<mode>"
- [(set (cc0)
- (compare (match_operand:DTI 0 "spu_reg_operand" "")
- (match_operand:DTI 1 "spu_reg_operand" "")))]
- ""
- {
- spu_compare_op0 = operands[0];
- spu_compare_op1 = operands[1];
- DONE;
- })
-
-(define_expand "cmp<mode>"
- [(set (cc0)
- (compare (match_operand:VSF 0 "spu_reg_operand" "")
- (match_operand:VSF 1 "spu_reg_operand" "")))]
- ""
- {
- spu_compare_op0 = operands[0];
- spu_compare_op1 = operands[1];
- DONE;
- })
-
-(define_expand "cmpdf"
- [(set (cc0)
- (compare (match_operand:DF 0 "register_operand" "")
- (match_operand:DF 1 "register_operand" "")))]
- ""
- "{
- spu_compare_op0 = operands[0];
- spu_compare_op1 = operands[1];
- DONE;
-}")
-
;; vector conditional compare patterns
(define_expand "vcond<mode>"
[(set (match_operand:VCMP 0 "spu_reg_operand" "=r")
@@ -3746,108 +3695,72 @@ selb\t%0,%4,%0,%3"
;; branch on condition
-(define_expand "beq"
- [(use (match_operand 0 "" ""))]
- ""
- { spu_emit_branch_or_set (0, EQ, operands); DONE; })
-
-(define_expand "bne"
- [(use (match_operand 0 "" ""))]
- ""
- { spu_emit_branch_or_set (0, NE, operands); DONE; })
-
-(define_expand "bge"
- [(use (match_operand 0 "" ""))]
- ""
- { spu_emit_branch_or_set (0, GE, operands); DONE; })
-
-(define_expand "bgt"
- [(use (match_operand 0 "" ""))]
- ""
- { spu_emit_branch_or_set (0, GT, operands); DONE; })
-
-(define_expand "ble"
- [(use (match_operand 0 "" ""))]
- ""
- { spu_emit_branch_or_set (0, LE, operands); DONE; })
-
-(define_expand "blt"
- [(use (match_operand 0 "" ""))]
+(define_expand "cbranch<mode>4"
+ [(use (match_operator 0 "ordered_comparison_operator"
+ [(match_operand:VQHSI 1 "spu_reg_operand" "")
+ (match_operand:VQHSI 2 "spu_nonmem_operand" "")]))
+ (use (match_operand 3 ""))]
""
- { spu_emit_branch_or_set (0, LT, operands); DONE; })
+ { spu_emit_branch_or_set (0, operands[0], operands); DONE; })
-(define_expand "bgeu"
- [(use (match_operand 0 "" ""))]
+(define_expand "cbranch<mode>4"
+ [(use (match_operator 0 "ordered_comparison_operator"
+ [(match_operand:DTI 1 "spu_reg_operand" "")
+ (match_operand:DTI 2 "spu_reg_operand" "")]))
+ (use (match_operand 3 ""))]
""
- { spu_emit_branch_or_set (0, GEU, operands); DONE; })
+ { spu_emit_branch_or_set (0, operands[0], operands); DONE; })
-(define_expand "bgtu"
- [(use (match_operand 0 "" ""))]
+(define_expand "cbranch<mode>4"
+ [(use (match_operator 0 "ordered_comparison_operator"
+ [(match_operand:VSF 1 "spu_reg_operand" "")
+ (match_operand:VSF 2 "spu_reg_operand" "")]))
+ (use (match_operand 3 ""))]
""
- { spu_emit_branch_or_set (0, GTU, operands); DONE; })
+ { spu_emit_branch_or_set (0, operands[0], operands); DONE; })
-(define_expand "bleu"
- [(use (match_operand 0 "" ""))]
+(define_expand "cbranchdf4"
+ [(use (match_operator 0 "ordered_comparison_operator"
+ [(match_operand:DF 1 "spu_reg_operand" "")
+ (match_operand:DF 2 "spu_reg_operand" "")]))
+ (use (match_operand 3 ""))]
""
- { spu_emit_branch_or_set (0, LEU, operands); DONE; })
-
-(define_expand "bltu"
- [(use (match_operand 0 "" ""))]
- ""
- { spu_emit_branch_or_set (0, LTU, operands); DONE; })
+ { spu_emit_branch_or_set (0, operands[0], operands); DONE; })
;; set on condition
-(define_expand "seq"
- [(clobber (match_operand:SI 0 "spu_reg_operand" ""))]
- ""
- { spu_emit_branch_or_set (1, EQ, operands); DONE; })
-
-(define_expand "sne"
- [(clobber (match_operand:SI 0 "spu_reg_operand" ""))]
- ""
- { spu_emit_branch_or_set (1, NE, operands); DONE; })
-
-(define_expand "sgt"
- [(clobber (match_operand:SI 0 "spu_reg_operand" ""))]
- ""
- { spu_emit_branch_or_set (1, GT, operands); DONE; })
-
-(define_expand "slt"
- [(clobber (match_operand:SI 0 "spu_reg_operand" ""))]
- ""
- { spu_emit_branch_or_set (1, LT, operands); DONE; })
-
-(define_expand "sge"
- [(clobber (match_operand:SI 0 "spu_reg_operand" ""))]
- ""
- { spu_emit_branch_or_set (1, GE, operands); DONE; })
-
-(define_expand "sle"
- [(clobber (match_operand:SI 0 "spu_reg_operand" ""))]
- ""
- { spu_emit_branch_or_set (1, LE, operands); DONE; })
-
-(define_expand "sgtu"
- [(clobber (match_operand:SI 0 "spu_reg_operand" ""))]
+(define_expand "cstore<mode>4"
+ [(use (match_operator 1 "ordered_comparison_operator"
+ [(match_operand:VQHSI 2 "spu_reg_operand" "")
+ (match_operand:VQHSI 3 "spu_nonmem_operand" "")]))
+ (clobber (match_operand:SI 0 "spu_reg_operand"))]
""
- { spu_emit_branch_or_set (1, GTU, operands); DONE; })
+ { spu_emit_branch_or_set (1, operands[1], operands); DONE; })
-(define_expand "sltu"
- [(clobber (match_operand:SI 0 "spu_reg_operand" ""))]
+(define_expand "cstore<mode>4"
+ [(use (match_operator 1 "ordered_comparison_operator"
+ [(match_operand:DTI 2 "spu_reg_operand" "")
+ (match_operand:DTI 3 "spu_reg_operand" "")]))
+ (clobber (match_operand:SI 0 "spu_reg_operand"))]
""
- { spu_emit_branch_or_set (1, LTU, operands); DONE; })
+ { spu_emit_branch_or_set (1, operands[1], operands); DONE; })
-(define_expand "sgeu"
- [(clobber (match_operand:SI 0 "spu_reg_operand" ""))]
+(define_expand "cstore<mode>4"
+ [(use (match_operator 1 "ordered_comparison_operator"
+ [(match_operand:VSF 2 "spu_reg_operand" "")
+ (match_operand:VSF 3 "spu_reg_operand" "")]))
+ (clobber (match_operand:SI 0 "spu_reg_operand"))]
""
- { spu_emit_branch_or_set (1, GEU, operands); DONE; })
+ { spu_emit_branch_or_set (1, operands[1], operands); DONE; })
-(define_expand "sleu"
- [(clobber (match_operand:SI 0 "spu_reg_operand" ""))]
+(define_expand "cstoredf4"
+ [(use (match_operator 1 "ordered_comparison_operator"
+ [(match_operand:DF 2 "spu_reg_operand" "")
+ (match_operand:DF 3 "spu_reg_operand" "")]))
+ (clobber (match_operand:SI 0 "spu_reg_operand"))]
""
- { spu_emit_branch_or_set (1, LEU, operands); DONE; })
+ { spu_emit_branch_or_set (1, operands[1], operands); DONE; })
;; conditional move
@@ -3863,12 +3776,12 @@ selb\t%0,%4,%0,%3"
(define_expand "mov<mode>cc"
[(set (match_operand:ALL 0 "spu_reg_operand" "")
- (if_then_else:ALL (match_operand 1 "comparison_operator" "")
+ (if_then_else:ALL (match_operand 1 "ordered_comparison_operator" "")
(match_operand:ALL 2 "spu_reg_operand" "")
(match_operand:ALL 3 "spu_reg_operand" "")))]
""
{
- spu_emit_branch_or_set(2, GET_CODE(operands[1]), operands);
+ spu_emit_branch_or_set(2, operands[1], operands);
DONE;
})
diff --git a/gcc/config/stormy16/stormy16-protos.h b/gcc/config/stormy16/stormy16-protos.h
index 58cff8a26e9..bde411b4e3a 100644
--- a/gcc/config/stormy16/stormy16-protos.h
+++ b/gcc/config/stormy16/stormy16-protos.h
@@ -48,7 +48,7 @@ extern rtx xstormy16_function_value (const_tree, const_tree);
#endif
#ifdef RTX_CODE
-extern void xstormy16_emit_cbranch (enum rtx_code, rtx);
+extern void xstormy16_emit_cbranch (enum rtx_code, rtx, rtx, rtx);
extern char *xstormy16_output_cbranch_hi (rtx, const char *, int, rtx);
extern char *xstormy16_output_cbranch_si (rtx, const char *, int, rtx);
extern int xstormy16_mode_dependent_address_p (rtx);
diff --git a/gcc/config/stormy16/stormy16.c b/gcc/config/stormy16/stormy16.c
index eefc58f0847..4d04cae95d9 100644
--- a/gcc/config/stormy16/stormy16.c
+++ b/gcc/config/stormy16/stormy16.c
@@ -61,11 +61,6 @@ static bool xstormy16_rtx_costs (rtx, int, int, int *, bool);
static int xstormy16_address_cost (rtx, bool);
static bool xstormy16_return_in_memory (const_tree, const_tree);
-/* Define the information needed to generate branch and scc insns. This is
- stored from the compare operation. */
-struct rtx_def * xstormy16_compare_op0;
-struct rtx_def * xstormy16_compare_op1;
-
static GTY(()) section *bss100_section;
/* Compute a (partial) cost for rtx X. Return true if the complete
@@ -139,10 +134,8 @@ xstormy16_address_cost (rtx x, bool speed ATTRIBUTE_UNUSED)
/* Emit a branch of kind CODE to location LOC. */
void
-xstormy16_emit_cbranch (enum rtx_code code, rtx loc)
+xstormy16_emit_cbranch (enum rtx_code code, rtx op0, rtx op1, rtx loc)
{
- rtx op0 = xstormy16_compare_op0;
- rtx op1 = xstormy16_compare_op1;
rtx condition_rtx, loc_ref, branch, cy_clobber;
rtvec vec;
enum machine_mode mode;
@@ -159,10 +152,10 @@ xstormy16_emit_cbranch (enum rtx_code code, rtx loc)
if (gt_p)
lab = gen_label_rtx ();
- xstormy16_emit_cbranch (unsigned_p ? LTU : LT, gt_p ? lab : loc);
+ xstormy16_emit_cbranch (unsigned_p ? LTU : LT, op0, op1, gt_p ? lab : loc);
/* This should be generated as a comparison against the temporary
created by the previous insn, but reload can't handle that. */
- xstormy16_emit_cbranch (gt_p ? NE : EQ, loc);
+ xstormy16_emit_cbranch (gt_p ? NE : EQ, op0, op1, loc);
if (gt_p)
emit_label (lab);
return;
@@ -171,6 +164,7 @@ xstormy16_emit_cbranch (enum rtx_code code, rtx loc)
&& (code == NE || code == EQ)
&& op1 != const0_rtx)
{
+ rtx op0_word, op1_word;
rtx lab = NULL_RTX;
int num_words = GET_MODE_BITSIZE (mode) / BITS_PER_WORD;
int i;
@@ -180,17 +174,17 @@ xstormy16_emit_cbranch (enum rtx_code code, rtx loc)
for (i = 0; i < num_words - 1; i++)
{
- xstormy16_compare_op0 = simplify_gen_subreg (word_mode, op0, mode,
- i * UNITS_PER_WORD);
- xstormy16_compare_op1 = simplify_gen_subreg (word_mode, op1, mode,
- i * UNITS_PER_WORD);
- xstormy16_emit_cbranch (NE, code == EQ ? lab : loc);
+ op0_word = simplify_gen_subreg (word_mode, op0, mode,
+ i * UNITS_PER_WORD);
+ op1_word = simplify_gen_subreg (word_mode, op1, mode,
+ i * UNITS_PER_WORD);
+ xstormy16_emit_cbranch (NE, op0_word, op1_word, code == EQ ? lab : loc);
}
- xstormy16_compare_op0 = simplify_gen_subreg (word_mode, op0, mode,
- i * UNITS_PER_WORD);
- xstormy16_compare_op1 = simplify_gen_subreg (word_mode, op1, mode,
- i * UNITS_PER_WORD);
- xstormy16_emit_cbranch (code, loc);
+ op0_word = simplify_gen_subreg (word_mode, op0, mode,
+ i * UNITS_PER_WORD);
+ op1_word = simplify_gen_subreg (word_mode, op1, mode,
+ i * UNITS_PER_WORD);
+ xstormy16_emit_cbranch (code, op0_word, op1_word, loc);
if (code == EQ)
emit_label (lab);
diff --git a/gcc/config/stormy16/stormy16.h b/gcc/config/stormy16/stormy16.h
index 675b94d9949..d626edf6e50 100644
--- a/gcc/config/stormy16/stormy16.h
+++ b/gcc/config/stormy16/stormy16.h
@@ -801,11 +801,4 @@ do { \
is responsible for updating the value of MORE (typically by (MORE)--). */
/* #define MD_SCHED_VARIABLE_ISSUE (FILE, VERBOSE, INSN, MORE) */
-
-/* Define the information needed to generate branch and scc insns. This is
- stored from the compare operation. Note that we can't use "rtx" here
- since it hasn't been defined! */
-
-extern struct rtx_def *xstormy16_compare_op0, *xstormy16_compare_op1;
-
/* End of xstormy16.h */
diff --git a/gcc/config/stormy16/stormy16.md b/gcc/config/stormy16/stormy16.md
index 43e454804a1..9c86d43e627 100644
--- a/gcc/config/stormy16/stormy16.md
+++ b/gcc/config/stormy16/stormy16.md
@@ -736,40 +736,7 @@
operands[0], operands[2], operands[3]);"
[(set_attr "length" "6,10")
(set_attr "psw_operand" "clobber,clobber")])
-
-;; ::::::::::::::::::::
-;; ::
-;; :: Comparisons
-;; ::
-;; ::::::::::::::::::::
-
-;; Note, we store the operands in the comparison insns, and use them later
-;; when generating the branch or scc operation.
-
-;; First the routines called by the machine independent part of the compiler
-(define_expand "cmphi"
- [(set (cc0)
- (compare (match_operand:HI 0 "register_operand" "")
- (match_operand:HI 1 "nonmemory_operand" "")))]
- ""
- {
- xstormy16_compare_op0 = operands[0];
- xstormy16_compare_op1 = operands[1];
- DONE;
- })
-; There are no real SImode comparisons, but some can be emulated
-; by performing a SImode subtract and looking at the condition flags.
-(define_expand "cmpsi"
- [(set (cc0)
- (compare (match_operand:SI 0 "register_operand" "")
- (match_operand:SI 1 "nonmemory_operand" "")))]
- ""
- {
- xstormy16_compare_op0 = operands[0];
- xstormy16_compare_op1 = operands[1];
- DONE;
- })
;; ::::::::::::::::::::
;; ::
@@ -777,55 +744,35 @@
;; ::
;; ::::::::::::::::::::
-(define_expand "beq"
- [(use (match_operand 0 "" ""))]
- ""
- { xstormy16_emit_cbranch (EQ, operands[0]); DONE; })
-
-(define_expand "bne"
- [(use (match_operand 0 "" ""))]
- ""
- { xstormy16_emit_cbranch (NE, operands[0]); DONE; })
-
-(define_expand "bge"
- [(use (match_operand 0 "" ""))]
- ""
- { xstormy16_emit_cbranch (GE, operands[0]); DONE; })
-
-(define_expand "bgt"
- [(use (match_operand 0 "" ""))]
- ""
- { xstormy16_emit_cbranch (GT, operands[0]); DONE; })
-
-(define_expand "ble"
- [(use (match_operand 0 "" ""))]
- ""
- { xstormy16_emit_cbranch (LE, operands[0]); DONE; })
-
-(define_expand "blt"
- [(use (match_operand 0 "" ""))]
- ""
- { xstormy16_emit_cbranch (LT, operands[0]); DONE; })
-
-(define_expand "bgeu"
- [(use (match_operand 0 "" ""))]
- ""
- { xstormy16_emit_cbranch (GEU, operands[0]); DONE; })
-
-(define_expand "bgtu"
- [(use (match_operand 0 "" ""))]
- ""
- { xstormy16_emit_cbranch (GTU, operands[0]); DONE; })
-
-(define_expand "bleu"
- [(use (match_operand 0 "" ""))]
+(define_expand "cbranchhi4"
+ [(set (pc)
+ (if_then_else (match_operator 0 "comparison_operator"
+ [(match_operand:HI 1 "register_operand" "")
+ (match_operand:HI 2 "nonmemory_operand" "")])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))
+ (clobber (reg:BI CARRY_REG))]
""
- { xstormy16_emit_cbranch (LEU, operands[0]); DONE; })
+ {
+ xstormy16_emit_cbranch (GET_CODE (operands[0]), operands[1], operands[2],
+ operands[3]);
+ DONE;
+})
-(define_expand "bltu"
- [(use (match_operand 0 "" ""))]
+(define_expand "cbranchsi4"
+ [(set (pc)
+ (if_then_else (match_operator 0 "comparison_operator"
+ [(match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "nonmemory_operand" "")])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))
+ (clobber (reg:BI CARRY_REG))]
""
- { xstormy16_emit_cbranch (LTU, operands[0]); DONE; })
+ {
+ xstormy16_emit_cbranch (GET_CODE (operands[0]), operands[1], operands[2],
+ operands[3]);
+ DONE;
+})
(define_insn "cbranchhi"
[(set (pc)
diff --git a/gcc/config/v850/v850.c b/gcc/config/v850/v850.c
index a562202538b..f9e8a7dd8b0 100644
--- a/gcc/config/v850/v850.c
+++ b/gcc/config/v850/v850.c
@@ -464,6 +464,11 @@ v850_rtx_costs (rtx x,
*total = 20;
return true;
+ case ZERO_EXTRACT:
+ if (outer_code == COMPARE)
+ *total = 0;
+ return false;
+
default:
return false;
}
diff --git a/gcc/config/v850/v850.md b/gcc/config/v850/v850.md
index dad3cdd885b..69c8d881f89 100644
--- a/gcc/config/v850/v850.md
+++ b/gcc/config/v850/v850.md
@@ -227,9 +227,11 @@
;; ----------------------------------------------------------------------
(define_insn "*v850_tst1"
- [(set (cc0) (zero_extract:SI (match_operand:QI 0 "memory_operand" "m")
- (const_int 1)
- (match_operand:QI 1 "const_int_operand" "n")))]
+ [(set (cc0)
+ (compare (zero_extract:SI (match_operand:QI 0 "memory_operand" "m")
+ (const_int 1)
+ (match_operand:QI 1 "const_int_operand" "n"))
+ (const_int 0)))]
""
"tst1 %1,%0"
[(set_attr "length" "4")
@@ -237,37 +239,52 @@
;; This replaces ld.b;sar;andi with tst1;setf nz.
-;; ??? The zero_extract sets the Z bit to the opposite of what one would
-;; expect. This perhaps should be wrapped in a (eq: X (const_int 0)).
-
(define_split
[(set (match_operand:SI 0 "register_operand" "")
- (zero_extract:SI (match_operand:QI 1 "memory_operand" "")
- (const_int 1)
- (match_operand 2 "const_int_operand" "")))]
- ""
- [(set (cc0) (zero_extract:SI (match_dup 1)
- (const_int 1)
- (match_dup 2)))
+ (compare (zero_extract:SI (match_operand:QI 1 "memory_operand" "")
+ (const_int 1)
+ (match_operand 2 "const_int_operand" ""))
+ (const_int 0)))]
+ ""
+ [(set (cc0) (compare (zero_extract:SI (match_dup 1)
+ (const_int 1)
+ (match_dup 2))
+ (const_int 0)))
(set (match_dup 0) (ne:SI (cc0) (const_int 0)))])
-(define_insn "tstsi"
- [(set (cc0) (match_operand:SI 0 "register_operand" "r"))]
- ""
- "cmp %.,%0"
- [(set_attr "length" "2")
- (set_attr "cc" "set_znv")])
+(define_expand "cbranchsi4"
+ [(set (cc0)
+ (compare (match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "reg_or_int5_operand" "")))
+ (set (pc)
+ (if_then_else
+ (match_operator 0 "ordered_comparison_operator" [(cc0)
+ (const_int 0)])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
+ "")
+
+(define_expand "cstoresi4"
+ [(set (cc0)
+ (compare (match_operand:SI 2 "register_operand" "")
+ (match_operand:SI 3 "reg_or_int5_operand" "")))
+ (set (match_operand:SI 0 "register_operand")
+ (match_operator:SI 1 "ordered_comparison_operator" [(cc0)
+ (const_int 0)]))]
+ "")
-(define_insn "cmpsi"
+(define_insn "*cmpsi"
[(set (cc0)
- (compare (match_operand:SI 0 "register_operand" "r,r")
- (match_operand:SI 1 "reg_or_int5_operand" "r,J")))]
+ (compare (match_operand:SI 0 "register_operand" "r,r,r")
+ (match_operand:SI 1 "reg_or_int5_operand" "r,I,J")))]
""
"@
cmp %1,%0
+ cmp %.,%0
cmp %1,%0"
- [(set_attr "length" "2,2")
- (set_attr "cc" "compare")])
+ [(set_attr "length" "2,2,2")
+ (set_attr "cc" "compare,set_znv,compare")])
+
;; ----------------------------------------------------------------------
;; ADD INSTRUCTIONS
@@ -688,110 +705,25 @@
;; Scc INSTRUCTIONS
;; -----------------------------------------------------------------
-(define_insn "sle"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (le:SI (cc0) (const_int 0)))]
- ""
- "*
-{
- if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
- return 0;
-
- return \"setf le,%0\";
-}"
- [(set_attr "length" "4")
- (set_attr "cc" "none_0hit")])
-
-(define_insn "sleu"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (leu:SI (cc0) (const_int 0)))]
- ""
- "setf nh,%0"
- [(set_attr "length" "4")
- (set_attr "cc" "none_0hit")])
-
-(define_insn "sge"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (ge:SI (cc0) (const_int 0)))]
- ""
- "*
-{
- if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
- return 0;
-
- return \"setf ge,%0\";
-}"
- [(set_attr "length" "4")
- (set_attr "cc" "none_0hit")])
-
-(define_insn "sgeu"
+(define_insn "*setcc"
[(set (match_operand:SI 0 "register_operand" "=r")
- (geu:SI (cc0) (const_int 0)))]
- ""
- "setf nl,%0"
- [(set_attr "length" "4")
- (set_attr "cc" "none_0hit")])
-
-(define_insn "slt"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (lt:SI (cc0) (const_int 0)))]
- ""
- "*
-{
- if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
- return 0;
-
- return \"setf lt,%0\";
-}"
- [(set_attr "length" "4")
- (set_attr "cc" "none_0hit")])
-
-(define_insn "sltu"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (ltu:SI (cc0) (const_int 0)))]
- ""
- "setf l,%0"
- [(set_attr "length" "4")
- (set_attr "cc" "none_0hit")])
-
-(define_insn "sgt"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (gt:SI (cc0) (const_int 0)))]
+ (match_operator:SI 1 "comparison_operator"
+ [(cc0) (const_int 0)]))]
""
"*
{
- if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
+ if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0
+ && (GET_CODE (operands[1]) == GT
+ || GET_CODE (operands[1]) == GE
+ || GET_CODE (operands[1]) == LE
+ || GET_CODE (operands[1]) == LT))
return 0;
- return \"setf gt,%0\";
+ return \"setf %c1,%0\";
}"
[(set_attr "length" "4")
(set_attr "cc" "none_0hit")])
-(define_insn "sgtu"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (gtu:SI (cc0) (const_int 0)))]
- ""
- "setf h,%0"
- [(set_attr "length" "4")
- (set_attr "cc" "none_0hit")])
-
-(define_insn "seq"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (eq:SI (cc0) (const_int 0)))]
- ""
- "setf z,%0"
- [(set_attr "length" "4")
- (set_attr "cc" "none_0hit")])
-
-(define_insn "sne"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (ne:SI (cc0) (const_int 0)))]
- ""
- "setf nz,%0"
- [(set_attr "length" "4")
- (set_attr "cc" "none_0hit")])
-
;; ----------------------------------------------------------------------
;; CONDITIONAL MOVE INSTRUCTIONS
;; ----------------------------------------------------------------------
@@ -800,25 +732,15 @@
;; hide the fact that this instruction uses cc0. We do so by including the
;; compare instruction inside it.
-;; ??? This is very ugly. The right way to do this is to modify cmpsi so
-;; that it doesn't emit RTL, and then modify the bcc/scc patterns so that
-;; they emit RTL for the compare instruction. Unfortunately, this requires
-;; lots of changes that will be hard to sanitize. So for now, cmpsi still
-;; emits RTL, and I get the compare operands here from the previous insn.
-
(define_expand "movsicc"
[(set (match_operand:SI 0 "register_operand" "=r")
(if_then_else:SI
- (match_operator 1 "comparison_operator"
- [(match_dup 4) (match_dup 5)])
+ (match_operand 1 "comparison_operator")
(match_operand:SI 2 "reg_or_const_operand" "rJ")
(match_operand:SI 3 "reg_or_const_operand" "rI")))]
"TARGET_V850E"
"
{
- rtx insn = get_last_insn_anywhere ();
- rtx src;
-
if ( (GET_CODE (operands[2]) == CONST_INT
&& GET_CODE (operands[3]) == CONST_INT))
{
@@ -845,28 +767,6 @@
if (GET_CODE (operands[3]) != REG)
operands[3] = copy_to_mode_reg (SImode, operands[3]);
}
- gcc_assert (GET_CODE (insn) == INSN
- && GET_CODE (PATTERN (insn)) == SET
- && SET_DEST (PATTERN (insn)) == cc0_rtx);
-
- src = SET_SRC (PATTERN (insn));
-
- switch (GET_CODE (src))
- {
- case COMPARE:
- operands[4] = XEXP (src, 0);
- operands[5] = XEXP (src, 1);
- break;
-
- case REG:
- case SUBREG:
- operands[4] = src;
- operands[5] = const0_rtx;
- break;
-
- default:
- gcc_unreachable ();
- }
}")
;; ??? Clobbering the condition codes is overkill.
@@ -1037,96 +937,6 @@
;; Conditional jump instructions
-(define_expand "ble"
- [(set (pc)
- (if_then_else (le (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "bleu"
- [(set (pc)
- (if_then_else (leu (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "bge"
- [(set (pc)
- (if_then_else (ge (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "bgeu"
- [(set (pc)
- (if_then_else (geu (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "blt"
- [(set (pc)
- (if_then_else (lt (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "bltu"
- [(set (pc)
- (if_then_else (ltu (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "bgt"
- [(set (pc)
- (if_then_else (gt (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "bgtu"
- [(set (pc)
- (if_then_else (gtu (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "beq"
- [(set (pc)
- (if_then_else (eq (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "bne"
- [(set (pc)
- (if_then_else (ne (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
(define_insn "*branch_normal"
[(set (pc)
(if_then_else (match_operator 1 "comparison_operator"
@@ -1241,14 +1051,16 @@
{
rtx reg = gen_reg_rtx (SImode);
rtx tableaddress = gen_reg_rtx (SImode);
+ rtx test;
rtx mem;
/* Subtract the lower bound from the index. */
emit_insn (gen_subsi3 (reg, operands[0], operands[1]));
- /* Compare the result against the number of table entries. */
- emit_insn (gen_cmpsi (reg, operands[2]));
- /* Branch to the default label if out of range of the table. */
- emit_jump_insn (gen_bgtu (operands[4]));
+
+ /* Compare the result against the number of table entries;
+ branch to the default label if out of range of the table. */
+ test = gen_rtx_fmt_ee (GTU, VOIDmode, reg, operands[2]);
+ emit_jump_insn (gen_cbranchsi4 (test, reg, operands[2], operands[4]));
/* Shift index for the table array access. */
emit_insn (gen_ashlsi3 (reg, reg, GEN_INT (TARGET_BIG_SWITCH ? 2 : 1)));
diff --git a/gcc/config/vax/vax-protos.h b/gcc/config/vax/vax-protos.h
index 9b43d4f86e9..c038b300d91 100644
--- a/gcc/config/vax/vax-protos.h
+++ b/gcc/config/vax/vax-protos.h
@@ -26,6 +26,7 @@ extern bool legitimate_address_p (enum machine_mode, rtx, bool);
extern bool vax_mode_dependent_address_p (rtx);
#ifdef RTX_CODE
+extern const char *cond_name (rtx);
extern bool adjacent_operands_p (rtx, rtx, enum machine_mode);
extern const char *rev_cond_name (rtx);
extern void print_operand_address (FILE *, rtx);
@@ -35,7 +36,6 @@ extern void vax_expand_addsub_di_operands (rtx *, enum rtx_code);
extern const char * vax_output_int_move (rtx, rtx *, enum machine_mode);
extern const char * vax_output_int_add (rtx, rtx *, enum machine_mode);
extern const char * vax_output_int_subtract (rtx, rtx *, enum machine_mode);
-extern const char * vax_output_conditional_branch (enum rtx_code);
extern const char * vax_output_movmemsi (rtx, rtx *);
#endif /* RTX_CODE */
diff --git a/gcc/config/vax/vax.c b/gcc/config/vax/vax.c
index e91696947e6..cd66bb4e2d7 100644
--- a/gcc/config/vax/vax.c
+++ b/gcc/config/vax/vax.c
@@ -428,6 +428,8 @@ print_operand (FILE *file, rtx x, int code)
fputc (ASM_DOUBLE_CHAR, file);
else if (code == '|')
fputs (REGISTER_PREFIX, file);
+ else if (code == 'c')
+ fputs (cond_name (x), file);
else if (code == 'C')
fputs (rev_cond_name (x), file);
else if (code == 'D' && CONST_INT_P (x) && INTVAL (x) < 0)
@@ -480,6 +482,37 @@ print_operand (FILE *file, rtx x, int code)
}
const char *
+cond_name (rtx op)
+{
+ switch (GET_CODE (op))
+ {
+ case NE:
+ return "neq";
+ case EQ:
+ return "eql";
+ case GE:
+ return "geq";
+ case GT:
+ return "gtr";
+ case LE:
+ return "leq";
+ case LT:
+ return "lss";
+ case GEU:
+ return "gequ";
+ case GTU:
+ return "gtru";
+ case LEU:
+ return "lequ";
+ case LTU:
+ return "lssu";
+
+ default:
+ gcc_unreachable ();
+ }
+}
+
+const char *
rev_cond_name (rtx op)
{
switch (GET_CODE (op))
@@ -1516,27 +1549,6 @@ vax_output_int_subtract (rtx insn, rtx *operands, enum machine_mode mode)
}
}
-/* Output a conditional branch. */
-const char *
-vax_output_conditional_branch (enum rtx_code code)
-{
- switch (code)
- {
- case EQ: return "jeql %l0";
- case NE: return "jneq %l0";
- case GT: return "jgtr %l0";
- case LT: return "jlss %l0";
- case GTU: return "jgtru %l0";
- case LTU: return "jlssu %l0";
- case GE: return "jgeq %l0";
- case LE: return "jleq %l0";
- case GEU: return "jgequ %l0";
- case LEU: return "jlequ %l0";
- default:
- gcc_unreachable ();
- }
-}
-
/* True if X is an rtx for a constant that is a valid address. */
bool
diff --git a/gcc/config/vax/vax.h b/gcc/config/vax/vax.h
index 997029e0f62..7fa2fbb870e 100644
--- a/gcc/config/vax/vax.h
+++ b/gcc/config/vax/vax.h
@@ -802,6 +802,7 @@ enum reg_class { NO_REGS, ALL_REGS, LIM_REG_CLASSES };
VAX operand formatting codes:
letter print
+ c direct branch condition
C reverse branch condition
D 64-bit immediate operand
B the low 8 bits of the complement of a constant operand
diff --git a/gcc/config/vax/vax.md b/gcc/config/vax/vax.md
index da3ca48e90b..649f17e36ba 100644
--- a/gcc/config/vax/vax.md
+++ b/gcc/config/vax/vax.md
@@ -58,30 +58,16 @@
(include "constraints.md")
(include "predicates.md")
-;; We don't want to allow a constant operand for test insns because
-;; (set (cc0) (const_int foo)) has no mode information. Such insns will
-;; be folded while optimizing anyway.
-
-(define_insn "tst<mode>"
- [(set (cc0)
- (match_operand:VAXint 0 "nonimmediate_operand" "nrmT"))]
- ""
- "tst<VAXint:isfx> %0")
-
-(define_insn "tst<mode>"
+(define_insn "*cmp<mode>"
[(set (cc0)
- (match_operand:VAXfp 0 "general_operand" "gF"))]
+ (compare (match_operand:VAXint 0 "nonimmediate_operand" "nrmT,nrmT")
+ (match_operand:VAXint 1 "general_operand" "I,nrmT")))]
""
- "tst<VAXfp:fsfx> %0")
-
-(define_insn "cmp<mode>"
- [(set (cc0)
- (compare (match_operand:VAXint 0 "nonimmediate_operand" "nrmT")
- (match_operand:VAXint 1 "general_operand" "nrmT")))]
- ""
- "cmp<VAXint:isfx> %0,%1")
+ "@
+ tst<VAXint:isfx> %0
+ cmp<VAXint:isfx> %0,%1")
-(define_insn "cmp<mode>"
+(define_insn "*cmp<mode>"
[(set (cc0)
(compare (match_operand:VAXfp 0 "general_operand" "gF,gF")
(match_operand:VAXfp 1 "general_operand" "G,gF")))]
@@ -92,8 +78,9 @@
(define_insn "*bit<mode>"
[(set (cc0)
- (and:VAXint (match_operand:VAXint 0 "general_operand" "nrmT")
- (match_operand:VAXint 1 "general_operand" "nrmT")))]
+ (compare (and:VAXint (match_operand:VAXint 0 "general_operand" "nrmT")
+ (match_operand:VAXint 1 "general_operand" "nrmT"))
+ (const_int 0)))]
""
"bit<VAXint:isfx> %0,%1")
@@ -1078,21 +1065,45 @@
"jbr %l0")
;; Conditional jumps
-(define_code_iterator any_cond [eq ne gt lt gtu ltu ge le geu leu])
-(define_insn "b<code>"
+(define_expand "cbranch<mode>4"
+ [(set (cc0)
+ (compare (match_operand:VAXint 1 "nonimmediate_operand" "")
+ (match_operand:VAXint 2 "general_operand" "")))
+ (set (pc)
+ (if_then_else
+ (match_operator 0 "ordered_comparison_operator" [(cc0)
+ (const_int 0)])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
+ "")
+
+(define_expand "cbranch<mode>4"
+ [(set (cc0)
+ (compare (match_operand:VAXfp 1 "general_operand" "")
+ (match_operand:VAXfp 2 "general_operand" "")))
+ (set (pc)
+ (if_then_else
+ (match_operator 0 "ordered_comparison_operator" [(cc0)
+ (const_int 0)])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
+ "")
+
+(define_insn "*branch"
[(set (pc)
- (if_then_else (any_cond (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
+ (if_then_else (match_operator 0 "ordered_comparison_operator"
+ [(cc0)
+ (const_int 0)])
+ (label_ref (match_operand 1 "" ""))
(pc)))]
""
- "* return vax_output_conditional_branch (<CODE>);")
+ "j%c0 %l1")
;; Recognize reversed jumps.
-(define_insn ""
+(define_insn "*branch_reversed"
[(set (pc)
- (if_then_else (match_operator 0 "comparison_operator"
+ (if_then_else (match_operator 0 "ordered_comparison_operator"
[(cc0)
(const_int 0)])
(pc)
@@ -1452,6 +1463,8 @@
(match_operand 4 "" "")]
""
{
+ rtx test;
+
/* i = index - minimum_bound;
But only if the lower bound is not already zero. */
if (operands[1] != const0_rtx)
@@ -1463,9 +1476,9 @@
operands[0] = index;
}
- /* if (i > (maximum_bound - minimum_bound + 1) goto default; */
- emit_insn (gen_cmpsi (operands[0], operands[2]));
- emit_jump_insn (gen_bgtu (operands[4]));
+ /* if (i > (maximum_bound - minimum_bound + 1)) goto default; */
+ test = gen_rtx_fmt_ee (GTU, VOIDmode, operands[0], operands[2]);
+ emit_jump_insn (gen_cbranchsi4 (test, operands[0], operands[2], operands[4]));
/* casesi (i, 0, table); */
emit_jump_insn (gen_casesi1 (operands[0], operands[2], operands[3]));
diff --git a/gcc/config/xtensa/predicates.md b/gcc/config/xtensa/predicates.md
index 2cb2a7d1757..27f058de796 100644
--- a/gcc/config/xtensa/predicates.md
+++ b/gcc/config/xtensa/predicates.md
@@ -167,6 +167,9 @@
(define_predicate "boolean_operator"
(match_code "eq,ne"))
+(define_predicate "xtensa_cstoresi_operator"
+ (match_code "eq,ne,gt,ge,lt,le"))
+
(define_predicate "tls_symbol_operand"
(and (match_code "symbol_ref")
(match_test "SYMBOL_REF_TLS_MODEL (op) != 0")))
diff --git a/gcc/config/xtensa/xtensa-protos.h b/gcc/config/xtensa/xtensa-protos.h
index 5f8cd74fe36..76f10179c75 100644
--- a/gcc/config/xtensa/xtensa-protos.h
+++ b/gcc/config/xtensa/xtensa-protos.h
@@ -39,9 +39,9 @@ extern int smalloffset_mem_p (rtx);
extern int constantpool_address_p (rtx);
extern int constantpool_mem_p (rtx);
extern void xtensa_extend_reg (rtx, rtx);
-extern void xtensa_expand_conditional_branch (rtx *, enum rtx_code);
+extern void xtensa_expand_conditional_branch (rtx *, enum machine_mode);
extern int xtensa_expand_conditional_move (rtx *, int);
-extern int xtensa_expand_scc (rtx *);
+extern int xtensa_expand_scc (rtx *, enum machine_mode);
extern int xtensa_expand_block_move (rtx *);
extern void xtensa_split_operand_pair (rtx *, enum machine_mode);
extern int xtensa_emit_move_sequence (rtx *, enum machine_mode);
diff --git a/gcc/config/xtensa/xtensa.c b/gcc/config/xtensa/xtensa.c
index 50467b4602c..35e399f54b4 100644
--- a/gcc/config/xtensa/xtensa.c
+++ b/gcc/config/xtensa/xtensa.c
@@ -71,13 +71,6 @@ enum internal_test
ITEST_MAX
};
-/* Cached operands, and operator to compare for use in set/branch on
- condition codes. */
-rtx branch_cmp[2];
-
-/* what type of branch to use */
-enum cmp_type branch_type;
-
/* Array giving truth value on whether or not a given hard register
can support a given mode. */
char xtensa_hard_regno_mode_ok[(int) MAX_MACHINE_MODE][FIRST_PSEUDO_REGISTER];
@@ -128,7 +121,7 @@ const enum reg_class xtensa_regno_to_class[FIRST_PSEUDO_REGISTER] =
static enum internal_test map_test_to_internal_test (enum rtx_code);
static rtx gen_int_relational (enum rtx_code, rtx, rtx, int *);
static rtx gen_float_relational (enum rtx_code, rtx, rtx);
-static rtx gen_conditional_move (rtx);
+static rtx gen_conditional_move (enum rtx_code, enum machine_mode, rtx, rtx);
static rtx fixup_subreg_mem (rtx);
static struct machine_function * xtensa_init_machine_status (void);
static rtx xtensa_legitimize_tls_address (rtx);
@@ -712,27 +705,27 @@ gen_float_relational (enum rtx_code test_code, /* relational test (EQ, etc) */
void
-xtensa_expand_conditional_branch (rtx *operands, enum rtx_code test_code)
+xtensa_expand_conditional_branch (rtx *operands, enum machine_mode mode)
{
- enum cmp_type type = branch_type;
- rtx cmp0 = branch_cmp[0];
- rtx cmp1 = branch_cmp[1];
+ enum rtx_code test_code = GET_CODE (operands[0]);
+ rtx cmp0 = operands[1];
+ rtx cmp1 = operands[2];
rtx cmp;
int invert;
rtx label1, label2;
- switch (type)
+ switch (mode)
{
- case CMP_DF:
+ case DFmode:
default:
fatal_insn ("bad test", gen_rtx_fmt_ee (test_code, VOIDmode, cmp0, cmp1));
- case CMP_SI:
+ case SImode:
invert = FALSE;
cmp = gen_int_relational (test_code, cmp0, cmp1, &invert);
break;
- case CMP_SF:
+ case SFmode:
if (!TARGET_HARD_FLOAT)
fatal_insn ("bad test", gen_rtx_fmt_ee (test_code, VOIDmode,
cmp0, cmp1));
@@ -743,7 +736,7 @@ xtensa_expand_conditional_branch (rtx *operands, enum rtx_code test_code)
/* Generate the branch. */
- label1 = gen_rtx_LABEL_REF (VOIDmode, operands[0]);
+ label1 = gen_rtx_LABEL_REF (VOIDmode, operands[3]);
label2 = pc_rtx;
if (invert)
@@ -760,14 +753,13 @@ xtensa_expand_conditional_branch (rtx *operands, enum rtx_code test_code)
static rtx
-gen_conditional_move (rtx cmp)
+gen_conditional_move (enum rtx_code code, enum machine_mode mode,
+ rtx op0, rtx op1)
{
- enum rtx_code code = GET_CODE (cmp);
- rtx op0 = branch_cmp[0];
- rtx op1 = branch_cmp[1];
-
- if (branch_type == CMP_SI)
+ if (mode == SImode)
{
+ rtx cmp;
+
/* Jump optimization calls get_condition() which canonicalizes
comparisons like (GE x <const>) to (GT x <const-1>).
Transform those comparisons back to GE, since that is the
@@ -825,7 +817,7 @@ gen_conditional_move (rtx cmp)
return gen_rtx_fmt_ee (code, VOIDmode, op0, op1);
}
- if (TARGET_HARD_FLOAT && (branch_type == CMP_SF))
+ if (TARGET_HARD_FLOAT && mode == SFmode)
return gen_float_relational (code, op0, op1);
return 0;
@@ -835,36 +827,39 @@ gen_conditional_move (rtx cmp)
int
xtensa_expand_conditional_move (rtx *operands, int isflt)
{
- rtx cmp;
+ rtx dest = operands[0];
+ rtx cmp = operands[1];
+ enum machine_mode cmp_mode = GET_MODE (XEXP (cmp, 0));
rtx (*gen_fn) (rtx, rtx, rtx, rtx, rtx);
- if (!(cmp = gen_conditional_move (operands[1])))
+ if (!(cmp = gen_conditional_move (GET_CODE (cmp), cmp_mode,
+ XEXP (cmp, 0), XEXP (cmp, 1))))
return 0;
if (isflt)
- gen_fn = (branch_type == CMP_SI
+ gen_fn = (cmp_mode == SImode
? gen_movsfcc_internal0
: gen_movsfcc_internal1);
else
- gen_fn = (branch_type == CMP_SI
+ gen_fn = (cmp_mode == SImode
? gen_movsicc_internal0
: gen_movsicc_internal1);
- emit_insn (gen_fn (operands[0], XEXP (cmp, 0),
- operands[2], operands[3], cmp));
+ emit_insn (gen_fn (dest, XEXP (cmp, 0), operands[2], operands[3], cmp));
return 1;
}
int
-xtensa_expand_scc (rtx *operands)
+xtensa_expand_scc (rtx operands[4], enum machine_mode cmp_mode)
{
rtx dest = operands[0];
- rtx cmp = operands[1];
+ rtx cmp;
rtx one_tmp, zero_tmp;
rtx (*gen_fn) (rtx, rtx, rtx, rtx, rtx);
- if (!(cmp = gen_conditional_move (cmp)))
+ if (!(cmp = gen_conditional_move (GET_CODE (operands[1]), cmp_mode,
+ operands[2], operands[3])))
return 0;
one_tmp = gen_reg_rtx (SImode);
@@ -872,7 +867,7 @@ xtensa_expand_scc (rtx *operands)
emit_insn (gen_movsi (one_tmp, const_true_rtx));
emit_insn (gen_movsi (zero_tmp, const0_rtx));
- gen_fn = (branch_type == CMP_SI
+ gen_fn = (cmp_mode == SImode
? gen_movsicc_internal0
: gen_movsicc_internal1);
emit_insn (gen_fn (dest, XEXP (cmp, 0), one_tmp, zero_tmp, cmp));
diff --git a/gcc/config/xtensa/xtensa.h b/gcc/config/xtensa/xtensa.h
index 73f68ef315f..c01a778bf2b 100644
--- a/gcc/config/xtensa/xtensa.h
+++ b/gcc/config/xtensa/xtensa.h
@@ -27,17 +27,6 @@ extern int optimize;
/* External variables defined in xtensa.c. */
-/* comparison type */
-enum cmp_type {
- CMP_SI, /* four byte integers */
- CMP_DI, /* eight byte integers */
- CMP_SF, /* single precision floats */
- CMP_DF, /* double precision floats */
- CMP_MAX /* max comparison type */
-};
-
-extern struct rtx_def * branch_cmp[2]; /* operands for compare */
-extern enum cmp_type branch_type; /* what type of branch to use */
extern unsigned xtensa_current_frame_size;
/* Macros used in the machine description to select various Xtensa
diff --git a/gcc/config/xtensa/xtensa.md b/gcc/config/xtensa/xtensa.md
index 63c5db5b476..13883f1d5ca 100644
--- a/gcc/config/xtensa/xtensa.md
+++ b/gcc/config/xtensa/xtensa.md
@@ -64,15 +64,6 @@
(define_code_attr minmax [(smin "min") (umin "minu")
(smax "max") (umax "maxu")])
-;; This code iterator allows all branch instructions to be generated from
-;; a single define_expand template.
-(define_code_iterator any_cond [eq ne gt ge lt le gtu geu ltu leu
- uneq ltgt ungt unge unlt unle
- unordered ordered])
-
-;; This code iterator is for setting a register from a comparison.
-(define_code_iterator any_scc [eq ne gt ge lt le])
-
;; This code iterator is for floating-point comparisons.
(define_code_iterator any_scc_sf [eq lt le uneq unlt unle unordered])
(define_code_attr scc_sf [(eq "oeq") (lt "olt") (le "ole")
@@ -1131,44 +1122,27 @@
;; Comparisons.
-;; Handle comparisons by stashing away the operands and then using that
-;; information in the subsequent conditional branch.
+;; Conditional branches.
-(define_expand "cmpsi"
- [(set (cc0)
- (compare:CC (match_operand:SI 0 "register_operand" "")
- (match_operand:SI 1 "nonmemory_operand" "")))]
+(define_expand "cbranchsi4"
+ [(match_operator 0 "comparison_operator"
+ [(match_operand:SI 1 "register_operand")
+ (match_operand:SI 2 "nonmemory_operand")])
+ (match_operand 3 "")]
""
{
- branch_cmp[0] = operands[0];
- branch_cmp[1] = operands[1];
- branch_type = CMP_SI;
+ xtensa_expand_conditional_branch (operands, SImode);
DONE;
})
-(define_expand "cmpsf"
- [(set (cc0)
- (compare:CC (match_operand:SF 0 "register_operand" "")
- (match_operand:SF 1 "register_operand" "")))]
+(define_expand "cbranchsf4"
+ [(match_operator 0 "comparison_operator"
+ [(match_operand:SF 1 "register_operand")
+ (match_operand:SF 2 "register_operand")])
+ (match_operand 3 "")]
"TARGET_HARD_FLOAT"
{
- branch_cmp[0] = operands[0];
- branch_cmp[1] = operands[1];
- branch_type = CMP_SF;
- DONE;
-})
-
-
-;; Conditional branches.
-
-(define_expand "b<code>"
- [(set (pc)
- (if_then_else (any_cond (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- xtensa_expand_conditional_branch (operands, <CODE>);
+ xtensa_expand_conditional_branch (operands, SFmode);
DONE;
})
@@ -1353,18 +1327,31 @@
;; Setting a register from a comparison.
-(define_expand "s<code>"
- [(set (match_operand:SI 0 "register_operand" "")
- (any_scc:SI (match_dup 1)
- (match_dup 2)))]
+(define_expand "cstoresi4"
+ [(match_operand:SI 0 "register_operand")
+ (match_operator 1 "xtensa_cstoresi_operator"
+ [(match_operand:SI 2 "register_operand")
+ (match_operand:SI 3 "nonmemory_operand")])]
""
{
- operands[1] = gen_rtx_<CODE> (SImode, branch_cmp[0], branch_cmp[1]);
- if (!xtensa_expand_scc (operands))
+ if (!xtensa_expand_scc (operands, SImode))
FAIL;
DONE;
})
+(define_expand "cstoresf4"
+ [(match_operand:SI 0 "register_operand")
+ (match_operator:SI 1 "comparison_operator"
+ [(match_operand:SF 2 "register_operand")
+ (match_operand:SF 3 "register_operand")])]
+ "TARGET_HARD_FLOAT"
+{
+ if (!xtensa_expand_scc (operands, SFmode))
+ FAIL;
+ DONE;
+})
+
+
;; Conditional moves.