[fix PR49030 ICE on ARM, bootstrapped + regtested, needs validation that the new codegen is correct, not yet submitted upstream ] gcc/ 2011-07-05 Mikael Pettersson PR target/49030 * config/arm/arm-modes.def: Add CC_NCV_REVmode. * config/arm/arm.c (arm_select_cc_mode): Use CC_NCV_REVmode for DImode comparisons that must be reversed. (get_arm_condition_code): Handle CC_NCV_REVmode. * config/arm/arm.md (*arm_cmpdi_insn_rev): New. gcc/testsuite/ 2011-07-05 Mikael Pettersson PR target/49030 * gcc.c-torture/compile/pr49030.c: New. --- gcc-4.6.1/gcc/config/arm/arm-modes.def.~1~ 2011-01-03 21:52:22.000000000 +0100 +++ gcc-4.6.1/gcc/config/arm/arm-modes.def 2011-07-05 16:48:17.000000000 +0200 @@ -47,6 +47,7 @@ CC_MODE (CC_NOOV); CC_MODE (CC_Z); CC_MODE (CC_CZ); CC_MODE (CC_NCV); +CC_MODE (CC_NCV_REV); CC_MODE (CC_SWP); CC_MODE (CCFP); CC_MODE (CCFPE); --- gcc-4.6.1/gcc/config/arm/arm.c.~1~ 2011-05-05 10:39:40.000000000 +0200 +++ gcc-4.6.1/gcc/config/arm/arm.c 2011-07-05 16:48:58.000000000 +0200 @@ -10797,7 +10797,16 @@ arm_select_cc_mode (enum rtx_code op, rt by cmp + sbcs with a scratch register, but that does not set the Z flag - we must reverse GT/LE/GTU/LEU. */ gcc_assert (op != EQ && op != NE); - return CC_NCVmode; + switch (op) + { + case GT: + case LE: + case GTU: + case LEU: + return CC_NCV_REVmode; + default: + return CC_NCVmode; + } default: gcc_unreachable (); @@ -17152,6 +17161,16 @@ get_arm_condition_code (rtx comparison) default: gcc_unreachable (); } + case CC_NCV_REVmode: + switch (comp_code) + { + case GT: return ARM_LT; + case LE: return ARM_GE; + case GTU: return ARM_CC; + case LEU: return ARM_CS; + default: gcc_unreachable (); + } + case CCmode: switch (comp_code) { --- gcc-4.6.1/gcc/config/arm/arm.md.~1~ 2011-04-13 09:41:08.000000000 +0200 +++ gcc-4.6.1/gcc/config/arm/arm.md 2011-07-05 16:48:17.000000000 +0200 @@ -7174,6 +7174,17 @@ (define_insn "*arm_cmpdi_insn" (set_attr "length" "8")] ) +(define_insn "*arm_cmpdi_insn_rev" + [(set (reg:CC_NCV_REV CC_REGNUM) + (compare:CC_NCV_REV (match_operand:DI 0 "s_register_operand" "r") + (match_operand:DI 1 "arm_di_operand" "rDi"))) + (clobber (match_scratch:SI 2 "=&r"))] + "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)" + "rsbs\\t%2, %Q0, %Q1\;rscs\\t%2, %R0, %R1" + [(set_attr "conds" "set") + (set_attr "length" "8")] +) + (define_insn "*arm_cmpdi_unsigned" [(set (reg:CC_CZ CC_REGNUM) (compare:CC_CZ (match_operand:DI 0 "s_register_operand" "r") --- gcc-4.6.1/gcc/testsuite/gcc.c-torture/compile/pr49030.c.~1~ 1970-01-01 01:00:00.000000000 +0100 +++ gcc-4.6.1/gcc/testsuite/gcc.c-torture/compile/pr49030.c 2011-07-05 16:51:32.000000000 +0200 @@ -0,0 +1,11 @@ +/* PR target/49030 */ +long long foo(void); +int temp[2] = { 0, 0 }; + +int *bar(void) +{ + if (foo() < ((foo() < 1) <= 1)) + return &temp[0]; + else + return &temp[1]; +}