My fix for PR49030 had the unintended side-effect of forcing libcalls to be used for some DImode comparisons. The problem (which I should have noticed at the time, sorry) is that arm_comparison_operator is used for both expanders and insns. The patch fixed the definition for insns, but made it too tight for expanders.
The expanders can't use the generic comparison_operator predicate because ARM has no support for UNEQ and LTGT. So this patch introduces an expandable_comparison_operator that the expanders can use instead. I've left incscc and decscc using arm_comparison_operator, since they expand directly into instructions without any manipulation. These expanders appear to be dead anyway, so I'd be happy to remove them if that seems better. It should probably be a separate patch though. Otherwise, all expanders use expandable_comparison_operator instead. This restores the previous behaviour for them, and I went through each one to try to make sure that it was handled correctly. Tested on arm-linux-gnueabi. OK to install? Richard gcc/ * config/arm/predicates.md (expandable_comparison_operator): New predicate, extracted from... (arm_comparison_operator): ...here. * config/arm/arm.md (cbranchsi4, cbranchsf4, cbranchdf4, cbranchdi4) (cstoresi4, cstoresf4, cstoredf4, cstoredi4, movsicc, movsfcc) (movdfcc): Use expandable_comparison_operator. gcc/testsuite/ * gcc.target/arm/cmp-1.c: New test. Index: gcc/config/arm/predicates.md =================================================================== --- gcc/config/arm/predicates.md 2011-09-15 15:40:35.039389194 +0100 +++ gcc/config/arm/predicates.md 2011-09-19 09:01:02.322632770 +0100 @@ -248,9 +248,14 @@ (define_special_predicate "equality_oper ;; True for integer comparisons and, if FP is active, for comparisons ;; other than LTGT or UNEQ. +(define_special_predicate "expandable_comparison_operator" + (match_code "eq,ne,le,lt,ge,gt,geu,gtu,leu,ltu, + unordered,ordered,unlt,unle,unge,ungt")) + +;; Likewise, but only accept comparisons that are directly supported +;; by ARM condition codes. (define_special_predicate "arm_comparison_operator" - (and (match_code "eq,ne,le,lt,ge,gt,geu,gtu,leu,ltu, - unordered,ordered,unlt,unle,unge,ungt") + (and (match_operand 0 "expandable_comparison_operator") (match_test "maybe_get_arm_condition_code (op) != ARM_NV"))) (define_special_predicate "lt_ge_comparison_operator" Index: gcc/config/arm/arm.md =================================================================== --- gcc/config/arm/arm.md 2011-09-15 15:40:35.039389194 +0100 +++ gcc/config/arm/arm.md 2011-09-15 15:40:43.330364362 +0100 @@ -6565,7 +6565,7 @@ (define_insn "movmem8b" (define_expand "cbranchsi4" [(set (pc) (if_then_else - (match_operator 0 "arm_comparison_operator" + (match_operator 0 "expandable_comparison_operator" [(match_operand:SI 1 "s_register_operand" "") (match_operand:SI 2 "nonmemory_operand" "")]) (label_ref (match_operand 3 "" "")) @@ -6616,7 +6616,7 @@ (define_expand "cbranchqi4" (define_expand "cbranchsf4" [(set (pc) (if_then_else - (match_operator 0 "arm_comparison_operator" + (match_operator 0 "expandable_comparison_operator" [(match_operand:SF 1 "s_register_operand" "") (match_operand:SF 2 "arm_float_compare_operand" "")]) (label_ref (match_operand 3 "" "")) @@ -6628,7 +6628,7 @@ (define_expand "cbranchsf4" (define_expand "cbranchdf4" [(set (pc) (if_then_else - (match_operator 0 "arm_comparison_operator" + (match_operator 0 "expandable_comparison_operator" [(match_operand:DF 1 "s_register_operand" "") (match_operand:DF 2 "arm_float_compare_operand" "")]) (label_ref (match_operand 3 "" "")) @@ -6640,7 +6640,7 @@ (define_expand "cbranchdf4" (define_expand "cbranchdi4" [(set (pc) (if_then_else - (match_operator 0 "arm_comparison_operator" + (match_operator 0 "expandable_comparison_operator" [(match_operand:DI 1 "cmpdi_operand" "") (match_operand:DI 2 "cmpdi_operand" "")]) (label_ref (match_operand 3 "" "")) @@ -7495,7 +7495,7 @@ (define_insn "*mov_notscc" (define_expand "cstoresi4" [(set (match_operand:SI 0 "s_register_operand" "") - (match_operator:SI 1 "arm_comparison_operator" + (match_operator:SI 1 "expandable_comparison_operator" [(match_operand:SI 2 "s_register_operand" "") (match_operand:SI 3 "reg_or_int_operand" "")]))] "TARGET_32BIT || TARGET_THUMB1" @@ -7631,7 +7631,7 @@ (define_expand "cstoresi4" (define_expand "cstoresf4" [(set (match_operand:SI 0 "s_register_operand" "") - (match_operator:SI 1 "arm_comparison_operator" + (match_operator:SI 1 "expandable_comparison_operator" [(match_operand:SF 2 "s_register_operand" "") (match_operand:SF 3 "arm_float_compare_operand" "")]))] "TARGET_32BIT && TARGET_HARD_FLOAT" @@ -7641,7 +7641,7 @@ (define_expand "cstoresf4" (define_expand "cstoredf4" [(set (match_operand:SI 0 "s_register_operand" "") - (match_operator:SI 1 "arm_comparison_operator" + (match_operator:SI 1 "expandable_comparison_operator" [(match_operand:DF 2 "s_register_operand" "") (match_operand:DF 3 "arm_float_compare_operand" "")]))] "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE" @@ -7651,7 +7651,7 @@ (define_expand "cstoredf4" (define_expand "cstoredi4" [(set (match_operand:SI 0 "s_register_operand" "") - (match_operator:SI 1 "arm_comparison_operator" + (match_operator:SI 1 "expandable_comparison_operator" [(match_operand:DI 2 "cmpdi_operand" "") (match_operand:DI 3 "cmpdi_operand" "")]))] "TARGET_32BIT" @@ -7771,7 +7771,7 @@ (define_insn "thumb1_addsi3_addgeu" (define_expand "movsicc" [(set (match_operand:SI 0 "s_register_operand" "") - (if_then_else:SI (match_operand 1 "arm_comparison_operator" "") + (if_then_else:SI (match_operand 1 "expandable_comparison_operator" "") (match_operand:SI 2 "arm_not_operand" "") (match_operand:SI 3 "arm_not_operand" "")))] "TARGET_32BIT" @@ -7791,7 +7791,7 @@ (define_expand "movsicc" (define_expand "movsfcc" [(set (match_operand:SF 0 "s_register_operand" "") - (if_then_else:SF (match_operand 1 "arm_comparison_operator" "") + (if_then_else:SF (match_operand 1 "expandable_comparison_operator" "") (match_operand:SF 2 "s_register_operand" "") (match_operand:SF 3 "nonmemory_operand" "")))] "TARGET_32BIT && TARGET_HARD_FLOAT" @@ -7817,7 +7817,7 @@ (define_expand "movsfcc" (define_expand "movdfcc" [(set (match_operand:DF 0 "s_register_operand" "") - (if_then_else:DF (match_operand 1 "arm_comparison_operator" "") + (if_then_else:DF (match_operand 1 "expandable_comparison_operator" "") (match_operand:DF 2 "s_register_operand" "") (match_operand:DF 3 "arm_float_add_operand" "")))] "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)" Index: gcc/testsuite/gcc.target/arm/cmp-1.c =================================================================== --- /dev/null 2011-09-08 10:02:38.944000001 +0100 +++ gcc/testsuite/gcc.target/arm/cmp-1.c 2011-09-15 15:40:43.332364356 +0100 @@ -0,0 +1,23 @@ +/* { dg-do compile } */ +/* { dg-options "-O" } */ +/* { dg-final { scan-assembler-not "\tbl\t" } } */ +/* { dg-final { scan-assembler-not "__aeabi" } } */ +#define TEST(NAME, TYPE, OPERATOR) \ + int NAME (TYPE *a1, TYPE *a2) { return *a1 OPERATOR *a2; } + +#define TEST_OP(NAME, OPERATOR) \ + TEST (sc_##NAME, signed char, OPERATOR) \ + TEST (uc_##NAME, unsigned char, OPERATOR) \ + TEST (ss_##NAME, short, OPERATOR) \ + TEST (us_##NAME, unsigned short, OPERATOR) \ + TEST (si_##NAME, int, OPERATOR) \ + TEST (ui_##NAME, unsigned int, OPERATOR) \ + TEST (sll_##NAME, long long, OPERATOR) \ + TEST (ull_##NAME, unsigned long long, OPERATOR) + +TEST_OP (eq, ==) +TEST_OP (ne, !=) +TEST_OP (lt, <) +TEST_OP (gt, >) +TEST_OP (le, <=) +TEST_OP (ge, >=)