diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 91690698cbd..da9e02f247d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2015-12-11 Dominik Vogt + + * config/s390/s390.c (s390_expand_setmem): Use new expanders. + * config/s390/s390.md ("*setmem_long") + ("*setmem_long_and", "*setmem_long_31z"): Fix warnings. + ("*setmem_long_and_31z"): New define_insn. + ("setmem_long_"): New expanders. + * (): New mode attribute + 2015-12-11 Dominik Vogt * config/s390/s390.md ("movstr", "*movstr"): Fix warning. diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index f8928b9ac3e..1695dfbac30 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -5237,7 +5237,12 @@ s390_expand_setmem (rtx dst, rtx len, rtx val) else if (TARGET_MVCLE) { val = force_not_mem (convert_modes (Pmode, QImode, val, 1)); - emit_insn (gen_setmem_long (dst, convert_to_mode (Pmode, len, 1), val)); + if (TARGET_64BIT) + emit_insn (gen_setmem_long_di (dst, convert_to_mode (Pmode, len, 1), + val)); + else + emit_insn (gen_setmem_long_si (dst, convert_to_mode (Pmode, len, 1), + val)); } else diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md index bc24a3665fb..a1fc96a0adc 100644 --- a/gcc/config/s390/s390.md +++ b/gcc/config/s390/s390.md @@ -70,6 +70,9 @@ ; Copy CC as is into the lower 2 bits of an integer register UNSPEC_CC_TO_INT + ; The right hand side of an setmem + UNSPEC_REPLICATE_BYTE + ; GOT/PLT and lt-relative accesses UNSPEC_LTREL_OFFSET UNSPEC_LTREL_BASE @@ -727,6 +730,9 @@ ;; In place of GET_MODE_BITSIZE (mode) (define_mode_attr bitsize [(DI "64") (SI "32") (HI "16") (QI "8")]) +;; In place of GET_MODE_SIZE (mode) +(define_mode_attr modesize [(DI "8") (SI "4")]) + ;; Allow return and simple_return to be defined from a single template. (define_code_iterator ANY_RETURN [return simple_return]) @@ -3280,12 +3286,12 @@ ; Initialize a block of arbitrary length with (operands[2] % 256). -(define_expand "setmem_long" +(define_expand "setmem_long_" [(parallel [(clobber (match_dup 1)) (set (match_operand:BLK 0 "memory_operand" "") - (match_operand 2 "shift_count_or_setmem_operand" "")) - (use (match_operand 1 "general_operand" "")) + (unspec:BLK [(match_operand:P 2 "shift_count_or_setmem_operand" "") + (match_dup 4)] UNSPEC_REPLICATE_BYTE)) (use (match_dup 3)) (clobber (reg:CC CC_REGNUM))])] "" @@ -3306,13 +3312,17 @@ operands[0] = replace_equiv_address_nv (operands[0], addr0); operands[1] = reg0; operands[3] = reg1; + operands[4] = gen_lowpart (Pmode, operands[1]); }) +; Patterns for 31 bit + Esa and 64 bit + Zarch. + (define_insn "*setmem_long" [(clobber (match_operand: 0 "register_operand" "=d")) (set (mem:BLK (subreg:P (match_operand: 3 "register_operand" "0") 0)) - (match_operand 2 "shift_count_or_setmem_operand" "Y")) - (use (match_dup 3)) + (unspec:BLK [(match_operand:P 2 "shift_count_or_setmem_operand" "Y") + (subreg:P (match_dup 3) )] + UNSPEC_REPLICATE_BYTE)) (use (match_operand: 1 "register_operand" "d")) (clobber (reg:CC CC_REGNUM))] "TARGET_64BIT || !TARGET_ZARCH" @@ -3323,9 +3333,11 @@ (define_insn "*setmem_long_and" [(clobber (match_operand: 0 "register_operand" "=d")) (set (mem:BLK (subreg:P (match_operand: 3 "register_operand" "0") 0)) - (and (match_operand 2 "shift_count_or_setmem_operand" "Y") - (match_operand 4 "const_int_operand" "n"))) - (use (match_dup 3)) + (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) )] + UNSPEC_REPLICATE_BYTE)) (use (match_operand: 1 "register_operand" "d")) (clobber (reg:CC CC_REGNUM))] "(TARGET_64BIT || !TARGET_ZARCH) && @@ -3334,11 +3346,14 @@ [(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)) - (match_operand 2 "shift_count_or_setmem_operand" "Y")) - (use (match_dup 3)) + (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" @@ -3346,6 +3361,21 @@ [(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" + [(set_attr "length" "8") + (set_attr "type" "vs")]) + ; ; cmpmemM instruction pattern(s). ; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 36132762600..283da3bbf2d 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2015-12-11 Dominik Vogt + + * gcc.target/s390/md/setmem_long-1.c: New test. + 2015-12-11 Dominik Vogt * gcc.target/s390/md/movstr-1.c: New test. diff --git a/gcc/testsuite/gcc.target/s390/md/setmem_long-1.c b/gcc/testsuite/gcc.target/s390/md/setmem_long-1.c new file mode 100644 index 00000000000..933a6985aa8 --- /dev/null +++ b/gcc/testsuite/gcc.target/s390/md/setmem_long-1.c @@ -0,0 +1,56 @@ +/* Machine description pattern tests. */ + +/* { dg-do run } */ +/* { dg-options "-mmvcle -dP -save-temps" } */ + +__attribute__ ((noinline)) +void test(char *p, char c, int len) +{ + __builtin_memset(p, c, len); +} + +__attribute__ ((noinline)) +void test2(char *p, int c, int len) +{ + __builtin_memset(p, (char)c, len); +} + +/* Check that the right patterns are used. */ +/* { dg-final { scan-assembler-times {c:9 .*{[*]setmem_long_?3?1?z?}} 1 } } */ +/* { dg-final { scan-assembler-times {c:15 .*{[*]setmem_long_and_?3?1?z?}} 1 { xfail *-*-* } } } */ + +#define LEN 500 +char buf[LEN + 2]; + +void init_buf(void) +{ + int i; + + buf[0] = 0; + for (i = 1; i <= LEN; i++) + buf[i] = (0x10 + (i & 0x3f)); + buf[LEN + 1] = 0x7f; +} + +void validate_buf(char val) +{ + int i; + + if (buf[0] != 0) + __builtin_abort(); + for (i = 1; i <= LEN; i++) + if (buf[i] != val) + __builtin_abort(); + if (buf[LEN + 1] != 0x7f) + __builtin_abort(); +} + +int main(void) +{ + init_buf(); + test(buf + 1, 55, LEN); + validate_buf(55); + init_buf(); + test(buf + 1, 66, LEN); + validate_buf(66); +}