http://gcc.gnu.org/bugzilla/show_bug.cgi?id=16458
--- Comment #5 from Peter Bergner <bergner at gcc dot gnu.org> 2011-12-14 22:42:57 UTC --- Created attachment 26091 --> http://gcc.gnu.org/bugzilla/attachment.cgi?id=26091 Another partial fix... Answering Nathan's comment from his patch: + /* These are unsigned values, perhaps there will be a later + ordering compare that can be shared with this one. + Unfortunately we cannot detect the signedness of the operands + for non-subregs. */ Actually, there is a way to tell whether some of our non-subreg operands are unsigned or not. For register operands of user defined variables: TYPE_UNSIGNED (TREE_TYPE (REG_EXPR (rtx))) will be true if the operand is unsigned. I've attached a patch that implements that and it does fix the test case. It also fixes a problem I encountered with switch statements and -fno-jump-tables: enum CASE_VALUES { CASE0 = 0, CASE1, CASE2, CASE3, CASE4 }; int test_switch (enum CASE_VALUES index) { switch (index) { case CASE0: return case0 (); case CASE1: return case1 (); case CASE2: return case2 (); case CASE3: return case3 (); case CASE4: return case4 (); default: return cased (); } } Currently, GCC generates (-fno-jump-tables) the following, because it notices that the enum contains no negative values, so it marks index as unsigned and we end up with unsigned compares (modulo the equality compares) so we cannot CSE them: test_switch: cmpwi 7,3,2 beq 7,.L5 cmplwi 7,3,2 ble 7,.L10 cmpwi 7,3,3 beq 7,.L6 ... With the attached patch, we generate all unsigned compares and CSE is able to remove the redundant compares: test_switch: cmplwi 7,3,2 beq 7,.L5 ble 7,.L10 cmplwi 7,3,3 beq 7,.L6 ... The patch still does not handle: if (*a == *b) ... else if (*a > *b) ... or: switch (*index) ... but we couldn't handle those before anyway.