@@ -140,6 +140,12 @@
(define_predicate "const_int_6bitset_operand"
(and (match_code "const_int")
(match_test "(INTVAL (op) & 63) == 63")))
+
+; An integer operand with the lowest order 8 bit all ones.
+(define_predicate "const_int_8bitset_operand"
+ (and (match_code "const_int")
+ (match_test "(INTVAL (op) & 255) == 255")))
+
(define_predicate "nonzero_shift_count_operand"
(and (match_code "const_int")
(match_test "IN_RANGE (INTVAL (op), 1, GET_MODE_BITSIZE (mode) - 1)")))
@@ -3313,62 +3313,16 @@
; Patterns for 31 bit + Esa and 64 bit + Zarch.
-(define_insn "*setmem_long"
+(define_insn "*setmem_long<setmem_31z><setmem_and>"
[(clobber (match_operand:<DBL> 0 "register_operand" "=d"))
- (set (mem:BLK (subreg:P (match_operand:<DBL> 3 "register_operand" "0") 0))
- (unspec:BLK [(match_operand:P 2 "shift_count_or_setmem_operand" "Y")
- (subreg:P (match_dup 3) <modesize>)]
+ (set (mem:BLK (subreg:P (match_operand:<DBL> 1 "register_operand" "0") 0))
+ (unspec:BLK [(match_operand:P 3 "shift_count_or_setmem_operand" "Y")
+ (subreg:P (match_operand:<DBL> 2 "register_operand" "0") <modesize>)]
UNSPEC_REPLICATE_BYTE))
- (use (match_operand:<DBL> 1 "register_operand" "d"))
+ (use (match_operand:<DBL> 4 "register_operand" "d"))
(clobber (reg:CC CC_REGNUM))]
- "TARGET_64BIT || !TARGET_ZARCH"
- "mvcle\t%0,%1,%Y2\;jo\t.-4"
- [(set_attr "length" "8")
- (set_attr "type" "vs")])
-
-(define_insn "*setmem_long_and"
- [(clobber (match_operand:<DBL> 0 "register_operand" "=d"))
- (set (mem:BLK (subreg:P (match_operand:<DBL> 3 "register_operand" "0") 0))
- (unspec:BLK [(and:P
- (match_operand:P 2 "shift_count_or_setmem_operand" "Y")
- (match_operand:P 4 "const_int_operand" "n"))
- (subreg:P (match_dup 3) <modesize>)]
- UNSPEC_REPLICATE_BYTE))
- (use (match_operand:<DBL> 1 "register_operand" "d"))
- (clobber (reg:CC CC_REGNUM))]
- "(TARGET_64BIT || !TARGET_ZARCH) &&
- (INTVAL (operands[4]) & 255) == 255"
- "mvcle\t%0,%1,%Y2\;jo\t.-4"
- [(set_attr "length" "8")
- (set_attr "type" "vs")])
-
-; Variants for 31 bit + Zarch, necessary because of the odd in-register offsets
-; of the SImode subregs.
-
-(define_insn "*setmem_long_31z"
- [(clobber (match_operand:TI 0 "register_operand" "=d"))
- (set (mem:BLK (subreg:SI (match_operand:TI 3 "register_operand" "0") 4))
- (unspec:BLK [(match_operand:SI 2 "shift_count_or_setmem_operand" "Y")
- (subreg:SI (match_dup 3) 12)] UNSPEC_REPLICATE_BYTE))
- (use (match_operand:TI 1 "register_operand" "d"))
- (clobber (reg:CC CC_REGNUM))]
- "!TARGET_64BIT && TARGET_ZARCH"
- "mvcle\t%0,%1,%Y2\;jo\t.-4"
- [(set_attr "length" "8")
- (set_attr "type" "vs")])
-
-(define_insn "*setmem_long_and_31z"
- [(clobber (match_operand:TI 0 "register_operand" "=d"))
- (set (mem:BLK (subreg:SI (match_operand:TI 3 "register_operand" "0") 4))
- (unspec:BLK [(and:SI
- (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")
- (match_operand:SI 4 "const_int_operand" "n"))
- (subreg:SI (match_dup 3) 12)] UNSPEC_REPLICATE_BYTE))
- (use (match_operand:TI 1 "register_operand" "d"))
- (clobber (reg:CC CC_REGNUM))]
- "(!TARGET_64BIT && TARGET_ZARCH) &&
- (INTVAL (operands[4]) & 255) == 255"
- "mvcle\t%0,%1,%Y2\;jo\t.-4"
+ "<setmem_31z_cond>"
+ "mvcle\t%0,%4,%Y3\;jo\t.-4"
[(set_attr "length" "8")
(set_attr "type" "vs")])
@@ -126,3 +126,55 @@
(clobber (match_scratch:DSI 0 "=d,d,d,d"))])
(define_subst_attr "cconly" "cconly_subst" "" "_cconly")
+
+
+;; setmem substitution patterns
+
+
+; Turn the DImode in the 31 bit pattern into TImode to enforce
+; register pair usage even with -mzarch.
+; The subreg offset is adjusted accordingly.
+(define_subst "setmem_31z_subst"
+ [(clobber (match_operand:DI 0 "register_operand" ""))
+ (set (mem:BLK (subreg:SI (match_operand:DI 3 "register_operand" "") 0))
+ (unspec:BLK [(match_operand:SI 2 "shift_count_or_setmem_operand" "")
+ (subreg:SI (match_operand:DI 4 "register_operand" "")
+ 0)]
+ UNSPEC_REPLICATE_BYTE))
+ (use (match_operand:DI 1 "register_operand" ""))
+ (clobber (reg:CC CC_REGNUM))]
+""
+ [(clobber (match_operand:TI 0 "register_operand" ""))
+ (set (mem:BLK (subreg:SI (match_operand:TI 3 "register_operand" "") 4))
+ (unspec:BLK [(match_operand:SI 2 "shift_count_or_setmem_operand" "")
+ (subreg:SI (match_operand:TI 4 "register_operand" "")
+ 12)]
+ UNSPEC_REPLICATE_BYTE))
+ (use (match_operand:TI 1 "register_operand" ""))
+ (clobber (reg:CC CC_REGNUM))])
+
+(define_subst_attr "setmem_31z" "setmem_31z_subst" "" "_31z")
+(define_subst_attr "setmem_31z_cond" "setmem_31z_subst" "TARGET_64BIT || !TARGET_ZARCH"
+ "!TARGET_64BIT && TARGET_ZARCH")
+
+; Add an AND operation on the padding byte operand. Only the lowest 8
+; bit are used and the rest is ignored.
+(define_subst "setmem_and_subst"
+ [(clobber (match_operand:TDI 0 "register_operand" ""))
+ (set (mem:BLK (subreg:DSI (match_operand:TDI 1 "register_operand" "") 0))
+ (unspec:BLK [(match_operand:DSI 2 "shift_count_or_setmem_operand" "")
+ (match_operand:DSI 3 "register_operand" "")]
+ UNSPEC_REPLICATE_BYTE))
+ (use (match_operand:TDI 4 "register_operand" ""))
+ (clobber (reg:CC CC_REGNUM))]
+""
+ [(clobber (match_dup 0))
+ (set (mem:BLK (subreg:SI (match_dup 1) 0))
+ (unspec:BLK [(and:DSI (match_dup 2)
+ (match_operand:DSI 5 "const_int_8bitset_operand" ""))
+ (match_dup 3)]
+ UNSPEC_REPLICATE_BYTE))
+ (use (match_dup 4))
+ (clobber (reg:CC CC_REGNUM))])
+
+(define_subst_attr "setmem_and" "setmem_and_subst" "" "_and")