http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53376
--- Comment #2 from Richard Earnshaw <rearnsha at gcc dot gnu.org> 2012-05-16 23:18:34 UTC --- (In reply to comment #0) > extern int x; > static long long p; > static long long *h1 ; > static long long *h2 ; > > void foo (void) > { > int i ; > for( i = 0 ; i < x ; i++ ) > { > if( (p >> 3) > 5000) > p += 5000; > *h2 = *h1 ; > h2++; > } > } > > > Fails with an ICE > > > > (insn 1166 1165 1167 155 (set (reg:CC 24 cc) > > (compare:CC (reg:SI 2148 [ D.6766 ]) > > (const_int 5000 [0x1388]))) iirflt01/bmark.c:501 -1 > > (nil)) > > internal compiler error: in extract_insn, at > > recog.c:2131 > > Compares with 5000 really aren't allowed and we appear to happily generate > this > in this particular case - The patch below completely untested fixes this by > forcing invalid operations of the comparison into a register like what happens > in other parts of the compiler that use arm_gen_compare_reg - > > For all cases other than DImode arm_gen_compare_reg expects to get only valid > operands to the arms of the compare. There are a number of places where these > checks already happen before the call to arm_gen_compare_reg and therefore it > seems pointless to check twice. > > diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md > index b1ad3bf..04be822 100644 > --- a/gcc/config/arm/arm.md > +++ b/gcc/config/arm/arm.md > @@ -8144,6 +8144,9 @@ > if (code == UNEQ || code == LTGT) > FAIL; > > + if (!arm_add_operand (XEXP (operands[1], 1), SImode)) > + XEXP (operands[1], 1) = force_reg (SImode, XEXP (operands[1], 1)); > + > ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0), > XEXP (operands[1], 1), NULL_RTX); > operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx); > > > > regards, > Ramana FTR this isn't safe. There's no requirement for the comparison to be SImode; it could be an FP mode or some other precision.