A double shift with both constants and cast in between is illegally folded into a single shift. My first checks indicate that the change made for PR tree-optimization/14796 on 2005-06-12 clashes with a piece of code earlier in the function fold_binary. The comment starting with "Strip any conversions that don't change the mode" is not correct for shifts. The signedness of the left operand of a right shift is relevant. It determines whether the sign bit or zero is shifted in. The problem occurs only if the shifts are within a single expression. Split accross different expression the behaviour is correct.
Here is a test case showing the different behaviour: int foo(int a) { int t2 = a >> 2; unsigned t3 = t2; unsigned t4 = t3 >> 15; return t4; } int bar(int a) { return ((unsigned) ((a) >> 2)) >> 15; } main() { int a = 0xffff3000; int b = foo(a); int c = bar(a); printf ("%x, %x\n", b, c); if (b != c) printf ("failed\n"); } -- Summary: Wrong code for ((unsigned) ((a) >> 2)) >> 15 Product: gcc Version: 4.1.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: tree-optimization AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: Erwin dot Unruh at fujitsu-siemens dot com GCC target triplet: sparc-sun-solaris2.8 http://gcc.gnu.org/bugzilla/show_bug.cgi?id=27743