aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Kenner <kenner@gcc.gnu.org>1996-04-16 10:53:48 -0400
committerRichard Kenner <kenner@gcc.gnu.org>1996-04-16 10:53:48 -0400
commit758d2c0c2f1a5b0011e8ba262e1d338e3fec813f (patch)
treef8dfe2a412f857aa0a4066e57bd0d06f0994e8e7 /gcc
parent04aa3b9c2673493bb39c0037f818066f9ee66b75 (diff)
downloadgcc-758d2c0c2f1a5b0011e8ba262e1d338e3fec813f.zip
gcc-758d2c0c2f1a5b0011e8ba262e1d338e3fec813f.tar.gz
gcc-758d2c0c2f1a5b0011e8ba262e1d338e3fec813f.tar.bz2
(alpha_emit_conditional_move): New function.
From-SVN: r11814
Diffstat (limited to 'gcc')
-rw-r--r--gcc/config/alpha/alpha.c61
1 files changed, 61 insertions, 0 deletions
diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c
index 4d1af85..e3edeca 100644
--- a/gcc/config/alpha/alpha.c
+++ b/gcc/config/alpha/alpha.c
@@ -965,6 +965,67 @@ alpha_emit_set_const_1 (target, mode, c, n)
return 0;
}
+
+/* Rewrite a comparison against zero CMP of the form
+ (CODE (cc0) (const_int 0)) so it can be written validly in
+ a conditional move (if_then_else CMP ...).
+ If both of the operands that set cc0 are non-zero we must emit
+ an insn to perform the compare (it can't be done within
+ the conditional move). */
+rtx
+alpha_emit_conditional_move (cmp, mode)
+ rtx cmp;
+ enum machine_mode mode;
+{
+ rtx op0 = alpha_compare_op0;
+ rtx op1 = alpha_compare_op1;
+ rtx zero = CONST0_RTX (mode);
+ rtx tmp;
+ enum rtx_code code = GET_CODE (cmp), code2;
+
+ if (alpha_compare_fp_p != FLOAT_MODE_P(mode))
+ return 0;
+
+ /* We may be able to use a conditional move directly.
+ This avoids emitting spurious compares. */
+ if (signed_comparison_operator (cmp, mode) && (op0 == zero || op1 == zero))
+ return gen_rtx (code, mode, op0, op1);
+
+ /* We can't put the comparison insides a conditional move;
+ emit a compare instruction and put that inside the
+ conditional move. */
+
+ /* The alpha does not have NE GE GT compares for any mode. Avoid them. */
+ code2 = NE;
+ switch (code)
+ {
+ /* We have these compares: */
+ case EQ: case LE: case LT:
+ break;
+ /* These must be inverted: */
+ case NE:
+ code = code2 = EQ;
+ break;
+ case GE:
+ code = LE;
+ op0 = force_reg (mode, alpha_compare_op1);
+ op1 = alpha_compare_op0;
+ break;
+ case GT:
+ code = LT;
+ op0 = force_reg (mode, alpha_compare_op1);
+ op1 = alpha_compare_op0;
+ break;
+ default:
+ return 0;
+ }
+
+ cmp = gen_rtx (code, mode, op0, op1);
+ tmp = gen_reg_rtx (mode);
+ emit_insn (gen_rtx (SET, VOIDmode, tmp, cmp));
+ cmp = gen_rtx (code2, VOIDmode, tmp, zero);
+ return cmp;
+}
/* 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. */