https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114932
--- Comment #11 from Tamar Christina <tnfchris at gcc dot gnu.org> --- (In reply to Richard Biener from comment #10) > I think the question is why IVOPTs ends up using both the signed and > unsigned variant of the same IV instead of expressing all uses of both with > one IV? > > That's where I'd look into. It looks like this is because of a subtle difference in the expressions. In get_loop_invariant_expr IVOPTs first tries to strip away all casts with STRIP_NOPS. The first expression is (unsigned long) (stride.3_27 * 4) and the second expression is ((unsigned long) stride.3_27) * 4 (The pretty printing here is pretty bad...) So the first one becomes: (unsigned long) (stride.3_27 * 4) -> stride.3_27 * 4 and second one: ((unsigned long) stride.3_27) * 4 -> ((unsigned long) stride.3_27) * 4 since we don't care about overflow here, it looks like the stripping should be recursive as long as it's a NOP expression between two integral types. That would get them to hash to the same IV expression. Trying now..