This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[patch] Use a conditional move when expanding MIN_EXPR and MAX_EXPR
- From: Steven Bosscher <stevenb at suse dot de>
- To: gcc-patches at gcc dot gnu dot org
- Cc: sayle at gcc dot gnu dot org
- Date: Wed, 9 Mar 2005 23:07:28 +0100
- Subject: [patch] Use a conditional move when expanding MIN_EXPR and MAX_EXPR
- Organization: SUSE Labs
Hi,
With this patch, we try a conditional move for MIN_EXPRs and MAX_EXPRs.
This patch was heavily exercised by another patch in my tree to PHI-OPTs,
to make it produce MIN_EXPRs and MAX_EXPRs where possible - but it seems
that patch broke PHI-OPT's value_replacement due to a thinko on my part.
Anyway, this patch by itself is useful, and the rest will just have to
wait a bit :-)
The patch was bootstrapped and tested on x86_64-suse-linux-gnu (-m32 and
"normal") with no new regressions except for two unrelated PHI-OPT test
cases that fail because of the other patch (they have nothing to do with
MIN_EXPR and MAX_EXPR). OK for mainline?
Gr.
Steven
* expr.c (expand_expr_real_1): If possible, use a conditional move
for expanding MIN_EXPR and MAX_EXPR.
Use temp for moving around rtx-en.
Index: expr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/expr.c,v
retrieving revision 1.780
diff -u -3 -p -r1.780 expr.c
--- expr.c 9 Mar 2005 07:07:37 -0000 1.780
+++ expr.c 9 Mar 2005 22:05:04 -0000
@@ -7876,9 +7876,9 @@ expand_expr_real_1 (tree exp, rtx target
/* If op1 was placed in target, swap op0 and op1. */
if (target != op0 && target == op1)
{
- rtx tem = op0;
+ temp = op0;
op0 = op1;
- op1 = tem;
+ op1 = temp;
}
/* We generate better code and avoid problems with op1 mentioning
@@ -7886,10 +7886,41 @@ expand_expr_real_1 (tree exp, rtx target
if (! CONSTANT_P (op1))
op1 = force_reg (mode, op1);
+#ifdef HAVE_conditional_move
+ /* Use a conditional move if possible. */
+ if (can_conditionally_move_p (mode))
+ {
+ enum rtx_code comparison_code;
+ rtx insn, cop0, cop1;
+
+ if (code == MAX_EXPR)
+ comparison_code = unsignedp ? GEU : GE;
+ else
+ comparison_code = unsignedp ? LEU : LE;
+
+ /* Force operands into registers if they are constants. Most
+ targets only have reg-reg conditional moves, and we can not
+ tell from here if a constant is also OK. Let's hope combine
+ combine can figure that out for us. */
+ cop0 = CONSTANT_P (op0) ? force_reg (mode, op0) : op0;
+ cop1 = CONSTANT_P (op1) ? force_reg (mode, op1) : op1;
+
+ /* Try to emit the conditional move. */
+ insn = emit_conditional_move (target, comparison_code,
+ cop0, cop1, mode,
+ cop0, cop1, mode,
+ unsignedp);
+
+ /* If we could do the conditional move, return. Otherwise
+ fall back to code with branches. */
+ if (insn)
+ return target;
+ }
+#endif
if (target != op0)
emit_move_insn (target, op0);
- op0 = gen_label_rtx ();
+ temp = gen_label_rtx ();
/* If this mode is an integer too wide to compare properly,
compare word by word. Rely on cse to optimize constant cases. */
@@ -7898,18 +7929,18 @@ expand_expr_real_1 (tree exp, rtx target
{
if (code == MAX_EXPR)
do_jump_by_parts_greater_rtx (mode, unsignedp, target, op1,
- NULL_RTX, op0);
+ NULL_RTX, temp);
else
do_jump_by_parts_greater_rtx (mode, unsignedp, op1, target,
- NULL_RTX, op0);
+ NULL_RTX, temp);
}
else
{
do_compare_rtx_and_jump (target, op1, code == MAX_EXPR ? GE : LE,
- unsignedp, mode, NULL_RTX, NULL_RTX, op0);
+ unsignedp, mode, NULL_RTX, NULL_RTX, temp);
}
emit_move_insn (target, op1);
- emit_label (op0);
+ emit_label (temp);
return target;
case BIT_NOT_EXPR: