Shift LEFT by the full length of integer is carried through to RTL as shift - rather than being ZERO.
This hidden zero prevents further optimization. For example x = a + (B<<16) should be reduced to x = a. Instead we get x = 0 | a; This can also be seen in rotate expressions. int16_t shiftzero(uint16_t x,uint16_t y) { return x + (y<<16); } shiftzero (uint16_tD.xxxx xD.xxxx, uint16_tD.xxxx yD.xxxx) { uint16_tD.xxxx D.xxxx; uint16_tD.xxxx D.xxxx; int16_tD.xxxx D.xxxx; # BLOCK 2 freq:10000 # PRED: ENTRY [100.0%] (fallthru,exec) D.xxxx_2 = yD.xxxx_1(D) << 16; D.xxxx_4 = D.xxxx_2 + xD.xxxx_3(D); D.xxxx_5 = (int16_tD.xxxx) D.xxxx_4; return D.xxxx_5; # SUCC: EXIT [100.0%] } /* NOTE Same on rotate - since expander is uses shift */ int16_t rotatezero(uint16_t x,uint16_t y) { return ROTATE (x,16); } rotatezero (uint16_tD.xxxx xD.xxxx, uint16_tD.xxxx yD.xxxx) { uint16_tD.xxxx D.xxxx; uint16_tD.xxxx D.xxxx; int16_tD.xxxx D.xxxx; # BLOCK 2 freq:10000 # PRED: ENTRY [100.0%] (fallthru,exec) D.xxxx_2 = xD.xxxx_1(D) << 16; D.xxxx_3 = D.xxxx_2 | xD.xxxx_1(D); D.xxxx_4 = (int16_tD.xxxx) D.xxxx_3; return D.xxxx_4; # SUCC: EXIT [100.0%] } -- Summary: Shift left as wide as mode is expanded into RTL as shift Product: gcc Version: unknown Status: UNCONFIRMED Severity: normal Priority: P3 Component: middle-end AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: hutchinsonandy at gcc dot gnu dot org GCC host triplet: i686-pc-linux-gnu GCC target triplet: avr-unknown-none http://gcc.gnu.org/bugzilla/show_bug.cgi?id=42303