@@ -16098,7 +16098,13 @@ aarch64_sve_prepare_conditional_op (rtx *operands, unsigned int nops,
whereas selecting the input avoids the MOVPRFX:
SEL Z0.S, P1, Z2.S, Z4.S
- ADD Z0.S, P1/M, Z0.S, Z3.S. */
+ ADD Z0.S, P1/M, Z0.S, Z3.S.
+
+ ??? Matching the other input can produce
+
+ MOVPRFX Z4.S, P1/M, Z2.S
+ ADD Z4.S, P1/M, Z4.S, Z3.S
+ */
machine_mode mode = GET_MODE (operands[0]);
rtx temp = gen_reg_rtx (mode);
rtvec vec = gen_rtvec (3, operands[1], operands[2], operands[nops - 1]);
@@ -1841,57 +1841,108 @@
})
;; Predicated integer operations.
-(define_insn "*cond_<optab><mode>"
- [(set (match_operand:SVE_I 0 "register_operand" "=w")
+;; All other things being equal, prefer the patterns for which the
+;; destination matches the select input, as that gives us the most
+;; freedom to swap the other operands.
+
+(define_insn "*cond_<optab><mode>_0"
+ [(set (match_operand:SVE_I 0 "register_operand" "+w, w, ?&w")
(unspec:SVE_I
- [(match_operand:<VPRED> 1 "register_operand" "Upl")
+ [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl, Upl")
(SVE_INT_BINARY:SVE_I
- (match_operand:SVE_I 2 "register_operand" "0")
- (match_operand:SVE_I 3 "register_operand" "w"))
- (match_dup 2)]
+ (match_operand:SVE_I 2 "register_operand" "0, w, w")
+ (match_operand:SVE_I 3 "register_operand" "w, 0, w"))
+ (match_dup 0)]
UNSPEC_SEL))]
"TARGET_SVE"
- "<sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>"
+ "@
+ <sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
+ <sve_int_op_rev>\t%0.<Vetype>, %1/m, %0.<Vetype>, %2.<Vetype>
+ movprfx\t%0, %1/m, %2\;<sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>"
+ [(set_attr "movprfx" "*,*,yes")]
)
-(define_insn "*cond_<optab><mode>"
- [(set (match_operand:SVE_SDI 0 "register_operand" "=w")
+(define_insn "*cond_<optab><mode>_0"
+ [(set (match_operand:SVE_SDI 0 "register_operand" "+w, w, ?&w")
(unspec:SVE_SDI
- [(match_operand:<VPRED> 1 "register_operand" "Upl")
+ [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl, Upl")
(SVE_INT_BINARY_SD:SVE_SDI
- (match_operand:SVE_SDI 2 "register_operand" "0")
- (match_operand:SVE_SDI 3 "register_operand" "w"))
- (match_dup 2)]
+ (match_operand:SVE_SDI 2 "register_operand" "0, w, w")
+ (match_operand:SVE_SDI 3 "register_operand" "w, 0, w"))
+ (match_dup 0)]
UNSPEC_SEL))]
"TARGET_SVE"
- "<sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>"
+ "@
+ <sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
+ <sve_int_op_rev>\t%0.<Vetype>, %1/m, %0.<Vetype>, %2.<Vetype>
+ movprfx\t%0, %1/m, %2\;<sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>"
+ [(set_attr "movprfx" "*,*,yes")]
)
-;; Predicated integer operations with the operands reversed.
-(define_insn "*cond_<optab><mode>"
- [(set (match_operand:SVE_I 0 "register_operand" "=w")
+;; Predicated integer operations with select matching the first operand.
+(define_insn "*cond_<optab><mode>_2"
+ [(set (match_operand:SVE_I 0 "register_operand" "=w, ?&w")
(unspec:SVE_I
- [(match_operand:<VPRED> 1 "register_operand" "Upl")
- (SVE_INT_BINARY_REV:SVE_I
- (match_operand:SVE_I 2 "register_operand" "w")
- (match_operand:SVE_I 3 "register_operand" "0"))
- (match_dup 3)]
+ [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
+ (SVE_INT_BINARY:SVE_I
+ (match_operand:SVE_I 2 "register_operand" "0, w")
+ (match_operand:SVE_I 3 "register_operand" "w, w"))
+ (match_dup 2)]
UNSPEC_SEL))]
"TARGET_SVE"
- "<sve_int_op>r\t%0.<Vetype>, %1/m, %0.<Vetype>, %2.<Vetype>"
+ "@
+ <sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
+ movprfx\t%0, %2\;<sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>"
+ [(set_attr "movprfx" "*,yes")]
)
-(define_insn "*cond_<optab><mode>"
- [(set (match_operand:SVE_SDI 0 "register_operand" "=w")
+(define_insn "*cond_<optab><mode>_2"
+ [(set (match_operand:SVE_SDI 0 "register_operand" "=w, ?&w")
(unspec:SVE_SDI
- [(match_operand:<VPRED> 1 "register_operand" "Upl")
+ [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
(SVE_INT_BINARY_SD:SVE_SDI
- (match_operand:SVE_SDI 2 "register_operand" "w")
- (match_operand:SVE_SDI 3 "register_operand" "0"))
+ (match_operand:SVE_SDI 2 "register_operand" "0, w")
+ (match_operand:SVE_SDI 3 "register_operand" "w, w"))
+ (match_dup 2)]
+ UNSPEC_SEL))]
+ "TARGET_SVE"
+ "@
+ <sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
+ movprfx\t%0, %2\;<sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>"
+ [(set_attr "movprfx" "*,yes")]
+)
+
+;; Predicated integer operations with select matching the second operand.
+(define_insn "*cond_<optab><mode>_3"
+ [(set (match_operand:SVE_I 0 "register_operand" "=w, ?&w")
+ (unspec:SVE_I
+ [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
+ (SVE_INT_BINARY:SVE_I
+ (match_operand:SVE_I 2 "register_operand" "w, w")
+ (match_operand:SVE_I 3 "register_operand" "0, w"))
(match_dup 3)]
UNSPEC_SEL))]
"TARGET_SVE"
- "<sve_int_op>r\t%0.<Vetype>, %1/m, %0.<Vetype>, %2.<Vetype>"
+ "@
+ <sve_int_op_rev>\t%0.<Vetype>, %1/m, %0.<Vetype>, %2.<Vetype>
+ movprfx\t%0, %3\;<sve_int_op_rev>\t%0.<Vetype>, %1/m, %0.<Vetype>, %2.<Vetype>"
+ [(set_attr "movprfx" "*,yes")]
+)
+
+(define_insn "*cond_<optab><mode>_3"
+ [(set (match_operand:SVE_SDI 0 "register_operand" "=w, ?&w")
+ (unspec:SVE_SDI
+ [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
+ (SVE_INT_BINARY_SD:SVE_SDI
+ (match_operand:SVE_SDI 2 "register_operand" "w, w")
+ (match_operand:SVE_SDI 3 "register_operand" "0, w"))
+ (match_dup 3)]
+ UNSPEC_SEL))]
+ "TARGET_SVE"
+ "@
+ <sve_int_op_rev>\t%0.<Vetype>, %1/m, %0.<Vetype>, %2.<Vetype>
+ movprfx\t%0, %3\;<sve_int_op_rev>\t%0.<Vetype>, %1/m, %0.<Vetype>, %2.<Vetype>"
+ [(set_attr "movprfx" "*,yes")]
)
;; Set operand 0 to the last active element in operand 3, or to tied
@@ -2687,34 +2738,60 @@
aarch64_sve_prepare_conditional_op (operands, 5, <commutative>);
})
-;; Predicated floating-point operations.
-(define_insn "*cond_<optab><mode>"
- [(set (match_operand:SVE_F 0 "register_operand" "=w")
+;; Predicated floating-point operations with select matching output.
+(define_insn "*cond_<optab><mode>_0"
+ [(set (match_operand:SVE_F 0 "register_operand" "+w, w, ?&w")
(unspec:SVE_F
- [(match_operand:<VPRED> 1 "register_operand" "Upl")
+ [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl, Upl")
(unspec:SVE_F
- [(match_operand:SVE_F 2 "register_operand" "0")
- (match_operand:SVE_F 3 "register_operand" "w")]
+ [(match_dup 1)
+ (match_operand:SVE_F 2 "register_operand" "0, w, w")
+ (match_operand:SVE_F 3 "register_operand" "w, 0, w")]
+ SVE_COND_FP_BINARY)
+ (match_dup 0)]
+ UNSPEC_SEL))]
+ "TARGET_SVE"
+ "@
+ <sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
+ <sve_fp_op_rev>\t%0.<Vetype>, %1/m, %0.<Vetype>, %2.<Vetype>
+ movprfx\t%0, %1/m, %2\;<sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>"
+ [(set_attr "movprfx" "*,*,yes")]
+)
+
+;; Predicated floating-point operations with select matching first operand.
+(define_insn "*cond_<optab><mode>_2"
+ [(set (match_operand:SVE_F 0 "register_operand" "=w, ?&w")
+ (unspec:SVE_F
+ [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
+ (unspec:SVE_F
+ [(match_operand:SVE_F 2 "register_operand" "0, w")
+ (match_operand:SVE_F 3 "register_operand" "w, w")]
SVE_COND_FP_BINARY)
(match_dup 2)]
UNSPEC_SEL))]
"TARGET_SVE"
- "<sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>"
+ "@
+ <sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
+ movprfx\t%0, %2\;<sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>"
+ [(set_attr "movprfx" "*,yes")]
)
-;; Predicated floating-point operations with the operands reversed.
-(define_insn "*cond_<optab><mode>"
- [(set (match_operand:SVE_F 0 "register_operand" "=w")
+;; Predicated floating-point operations with select matching second operand.
+(define_insn "*cond_<optab><mode>_3"
+ [(set (match_operand:SVE_F 0 "register_operand" "=w, ?&w")
(unspec:SVE_F
- [(match_operand:<VPRED> 1 "register_operand" "Upl")
+ [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
(unspec:SVE_F
- [(match_operand:SVE_F 2 "register_operand" "w")
- (match_operand:SVE_F 3 "register_operand" "0")]
+ [(match_operand:SVE_F 2 "register_operand" "w, w")
+ (match_operand:SVE_F 3 "register_operand" "0, w")]
SVE_COND_FP_BINARY)
(match_dup 3)]
UNSPEC_SEL))]
"TARGET_SVE"
- "<sve_fp_op>r\t%0.<Vetype>, %1/m, %0.<Vetype>, %2.<Vetype>"
+ "@
+ <sve_fp_op_rev>\t%0.<Vetype>, %1/m, %0.<Vetype>, %2.<Vetype>
+ movprfx\t%0, %3\;<sve_fp_op_rev>\t%0.<Vetype>, %1/m, %0.<Vetype>, %2.<Vetype>"
+ [(set_attr "movprfx" "*,yes")]
)
;; Shift an SVE vector left and insert a scalar into element 0.
@@ -1207,11 +1207,11 @@
;; SVE floating-point unary operations.
(define_code_iterator SVE_FP_UNARY [neg abs sqrt])
+;; SVE integer binary operations.
(define_code_iterator SVE_INT_BINARY [plus minus mult smax umax smin umin
and ior xor])
-(define_code_iterator SVE_INT_BINARY_REV [minus])
-
+;; SVE integer binary division operations.
(define_code_iterator SVE_INT_BINARY_SD [div udiv])
;; SVE integer comparisons.
@@ -1402,6 +1402,19 @@
(not "not")
(popcount "cnt")])
+(define_code_attr sve_int_op_rev [(plus "add")
+ (minus "subr")
+ (mult "mul")
+ (div "sdivr")
+ (udiv "udivr")
+ (smin "smin")
+ (smax "smax")
+ (umin "umin")
+ (umax "umax")
+ (and "and")
+ (ior "orr")
+ (xor "eor")])
+
;; The floating-point SVE instruction that implements an rtx code.
(define_code_attr sve_fp_op [(plus "fadd")
(neg "fneg")
@@ -1550,8 +1563,6 @@
UNSPEC_COND_MUL UNSPEC_COND_DIV
UNSPEC_COND_MAX UNSPEC_COND_MIN])
-(define_int_iterator SVE_COND_FP_BINARY_REV [UNSPEC_COND_SUB UNSPEC_COND_DIV])
-
(define_int_iterator SVE_COND_FP_CMP [UNSPEC_COND_LT UNSPEC_COND_LE
UNSPEC_COND_EQ UNSPEC_COND_NE
UNSPEC_COND_GE UNSPEC_COND_GT])
@@ -1802,6 +1813,13 @@
(UNSPEC_COND_MAX "fmaxnm")
(UNSPEC_COND_MIN "fminnm")])
+(define_int_attr sve_fp_op_rev [(UNSPEC_COND_ADD "fadd")
+ (UNSPEC_COND_SUB "fsubr")
+ (UNSPEC_COND_MUL "fmul")
+ (UNSPEC_COND_DIV "fdivr")
+ (UNSPEC_COND_MAX "fmaxnm")
+ (UNSPEC_COND_MIN "fminnm")])
+
(define_int_attr commutative [(UNSPEC_COND_ADD "true")
(UNSPEC_COND_SUB "false")
(UNSPEC_COND_MUL "true")