https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64705
--- Comment #2 from amker at gcc dot gnu.org --- Loop dump before IVOPT is like below: Loop 4, basic blocks 28/30; <bb 26>: count_54 = count_172 + 1; _55 = i_161 + i_161; prime_56 = _55 + 3; k_57 = prime_56 + i_161; if (size_26 >= k_57) goto <bb 27>; else goto <bb 31>; <bb 27>: <bb 28>: # k_167 = PHI <k_57(27), k_62(30)> # ci_168 = PHI <ci_169(27), ci_58(30)> ci_58 = ci_168 + 1; k.19_59 = (sizetype) k_167; _60 = flags_30 + k.19_59; *_60 = 0; k_62 = prime_56 + k_167; if (size_26 >= k_62) goto <bb 30>; else goto <bb 29>; <bb 29>: # ci_154 = PHI <ci_58(28)> goto <bb 31>; <bb 30>: goto <bb 28>; The IV uses found by IVOPT is like below: use 0 address defined in statement used in statement *_60 = 0; at position *_60 type char * base flags_30 + (sizetype) k_57 step (sizetype) prime_56 base object (void *) flags_30 related candidates use 1 compare defined in statement used in statement if (size_26 >= k_62) at position type long int base (_55 + 3) + k_57 step prime_56 is a biv related candidates use 2 generic (computed on exit edge) defined in statement ci_58 = ci_168 + 1; used in statement ci_154 = PHI <ci_58(28)> at position type long int base ci_169 + 1 step 1 is a biv related candidates Root cause is IVOPT expands use 1 from {prime_56 + k_57, prime_56}_loop to {(_55 + _3) + k_57, prime_56}_loop. Thus information of "iv.step == prime_56 == (_55+_3)" is lost during costs computation and uses rewrting, resulting in wrong candidate selected and bloated loop after IVOPT. The related code is in function find_givs_in_stmt_scev, specifically, if (!simple_iv (loop, loop_containing_stmt (stmt), lhs, iv, true)) return false; iv->base = expand_simple_operations (iv->base); // <--- expansion I will see how to fix the issue by skipping expansion in case like this. Thanks, bin