This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch] Use a conditional move when expanding MIN_EXPR and MAX_EXPR


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:


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]