Hi!

The testcase uses two uninitialized variables in a loop, the iterator
as well as the upper bound in the condition, and due to that and bad luck
we end up with:
(insn 6 70 71 14 (set (reg/v:DI 90 [ pend ])
        (reg/v:DI 89 [ p ])) "pr56348.c":29:5 66 {*movdi_internal}
     (nil))
and
(insn 9 88 63 12 (set (reg/v:DI 89 [ p ])
        (reg/v:DI 90 [ pend ])) "pr56348.c":28:3 66 {*movdi_internal}
     (nil))
as the only setters of those two pseudos (plus a bunch of uses in loop
conditions).  When loop-iv.c tries to determine loop invariants,
it performs since
https://gcc.gnu.org/ml/gcc-patches/2009-04/msg00246.html
an unbounded search through register copies with single definitions and on
the above loops forever.
While we could add some hash_table/bitmap or whatever other data structure
to track registers we've already looked at, having unbounded look through
register copies looks dangerous to me for compile time complexity in
pathological cases, and while on certain architectures I could understand
very deep chains of say reg2 = reg1 + constant; reg3 = reg2 + constant; ...
(or with post-increment/decrement/modify) if the target addressing mode
doesn't allow suitable immediates in addresses, having chains of simple
reg2 = reg1; reg3 = reg2; reg4 = reg3; reg5 = reg4; ...
chains with thousands copies will unlikely appear and would unlikely result
in something useful for the loop iv optimization, so this patch instead
just looks through at most 128 copies (I don't think we need a param for
that).

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2020-01-03  Jakub Jelinek  <ja...@redhat.com>

        PR rtl-optimization/93088
        * loop-iv.c (find_single_def_src): Punt after looking through
        128 reg copies for regs with single definitions.  Move definitions
        to first uses.

        * gcc.target/i386/pr93088.c: New test.

--- gcc/loop-iv.c.jj    2020-01-01 12:15:44.596661415 +0100
+++ gcc/loop-iv.c       2020-01-02 18:07:00.238120307 +0100
@@ -1384,24 +1384,23 @@ simple_rhs_p (rtx rhs)
 static rtx
 find_single_def_src (unsigned int regno)
 {
-  df_ref adef;
-  rtx set, src;
+  rtx src = NULL_RTX;
 
-  for (;;)
+  /* Don't look through unbounded number of single definition REG copies,
+     there might be loops for sources with uninitialized variables.  */
+  for (int cnt = 0; cnt < 128; cnt++)
     {
-      rtx note;
-      adef = DF_REG_DEF_CHAIN (regno);
+      df_ref adef = DF_REG_DEF_CHAIN (regno);
       if (adef == NULL || DF_REF_NEXT_REG (adef) != NULL
          || DF_REF_IS_ARTIFICIAL (adef))
        return NULL_RTX;
 
-      set = single_set (DF_REF_INSN (adef));
+      rtx set = single_set (DF_REF_INSN (adef));
       if (set == NULL || !REG_P (SET_DEST (set))
          || REGNO (SET_DEST (set)) != regno)
        return NULL_RTX;
 
-      note = find_reg_equal_equiv_note (DF_REF_INSN (adef));
-
+      rtx note = find_reg_equal_equiv_note (DF_REF_INSN (adef));
       if (note && function_invariant_p (XEXP (note, 0)))
        {
          src = XEXP (note, 0);
--- gcc/testsuite/gcc.target/i386/pr93088.c.jj  2020-01-02 18:25:34.904318975 
+0100
+++ gcc/testsuite/gcc.target/i386/pr93088.c     2020-01-02 18:25:01.944815342 
+0100
@@ -0,0 +1,5 @@
+/* PR rtl-optimization/93088 */
+/* { dg-do compile } */
+/* { dg-options "-O3 -funroll-loops -fno-tree-dominator-opts -fno-tree-vrp -w" 
} */
+
+#include "pr56348.c"

        Jakub

Reply via email to