http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55278
--- Comment #8 from Jakub Jelinek <jakub at gcc dot gnu.org> 2013-05-08 06:58:37 UTC --- unsigned int f1 (unsigned int x, unsigned int y) { return (x << y) | (x >> (32 - y)); } unsigned int f2 (unsigned int x, unsigned long y) { return (x << y) | (x >> (32 - y)); } unsigned int f3 (unsigned int x) { return (x << 1) | (x >> (32 - 1)); } unsigned int f4 (unsigned int x) { return (x << (32 - 1)) | (x >> 1); } unsigned short int f5 (unsigned short int x, unsigned int y) { return (x << y) | (x >> (16 - y)); } unsigned short int f6 (unsigned short int x, unsigned long y) { return (x << y) | (x >> (16 - y)); } unsigned char f7 (unsigned char x, unsigned int y) { return (x << y) | (x >> (8 - y)); } unsigned char f8 (unsigned char x, unsigned long y) { return (x << y) | (x >> (8 - y)); } unsigned int f9 (unsigned int x, unsigned int y) { return (x << y) | (x >> (sizeof (unsigned int) - y)); } unsigned int f10 (unsigned int x, unsigned long y) { return (x << y) | (x >> (sizeof (unsigned int) - y)); } unsigned int f11 (unsigned int x) { return (x << 1) | (x >> (sizeof (unsigned int) - 1)); } unsigned int f12 (unsigned int x) { return (x << (sizeof (unsigned int) - 1)) | (x >> 1); } unsigned short int f13 (unsigned short int x, unsigned int y) { return (x << y) | (x >> (sizeof (unsigned short) - y)); } unsigned short int f14 (unsigned short int x, unsigned long y) { return (x << y) | (x >> (sizeof (unsigned short) - y)); } unsigned char f15 (unsigned char x, unsigned int y) { return (x << y) | (x >> (sizeof (unsigned char) - y)); } unsigned char f16 (unsigned char x, unsigned long y) { return (x << y) | (x >> (sizeof (unsigned char) - y)); } shows lots of various issues with rotates: 1) if the shift count isn't int expression, we don't detect that (there is extra cast that bit_rotate: doesn't handle) - example f2 2) for f3 we emit rorl $31, %eax while we should special case it and emit roll %eax instead (shorter insn; backend issue) 3) the casts added for promoted types aren't handled - example f5 - I guess even that is fine to handle, because say for y 17, while << 17 is defined behavior, >> (16 - 17) or >> (16U - 17) should be undefined behavior and thus really y should be [1, 15]. 4) the deferred SIZEOF_EXPR folding in C++ plays a role here 5) as mentioned in another PR, these rotate idioms assume non-zero rotation count, for 0 they have undefined behavior, so we should recognize also another form So, IMHO bit_rotate: should be extended to handle these (except that it can't do anything about SIZEOF_EXPR, being a FE tree (unless we add some langhook for it or handle it again in C++ lang folder), and perhaps some later pass (bswap pass or gimple-fold?) should be taught to recognize it too. And the vectorizer pattern detection needs to be taught to undo that if there is no vector rotation optab.