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