aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/aarch64/aarch64.md
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/aarch64/aarch64.md')
-rw-r--r--gcc/config/aarch64/aarch64.md300
1 files changed, 191 insertions, 109 deletions
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index e946b23ec52..cdf7b482f74 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -1703,7 +1703,7 @@
""
{
rtx low = gen_reg_rtx (DImode);
- emit_insn (gen_adddi3_compare0 (low, gen_lowpart (DImode, operands[1]),
+ emit_insn (gen_adddi3_compareC (low, gen_lowpart (DImode, operands[1]),
gen_lowpart (DImode, operands[2])));
rtx high = gen_reg_rtx (DImode);
@@ -1748,6 +1748,71 @@
[(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
)
+(define_insn "*add<mode>3_compareC_cconly_imm"
+ [(set (reg:CC_C CC_REGNUM)
+ (ne:CC_C
+ (plus:<DWI>
+ (zero_extend:<DWI> (match_operand:GPI 0 "register_operand" "r,r"))
+ (match_operand:<DWI> 2 "const_scalar_int_operand" ""))
+ (zero_extend:<DWI>
+ (plus:GPI
+ (match_dup 0)
+ (match_operand:GPI 1 "aarch64_plus_immediate" "I,J")))))]
+ "aarch64_zero_extend_const_eq (<DWI>mode, operands[2],
+ <MODE>mode, operands[1])"
+ "@
+ cmn\\t%<w>0, %<w>1
+ cmp\\t%<w>0, #%n1"
+ [(set_attr "type" "alus_imm")]
+)
+
+(define_insn "*add<mode>3_compareC_cconly"
+ [(set (reg:CC_C CC_REGNUM)
+ (ne:CC_C
+ (plus:<DWI>
+ (zero_extend:<DWI> (match_operand:GPI 0 "register_operand" "r"))
+ (zero_extend:<DWI> (match_operand:GPI 1 "register_operand" "r")))
+ (zero_extend:<DWI> (plus:GPI (match_dup 0) (match_dup 1)))))]
+ ""
+ "cmn\\t%<w>0, %<w>1"
+ [(set_attr "type" "alus_sreg")]
+)
+
+(define_insn "*add<mode>3_compareC_imm"
+ [(set (reg:CC_C CC_REGNUM)
+ (ne:CC_C
+ (plus:<DWI>
+ (zero_extend:<DWI> (match_operand:GPI 1 "register_operand" "r,r"))
+ (match_operand:<DWI> 3 "const_scalar_int_operand" ""))
+ (zero_extend:<DWI>
+ (plus:GPI
+ (match_dup 1)
+ (match_operand:GPI 2 "aarch64_plus_immediate" "I,J")))))
+ (set (match_operand:GPI 0 "register_operand" "=r,r")
+ (plus:GPI (match_dup 1) (match_dup 2)))]
+ "aarch64_zero_extend_const_eq (<DWI>mode, operands[3],
+ <MODE>mode, operands[2])"
+ "@
+ adds\\t%<w>0, %<w>1, %<w>2
+ subs\\t%<w>0, %<w>1, #%n2"
+ [(set_attr "type" "alus_imm")]
+)
+
+(define_insn "add<mode>3_compareC"
+ [(set (reg:CC_C CC_REGNUM)
+ (ne:CC_C
+ (plus:<DWI>
+ (zero_extend:<DWI> (match_operand:GPI 1 "register_operand" "r"))
+ (zero_extend:<DWI> (match_operand:GPI 2 "register_operand" "r")))
+ (zero_extend:<DWI>
+ (plus:GPI (match_dup 1) (match_dup 2)))))
+ (set (match_operand:GPI 0 "register_operand" "=r")
+ (plus:GPI (match_dup 1) (match_dup 2)))]
+ ""
+ "adds\\t%<w>0, %<w>1, %<w>2"
+ [(set_attr "type" "alus_sreg")]
+)
+
(define_insn "*adds_shift_imm_<mode>"
[(set (reg:CC_NZ CC_REGNUM)
(compare:CC_NZ
@@ -2067,105 +2132,41 @@
[(set_attr "type" "alu_ext")]
)
-(define_insn "add<mode>3_carryin"
- [(set
- (match_operand:GPI 0 "register_operand" "=r")
- (plus:GPI (geu:GPI (reg:CC CC_REGNUM) (const_int 0))
- (plus:GPI
- (match_operand:GPI 1 "register_operand" "r")
- (match_operand:GPI 2 "register_operand" "r"))))]
- ""
- "adc\\t%<w>0, %<w>1, %<w>2"
- [(set_attr "type" "adc_reg")]
-)
-
-;; zero_extend version of above
-(define_insn "*addsi3_carryin_uxtw"
- [(set
- (match_operand:DI 0 "register_operand" "=r")
- (zero_extend:DI
- (plus:SI (geu:SI (reg:CC CC_REGNUM) (const_int 0))
- (plus:SI
- (match_operand:SI 1 "register_operand" "r")
- (match_operand:SI 2 "register_operand" "r")))))]
- ""
- "adc\\t%w0, %w1, %w2"
- [(set_attr "type" "adc_reg")]
-)
-
-(define_insn "*add<mode>3_carryin_alt1"
- [(set
- (match_operand:GPI 0 "register_operand" "=r")
- (plus:GPI (plus:GPI
- (match_operand:GPI 1 "register_operand" "r")
- (match_operand:GPI 2 "register_operand" "r"))
- (geu:GPI (reg:CC CC_REGNUM) (const_int 0))))]
+(define_expand "add<mode>3_carryin"
+ [(set (match_operand:GPI 0 "register_operand")
+ (plus:GPI
+ (plus:GPI
+ (ne:GPI (reg:CC_C CC_REGNUM) (const_int 0))
+ (match_operand:GPI 1 "aarch64_reg_or_zero"))
+ (match_operand:GPI 2 "aarch64_reg_or_zero")))]
""
- "adc\\t%<w>0, %<w>1, %<w>2"
- [(set_attr "type" "adc_reg")]
-)
-
-;; zero_extend version of above
-(define_insn "*addsi3_carryin_alt1_uxtw"
- [(set
- (match_operand:DI 0 "register_operand" "=r")
- (zero_extend:DI
- (plus:SI (plus:SI
- (match_operand:SI 1 "register_operand" "r")
- (match_operand:SI 2 "register_operand" "r"))
- (geu:SI (reg:CC CC_REGNUM) (const_int 0)))))]
""
- "adc\\t%w0, %w1, %w2"
- [(set_attr "type" "adc_reg")]
)
-(define_insn "*add<mode>3_carryin_alt2"
- [(set
- (match_operand:GPI 0 "register_operand" "=r")
- (plus:GPI (plus:GPI
- (geu:GPI (reg:CC CC_REGNUM) (const_int 0))
- (match_operand:GPI 1 "register_operand" "r"))
- (match_operand:GPI 2 "register_operand" "r")))]
- ""
- "adc\\t%<w>0, %<w>1, %<w>2"
- [(set_attr "type" "adc_reg")]
-)
+;; Note that add with carry with two zero inputs is matched by cset,
+;; and that add with carry with one zero input is matched by cinc.
-;; zero_extend version of above
-(define_insn "*addsi3_carryin_alt2_uxtw"
- [(set
- (match_operand:DI 0 "register_operand" "=r")
- (zero_extend:DI
- (plus:SI (plus:SI
- (geu:SI (reg:CC CC_REGNUM) (const_int 0))
- (match_operand:SI 1 "register_operand" "r"))
- (match_operand:SI 2 "register_operand" "r"))))]
- ""
- "adc\\t%w0, %w1, %w2"
- [(set_attr "type" "adc_reg")]
-)
-
-(define_insn "*add<mode>3_carryin_alt3"
- [(set
- (match_operand:GPI 0 "register_operand" "=r")
- (plus:GPI (plus:GPI
- (geu:GPI (reg:CC CC_REGNUM) (const_int 0))
- (match_operand:GPI 2 "register_operand" "r"))
- (match_operand:GPI 1 "register_operand" "r")))]
+(define_insn "*add<mode>3_carryin"
+ [(set (match_operand:GPI 0 "register_operand" "=r")
+ (plus:GPI
+ (plus:GPI
+ (match_operand:GPI 3 "aarch64_carry_operation" "")
+ (match_operand:GPI 1 "register_operand" "r"))
+ (match_operand:GPI 2 "register_operand" "r")))]
""
"adc\\t%<w>0, %<w>1, %<w>2"
[(set_attr "type" "adc_reg")]
)
;; zero_extend version of above
-(define_insn "*addsi3_carryin_alt3_uxtw"
- [(set
- (match_operand:DI 0 "register_operand" "=r")
- (zero_extend:DI
- (plus:SI (plus:SI
- (geu:SI (reg:CC CC_REGNUM) (const_int 0))
- (match_operand:SI 2 "register_operand" "r"))
- (match_operand:SI 1 "register_operand" "r"))))]
+(define_insn "*addsi3_carryin_uxtw"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (zero_extend:DI
+ (plus:SI
+ (plus:SI
+ (match_operand:SI 3 "aarch64_carry_operation" "")
+ (match_operand:SI 1 "register_operand" "r"))
+ (match_operand:SI 2 "register_operand" "r"))))]
""
"adc\\t%w0, %w1, %w2"
[(set_attr "type" "adc_reg")]
@@ -2274,7 +2275,7 @@
""
{
rtx low = gen_reg_rtx (DImode);
- emit_insn (gen_subdi3_compare0 (low, gen_lowpart (DImode, operands[1]),
+ emit_insn (gen_subdi3_compare1 (low, gen_lowpart (DImode, operands[1]),
gen_lowpart (DImode, operands[2])));
rtx high = gen_reg_rtx (DImode);
@@ -2286,7 +2287,7 @@
DONE;
})
-(define_insn "sub<mode>3_compare0"
+(define_insn "*sub<mode>3_compare0"
[(set (reg:CC_NZ CC_REGNUM)
(compare:CC_NZ (minus:GPI (match_operand:GPI 1 "register_operand" "r")
(match_operand:GPI 2 "register_operand" "r"))
@@ -2311,6 +2312,18 @@
[(set_attr "type" "alus_sreg")]
)
+(define_insn "sub<mode>3_compare1"
+ [(set (reg:CC CC_REGNUM)
+ (compare:CC
+ (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
+ (match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")))
+ (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 "*sub_<shift>_<mode>"
[(set (match_operand:GPI 0 "register_operand" "=r")
(minus:GPI (match_operand:GPI 3 "register_operand" "r")
@@ -2433,13 +2446,53 @@
[(set_attr "type" "alu_ext")]
)
-(define_insn "sub<mode>3_carryin"
- [(set
- (match_operand:GPI 0 "register_operand" "=r")
- (minus:GPI (minus:GPI
- (match_operand:GPI 1 "register_operand" "r")
- (ltu:GPI (reg:CC CC_REGNUM) (const_int 0)))
- (match_operand:GPI 2 "register_operand" "r")))]
+;; The hardware description is op1 + ~op2 + C.
+;; = op1 + (-op2 + 1) + (1 - !C)
+;; = op1 - op2 - 1 + 1 - !C
+;; = op1 - op2 - !C.
+;; We describe the latter.
+
+(define_insn "*sub<mode>3_carryin0"
+ [(set (match_operand:GPI 0 "register_operand" "=r")
+ (minus:GPI
+ (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
+ (match_operand:GPI 2 "aarch64_borrow_operation" "")))]
+ ""
+ "sbc\\t%<w>0, %<w>1, <w>zr"
+ [(set_attr "type" "adc_reg")]
+)
+
+;; zero_extend version of the above
+(define_insn "*subsi3_carryin_uxtw"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (zero_extend:DI
+ (minus:SI
+ (match_operand:SI 1 "aarch64_reg_or_zero" "rZ")
+ (match_operand:SI 2 "aarch64_borrow_operation" ""))))]
+ ""
+ "sbc\\t%w0, %w1, wzr"
+ [(set_attr "type" "adc_reg")]
+)
+
+(define_expand "sub<mode>3_carryin"
+ [(set (match_operand:GPI 0 "register_operand")
+ (minus:GPI
+ (minus:GPI
+ (match_operand:GPI 1 "aarch64_reg_or_zero")
+ (match_operand:GPI 2 "register_operand"))
+ (ltu:GPI (reg:CC CC_REGNUM) (const_int 0))))]
+ ""
+ ""
+)
+
+(define_insn "*sub<mode>3_carryin"
+ [(set (match_operand:GPI 0 "register_operand" "=r")
+ (minus:GPI
+ (minus:GPI
+ (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
+ (match_operand:GPI 2 "register_operand" "r"))
+ (match_operand:GPI 3 "aarch64_borrow_operation" "")))]
+
""
"sbc\\t%<w>0, %<w>1, %<w>2"
[(set_attr "type" "adc_reg")]
@@ -2447,13 +2500,40 @@
;; zero_extend version of the above
(define_insn "*subsi3_carryin_uxtw"
- [(set
- (match_operand:DI 0 "register_operand" "=r")
- (zero_extend:DI
- (minus:SI (minus:SI
- (match_operand:SI 1 "register_operand" "r")
- (ltu:SI (reg:CC CC_REGNUM) (const_int 0)))
- (match_operand:SI 2 "register_operand" "r"))))]
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (zero_extend:DI
+ (minus:SI
+ (minus:SI
+ (match_operand:SI 1 "aarch64_reg_or_zero" "rZ")
+ (match_operand:SI 2 "register_operand" "r"))
+ (match_operand:SI 3 "aarch64_borrow_operation" ""))))]
+
+ ""
+ "sbc\\t%w0, %w1, %w2"
+ [(set_attr "type" "adc_reg")]
+)
+
+(define_insn "*sub<mode>3_carryin_alt"
+ [(set (match_operand:GPI 0 "register_operand" "=r")
+ (minus:GPI
+ (minus:GPI
+ (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
+ (match_operand:GPI 3 "aarch64_borrow_operation" ""))
+ (match_operand:GPI 2 "register_operand" "r")))]
+ ""
+ "sbc\\t%<w>0, %<w>1, %<w>2"
+ [(set_attr "type" "adc_reg")]
+)
+
+;; zero_extend version of the above
+(define_insn "*subsi3_carryin_alt_uxtw"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (zero_extend:DI
+ (minus:SI
+ (minus:SI
+ (match_operand:SI 1 "aarch64_reg_or_zero" "rZ")
+ (match_operand:SI 3 "aarch64_borrow_operation" ""))
+ (match_operand:SI 2 "register_operand" "r"))))]
""
"sbc\\t%w0, %w1, %w2"
[(set_attr "type" "adc_reg")]
@@ -2557,8 +2637,9 @@
(define_insn "*ngc<mode>"
[(set (match_operand:GPI 0 "register_operand" "=r")
- (minus:GPI (neg:GPI (ltu:GPI (reg:CC CC_REGNUM) (const_int 0)))
- (match_operand:GPI 1 "register_operand" "r")))]
+ (minus:GPI
+ (neg:GPI (match_operand:GPI 2 "aarch64_borrow_operation" ""))
+ (match_operand:GPI 1 "register_operand" "r")))]
""
"ngc\\t%<w>0, %<w>1"
[(set_attr "type" "adc_reg")]
@@ -2567,8 +2648,9 @@
(define_insn "*ngcsi_uxtw"
[(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI
- (minus:SI (neg:SI (ltu:SI (reg:CC CC_REGNUM) (const_int 0)))
- (match_operand:SI 1 "register_operand" "r"))))]
+ (minus:SI
+ (neg:SI (match_operand:SI 2 "aarch64_borrow_operation" ""))
+ (match_operand:SI 1 "register_operand" "r"))))]
""
"ngc\\t%w0, %w1"
[(set_attr "type" "adc_reg")]