]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Investigating PR target/86891 revealed a number of issues with the way
authorrearnsha <rearnsha@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 7 Jan 2019 14:49:00 +0000 (14:49 +0000)
committerrearnsha <rearnsha@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 7 Jan 2019 14:49:00 +0000 (14:49 +0000)
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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@267650 138bc75d-0d04-0410-961f-82ee72b054a4

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\]+" } } */