https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68021
Jakub Jelinek <jakub at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |amker at gcc dot gnu.org --- Comment #8 from Jakub Jelinek <jakub at gcc dot gnu.org> --- Seems the problem is that we have use->iv->step (_2 - (sizetype) ((unsigned int) p3_11(D) + 4294967295)) + 18446744073709551615; and cand->iv->step (_2 - (sizetype) ((unsigned int) p3_11(D) + 4294967295)) - 1; Both are really equivalent, but when constant_multiple_of is called on these, it calls operand_equal_p and that will return they are not equal and thus not multiple of each other. This boils down to the canonicalization we do on MINUS_EXPR: /* A - B -> A + (-B) if B is easily negatable. */ if (negate_expr_p (op1) && ! TYPE_OVERFLOW_SANITIZED (type) && ((FLOAT_TYPE_P (type) /* Avoid this transformation if B is a positive REAL_CST. */ && (TREE_CODE (op1) != REAL_CST || REAL_VALUE_NEGATIVE (TREE_REAL_CST (op1)))) || INTEGRAL_TYPE_P (type))) return fold_build2_loc (loc, PLUS_EXPR, type, fold_convert_loc (loc, type, arg0), negate_expr (op1)); but don't really do it in associate_trees. The caller of associate_trees has worrying comments on that though: /* Preserve the MINUS_EXPR if the negative part of the literal is greater than the positive part. Otherwise, the multiplicative folding code (i.e extract_muldiv) may be fooled in case unsigned constants are subtracted, like in the following example: ((X*2 + 4) - 8U)/2. */ which is pretty much the case here, - 1 constant is smaller than + (-1UL). So, are we ok that this isn't really canonicalized always the same? Shall operand_equal_p be treating those two cases as equal (perhaps under some flag)? Or shall constant_multiple_of be using some different comparison? Or shall something much earlier in the IVOPTS code just give up if the steps aren't really equal/multiples of each other?