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, >=)

Reply via email to