[arm] Add alternative canonicalizations for subtract-with-carry + shift
authorRichard Earnshaw <rearnsha@arm.com>
Fri, 18 Oct 2019 19:03:19 +0000 (19:03 +0000)
committerRichard Earnshaw <rearnsha@gcc.gnu.org>
Fri, 18 Oct 2019 19:03:19 +0000 (19:03 +0000)
This patch adds a couple of alternative canonicalizations to allow
combine to match a subtract-with-carry operation when one of the operands
is shifted first.  The most common case of this is when combining a
sign-extend of one operand with a long-long value during subtraction.
The RSC variant is only enabled for Arm, the SBC variant for any 32-bit
compilation.

* config/arm/arm.md (subsi3_carryin_shift_alt): New pattern.
(rsbsi3_carryin_shift_alt): Likewise.

From-SVN: r277176

gcc/ChangeLog
gcc/config/arm/arm.md

index 4d2812a08937cc8b2758135987be17d8aa9ed5f3..393fcbdcfff74f70a76346d9ce4dc9a2d87b1ba4 100644 (file)
@@ -1,3 +1,8 @@
+2019-10-18  Richard Earnshaw  <rearnsha@arm.com>
+
+       * config/arm/arm.md (subsi3_carryin_shift_alt): New pattern.
+       (rsbsi3_carryin_shift_alt): Likewise.
+
 2019-10-18  Richard Earnshaw  <rearnsha@arm.com>
 
        * config/arm/arm.md (negscc_borrow): New pattern.
index 74f417fbe4b20d390251e70acdeb0a08c6187745..613f50ae5f05283cbf01ad6ab635b5e950c8afcd 100644 (file)
                                    (const_string "alu_shift_reg")))]
 )
 
+(define_insn "*subsi3_carryin_shift_alt"
+  [(set (match_operand:SI 0 "s_register_operand" "=r")
+       (minus:SI (minus:SI
+                  (match_operand:SI 1 "s_register_operand" "r")
+                  (match_operand:SI 5 "arm_borrow_operation" ""))
+                 (match_operator:SI 2 "shift_operator"
+                  [(match_operand:SI 3 "s_register_operand" "r")
+                   (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
+  "TARGET_32BIT"
+  "sbc%?\\t%0, %1, %3%S2"
+  [(set_attr "conds" "use")
+   (set_attr "predicable" "yes")
+   (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
+                                   (const_string "alu_shift_imm")
+                                   (const_string "alu_shift_reg")))]
+)
+
 (define_insn "*rsbsi3_carryin_shift"
   [(set (match_operand:SI 0 "s_register_operand" "=r")
        (minus:SI (minus:SI
                      (const_string "alu_shift_reg")))]
 )
 
+(define_insn "*rsbsi3_carryin_shift_alt"
+  [(set (match_operand:SI 0 "s_register_operand" "=r")
+       (minus:SI (minus:SI
+                  (match_operator:SI 2 "shift_operator"
+                   [(match_operand:SI 3 "s_register_operand" "r")
+                    (match_operand:SI 4 "reg_or_int_operand" "rM")])
+                   (match_operand:SI 5 "arm_borrow_operation" ""))
+                 (match_operand:SI 1 "s_register_operand" "r")))]
+  "TARGET_ARM"
+  "rsc%?\\t%0, %1, %3%S2"
+  [(set_attr "conds" "use")
+   (set_attr "predicable" "yes")
+   (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
+                     (const_string "alu_shift_imm")
+                     (const_string "alu_shift_reg")))]
+)
+
 ; transform ((x << y) - 1) to ~(~(x-1) << y)  Where X is a constant.
 (define_split
   [(set (match_operand:SI 0 "s_register_operand" "")