re PR rtl-optimization/16380 (Use of uninitialised register after dbra conversion)
authorRichard Sandiford <rsandifo@redhat.com>
Tue, 6 Jul 2004 18:27:35 +0000 (18:27 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Tue, 6 Jul 2004 18:27:35 +0000 (18:27 +0000)
PR rtl-optimization/16380
* loop.c (check_dbra_loop): Sink comparison instructions if they
do something other than set cc0.

From-SVN: r84161

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

index 9f2d1c1bc56b3f3ff6c293eb17a09caa7bdaab22..c9e02507f532920f0cd98c103ed44ce9f1ca3bb3 100644 (file)
@@ -1,3 +1,9 @@
+2004-07-06  Richard Sandiford  <rsandifo@redhat.com>
+
+       PR rtl-optimization/16380
+       * loop.c (check_dbra_loop): Sink comparison instructions if they
+       do something other than set cc0.
+
 2004-07-06  James E Wilson  <wilson@specifixinc.com>
 
        * doc/interface.texi (longjmp and automatic variables): Delete
index 17955b49dea987ca4887a697a9e4f521b9eff6ad..e0af19dd45e47f079dd3ac1328610f793c23f0cd 100644 (file)
@@ -8284,6 +8284,7 @@ check_dbra_loop (struct loop *loop, int insn_count)
              enum rtx_code cmp_code;
              int comparison_const_width;
              unsigned HOST_WIDE_INT comparison_sign_mask;
+             bool keep_first_compare;
 
              add_val = INTVAL (bl->biv->add_val);
              comparison_value = XEXP (comparison, 1);
@@ -8476,13 +8477,26 @@ check_dbra_loop (struct loop *loop, int insn_count)
                 not delete the label.  */
              LABEL_NUSES (XEXP (jump_label, 0))++;
 
+             /* If we have a separate comparison insn that does more
+                than just set cc0, the result of the comparison might
+                be used outside the loop.  */
+             keep_first_compare = (compare_and_branch == 2
+#ifdef HAVE_CC0
+                                   && sets_cc0_p (first_compare) <= 0
+#endif
+                                   );
+
              /* Emit an insn after the end of the loop to set the biv's
                 proper exit value if it is used anywhere outside the loop.  */
-             if ((REGNO_LAST_UID (bl->regno) != INSN_UID (first_compare))
+             if (keep_first_compare
+                 || (REGNO_LAST_UID (bl->regno) != INSN_UID (first_compare))
                  || ! bl->init_insn
                  || REGNO_FIRST_UID (bl->regno) != INSN_UID (bl->init_insn))
                loop_insn_sink (loop, gen_load_of_final_value (reg, final_value));
 
+             if (keep_first_compare)
+               loop_insn_sink (loop, PATTERN (first_compare));
+
              /* Delete compare/branch at end of loop.  */
              delete_related_insns (PREV_INSN (loop_end));
              if (compare_and_branch == 2)
index 4f62f1a2199bd799c6710dfa997855a1a58adfd2..4168a683c5ad70e58ed6b79fba7986b3a8d77fe1 100644 (file)
@@ -1,3 +1,7 @@
+2004-07-06  Richard Sandiford  <rsandifo@redhat.com>
+
+       * gcc.c-torture/execute/20040706-1.c: New test.
+
 2004-07-06  Giovanni Bajo  <giovannibajo@gcc.gnu.org>
 
        PR c++/3671
diff --git a/gcc/testsuite/gcc.c-torture/execute/20040706-1.c b/gcc/testsuite/gcc.c-torture/execute/20040706-1.c
new file mode 100644 (file)
index 0000000..6b0ab36
--- /dev/null
@@ -0,0 +1,9 @@
+int main ()
+{
+  int i;
+  for (i = 0; i < 10; i++)
+    continue;
+  if (i < 10)
+    abort ();
+  exit (0);
+}