@@ -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. */
@@ -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);
@@ -1842,11 +1842,15 @@ (define_split
(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;
@@ -2093,7 +2097,7 @@ (define_insn "*add<mode>3_compareV_cconly"
[(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>
@@ -2723,19 +2727,109 @@ (define_insn "subdi3"
(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")
@@ -2771,7 +2865,7 @@ (define_expand "subti3"
(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 "" ""))]
""
@@ -2782,7 +2876,7 @@ (define_expand "subvti4"
&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;
@@ -2790,7 +2884,7 @@ (define_expand "subvti4"
(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 "" ""))]
""
@@ -2801,12 +2895,56 @@ (define_expand "usubvti4"
&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")
@@ -2832,7 +2970,7 @@ (define_insn "*subsi3_compare0_uxtw"
[(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")
@@ -2843,8 +2981,8 @@ (define_insn "*sub<mode>3_compare1_imm"
(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")]
)
@@ -2860,19 +2998,6 @@ (define_insn "sub<mode>3_compare1"
[(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")
@@ -2914,7 +3039,7 @@ (define_peephole2
(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)
@@ -2924,7 +3049,7 @@ (define_peephole2
[(const_int 0)]
{
emit_insn (gen_sub<mode>3_compare1_imm (operands[0], operands[1],
- operands[2], operands[3]));
+ operands[3], operands[2]));
DONE;
}
)
@@ -2939,12 +3064,12 @@ (define_peephole2
(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;
}
)
@@ -3164,14 +3289,14 @@ (define_insn "*subsi3_carryin_alt_uxtw"
[(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" "")
@@ -3181,24 +3306,12 @@ (define_expand "sub<mode>3_carryinCV"
""
)
-(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")
@@ -3210,10 +3323,10 @@ (define_insn "*sub<mode>3_carryinCV_z1"
[(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")
@@ -3225,13 +3338,13 @@ (define_insn "*sub<mode>3_carryinCV_z2"
[(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")
@@ -3243,6 +3356,69 @@ (define_insn "*sub<mode>3_carryinCV"
[(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")
@@ -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\]+" } } */