http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52578
Bug #: 52578 Summary: Fails to fold another size difference Classification: Unclassified Product: gcc Version: 4.7.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: middle-end AssignedTo: unassig...@gcc.gnu.org ReportedBy: rgue...@gcc.gnu.org gnat.dg/opt9.adb will fail with the bitfield handling patch with -m32 because we do not fold long bar (long i) { return (long)((unsigned long)i + 2) - (long)i; } long foo (int i) { return (long)((unsigned long)i + 2) - (long)i; } to constants. the associate: path splits the above to var0 == (long unsigned int) i, lit0 == 2, var1 == -i which fails to associate because of /* With undefined overflow we can only associate constants with one variable, and constants whose association doesn't overflow. */ if ((POINTER_TYPE_P (type) && POINTER_TYPE_OVERFLOW_UNDEFINED) || (INTEGRAL_TYPE_P (type) && !TYPE_OVERFLOW_WRAPS (type))) { if (var0 && var1) { tree tmp0 = var0; tree tmp1 = var1; if (TREE_CODE (tmp0) == NEGATE_EXPR) tmp0 = TREE_OPERAND (tmp0, 0); if (TREE_CODE (tmp1) == NEGATE_EXPR) tmp1 = TREE_OPERAND (tmp1, 0); /* The only case we can still associate with two variables is if they are the same, modulo negation. */ if (!operand_equal_p (tmp0, tmp1, 0)) ok = false; but we can as well strip widening and sign-changing conversions I think.