From 9ec988605d388be904e9b6f391ea67b4f456385a Mon Sep 17 00:00:00 2001 From: Andreas Krebbel Date: Fri, 24 Mar 2017 14:00:43 +0000 Subject: [PATCH] S/390: arch12: Add support for new vector bit operations. This patch adds support for the new bit operations introduced with arch12. The patch also renames the one complement pattern to the proper RTL standard name. 2017-03-24 Andreas Krebbel * config/s390/s390.c (s390_rtx_costs): Return low costs for the canonical form of ~AND to make sure the new instruction will be used. * config/s390/vector.md ("notand3", "ior_not3") ("notxor3"): Add new pattern definitions. ("*not"): Rename to ... ("one_cmpl2"): ... this. gcc/testsuite/ChangeLog: 2017-03-24 Andreas Krebbel * gcc.target/s390/vxe/bitops-1.c: New test. From-SVN: r246453 --- gcc/config/s390/s390.c | 15 ++++++ gcc/config/s390/vector.md | 31 +++++++++++- gcc/testsuite/ChangeLog | 4 ++ gcc/testsuite/gcc.target/s390/vxe/bitops-1.c | 52 ++++++++++++++++++++ 4 files changed, 100 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gcc.target/s390/vxe/bitops-1.c diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index c94edcc7a62..416a15ed549 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -3373,6 +3373,21 @@ s390_rtx_costs (rtx x, machine_mode mode, int outer_code, *total = COSTS_N_INSNS (2); return true; } + + /* ~AND on a 128 bit mode. This can be done using a vector + instruction. */ + if (TARGET_VXE + && GET_CODE (XEXP (x, 0)) == NOT + && GET_CODE (XEXP (x, 1)) == NOT + && REG_P (XEXP (XEXP (x, 0), 0)) + && REG_P (XEXP (XEXP (x, 1), 0)) + && GET_MODE_SIZE (GET_MODE (XEXP (XEXP (x, 0), 0))) == 16 + && s390_hard_regno_mode_ok (VR0_REGNUM, + GET_MODE (XEXP (XEXP (x, 0), 0)))) + { + *total = COSTS_N_INSNS (1); + return true; + } /* fallthrough */ case ASHIFT: case ASHIFTRT: diff --git a/gcc/config/s390/vector.md b/gcc/config/s390/vector.md index 7ddeb9a2f9c..68a8ed095a3 100644 --- a/gcc/config/s390/vector.md +++ b/gcc/config/s390/vector.md @@ -655,6 +655,15 @@ "vn\t%v0,%v1,%v2" [(set_attr "op_type" "VRR")]) +; Vector not and + +(define_insn "notand3" + [(set (match_operand:VT 0 "register_operand" "=v") + (ior:VT (not:VT (match_operand:VT 1 "register_operand" "%v")) + (not:VT (match_operand:VT 2 "register_operand" "v"))))] + "TARGET_VXE" + "vnn\t%v0,%v1,%v2" + [(set_attr "op_type" "VRR")]) ; Vector or @@ -666,6 +675,15 @@ "vo\t%v0,%v1,%v2" [(set_attr "op_type" "VRR")]) +; Vector or with complement + +(define_insn "ior_not3" + [(set (match_operand:VT 0 "register_operand" "=v") + (ior:VT (not:VT (match_operand:VT 2 "register_operand" "v")) + (match_operand:VT 1 "register_operand" "%v")))] + "TARGET_VXE" + "voc\t%v0,%v1,%v2" + [(set_attr "op_type" "VRR")]) ; Vector xor @@ -677,9 +695,18 @@ "vx\t%v0,%v1,%v2" [(set_attr "op_type" "VRR")]) +; Vector not xor -; Bitwise inversion of a vector - used for vec_cmpne -(define_insn "*not" +(define_insn "notxor3" + [(set (match_operand:VT 0 "register_operand" "=v") + (not:VT (xor:VT (match_operand:VT 1 "register_operand" "%v") + (match_operand:VT 2 "register_operand" "v"))))] + "TARGET_VXE" + "vnx\t%v0,%v1,%v2" + [(set_attr "op_type" "VRR")]) + +; Bitwise inversion of a vector +(define_insn "one_cmpl2" [(set (match_operand:VT 0 "register_operand" "=v") (not:VT (match_operand:VT 1 "register_operand" "v")))] "TARGET_VX" diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 4c59d68fb94..1a74e0dac65 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2017-03-24 Andreas Krebbel + + * gcc.target/s390/vxe/bitops-1.c: New test. + 2017-03-24 Andreas Krebbel * gcc.target/s390/s390.exp: Run tests in arch12 and vxe dirs. diff --git a/gcc/testsuite/gcc.target/s390/vxe/bitops-1.c b/gcc/testsuite/gcc.target/s390/vxe/bitops-1.c new file mode 100644 index 00000000000..bdf74575914 --- /dev/null +++ b/gcc/testsuite/gcc.target/s390/vxe/bitops-1.c @@ -0,0 +1,52 @@ +/* { dg-do run } */ +/* { dg-options "-O3 -mzarch -march=arch12 --save-temps" } */ +/* { dg-require-effective-target s390_vxe } */ + +typedef unsigned int uv4si __attribute__((vector_size(16))); + +uv4si __attribute__((noinline)) +not_xor (uv4si a, uv4si b) +{ + return ~(a ^ b); +} +/* { dg-final { scan-assembler-times "vnx\t%v24,%v24,%v26" 1 } } */ + +uv4si __attribute__((noinline)) +not_and (uv4si a, uv4si b) +{ + return ~(a & b); +} +/* { dg-final { scan-assembler-times "vnn\t%v24,%v24,%v26" 1 } } */ + +uv4si __attribute__((noinline)) +or_not (uv4si a, uv4si b) +{ + return a | ~b; +} +/* { dg-final { scan-assembler-times "voc\t%v24,%v24,%v26" 1 } } */ + + +int +main () +{ + uv4si a = (uv4si){ 42, 1, 0, 2 }; + uv4si b = (uv4si){ 42, 2, 0, 2 }; + uv4si c; + + c = not_xor (a, b); + + if (c[0] != ~0 || c[1] != ~3 || c[2] != ~0 || c[3] != ~0) + __builtin_abort (); + + c = not_and (a, b); + + if (c[0] != ~42 || c[1] != ~0 || c[2] != ~0 || c[3] != ~2) + __builtin_abort (); + + c = or_not (a, b); + + if (c[0] != ~0 || c[1] != ~2 || c[2] != ~0 || c[3] != ~0) + __builtin_abort (); + + return 0; +}