S/390: arch12: Add vllezlf instruction.
authorAndreas Krebbel <krebbel@linux.vnet.ibm.com>
Fri, 24 Mar 2017 14:01:54 +0000 (14:01 +0000)
committerAndreas Krebbel <krebbel@gcc.gnu.org>
Fri, 24 Mar 2017 14:01:54 +0000 (14:01 +0000)
This adds support for the vector load element and zero instruction and
makes sure it is used when initializing vectors with elements while
setting the rest to 0.

gcc/ChangeLog:

2017-03-24  Andreas Krebbel  <krebbel@linux.vnet.ibm.com>

* config/s390/s390.c (s390_expand_vec_init): Use vllezl
instruction if possible.
* config/s390/vector.md (vec_halfnumelts): New mode
attribute.
("*vec_vllezlf<mode>"): New pattern.

gcc/testsuite/ChangeLog:

2017-03-24  Andreas Krebbel  <krebbel@linux.vnet.ibm.com>

* gcc.target/s390/vxe/vllezlf-1.c: New test.

From-SVN: r246455

gcc/ChangeLog
gcc/config/s390/s390.c
gcc/config/s390/vector.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/s390/vxe/vllezlf-1.c [new file with mode: 0644]

index b669724c749484e0ab7ffd82480f88018f500c38..8f742aafff101ab4e13544bc99850f4a297ae39f 100644 (file)
@@ -1,3 +1,11 @@
+2017-03-24  Andreas Krebbel  <krebbel@linux.vnet.ibm.com>
+
+       * config/s390/s390.c (s390_expand_vec_init): Use vllezl
+       instruction if possible.
+       * config/s390/vector.md (vec_halfnumelts): New mode
+       attribute.
+       ("*vec_vllezlf<mode>"): New pattern.
+
 2017-03-24  Andreas Krebbel  <krebbel@linux.vnet.ibm.com>
 
        * config/s390/vector.md ("popcountv16qi2", "popcountv8hi2")
index 416a15ed549dc24c68b720d918b1e93a7a2e47b2..e8003233165387c37b0a7a0ad760130581b3ca03 100644 (file)
@@ -6552,6 +6552,34 @@ s390_expand_vec_init (rtx target, rtx vals)
       return;
     }
 
+  /* Use vector load logical element and zero.  */
+  if (TARGET_VXE && (mode == V4SImode || mode == V4SFmode))
+    {
+      bool found = true;
+
+      x = XVECEXP (vals, 0, 0);
+      if (memory_operand (x, inner_mode))
+       {
+         for (i = 1; i < n_elts; ++i)
+           found = found && XVECEXP (vals, 0, i) == const0_rtx;
+
+         if (found)
+           {
+             machine_mode half_mode = (inner_mode == SFmode
+                                       ? V2SFmode : V2SImode);
+             emit_insn (gen_rtx_SET (target,
+                             gen_rtx_VEC_CONCAT (mode,
+                                                 gen_rtx_VEC_CONCAT (half_mode,
+                                                                     x,
+                                                                     const0_rtx),
+                                                 gen_rtx_VEC_CONCAT (half_mode,
+                                                                     const0_rtx,
+                                                                     const0_rtx))));
+             return;
+           }
+       }
+    }
+
   /* We are about to set the vector elements one by one.  Zero out the
      full register first in order to help the data flow framework to
      detect it as full VR set.  */
index d4c0e95503f814289dedf4d88768ae8d04e51508..6a726a30e30fd95180dbb34c45fe51ca468b65f5 100644 (file)
@@ -44,6 +44,7 @@
 (define_mode_iterator VI_HW_HSD [V8HI  V4SI V2DI])
 (define_mode_iterator VI_HW_HS  [V8HI  V4SI])
 (define_mode_iterator VI_HW_QH  [V16QI V8HI])
+(define_mode_iterator VI_HW_4   [V4SI V4SF])
 
 ; All integer vector modes supported in a vector register + TImode
 (define_mode_iterator VIT [V1QI V2QI V4QI V8QI V16QI V1HI V2HI V4HI V8HI V1SI V2SI V4SI V1DI V2DI V1TI TI])
    (V2DI "V2SI")
    (V2DF "V2SF")])
 
+(define_mode_attr vec_halfnumelts
+  [(V4SF "V2SF") (V4SI "V2SI")])
+
 ; The comparisons not setting CC iterate over the rtx code.
 (define_code_iterator VFCMP_HW_OP [eq gt ge])
 (define_code_attr asm_fcmp_op [(eq "e") (gt "h") (ge "he")])
   DONE;
 })
 
+(define_insn "*vec_vllezlf<mode>"
+  [(set (match_operand:VI_HW_4              0 "register_operand" "=v")
+       (vec_concat:VI_HW_4
+        (vec_concat:<vec_halfnumelts>
+         (match_operand:<non_vec> 1 "memory_operand"    "R")
+         (const_int 0))
+        (vec_concat:<vec_halfnumelts>
+         (const_int 0)
+         (const_int 0))))]
+  "TARGET_VXE"
+  "vllezlf\t%v0,%1"
+  [(set_attr "op_type" "VRX")])
+
 ; Replicate from vector element
 ; vrepb, vreph, vrepf, vrepg
 (define_insn "*vec_splat<mode>"
index 6edd4c150e8879ef231bd11e069cab6234c0b8d6..4405d367e77699f4c1a9bace8f8658218bed771a 100644 (file)
@@ -1,3 +1,7 @@
+2017-03-24  Andreas Krebbel  <krebbel@linux.vnet.ibm.com>
+
+       * gcc.target/s390/vxe/vllezlf-1.c: New test.
+
 2017-03-24  Andreas Krebbel  <krebbel@linux.vnet.ibm.com>
 
        * gcc.target/s390/vxe/popcount-1.c: New test.
diff --git a/gcc/testsuite/gcc.target/s390/vxe/vllezlf-1.c b/gcc/testsuite/gcc.target/s390/vxe/vllezlf-1.c
new file mode 100644 (file)
index 0000000..14ea4f7
--- /dev/null
@@ -0,0 +1,30 @@
+/* Make sure the vector load and zero instruction is being used for
+   initializing a 32 bit vector with the first element taken from
+   memory.  */
+
+/* { 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))
+foo (int *a)
+{
+  return (uv4si){ *a, 0, 0, 0 };
+}
+
+int
+main ()
+{
+  int b = 4;
+  uv4si a = (uv4si){ 1, 2, 3, 4 };
+
+  a = foo (&b);
+
+  if (a[0] != 4 || a[1] != 0 || a[2] != 0 || a[3] != 0)
+    __builtin_abort ();
+
+  return 0;
+}
+/* { dg-final { scan-assembler-times "vllezlf\t%v24,0\\(%r2\\)" 1 } } */