http://gcc.gnu.org/bugzilla/show_bug.cgi?id=50193
Bug #: 50193 Summary: ARM: ICE on a | (b << negative-constant) Classification: Unclassified Product: gcc Version: 4.7.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: target AssignedTo: unassig...@gcc.gnu.org ReportedBy: michael.h...@linaro.org trunk r178025, 4.6.1, and 4.5.3 all ICE with unsatisfied constraints on the following code: int foo(int a, int b) { return a | (b << -3); } shift.c: In function 'foo': shift.c:3:5: warning: left shift count is negative [enabled by default] shift.c:4:1: error: insn does not satisfy its constraints: (insn 14 9 17 2 (set (reg/i:SI 0 r0) (ior:SI (ashift:SI (reg:SI 1 r1 [ b ]) (const_int -3 [0xfffffffffffffffd])) (reg:SI 0 r0 [ a ]))) shift.c:4 259 {*arith_shiftsi} (expr_list:REG_DEAD (reg:SI 1 r1 [ b ]) (nil))) shift.c:4:1: internal compiler error: in extract_constrain_insn_cached, at recog.c:2030 This happens with -mcpu=cortex-a9 -mthumb. With -marm, GCC recognises that the shift is unusual, loads it into a register, then uses this in the register-shifted-register form of ORR. This form isn't available in Thumb-2. The problem was originally seen in libtheora:lib/mathops.c when built with -O3 -funroll-loops when a shift by negative 8 is generated.