http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56363
Bug #: 56363 Summary: over aggressive division folding ignores sign conversion Classification: Unclassified Product: gcc Version: 4.7.2 Status: UNCONFIRMED Severity: normal Priority: P3 Component: middle-end AssignedTo: unassig...@gcc.gnu.org ReportedBy: jay.kr...@cornell.edu Our frontend is slightly unusual in that it uses FLOOR_DIV_EXPR instead of C's more common TRUNC_DIV_EXPR. (For years it generated calls to helper functions for div and mod, but then I noticed this builtin support.) So it hits perhaps not well covered code? Based on debugging this years ago (in an older version of gcc), I think gcc is a bit overaggressive at folding constants in division. 4.7.2/gcc/fold-const.c has this code: tree fold_binary_loc (location_t loc, enum tree_code code, tree type, tree op0, tree op1) . . . arg0 = op0; arg1 = op1; . . . STRIP_NOPS (arg0); STRIP_NOPS (arg1); . . . /* If arg0 is a multiple of arg1, then rewrite to the fastest div operation, EXACT_DIV_EXPR. Note that only CEIL_DIV_EXPR and FLOOR_DIV_EXPR are rewritten now. At one time others generated faster code, it's not clear if they do after the last round to changes to the DIV code in expmed.c. */ if ((code == CEIL_DIV_EXPR || code == FLOOR_DIV_EXPR) && multiple_of_p (type, arg0, arg1)) return fold_build2_loc (loc, EXACT_DIV_EXPR, type, arg0, arg1); I think this is wrong if strip_nops stripped some signedness or other conversions. I added this condition: && arg0 == op0 && arg1 == op1 Given the comment, that the code is not applied to C's TRUNC_DIV_EXPR, maybe this can/should just be removed?