re PR rtl-optimization/19579 (-march=i686 generates a bogus program for x86*)
authorJakub Jelinek <jakub@redhat.com>
Tue, 25 Jan 2005 23:09:10 +0000 (00:09 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Tue, 25 Jan 2005 23:09:10 +0000 (00:09 +0100)
PR rtl-optimization/19579
* ifcvt.c (noce_try_cmove_arith): If emitting instructions to set up
both A and B, see if they don't clobber registers the other expr uses.

* gcc.c-torture/execute/20050124-1.c: New test.

From-SVN: r94234

gcc/ChangeLog
gcc/ifcvt.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/20050124-1.c [new file with mode: 0644]

index 8d3d43a031e0cab2410091ab6a15e8eff886bcd8..0596f1153be0c6c93dfc2678a93b14e6fce5cf99 100644 (file)
@@ -1,3 +1,9 @@
+2005-01-26  Jakub Jelinek  <jakub@redhat.com>
+
+       PR rtl-optimization/19579
+       * ifcvt.c (noce_try_cmove_arith): If emitting instructions to set up
+       both A and B, see if they don't clobber registers the other expr uses.
+
 2005-01-25  J"orn Rennecke <joern.rennecke@st.com>
 
        * real.c (do_add): Initialize signalling and canonical members.
index 49f9065c840d9f5def7541ed5f0d503ed9f0a9f6..39fced43b2447ca88a7ed89e7ac8d0f3f3ac5cdf 100644 (file)
@@ -1229,6 +1229,7 @@ noce_try_cmove_arith (struct noce_if_info *if_info)
   rtx a = if_info->a;
   rtx b = if_info->b;
   rtx x = if_info->x;
+  rtx orig_a, orig_b;
   rtx insn_a, insn_b;
   rtx tmp, target;
   int is_mem = 0;
@@ -1304,6 +1305,9 @@ noce_try_cmove_arith (struct noce_if_info *if_info)
 
   start_sequence ();
 
+  orig_a = a;
+  orig_b = b;
+
   /* If either operand is complex, load it into a register first.
      The best way to do this is to copy the original insn.  In this
      way we preserve any clobbers etc that the insn may have had.
@@ -1335,7 +1339,7 @@ noce_try_cmove_arith (struct noce_if_info *if_info)
     }
   if (! general_operand (b, GET_MODE (b)))
     {
-      rtx set;
+      rtx set, last;
 
       if (no_new_pseudos)
        goto end_seq_and_fail;
@@ -1343,9 +1347,7 @@ noce_try_cmove_arith (struct noce_if_info *if_info)
       if (is_mem)
        {
           tmp = gen_reg_rtx (GET_MODE (b));
-         tmp = emit_insn (gen_rtx_SET (VOIDmode,
-                                       tmp,
-                                       b));
+         tmp = gen_rtx_SET (VOIDmode, tmp, b);
        }
       else if (! insn_b)
        goto end_seq_and_fail;
@@ -1355,8 +1357,22 @@ noce_try_cmove_arith (struct noce_if_info *if_info)
          tmp = copy_rtx (insn_b);
          set = single_set (tmp);
          SET_DEST (set) = b;
-         tmp = emit_insn (PATTERN (tmp));
+         tmp = PATTERN (tmp);
+       }
+
+      /* If insn to set up A clobbers any registers B depends on, try to
+        swap insn that sets up A with the one that sets up B.  If even
+        that doesn't help, punt.  */
+      last = get_last_insn ();
+      if (last && modified_in_p (orig_b, last))
+       {
+         tmp = emit_insn_before (tmp, get_insns ());
+         if (modified_in_p (orig_a, tmp))
+           goto end_seq_and_fail;
        }
+      else
+       tmp = emit_insn (tmp);
+
       if (recog_memoized (tmp) < 0)
        goto end_seq_and_fail;
     }
index bc2bc8346a3d57f9b0541c22032ea4e48f1a7441..2f7606aff2ad6b95486f7e736aaf4e8864876485 100644 (file)
@@ -1,3 +1,8 @@
+2005-01-26  Jakub Jelinek  <jakub@redhat.com>
+
+       PR rtl-optimization/19579
+       * gcc.c-torture/execute/20050124-1.c: New test.
+
 2005-01-18  Jan Hubicka  <jh@suse.cz>
 
        PR tree-optimize/19337
diff --git a/gcc/testsuite/gcc.c-torture/execute/20050124-1.c b/gcc/testsuite/gcc.c-torture/execute/20050124-1.c
new file mode 100644 (file)
index 0000000..9d039ef
--- /dev/null
@@ -0,0 +1,41 @@
+/* PR rtl-optimization/19579 */
+
+extern void abort (void);
+
+int
+foo (int i, int j)
+{
+  int k = i + 1;
+
+  if (j)
+    {
+      if (k > 0)
+       k++;
+      else if (k < 0)
+       k--;
+    }
+
+  return k;
+}
+
+int
+main (void)
+{
+  if (foo (-2, 0) != -1)
+    abort ();
+  if (foo (-1, 0) != 0)
+    abort ();
+  if (foo (0, 0) != 1)
+    abort ();
+  if (foo (1, 0) != 2)
+    abort ();
+  if (foo (-2, 1) != -2)
+    abort ();
+  if (foo (-1, 1) != 0)
+    abort ();
+  if (foo (0, 1) != 2)
+    abort ();
+  if (foo (1, 1) != 3)
+    abort ();
+  return 0;
+}