Investigating PR target/86891 revealed a number of issues with the way the...
authorRichard Earnshaw <rearnsha@arm.com>
Mon, 7 Jan 2019 14:49:00 +0000 (14:49 +0000)
committerRichard Earnshaw <rearnsha@gcc.gnu.org>
Mon, 7 Jan 2019 14:49:00 +0000 (14:49 +0000)
Investigating PR target/86891 revealed a number of issues with the way
the AArch64 backend was handing overflow detection patterns.  Firstly,
expansion for signed and unsigned types is not the same as in one form
the overflow is detected via the C flag and in the other it is done
via the V flag in the PSR.  Secondly, particular care has to be taken
when describing overflow of signed types: the comparison has to be
performed conceptually on a value that cannot overflow and compared to
a value that might have overflowed.

It became apparent that some of the patterns were simply unmatchable
(they collapse to NEG in the RTL rather than subtracting from zero)
and a number of patterns were overly restrictive in terms of the
immediate constants that they supported.  I've tried to address all of
these issues as well.

gcc:

PR target/86891
* config/aarch64/aarch64.c (aarch64_expand_subvti): New parameter
unsigned_p.  Handle signed and unsigned overflow correction as
required.
* config/aarch64/aarch64-protos.h (aarch64_expand_subvti): Update
prototype.
* config/aarch64/aarch64.md (addv<mode>4): Use aarch64_plus_operand
for operand 2.
(add<mode>3_compareV_imm): Make this callable for expanding.
(subv<GPI:mode>4): Use register_operand for operand 1.  Use
aarch64_plus_operand for operand 2.
(subv<GPI:mode>_insn): New insn pattern.
(subv<GPI:mode>_imm): Likewise.
(negv<GPI:mode>3): New expand pattern.
(negv<GPI:mode>_insn): New insn pattern.
(negv<GPI:mode>_cmp_only): Likewise.
(cmpv<GPI:mode>_insn): Likewise.
(subvti4): Use register_operand for operand 1.  Update call to
aarch64_expand_subvti.
(usubvti4): Likewise.
(negvti3): New expand pattern.
(negdi_carryout): New insn pattern.
(negvdi_carryinV): New insn pattern.
(sub<mode3>_compare1_imm): Delete named insn pattern, make anonymous
version the named version.
(peepholes to convert to sub<mode3>_compare1_imm): Adjust order of
operands.
(usub<GPI:mode>3_carryinC, usub<GPI:mode>3_carryinC_z1): New insn
patterns.
(usub<GPI:mode>3_carryinC_z2, usub<GPI:mode>3_carryinC): New insn
patterns.
(sub<mode>3_carryinCV, sub<mode>3_carryinCV_z1_z2): Delete.
(sub<mode>3_carryinCV_z1, sub<mode>3_carryinCV_z2): Delete.
(sub<mode>3_carryinCV): Delete.
(sub<GPI:mode>3_carryinV): New expand pattern.
sub<mode>3_carryinV, sub<mode>3_carryinV_z2): New insn patterns.

testsuite:

* gcc.target/aarch64/subs_compare_2.c: Make '#' immediate prefix
optional in scan pattern.

From-SVN: r267650

gcc/ChangeLog
gcc/config/aarch64/aarch64-protos.h
gcc/config/aarch64/aarch64.c
gcc/config/aarch64/aarch64.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/aarch64/subs_compare_2.c

index 472145b6cb7d92d79727d54e0a03241d561e5597..0aad583866498b9fa51c6221b94bf6b9549a028e 100644 (file)
@@ -1,3 +1,42 @@
+2019-01-07  Richard Earnshaw  <rearnsha@arm.com>
+
+       PR target/86891
+       * config/aarch64/aarch64.c (aarch64_expand_subvti): New parameter
+       unsigned_p.  Handle signed and unsigned overflow correction as
+       required.
+       * config/aarch64/aarch64-protos.h (aarch64_expand_subvti): Update
+       prototype.
+       * config/aarch64/aarch64.md (addv<mode>4): Use aarch64_plus_operand
+       for operand 2.
+       (add<mode>3_compareV_imm): Make this callable for expanding.
+       (subv<GPI:mode>4): Use register_operand for operand 1.  Use
+       aarch64_plus_operand for operand 2.
+       (subv<GPI:mode>_insn): New insn pattern.
+       (subv<GPI:mode>_imm): Likewise.
+       (negv<GPI:mode>3): New expand pattern.
+       (negv<GPI:mode>_insn): New insn pattern.
+       (negv<GPI:mode>_cmp_only): Likewise.
+       (cmpv<GPI:mode>_insn): Likewise.
+       (subvti4): Use register_operand for operand 1.  Update call to
+       aarch64_expand_subvti.
+       (usubvti4): Likewise.
+       (negvti3): New expand pattern.
+       (negdi_carryout): New insn pattern.
+       (negvdi_carryinV): New insn pattern.
+       (sub<mode3>_compare1_imm): Delete named insn pattern, make anonymous
+       version the named version.
+       (peepholes to convert to sub<mode3>_compare1_imm): Adjust order of
+       operands.
+       (usub<GPI:mode>3_carryinC, usub<GPI:mode>3_carryinC_z1): New insn
+       patterns.
+       (usub<GPI:mode>3_carryinC_z2, usub<GPI:mode>3_carryinC): New insn
+       patterns.
+       (sub<mode>3_carryinCV, sub<mode>3_carryinCV_z1_z2): Delete.
+       (sub<mode>3_carryinCV_z1, sub<mode>3_carryinCV_z2): Delete.
+       (sub<mode>3_carryinCV): Delete.
+       (sub<GPI:mode>3_carryinV): New expand pattern.
+       sub<mode>3_carryinV, sub<mode>3_carryinV_z2): New insn patterns.
+
 2019-01-07  Richard Biener  <rguenther@suse.de>
 
        * tree-ssa-uncprop.c (ssa_equip_hash_traits): Remove in favor
index 9a8f81ee13415d12693c3226e38054e7a139177c..209c09be669cc139d82d5c7aedb6e59292c50f07 100644 (file)
@@ -530,7 +530,7 @@ void aarch64_subvti_scratch_regs (rtx, rtx, rtx *,
                                  rtx *, rtx *,
                                  rtx *, rtx *, rtx *);
 void aarch64_expand_subvti (rtx, rtx, rtx,
-                           rtx, rtx, rtx, rtx);
+                           rtx, rtx, rtx, rtx, bool);
 
 
 /* Initialize builtins for SIMD intrinsics.  */
index c5036c83531225c8e0b994cb78154cefeeb6e04a..c87994011bb55b36ded4755bbac510f247580935 100644 (file)
@@ -16668,32 +16668,38 @@ aarch64_subvti_scratch_regs (rtx op1, rtx op2, rtx *low_dest,
    LOW_IN2 represents the low half (DImode) of TImode operand 2
    HIGH_DEST represents the high half (DImode) of TImode operand 0
    HIGH_IN1 represents the high half (DImode) of TImode operand 1
-   HIGH_IN2 represents the high half (DImode) of TImode operand 2.  */
-
+   HIGH_IN2 represents the high half (DImode) of TImode operand 2
+   UNSIGNED_P is true if the operation is being performed on unsigned
+   values.  */
 void
 aarch64_expand_subvti (rtx op0, rtx low_dest, rtx low_in1,
                       rtx low_in2, rtx high_dest, rtx high_in1,
-                      rtx high_in2)
+                      rtx high_in2, bool unsigned_p)
 {
   if (low_in2 == const0_rtx)
     {
       low_dest = low_in1;
-      emit_insn (gen_subdi3_compare1 (high_dest, high_in1,
-                                     force_reg (DImode, high_in2)));
+      high_in2 = force_reg (DImode, high_in2);
+      if (unsigned_p)
+       emit_insn (gen_subdi3_compare1 (high_dest, high_in1, high_in2));
+      else
+       emit_insn (gen_subvdi_insn (high_dest, high_in1, high_in2));
     }
   else
     {
       if (CONST_INT_P (low_in2))
        {
-         low_in2 = force_reg (DImode, GEN_INT (-UINTVAL (low_in2)));
          high_in2 = force_reg (DImode, high_in2);
-         emit_insn (gen_adddi3_compareC (low_dest, low_in1, low_in2));
+         emit_insn (gen_subdi3_compare1_imm (low_dest, low_in1, low_in2,
+                                             GEN_INT (-INTVAL (low_in2))));
        }
       else
        emit_insn (gen_subdi3_compare1 (low_dest, low_in1, low_in2));
-      emit_insn (gen_subdi3_carryinCV (high_dest,
-                                      force_reg (DImode, high_in1),
-                                      high_in2));
+
+      if (unsigned_p)
+       emit_insn (gen_usubdi3_carryinC (high_dest, high_in1, high_in2));
+      else
+       emit_insn (gen_subdi3_carryinV (high_dest, high_in1, high_in2));
     }
 
   emit_move_insn (gen_lowpart (DImode, op0), low_dest);
index d2642ef328cf2863e788cbd4942acb255d5e6be3..37322fbbfa32b298a7ad7f2bd5eebe2324238c78 100644 (file)
 (define_expand "addv<mode>4"
   [(match_operand:GPI 0 "register_operand")
    (match_operand:GPI 1 "register_operand")
-   (match_operand:GPI 2 "register_operand")
+   (match_operand:GPI 2 "aarch64_plus_operand")
    (label_ref (match_operand 3 "" ""))]
   ""
 {
-  emit_insn (gen_add<mode>3_compareV (operands[0], operands[1], operands[2]));
+  if (CONST_INT_P (operands[2]))
+    emit_insn (gen_add<mode>3_compareV_imm (operands[0], operands[1],
+                                           operands[2]));
+  else
+    emit_insn (gen_add<mode>3_compareV (operands[0], operands[1], operands[2]));
   aarch64_gen_unlikely_cbranch (NE, CC_Vmode, operands[3]);
 
   DONE;
   [(set_attr "type" "alus_sreg")]
 )
 
-(define_insn "*add<mode>3_compareV_imm"
+(define_insn "add<mode>3_compareV_imm"
   [(set (reg:CC_V CC_REGNUM)
        (compare:CC_V
          (plus:<DWI>
    (set_attr "arch" "*,simd")]
 )
 
-(define_expand "subv<mode>4"
+(define_expand "subv<GPI:mode>4"
   [(match_operand:GPI 0 "register_operand")
-   (match_operand:GPI 1 "aarch64_reg_or_zero")
-   (match_operand:GPI 2 "aarch64_reg_or_zero")
+   (match_operand:GPI 1 "register_operand")
+   (match_operand:GPI 2 "aarch64_plus_operand")
    (label_ref (match_operand 3 "" ""))]
   ""
 {
-  emit_insn (gen_sub<mode>3_compare1 (operands[0], operands[1], operands[2]));
+  if (CONST_INT_P (operands[2]))
+    emit_insn (gen_subv<mode>_imm (operands[0], operands[1], operands[2]));
+  else
+    emit_insn (gen_subv<mode>_insn (operands[0], operands[1], operands[2]));
   aarch64_gen_unlikely_cbranch (NE, CC_Vmode, operands[3]);
 
   DONE;
 })
 
+(define_insn "subv<GPI:mode>_insn"
+  [(set (reg:CC_V CC_REGNUM)
+       (compare:CC_V
+        (sign_extend:<DWI>
+         (minus:GPI
+          (match_operand:GPI 1 "register_operand" "rk")
+          (match_operand:GPI 2 "register_operand" "r")))
+        (minus:<DWI> (sign_extend:<DWI> (match_dup 1))
+                     (sign_extend:<DWI> (match_dup 2)))))
+   (set (match_operand:GPI 0 "register_operand" "=r")
+       (minus:GPI (match_dup 1) (match_dup 2)))]
+  ""
+  "subs\\t%<w>0, %<w>1, %<w>2"
+  [(set_attr "type" "alus_sreg")]
+)
+
+(define_insn "subv<GPI:mode>_imm"
+  [(set (reg:CC_V CC_REGNUM)
+       (compare:CC_V
+        (sign_extend:<DWI>
+         (minus:GPI
+          (match_operand:GPI 1 "register_operand" "rk,rk")
+          (match_operand:GPI 2 "aarch64_plus_immediate" "I,J")))
+        (minus:<DWI> (sign_extend:<DWI> (match_dup 1))
+                     (match_dup 2))))
+   (set (match_operand:GPI 0 "register_operand" "=r,r")
+       (minus:GPI (match_dup 1) (match_dup 2)))]
+  ""
+  "@
+   subs\\t%<w>0, %<w>1, %2
+   adds\\t%<w>0, %<w>1, #%n2"
+  [(set_attr "type" "alus_sreg")]
+)
+
+(define_expand "negv<GPI:mode>3"
+  [(match_operand:GPI 0 "register_operand")
+   (match_operand:GPI 1 "register_operand")
+   (label_ref (match_operand 2 "" ""))]
+  ""
+  {
+    emit_insn (gen_negv<mode>_insn (operands[0], operands[1]));
+    aarch64_gen_unlikely_cbranch (NE, CC_Vmode, operands[2]);
+
+    DONE;
+  }
+)
+
+(define_insn "negv<GPI:mode>_insn"
+  [(set (reg:CC_V CC_REGNUM)
+       (compare:CC_V
+        (sign_extend:<DWI>
+         (neg:GPI (match_operand:GPI 1 "register_operand" "r")))
+        (neg:<DWI> (sign_extend:<DWI> (match_dup 1)))))
+   (set (match_operand:GPI 0 "register_operand" "=r")
+       (neg:GPI (match_dup 1)))]
+  ""
+  "negs\\t%<w>0, %<w>1"
+  [(set_attr "type" "alus_sreg")]
+)
+
+(define_insn "negv<GPI:mode>_cmp_only"
+  [(set (reg:CC_V CC_REGNUM)
+       (compare:CC_V
+        (sign_extend:<DWI>
+         (neg:GPI (match_operand:GPI 0 "register_operand" "r")))
+        (neg:<DWI> (sign_extend:<DWI> (match_dup 0)))))]
+  ""
+  "negs\\t%<w>zr, %<w>0"
+  [(set_attr "type" "alus_sreg")]
+)
+
+(define_insn "*cmpv<GPI:mode>_insn"
+  [(set (reg:CC_V CC_REGNUM)
+       (compare:CC_V
+        (sign_extend:<DWI>
+         (minus:GPI (match_operand:GPI 0 "register_operand" "r,r,r")
+                    (match_operand:GPI 1 "aarch64_plus_operand" "r,I,J")))
+        (minus:<DWI> (sign_extend:<DWI> (match_dup 0))
+                   (sign_extend:<DWI> (match_dup 1)))))]
+  ""
+  "@
+   cmp\\t%<w>0, %<w>1
+   cmp\\t%<w>0, %1
+   cmp\\t%<w>0, #%n1"
+  [(set_attr "type" "alus_sreg")]
+)
+
 (define_expand "usubv<mode>4"
   [(match_operand:GPI 0 "register_operand")
    (match_operand:GPI 1 "aarch64_reg_or_zero")
 
 (define_expand "subvti4"
   [(match_operand:TI 0 "register_operand")
-   (match_operand:TI 1 "aarch64_reg_or_zero")
+   (match_operand:TI 1 "register_operand")
    (match_operand:TI 2 "aarch64_reg_or_imm")
    (label_ref (match_operand 3 "" ""))]
   ""
                               &low_dest, &op1_low, &op2_low,
                               &high_dest, &op1_high, &op2_high);
   aarch64_expand_subvti (operands[0], low_dest, op1_low, op2_low,
-                        high_dest, op1_high, op2_high);
+                        high_dest, op1_high, op2_high, false);
 
   aarch64_gen_unlikely_cbranch (NE, CC_Vmode, operands[3]);
   DONE;
 
 (define_expand "usubvti4"
   [(match_operand:TI 0 "register_operand")
-   (match_operand:TI 1 "aarch64_reg_or_zero")
+   (match_operand:TI 1 "register_operand")
    (match_operand:TI 2 "aarch64_reg_or_imm")
    (label_ref (match_operand 3 "" ""))]
   ""
                                    &low_dest, &op1_low, &op2_low,
                               &high_dest, &op1_high, &op2_high);
   aarch64_expand_subvti (operands[0], low_dest, op1_low, op2_low,
-                        high_dest, op1_high, op2_high);
+                        high_dest, op1_high, op2_high, true);
 
   aarch64_gen_unlikely_cbranch (LTU, CCmode, operands[3]);
   DONE;
 })
 
+(define_expand "negvti3"
+  [(match_operand:TI 0 "register_operand")
+   (match_operand:TI 1 "register_operand")
+   (label_ref (match_operand 2 "" ""))]
+  ""
+  {
+    emit_insn (gen_negdi_carryout (gen_lowpart (DImode, operands[0]),
+                                  gen_lowpart (DImode, operands[1])));
+    emit_insn (gen_negvdi_carryinV (gen_highpart (DImode, operands[0]),
+                                   gen_highpart (DImode, operands[1])));
+    aarch64_gen_unlikely_cbranch (NE, CC_Vmode, operands[2]);
+
+    DONE;
+  }
+)
+
+(define_insn "negdi_carryout"
+  [(set (reg:CC CC_REGNUM)
+       (compare:CC
+        (const_int 0) (match_operand:DI 1 "register_operand" "r")))
+   (set (match_operand:DI 0 "register_operand" "=r")
+       (neg:DI (match_dup 1)))]
+  ""
+  "negs\\t%0, %1"
+  [(set_attr "type" "alus_sreg")]
+)
+
+(define_insn "negvdi_carryinV"
+  [(set (reg:CC_V CC_REGNUM)
+       (compare:CC_V
+        (neg:TI (plus:TI
+                 (ltu:TI (reg:CC CC_REGNUM) (const_int 0))
+                 (sign_extend:TI (match_operand:DI 1 "register_operand" "r"))))
+        (sign_extend:TI
+         (neg:DI (plus:DI (ltu:DI (reg:CC CC_REGNUM) (const_int 0))
+                          (match_dup 1))))))
+   (set (match_operand:DI 0 "register_operand" "=r")
+       (neg:DI (plus:DI (ltu:DI (reg:CC CC_REGNUM) (const_int 0))
+                        (match_dup 1))))]
+  ""
+  "ngcs\\t%0, %1"
+  [(set_attr "type" "alus_sreg")]
+)
+
 (define_insn "*sub<mode>3_compare0"
   [(set (reg:CC_NZ CC_REGNUM)
        (compare:CC_NZ (minus:GPI (match_operand:GPI 1 "register_operand" "r")
   [(set_attr "type" "alus_sreg")]
 )
 
-(define_insn "*sub<mode>3_compare1_imm"
+(define_insn "sub<mode>3_compare1_imm"
   [(set (reg:CC CC_REGNUM)
        (compare:CC
          (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ,rZ")
          (match_operand:GPI 3 "aarch64_plus_immediate" "J,I")))]
   "UINTVAL (operands[2]) == -UINTVAL (operands[3])"
   "@
-  subs\\t%<w>0, %<w>1, #%n3
-  adds\\t%<w>0, %<w>1, %3"
+  subs\\t%<w>0, %<w>1, %2
+  adds\\t%<w>0, %<w>1, #%n2"
   [(set_attr "type" "alus_imm")]
 )
 
   [(set_attr "type" "alus_sreg")]
 )
 
-(define_insn "sub<mode>3_compare1_imm"
-  [(set (reg:CC CC_REGNUM)
-       (compare:CC
-         (match_operand:GPI 1 "register_operand" "r")
-         (match_operand:GPI 3 "const_int_operand" "n")))
-   (set (match_operand:GPI 0 "register_operand" "=r")
-       (plus:GPI (match_dup 1)
-                 (match_operand:GPI 2 "aarch64_sub_immediate" "J")))]
-  "INTVAL (operands[3]) == -INTVAL (operands[2])"
-  "subs\\t%<w>0, %<w>1, #%n2"
-  [(set_attr "type" "alus_sreg")]
-)
-
 (define_peephole2
   [(set (match_operand:GPI 0 "register_operand")
        (minus:GPI (match_operand:GPI 1 "aarch64_reg_or_zero")
 (define_peephole2
   [(set (match_operand:GPI 0 "register_operand")
        (plus:GPI (match_operand:GPI 1 "register_operand")
-                 (match_operand:GPI 2 "aarch64_sub_immediate")))
+                 (match_operand:GPI 2 "aarch64_plus_immediate")))
    (set (reg:CC CC_REGNUM)
        (compare:CC
          (match_dup 1)
   [(const_int 0)]
   {
     emit_insn (gen_sub<mode>3_compare1_imm (operands[0], operands[1],
-                                        operands[2], operands[3]));
+                                        operands[3], operands[2]));
     DONE;
   }
 )
          (match_operand:GPI 3 "const_int_operand")))
    (set (match_operand:GPI 0 "register_operand")
        (plus:GPI (match_dup 1)
-                 (match_operand:GPI 2 "aarch64_sub_immediate")))]
+                 (match_operand:GPI 2 "aarch64_plus_immediate")))]
   "INTVAL (operands[3]) == -INTVAL (operands[2])"
   [(const_int 0)]
   {
     emit_insn (gen_sub<mode>3_compare1_imm (operands[0], operands[1],
-                                        operands[2], operands[3]));
+                                        operands[3], operands[2]));
     DONE;
   }
 )
   [(set_attr "type" "adc_reg")]
 )
 
-(define_expand "sub<mode>3_carryinCV"
+(define_expand "usub<GPI:mode>3_carryinC"
   [(parallel
      [(set (reg:CC CC_REGNUM)
           (compare:CC
-            (sign_extend:<DWI>
+            (zero_extend:<DWI>
               (match_operand:GPI 1 "aarch64_reg_or_zero" ""))
             (plus:<DWI>
-              (sign_extend:<DWI>
+              (zero_extend:<DWI>
                 (match_operand:GPI 2 "register_operand" ""))
               (ltu:<DWI> (reg:CC CC_REGNUM) (const_int 0)))))
       (set (match_operand:GPI 0 "register_operand" "")
    ""
 )
 
-(define_insn "*sub<mode>3_carryinCV_z1_z2"
-  [(set (reg:CC CC_REGNUM)
-       (compare:CC
-         (const_int 0)
-         (match_operand:<DWI> 2 "aarch64_borrow_operation" "")))
-   (set (match_operand:GPI 0 "register_operand" "=r")
-       (neg:GPI (match_operand:GPI 1 "aarch64_borrow_operation" "")))]
-   ""
-   "sbcs\\t%<w>0, <w>zr, <w>zr"
-  [(set_attr "type" "adc_reg")]
-)
-
-(define_insn "*sub<mode>3_carryinCV_z1"
+(define_insn "*usub<GPI:mode>3_carryinC_z1"
   [(set (reg:CC CC_REGNUM)
        (compare:CC
          (const_int 0)
          (plus:<DWI>
-           (sign_extend:<DWI>
+           (zero_extend:<DWI>
              (match_operand:GPI 1 "register_operand" "r"))
            (match_operand:<DWI> 2 "aarch64_borrow_operation" ""))))
    (set (match_operand:GPI 0 "register_operand" "=r")
   [(set_attr "type" "adc_reg")]
 )
 
-(define_insn "*sub<mode>3_carryinCV_z2"
+(define_insn "*usub<GPI:mode>3_carryinC_z2"
   [(set (reg:CC CC_REGNUM)
        (compare:CC
-         (sign_extend:<DWI>
+         (zero_extend:<DWI>
            (match_operand:GPI 1 "register_operand" "r"))
          (match_operand:<DWI> 2 "aarch64_borrow_operation" "")))
    (set (match_operand:GPI 0 "register_operand" "=r")
   [(set_attr "type" "adc_reg")]
 )
 
-(define_insn "*sub<mode>3_carryinCV"
+(define_insn "*usub<GPI:mode>3_carryinC"
   [(set (reg:CC CC_REGNUM)
        (compare:CC
-         (sign_extend:<DWI>
+         (zero_extend:<DWI>
            (match_operand:GPI 1 "register_operand" "r"))
          (plus:<DWI>
-           (sign_extend:<DWI>
+           (zero_extend:<DWI>
              (match_operand:GPI 2 "register_operand" "r"))
            (match_operand:<DWI> 3 "aarch64_borrow_operation" ""))))
    (set (match_operand:GPI 0 "register_operand" "=r")
   [(set_attr "type" "adc_reg")]
 )
 
+(define_expand "sub<GPI:mode>3_carryinV"
+  [(parallel
+     [(set (reg:CC_V CC_REGNUM)
+          (compare:CC_V
+           (minus:<DWI>
+            (sign_extend:<DWI>
+              (match_operand:GPI 1 "aarch64_reg_or_zero" ""))
+            (plus:<DWI>
+              (sign_extend:<DWI>
+                (match_operand:GPI 2 "register_operand" ""))
+              (ltu:<DWI> (reg:CC CC_REGNUM) (const_int 0))))
+           (sign_extend:<DWI>
+            (minus:GPI (match_dup 1)
+                       (plus:GPI (ltu:GPI (reg:CC CC_REGNUM) (const_int 0))
+                                 (match_dup 2))))))
+      (set (match_operand:GPI 0 "register_operand" "")
+          (minus:GPI
+            (minus:GPI (match_dup 1) (match_dup 2))
+            (ltu:GPI (reg:CC CC_REGNUM) (const_int 0))))])]
+   ""
+)
+
+(define_insn "*sub<mode>3_carryinV_z2"
+  [(set (reg:CC_V CC_REGNUM)
+       (compare:CC_V
+        (minus:<DWI>
+         (sign_extend:<DWI> (match_operand:GPI 1 "register_operand" "r"))
+         (match_operand:<DWI> 2 "aarch64_borrow_operation" ""))
+        (sign_extend:<DWI>
+         (minus:GPI (match_dup 1)
+                    (match_operand:GPI 3 "aarch64_borrow_operation" "")))))
+   (set (match_operand:GPI 0 "register_operand" "=r")
+       (minus:GPI
+        (match_dup 1) (match_dup 3)))]
+   ""
+   "sbcs\\t%<w>0, %<w>1, <w>zr"
+  [(set_attr "type" "adc_reg")]
+)
+
+(define_insn "*sub<mode>3_carryinV"
+  [(set (reg:CC_V CC_REGNUM)
+       (compare:CC_V
+        (minus:<DWI>
+         (sign_extend:<DWI>
+           (match_operand:GPI 1 "register_operand" "r"))
+         (plus:<DWI>
+           (sign_extend:<DWI>
+             (match_operand:GPI 2 "register_operand" "r"))
+           (match_operand:<DWI> 3 "aarch64_borrow_operation" "")))
+        (sign_extend:<DWI>
+         (minus:GPI
+          (match_dup 1)
+          (plus:GPI (match_operand:GPI 4 "aarch64_borrow_operation" "")
+                    (match_dup 2))))))
+   (set (match_operand:GPI 0 "register_operand" "=r")
+       (minus:GPI
+         (minus:GPI (match_dup 1) (match_dup 2))
+         (match_dup 4)))]
+   ""
+   "sbcs\\t%<w>0, %<w>1, %<w>2"
+  [(set_attr "type" "adc_reg")]
+)
+
 (define_insn "*sub_uxt<mode>_shift2"
   [(set (match_operand:GPI 0 "register_operand" "=rk")
        (minus:GPI (match_operand:GPI 4 "register_operand" "rk")
index 0dc5707e7b78608f41516c3f461d601834f893c1..13d8c065b1188541781193e532d68d9c5a7baa9a 100644 (file)
@@ -1,3 +1,8 @@
+2019-01-07  Richard Earnshaw  <rearnsha@arm.com>
+
+       * gcc.target/aarch64/subs_compare_2.c: Make '#' immediate prefix
+       optional in scan pattern.
+
 2019-01-07  Richard Sandiford  <richard.sandiford@arm.com>
 
        PR tree-optimization/88598
index 60c6d9e5ccd8fce42c388c831a8060dead128491..41a256619b7ed0326ac4653af6e2e1d58e949b4b 100644 (file)
@@ -11,5 +11,5 @@ foo (int a, int b)
     return 0;
 }
 
-/* { dg-final { scan-assembler-times "subs\\tw\[0-9\]+, w\[0-9\]+, #4" 1 } } */
+/* { dg-final { scan-assembler-times "subs\\tw\[0-9\]+, w\[0-9\]+, \[#\]?4" 1 } } */
 /* { dg-final { scan-assembler-not "cmp\\tw\[0-9\]+, w\[0-9\]+" } } */