http://gcc.gnu.org/bugzilla/show_bug.cgi?id=49095
--- Comment #6 from Linus Torvalds <torva...@linux-foundation.org> 2011-05-27 14:15:25 UTC --- Jakub - the patch looks sane, although I don't currently have a gcc build environment to actually test it with, and there is no way I'm going to claim that I follow all the matches and understand why you have that third pattern with SWI12 (but I'm guessing it's because the op and the test are being done in the "explicit cast to integer" mode). One thing I wanted to check, though: I hope everybody is aware that op $x,mem is not identically the same as mov mem,reg op $x, reg mov reg,mem test reg WRT the carry flag. The "test" version will always clear the carry flag, while the "op" version will obviously set it according to the "op". For the logical ops, this isn't a problem (they also clear carry), but for "add" and "sub" this transformation *will* result in a difference in the C flag. Now, "carry" is meaningless when talking about compare with zero, so this should all be trivially ok. But I bring it up because it is possible that gcc perhaps still uses the "unsigned compare" versions with zero. In particular, the thing to look out for would be code like unsigned int *a; if (--*a > 0) do_something(); and if the comparison uses "jg" ("unsigned greater than") for the comparison, it will get the wrong end result. Now, unsigned compares against zero are always expressible as "ne" or "eq", so this is not a fundamental problem. In fact, my trivial testing with a few cases seems to imply that gcc already does that conversion to inequality, and you'd obviously have exactly the same issue with eliding the "test" instruction for the cases you already handle (when things are in registers). So I think everything is fine - but I wanted to mention it explicitly in case it makes you go "ooh, yes, there are cases when this is an issue"