@@ -81,7 +81,13 @@
;; Return true if OP is a valid operand as scalar shift count or setmem.
-(define_predicate "shift_count_or_setmem_operand"
+;; In the end a shift count operand must always be Pmode (or VOIDmode)
+;; but during expansion we allow also SImode on 64 bit. Otherwise it
+;; would be impossible to e.g. write the rotlsi3 expander which would
+;; require both DI and SI for the shift count depending on the
+;; addressing mode.
+
+(define_predicate "shift_count_or_setmem_operand_expand"
(match_code "reg, subreg, plus, const_int")
{
HOST_WIDE_INT offset;
@@ -109,6 +115,22 @@
return true;
})
+;; Return true if OP is a valid operand as shift count or setmem in
+;; matching patterns.
+
+(define_predicate "shift_count_or_setmem_operand"
+ (and (match_code "reg, subreg, plus, const_int")
+ (match_operand 0 "shift_count_or_setmem_operand_expand"))
+{
+ /* The Y constraint used in conjunction with this predicate is an
+ extra memory constraint and therefore goes through
+ s390_decompose_address. That's why we need Pmode mode here. */
+ if (GET_MODE (op) != VOIDmode && GET_MODE (op) != Pmode)
+ return false;
+
+ return true;
+})
+
(define_predicate "nonzero_shift_count_operand"
(and (match_code "const_int")
(match_test "IN_RANGE (INTVAL (op), 1, GET_MODE_BITSIZE (mode) - 1)")))
@@ -118,6 +118,7 @@ extern rtx_insn *s390_load_got (void);
extern rtx s390_get_thread_pointer (void);
extern void s390_emit_tpf_eh_return (rtx);
extern bool s390_legitimate_address_without_index_p (rtx);
+extern rtx s390_expand_masked_address_operand (rtx, int);
extern bool s390_decompose_shift_count (rtx, rtx *, HOST_WIDE_INT *);
extern int s390_branch_condition_mask (rtx);
extern int s390_compare_and_branch_condition_mask (rtx);
@@ -2757,9 +2757,7 @@ s390_decompose_address (rtx addr, struct s390_address *out)
return false;
}
- if (!REG_P (base)
- || (GET_MODE (base) != SImode
- && GET_MODE (base) != Pmode))
+ if (!REG_P (base) || GET_MODE (base) != Pmode)
return false;
if (REGNO (base) == STACK_POINTER_REGNUM
@@ -2805,9 +2803,7 @@ s390_decompose_address (rtx addr, struct s390_address *out)
return false;
}
- if (!REG_P (indx)
- || (GET_MODE (indx) != SImode
- && GET_MODE (indx) != Pmode))
+ if (!REG_P (indx) || GET_MODE (indx) != Pmode)
return false;
if (REGNO (indx) == STACK_POINTER_REGNUM
@@ -2926,6 +2922,34 @@ s390_decompose_address (rtx addr, struct s390_address *out)
return true;
}
+/* Convert the shift count operand OP to Pmode under the assumption
+ that only the NUM_MASK_BITS lower significant bits are really
+ used. */
+rtx
+s390_expand_masked_address_operand (rtx op, int num_mask_bits)
+{
+ gcc_assert (GET_MODE (op) == VOIDmode
+ || GET_MODE_SIZE (GET_MODE (op)) <= GET_MODE_SIZE (Pmode));
+
+ if (GET_MODE (op) == VOIDmode)
+ return op;
+
+ if (GET_MODE (op) != Pmode)
+ {
+ /* In case we anyway only need at most the bits of the smaller
+ mode we do not need to zero-extend the shift count. */
+ if (num_mask_bits <= GET_MODE_BITSIZE (GET_MODE (op)))
+ op = simplify_gen_subreg (Pmode, op, GET_MODE (op), 0);
+ else
+ op = convert_to_mode (Pmode, op, true);
+ }
+
+ if (num_mask_bits < GET_MODE_BITSIZE (Pmode))
+ op = gen_rtx_AND (Pmode, op,
+ GEN_INT ((HOST_WIDE_INT_1U << num_mask_bits) - 1));
+ return op;
+}
+
/* Decompose a RTL expression OP for a shift count into its components,
and return the base register in BASE and the offset in OFFSET.
@@ -8276,11 +8276,20 @@
; rotl(di|si)3 instruction pattern(s).
;
+(define_expand "rotl<mode>3"
+ [(set (match_operand:GPR 0 "register_operand" "")
+ (rotate:GPR (match_operand:GPR 1 "register_operand" "")
+ (match_operand:SI 2 "shift_count_or_setmem_operand_expand" "")))]
+ "TARGET_CPU_ZARCH"
+{
+ operands[2] = s390_expand_masked_address_operand (operands[2], 6);
+})
+
; rll, rllg
-(define_insn "rotl<mode>3"
+(define_insn "*rotl<GPR:mode>3_<P:mode>"
[(set (match_operand:GPR 0 "register_operand" "=d")
(rotate:GPR (match_operand:GPR 1 "register_operand" "d")
- (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")))]
+ (match_operand:P 2 "shift_count_or_setmem_operand" "Y")))]
"TARGET_CPU_ZARCH"
"rll<g>\t%0,%1,%Y2"
[(set_attr "op_type" "RSE")
@@ -8288,11 +8297,11 @@
(set_attr "z10prop" "z10_super_E1")])
; rll, rllg
-(define_insn "*rotl<mode>3_and"
+(define_insn "*rotl<mode>3_and_<P:mode>"
[(set (match_operand:GPR 0 "register_operand" "=d")
(rotate:GPR (match_operand:GPR 1 "register_operand" "d")
- (and:SI (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")
- (match_operand:SI 3 "const_int_operand" "n"))))]
+ (and:P (match_operand:P 2 "shift_count_or_setmem_operand" "Y")
+ (match_operand:P 3 "const_int_operand" "n"))))]
"TARGET_CPU_ZARCH && (INTVAL (operands[3]) & 63) == 63"
"rll<g>\t%0,%1,%Y2"
[(set_attr "op_type" "RSE")
@@ -8310,10 +8319,12 @@
(define_expand "<shift><mode>3"
[(set (match_operand:DSI 0 "register_operand" "")
- (SHIFT:DSI (match_operand:DSI 1 "register_operand" "")
- (match_operand:SI 2 "shift_count_or_setmem_operand" "")))]
+ (SHIFT:DSI (match_operand:DSI 1 "register_operand" "")
+ (match_operand:SI 2 "shift_count_or_setmem_operand_expand" "")))]
""
- "")
+{
+ operands[2] = s390_expand_masked_address_operand (operands[2], 6);
+})
; sldl, srdl
(define_insn "*<shift>di3_31"
@@ -8327,10 +8338,10 @@
(set_attr "z196prop" "z196_cracked")])
; sll, srl, sllg, srlg, sllk, srlk
-(define_insn "*<shift><mode>3"
+(define_insn "*<shift><mode>3_<P:mode>"
[(set (match_operand:GPR 0 "register_operand" "=d,d")
(SHIFT:GPR (match_operand:GPR 1 "register_operand" "<d0>,d")
- (match_operand:SI 2 "shift_count_or_setmem_operand" "Y,Y")))]
+ (match_operand:P 2 "shift_count_or_setmem_operand" "Y,Y")))]
""
"@
s<lr>l<g>\t%0,<1>%Y2
@@ -8353,10 +8364,10 @@
; sll, srl, sllg, srlg, sllk, srlk
(define_insn "*<shift><mode>3_and"
- [(set (match_operand:GPR 0 "register_operand" "=d,d")
- (SHIFT:GPR (match_operand:GPR 1 "register_operand" "<d0>,d")
- (and:SI (match_operand:SI 2 "shift_count_or_setmem_operand" "Y,Y")
- (match_operand:SI 3 "const_int_operand" "n,n"))))]
+ [(set (match_operand:GPR 0 "register_operand" "=d,d")
+ (SHIFT:GPR (match_operand:GPR 1 "register_operand" "<d0>,d")
+ (and:P (match_operand:P 2 "shift_count_or_setmem_operand" "Y,Y")
+ (match_operand:P 3 "const_int_operand" "n,n"))))]
"(INTVAL (operands[3]) & 63) == 63"
"@
s<lr>l<g>\t%0,<1>%Y2
@@ -8374,10 +8385,12 @@
[(parallel
[(set (match_operand:DSI 0 "register_operand" "")
(ashiftrt:DSI (match_operand:DSI 1 "register_operand" "")
- (match_operand:SI 2 "shift_count_or_setmem_operand" "")))
+ (match_operand:SI 2 "shift_count_or_setmem_operand_expand" "")))
(clobber (reg:CC CC_REGNUM))])]
""
- "")
+{
+ operands[2] = s390_expand_masked_address_operand (operands[2], 6);
+})
(define_insn "*ashrdi3_cc_31"
[(set (reg CC_REGNUM)
@@ -8413,10 +8426,10 @@
(set_attr "atype" "reg")])
; sra, srag, srak
-(define_insn "*ashr<mode>3_cc"
+(define_insn "*ashr<GPR:mode>3_cc_<P:mode>"
[(set (reg CC_REGNUM)
- (compare (ashiftrt:GPR (match_operand:GPR 1 "register_operand" "<d0>,d")
- (match_operand:SI 2 "shift_count_or_setmem_operand" "Y,Y"))
+ (compare (ashiftrt:GPR (match_operand:GPR 1 "register_operand" "<d0>,d")
+ (match_operand:P 2 "shift_count_or_setmem_operand" "Y,Y"))
(const_int 0)))
(set (match_operand:GPR 0 "register_operand" "=d,d")
(ashiftrt:GPR (match_dup 1) (match_dup 2)))]
@@ -8430,10 +8443,10 @@
(set_attr "z10prop" "z10_super_E1,*")])
; sra, srag, srak
-(define_insn "*ashr<mode>3_cconly"
+(define_insn "*ashr<GPR:mode>3_cconly_<P:mode>"
[(set (reg CC_REGNUM)
- (compare (ashiftrt:GPR (match_operand:GPR 1 "register_operand" "<d0>,d")
- (match_operand:SI 2 "shift_count_or_setmem_operand" "Y,Y"))
+ (compare (ashiftrt:GPR (match_operand:GPR 1 "register_operand" "<d0>,d")
+ (match_operand:P 2 "shift_count_or_setmem_operand" "Y,Y"))
(const_int 0)))
(clobber (match_scratch:GPR 0 "=d,d"))]
"s390_match_ccmode(insn, CCSmode)"
@@ -8446,10 +8459,10 @@
(set_attr "z10prop" "z10_super_E1,*")])
; sra, srag
-(define_insn "*ashr<mode>3"
- [(set (match_operand:GPR 0 "register_operand" "=d,d")
- (ashiftrt:GPR (match_operand:GPR 1 "register_operand" "<d0>,d")
- (match_operand:SI 2 "shift_count_or_setmem_operand" "Y,Y")))
+(define_insn "*ashr<GPR:mode>3_<P:mode>"
+ [(set (match_operand:GPR 0 "register_operand" "=d,d")
+ (ashiftrt:GPR (match_operand:GPR 1 "register_operand" "<d0>,d")
+ (match_operand:P 2 "shift_count_or_setmem_operand" "Y,Y")))
(clobber (reg:CC CC_REGNUM))]
""
"@
@@ -8502,14 +8515,14 @@
(set_attr "atype" "reg")])
; sra, srag, srak
-(define_insn "*ashr<mode>3_cc_and"
+(define_insn "*ashr<GPR:mode>3_cc_and_<P:mode>"
[(set (reg CC_REGNUM)
- (compare (ashiftrt:GPR (match_operand:GPR 1 "register_operand" "<d0>,d")
- (and:SI (match_operand:SI 2 "shift_count_or_setmem_operand" "Y,Y")
- (match_operand:SI 3 "const_int_operand" "n,n")))
+ (compare (ashiftrt:GPR (match_operand:GPR 1 "register_operand" "<d0>,d")
+ (and:P (match_operand:P 2 "shift_count_or_setmem_operand" "Y,Y")
+ (match_operand:P 3 "const_int_operand" "n,n")))
(const_int 0)))
- (set (match_operand:GPR 0 "register_operand" "=d,d")
- (ashiftrt:GPR (match_dup 1) (and:SI (match_dup 2) (match_dup 3))))]
+ (set (match_operand:GPR 0 "register_operand" "=d,d")
+ (ashiftrt:GPR (match_dup 1) (and (match_dup 2) (match_dup 3))))]
"s390_match_ccmode(insn, CCSmode) && (INTVAL (operands[3]) & 63) == 63"
"@
sra<g>\t%0,<1>%Y2
@@ -8520,13 +8533,13 @@
(set_attr "z10prop" "z10_super_E1,*")])
; sra, srag, srak
-(define_insn "*ashr<mode>3_cconly_and"
+(define_insn "*ashr<GPR:mode>3_cconly_and_<P:mode>"
[(set (reg CC_REGNUM)
- (compare (ashiftrt:GPR (match_operand:GPR 1 "register_operand" "<d0>,d")
- (and:SI (match_operand:SI 2 "shift_count_or_setmem_operand" "Y,Y")
- (match_operand:SI 3 "const_int_operand" "n,n")))
+ (compare (ashiftrt:GPR (match_operand:GPR 1 "register_operand" "<d0>,d")
+ (and:P (match_operand:P 2 "shift_count_or_setmem_operand" "Y,Y")
+ (match_operand:P 3 "const_int_operand" "n,n")))
(const_int 0)))
- (clobber (match_scratch:GPR 0 "=d,d"))]
+ (clobber (match_scratch:GPR 0 "=d,d"))]
"s390_match_ccmode(insn, CCSmode) && (INTVAL (operands[3]) & 63) == 63"
"@
sra<g>\t%0,<1>%Y2
@@ -8537,11 +8550,11 @@
(set_attr "z10prop" "z10_super_E1,*")])
; sra, srag, srak
-(define_insn "*ashr<mode>3_and"
- [(set (match_operand:GPR 0 "register_operand" "=d,d")
- (ashiftrt:GPR (match_operand:GPR 1 "register_operand" "<d0>,d")
- (and:SI (match_operand:SI 2 "shift_count_or_setmem_operand" "Y,Y")
- (match_operand:SI 3 "const_int_operand" "n,n"))))
+(define_insn "*ashr<GPR:mode>3_and_<P:mode>"
+ [(set (match_operand:GPR 0 "register_operand" "=d,d")
+ (ashiftrt:GPR (match_operand:GPR 1 "register_operand" "<d0>,d")
+ (and:P (match_operand:P 2 "shift_count_or_setmem_operand" "Y,Y")
+ (match_operand:P 3 "const_int_operand" "n,n"))))
(clobber (reg:CC CC_REGNUM))]
"(INTVAL (operands[3]) & 63) == 63"
"@
@@ -10703,7 +10716,7 @@
; Transaction abort
(define_expand "tabort"
- [(unspec_volatile [(match_operand:SI 0 "shift_count_or_setmem_operand" "")]
+ [(unspec_volatile [(match_operand:SI 0 "shift_count_or_setmem_operand_expand" "")]
UNSPECV_TABORT)]
"TARGET_HTM && operands != NULL"
{
@@ -10715,15 +10728,39 @@
INTVAL (operands[0]));
FAIL;
}
+ operands[0] = s390_expand_masked_address_operand (operands[0],
+ GET_MODE_BITSIZE (Pmode));
})
-(define_insn "*tabort_1"
- [(unspec_volatile [(match_operand:SI 0 "shift_count_or_setmem_operand" "Y")]
+(define_insn "*tabort_1_<mode>"
+ [(unspec_volatile [(match_operand:P 0 "shift_count_or_setmem_operand" "Y")]
UNSPECV_TABORT)]
"TARGET_HTM && operands != NULL"
"tabort\t%Y0"
[(set_attr "op_type" "S")])
+; This splitter pulls a SI->DI zeroextend out of the address
+; calculation in order to enable the PLUS being executed as part of
+; the address operand.
+(define_insn_and_split "*tabort_1_add"
+ [(unspec_volatile
+ [(and:DI
+ (subreg:DI
+ (plus:SI (match_operand:SI 0 "register_operand" "d")
+ (match_operand 1 "immediate_operand" "J"))
+ 0)
+ (const_int 4294967295))] UNSPECV_TABORT)]
+ "TARGET_HTM"
+ "#"
+ ""
+ [(set (match_dup 2)
+ (zero_extend:DI (match_dup 0)))
+ (unspec_volatile [(plus:DI (match_dup 2) (match_dup 1))] UNSPECV_TABORT)]
+{
+ operands[2] = gen_reg_rtx(DImode);
+})
+
+
; Transaction extract nesting depth
(define_insn "etnd"
@@ -81,6 +81,27 @@
(V1DF "g") (V2DF "g")
(V1TF "q")])
+; Number of bits required to specify an element of a vector type
+(define_mode_attr selbits[(V1QI "4") (V2QI "4") (V4QI "4") (V8QI "4") (V16QI "4")
+ (V1HI "3") (V2HI "3") (V4HI "3") (V8HI "3")
+ (V1SI "2") (V2SI "2") (V4SI "2")
+ (V1DI "1") (V2DI "1")
+ (V1TI "0") (TI "0")
+ (V1SF "2") (V2SF "2") (V4SF "2")
+ (V1DF "1") (V2DF "1")
+ (V1TF "0")])
+
+; Bitmask required to specify an element of a vector type
+; (1 << <selbits>) - 1
+(define_mode_attr selmask[(V1QI "15") (V2QI "15") (V4QI "15") (V8QI "15") (V16QI "15")
+ (V1HI "7") (V2HI "7") (V4HI "7") (V8HI "7")
+ (V1SI "3") (V2SI "3") (V4SI "3")
+ (V1DI "1") (V2DI "1")
+ (V1TI "0") (TI "0")
+ (V1SF "3") (V2SF "3") (V4SF "3")
+ (V1DF "1") (V2DF "1")
+ (V1TF "0")])
+
; This is for vmalhw. It gets an 'w' attached to avoid confusion with
; multiply and add logical high vmalh.
(define_mode_attr w [(V1QI "") (V2QI "") (V4QI "") (V8QI "") (V16QI "")
@@ -306,6 +327,19 @@
; vec_store_lanes?
+; vec_set is supposed to *modify* an existing vector so operand 0 is
+; duplicated as input operand.
+(define_expand "vec_set<mode>"
+ [(set (match_operand:V 0 "register_operand" "")
+ (unspec:V [(match_operand:<non_vec> 1 "general_operand" "")
+ (match_operand:SI 2 "shift_count_or_setmem_operand_expand" "")
+ (match_dup 0)]
+ UNSPEC_VEC_SET))]
+ "TARGET_VX"
+{
+ operands[2] = s390_expand_masked_address_operand (operands[2], 12);
+})
+
; FIXME: Support also vector mode operands for 1
; FIXME: A target memory operand seems to be useful otherwise we end
; up with vl vlvgg vst. Shouldn't the middle-end be able to handle
@@ -313,7 +347,7 @@
(define_insn "*vec_set<mode>"
[(set (match_operand:V 0 "register_operand" "=v, v,v")
(unspec:V [(match_operand:<non_vec> 1 "general_operand" "d,QR,K")
- (match_operand:DI 2 "shift_count_or_setmem_operand" "Y, I,I")
+ (match_operand:P 2 "shift_count_or_setmem_operand" "Y, I,I")
(match_operand:V 3 "register_operand" "0, 0,0")]
UNSPEC_VEC_SET))]
"TARGET_VX"
@@ -323,23 +357,34 @@
vlei<bhfgq>\t%v0,%1,%2"
[(set_attr "op_type" "VRS,VRX,VRI")])
-; vec_set is supposed to *modify* an existing vector so operand 0 is
-; duplicated as input operand.
-(define_expand "vec_set<mode>"
- [(set (match_operand:V 0 "register_operand" "")
- (unspec:V [(match_operand:<non_vec> 1 "general_operand" "")
- (match_operand:SI 2 "shift_count_or_setmem_operand" "")
- (match_dup 0)]
- UNSPEC_VEC_SET))]
- "TARGET_VX")
+(define_insn "*vec_set<mode>_and"
+ [(set (match_operand:V 0 "register_operand" "=v")
+ (unspec:V [(match_operand:<non_vec> 1 "general_operand" "d")
+ (and:P (match_operand:P 2 "shift_count_or_setmem_operand" "Y")
+ (const_int 4095))
+ (match_operand:V 3 "register_operand" "0")]
+ UNSPEC_VEC_SET))]
+ "TARGET_VX"
+ "vlvg<bhfgq>\t%v0,%1,%Y2"
+ [(set_attr "op_type" "VRS")])
; FIXME: Support also vector mode operands for 0
; FIXME: This should be (vec_select ..) or something but it does only allow constant selectors :(
; This is used via RTL standard name as well as for expanding the builtin
-(define_insn "vec_extract<mode>"
- [(set (match_operand:<non_vec> 0 "nonimmediate_operand" "=d,QR")
- (unspec:<non_vec> [(match_operand:V 1 "register_operand" " v, v")
- (match_operand:SI 2 "shift_count_or_setmem_operand" " Y, I")]
+(define_expand "vec_extract<mode>"
+ [(set (match_operand:<non_vec> 0 "nonimmediate_operand" "")
+ (unspec:<non_vec> [(match_operand:V 1 "register_operand" "")
+ (match_operand:SI 2 "shift_count_or_setmem_operand_expand" "")]
+ UNSPEC_VEC_EXTRACT))]
+ "TARGET_VX"
+{
+ operands[2] = s390_expand_masked_address_operand (operands[2], 12);
+})
+
+(define_insn "*vec_extract<mode>"
+ [(set (match_operand:<non_vec> 0 "nonimmediate_operand" "=d,QR")
+ (unspec:<non_vec> [(match_operand:V 1 "register_operand" " v, v")
+ (match_operand:P 2 "shift_count_or_setmem_operand" " Y, I")]
UNSPEC_VEC_EXTRACT))]
"TARGET_VX"
"@
@@ -347,6 +392,16 @@
vste<bhfgq>\t%v1,%0,%2"
[(set_attr "op_type" "VRS,VRX")])
+(define_insn "*vec_extract<mode>_and"
+ [(set (match_operand:<non_vec> 0 "nonimmediate_operand" "=d")
+ (unspec:<non_vec> [(match_operand:V 1 "register_operand" "v")
+ (and:P (match_operand:P 2 "shift_count_or_setmem_operand" "Y")
+ (const_int 4095))]
+ UNSPEC_VEC_EXTRACT))]
+ "TARGET_VX"
+ "vlgv<bhfgq>\t%0,%v1,%Y2"
+ [(set_attr "op_type" "VRS")])
+
(define_expand "vec_init<V_HW:mode>"
[(match_operand:V_HW 0 "register_operand" "")
(match_operand:V_HW 1 "nonmemory_operand" "")]
@@ -669,15 +724,33 @@
; Vector rotate instructions
; Each vector element rotated by a scalar
+(define_expand "rotl<mode>3"
+ [(set (match_operand:VI 0 "register_operand" "=v")
+ (rotate:VI (match_operand:VI 1 "register_operand" "v")
+ (match_operand:SI 2 "shift_count_or_setmem_operand_expand" "Y")))]
+ "TARGET_VX"
+{
+ operands[2] = s390_expand_masked_address_operand (operands[2], <selbits>);
+})
+
; verllb, verllh, verllf, verllg
-(define_insn "rotl<mode>3"
+(define_insn "*rotl<mode>3"
[(set (match_operand:VI 0 "register_operand" "=v")
(rotate:VI (match_operand:VI 1 "register_operand" "v")
- (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")))]
+ (match_operand:P 2 "shift_count_or_setmem_operand" "Y")))]
"TARGET_VX"
"verll<bhfgq>\t%v0,%v1,%Y2"
[(set_attr "op_type" "VRS")])
+(define_insn "*rotl<mode>3_and"
+ [(set (match_operand:VI 0 "register_operand" "=v")
+ (rotate:VI (match_operand:VI 1 "register_operand" "v")
+ (and:P (match_operand:P 2 "shift_count_or_setmem_operand" "Y")
+ (match_operand 3 "const_int_operand" ""))))]
+ "TARGET_VX && (INTVAL (operands[3]) & <VI:selmask>) == <VI:selmask>"
+ "verll<bhfgq>\t%v0,%v1,%Y2"
+ [(set_attr "op_type" "VRS")])
+
; Each vector element rotated by the corresponding vector element
; verllvb, verllvh, verllvf, verllvg
(define_insn "vrotl<mode>3"
@@ -692,32 +765,87 @@
; Shift each element by scalar value
; veslb, veslh, veslf, veslg
-(define_insn "ashl<mode>3"
+(define_expand "ashl<mode>3"
+ [(set (match_operand:VI 0 "register_operand" "")
+ (ashift:VI (match_operand:VI 1 "register_operand" "")
+ (match_operand:SI 2 "shift_count_or_setmem_operand_expand" "")))]
+ "TARGET_VX"
+{
+ operands[2] = s390_expand_masked_address_operand (operands[2], <selbits>);
+})
+
+(define_insn "*ashl<mode>3"
[(set (match_operand:VI 0 "register_operand" "=v")
(ashift:VI (match_operand:VI 1 "register_operand" "v")
- (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")))]
+ (match_operand:P 2 "shift_count_or_setmem_operand" "Y")))]
"TARGET_VX"
"vesl<bhfgq>\t%v0,%v1,%Y2"
[(set_attr "op_type" "VRS")])
+(define_insn "*ashl<mode>3_and"
+ [(set (match_operand:VI 0 "register_operand" "=v")
+ (ashift:VI (match_operand:VI 1 "register_operand" "v")
+ (and:P (match_operand:P 2 "shift_count_or_setmem_operand" "Y")
+ (match_operand 3 "const_int_operand" ""))))]
+ "TARGET_VX && (INTVAL (operands[3]) & <VI:selmask>) == <VI:selmask>"
+ "vesl<bhfgq>\t%v0,%v1,%Y2"
+ [(set_attr "op_type" "VRS")])
+
; vesrab, vesrah, vesraf, vesrag
-(define_insn "ashr<mode>3"
+(define_expand "ashr<mode>3"
+ [(set (match_operand:VI 0 "register_operand" "")
+ (ashiftrt:VI (match_operand:VI 1 "register_operand" "")
+ (match_operand:SI 2 "shift_count_or_setmem_operand_expand" "")))]
+ "TARGET_VX"
+{
+ operands[2] = s390_expand_masked_address_operand (operands[2], <VI:selbits>);
+})
+
+(define_insn "*ashr<mode>3"
[(set (match_operand:VI 0 "register_operand" "=v")
(ashiftrt:VI (match_operand:VI 1 "register_operand" "v")
- (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")))]
+ (match_operand:P 2 "shift_count_or_setmem_operand" "Y")))]
"TARGET_VX"
"vesra<bhfgq>\t%v0,%v1,%Y2"
[(set_attr "op_type" "VRS")])
+(define_insn "*ashr<mode>3_and"
+ [(set (match_operand:VI 0 "register_operand" "=v")
+ (ashiftrt:VI (match_operand:VI 1 "register_operand" "v")
+ (and:P (match_operand:P 2 "shift_count_or_setmem_operand" "Y")
+ (match_operand 3 "const_int_operand" ""))))]
+ "TARGET_VX && (INTVAL (operands[3]) & <VI:selmask>) == <VI:selmask>"
+ "vesra<bhfgq>\t%v0,%v1,%Y2"
+ [(set_attr "op_type" "VRS")])
+
+
+(define_expand "lshr<mode>3"
+ [(set (match_operand:VI 0 "register_operand" "=v")
+ (lshiftrt:VI (match_operand:VI 1 "register_operand" "v")
+ (match_operand:SI 2 "shift_count_or_setmem_operand_expand" "Y")))]
+ "TARGET_VX"
+{
+ operands[2] = s390_expand_masked_address_operand (operands[2], <VI:selbits>);
+})
+
; vesrlb, vesrlh, vesrlf, vesrlg
-(define_insn "lshr<mode>3"
+(define_insn "*lshr<mode>3"
[(set (match_operand:VI 0 "register_operand" "=v")
(lshiftrt:VI (match_operand:VI 1 "register_operand" "v")
- (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")))]
+ (match_operand:P 2 "shift_count_or_setmem_operand" "Y")))]
"TARGET_VX"
"vesrl<bhfgq>\t%v0,%v1,%Y2"
[(set_attr "op_type" "VRS")])
+(define_insn "*lshr<mode>3_and"
+ [(set (match_operand:VI 0 "register_operand" "=v")
+ (lshiftrt:VI (match_operand:VI 1 "register_operand" "v")
+ (and:P (match_operand:P 2 "shift_count_or_setmem_operand" "Y")
+ (match_operand 3 "const_int_operand" ""))))]
+ "TARGET_VX && (INTVAL (operands[3]) & <VI:selmask>) == <VI:selmask>"
+ "vesrl<bhfgq>\t%v0,%v1,%Y2"
+ [(set_attr "op_type" "VRS")])
+
; Shift each element by corresponding vector element
@@ -150,21 +150,27 @@
(define_expand "vec_insert<mode>"
[(set (match_operand:V_HW 0 "register_operand" "")
(unspec:V_HW [(match_operand:<non_vec> 2 "register_operand" "")
- (match_operand:SI 3 "shift_count_or_setmem_operand" "")
+ (match_operand:SI 3 "shift_count_or_setmem_operand_expand" "")
(match_operand:V_HW 1 "register_operand" "")]
UNSPEC_VEC_SET))]
"TARGET_VX"
- "")
+{
+ operands[3] = s390_expand_masked_address_operand (operands[3], 12);
+})
+
; This is vec_set + modulo arithmetic on the element selector (op 2)
+; The modulo operation is emitted in s390-c.c.
(define_expand "vec_promote<mode>"
[(set (match_operand:V_HW 0 "register_operand" "")
(unspec:V_HW [(match_operand:<non_vec> 1 "register_operand" "")
- (match_operand:SI 2 "shift_count_or_setmem_operand" "")
+ (match_operand:SI 2 "shift_count_or_setmem_operand_expand" "")
(match_dup 0)]
UNSPEC_VEC_SET))]
"TARGET_VX"
- "")
+{
+ operands[2] = s390_expand_masked_address_operand (operands[2], 12);
+})
; vec_extract is also an RTL standard name -> vector.md