OSDN Git Service

* expr.c (expand_expr_real_1): <MAX_EXPR, MIN_EXPR>: Canonicalize
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 12 Nov 2005 17:35:06 +0000 (17:35 +0000)
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 12 Nov 2005 17:35:06 +0000 (17:35 +0000)
to compare against 0 when possible.
* gcc.target/i386/minmax-1.c: New.
* gcc.target/i386/minmax-2.c: New.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@106827 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/expr.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/i386/minmax-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/minmax-2.c [new file with mode: 0644]

index 395df13..3c01cf7 100644 (file)
@@ -1,3 +1,8 @@
+2005-11-12  Jan Hubicka  <jh@suse.cz>
+
+       * expr.c (expand_expr_real_1): <MAX_EXPR, MIN_EXPR>: Canonicalize
+       to compare against 0 when possible.
+
 2005-11-12  Jie Zhang  <jie.zhang@analog.com>
 
        * config/bfin/bfin.h (REGISTER_NAMES, SHORT_REGISTER_NAMES,
index 9743c2a..125e370 100644 (file)
@@ -8020,69 +8020,92 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
       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;
+      {
+       enum rtx_code comparison_code;
+       rtx cmpop1 = op1;
 
-         if (code == MAX_EXPR)
-           comparison_code = unsignedp ? GEU : GE;
-         else
-           comparison_code = unsignedp ? LEU : LE;
+       if (code == MAX_EXPR)
+         comparison_code = unsignedp ? GEU : GE;
+       else
+         comparison_code = unsignedp ? LEU : LE;
 
-         /* ??? Same problem as in expmed.c: emit_conditional_move
-            forces a stack adjustment via compare_from_rtx, and we
-            lose the stack adjustment if the sequence we are about
-            to create is discarded.  */
-         do_pending_stack_adjust ();
+       /* Canonicalize to comparsions against 0.  */
+       if (op1 == const1_rtx)
+         {
+           /* Converting (a >= 1 ? a : 1) into (a > 0 ? a : 1)
+              or (a != 0 ? a : 1) for unsigned.
+              For MIN we are safe converting (a <= 1 ? a : 1)
+              into (a <= 0 ? a : 1)  */
+           cmpop1 = const0_rtx;
+           if (code == MAX_EXPR)
+             comparison_code = unsignedp ? NE : GT;
+         }
+       if (op1 == constm1_rtx && !unsignedp)
+         {
+           /* Converting (a >= -1 ? a : -1) into (a >= 0 ? a : -1)
+              and (a <= -1 ? a : -1) into (a < 0 ? a : -1) */
+           cmpop1 = const0_rtx;
+           if (code == MIN_EXPR)
+             comparison_code = LT;
+         }
+#ifdef HAVE_conditional_move
+       /* Use a conditional move if possible.  */
+       if (can_conditionally_move_p (mode))
+         {
+           rtx insn;
 
-         start_sequence ();
+           /* ??? Same problem as in expmed.c: emit_conditional_move
+              forces a stack adjustment via compare_from_rtx, and we
+              lose the stack adjustment if the sequence we are about
+              to create is discarded.  */
+           do_pending_stack_adjust ();
 
-         /* Try to emit the conditional move.  */
-         insn = emit_conditional_move (target, comparison_code,
-                                       op0, op1, mode,
-                                       op0, op1, mode,
-                                       unsignedp);
+           start_sequence ();
 
-         /* If we could do the conditional move, emit the sequence,
-            and return.  */
-         if (insn)
-           {
-             rtx seq = get_insns ();
-             end_sequence ();
-             emit_insn (seq);
-             return target;
-           }
+           /* Try to emit the conditional move.  */
+           insn = emit_conditional_move (target, comparison_code,
+                                         op0, cmpop1, mode,
+                                         op0, op1, mode,
+                                         unsignedp);
 
-         /* Otherwise discard the sequence and fall back to code with
-            branches.  */
-         end_sequence ();
-       }
+           /* If we could do the conditional move, emit the sequence,
+              and return.  */
+           if (insn)
+             {
+               rtx seq = get_insns ();
+               end_sequence ();
+               emit_insn (seq);
+               return target;
+             }
+
+           /* Otherwise discard the sequence and fall back to code with
+              branches.  */
+           end_sequence ();
+         }
 #endif
-      if (target != op0)
-       emit_move_insn (target, op0);
+       if (target != op0)
+         emit_move_insn (target, op0);
 
-      temp = 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.  */
-      if (GET_MODE_CLASS (mode) == MODE_INT
-         && ! can_compare_p (GE, mode, ccp_jump))
-       {
-         if (code == MAX_EXPR)
-           do_jump_by_parts_greater_rtx (mode, unsignedp, target, op1,
-                                         NULL_RTX, temp);
-         else
-           do_jump_by_parts_greater_rtx (mode, unsignedp, op1, target,
-                                         NULL_RTX, temp);
-       }
-      else
-       {
-         do_compare_rtx_and_jump (target, op1, code == MAX_EXPR ? GE : LE,
-                                  unsignedp, mode, NULL_RTX, NULL_RTX, temp);
-       }
+       /* If this mode is an integer too wide to compare properly,
+          compare word by word.  Rely on cse to optimize constant cases.  */
+       if (GET_MODE_CLASS (mode) == MODE_INT
+           && ! can_compare_p (GE, mode, ccp_jump))
+         {
+           if (code == MAX_EXPR)
+             do_jump_by_parts_greater_rtx (mode, unsignedp, target, op1,
+                                           NULL_RTX, temp);
+           else
+             do_jump_by_parts_greater_rtx (mode, unsignedp, op1, target,
+                                           NULL_RTX, temp);
+         }
+       else
+         {
+           do_compare_rtx_and_jump (target, cmpop1, comparison_code,
+                                    unsignedp, mode, NULL_RTX, NULL_RTX, temp);
+         }
+      }
       emit_move_insn (target, op1);
       emit_label (temp);
       return target;
index aabc14b..2767bb5 100644 (file)
@@ -1,3 +1,8 @@
+2005-11-12  Jan Hubicka  <jh@suse.cz>
+
+       * gcc.target/i386/minmax-1.c: New.
+       * gcc.target/i386/minmax-2.c: New.
+
 2005-11-12  Kaz Kojima  <kkojima@gcc.gnu.org>
 
        * gcc.dg/pr24445.c: Fix for 64-bit targets.
diff --git a/gcc/testsuite/gcc.target/i386/minmax-1.c b/gcc/testsuite/gcc.target/i386/minmax-1.c
new file mode 100644 (file)
index 0000000..ca7fb6a
--- /dev/null
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=opteron" } */
+/* { dg-final { scan-assembler "test" } } */
+/* { dg-final { scan-assembler-not "cmp" } } */
+#define max(a,b) (((a) > (b))? (a) : (b))
+t(int a)
+{
+  return (max(a,1));
+}
diff --git a/gcc/testsuite/gcc.target/i386/minmax-2.c b/gcc/testsuite/gcc.target/i386/minmax-2.c
new file mode 100644 (file)
index 0000000..2021aaa
--- /dev/null
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { scan-assembler "test" } } */
+/* { dg-final { scan-assembler-not "cmp" } } */
+#define max(a,b) (((a) > (b))? (a) : (b))
+t(unsigned int a)
+{
+  return (max(a,1));
+}