http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53376
Bug #: 53376 Summary: Unrecognizable compare insn generated by movsicc in arm backend. Classification: Unclassified Product: gcc Version: 4.8.0 Status: UNCONFIRMED Keywords: ice-on-valid-code Severity: normal Priority: P3 Component: target AssignedTo: unassig...@gcc.gnu.org ReportedBy: ram...@gcc.gnu.org Target: arm-linux-gnueabi Build: x86* 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