rs6000.c (rs6000_gimple_fold_builtin): Shift-right and shift-left vector built-ins...
authorBill Schmidt <wschmidt@linux.ibm.com>
Mon, 11 Feb 2019 16:50:33 +0000 (16:50 +0000)
committerWilliam Schmidt <wschmidt@gcc.gnu.org>
Mon, 11 Feb 2019 16:50:33 +0000 (16:50 +0000)
[gcc]

2019-02-11  Bill Schmidt  <wschmidt@linux.ibm.com>

* config/rs6000/rs6000.c (rs6000_gimple_fold_builtin): Shift-right
and shift-left vector built-ins need to include a TRUNC_MOD_EXPR
for correct semantics.

[gcc/testsuite]

2019-02-11  Bill Schmidt  <wschmidt@linux.ibm.com>

* gcc.target/powerpc/vec-sld-modulo.c: New.
* gcc.target/powerpc/vec-srad-modulo.c: New.
* gcc.target/powerpc/vec-srd-modulo.c: New.

From-SVN: r268771

gcc/ChangeLog
gcc/config/rs6000/rs6000.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/powerpc/vec-sld-modulo.c [new file with mode: 0644]
gcc/testsuite/gcc.target/powerpc/vec-srad-modulo.c [new file with mode: 0644]
gcc/testsuite/gcc.target/powerpc/vec-srd-modulo.c [new file with mode: 0644]

index b43bf022066f18ec769bdde155123a2343d90929..4a66632e740127b616230f7782b0d777890062db 100644 (file)
@@ -1,3 +1,9 @@
+2019-02-11  Bill Schmidt  <wschmidt@linux.ibm.com>
+
+       * config/rs6000/rs6000.c (rs6000_gimple_fold_builtin): Shift-right
+       and shift-left vector built-ins need to include a TRUNC_MOD_EXPR
+       for correct semantics.
+
 2019-02-11  Alan Modra  <amodra@gmail.com>
 
        * doc/invoke.texi (man page RS/6000 and PowerPC Options): Mention
index b4db03203a24abde5890b3900c1ce83cc8ab60a2..ff51e48eae46bac1a4ef738d1ba0c7025936f13a 100644 (file)
@@ -15735,13 +15735,37 @@ rs6000_gimple_fold_builtin (gimple_stmt_iterator *gsi)
     case ALTIVEC_BUILTIN_VSRAH:
     case ALTIVEC_BUILTIN_VSRAW:
     case P8V_BUILTIN_VSRAD:
-      arg0 = gimple_call_arg (stmt, 0);
-      arg1 = gimple_call_arg (stmt, 1);
-      lhs = gimple_call_lhs (stmt);
-      g = gimple_build_assign (lhs, RSHIFT_EXPR, arg0, arg1);
-      gimple_set_location (g, gimple_location (stmt));
-      gsi_replace (gsi, g, true);
-      return true;
+      {
+       arg0 = gimple_call_arg (stmt, 0);
+       arg1 = gimple_call_arg (stmt, 1);
+       lhs = gimple_call_lhs (stmt);
+       tree arg1_type = TREE_TYPE (arg1);
+       tree unsigned_arg1_type = unsigned_type_for (TREE_TYPE (arg1));
+       tree unsigned_element_type = unsigned_type_for (TREE_TYPE (arg1_type));
+       location_t loc = gimple_location (stmt);
+       /* Force arg1 into the range valid matching the arg0 type.  */
+       /* Build a vector consisting of the max valid bit-size values.  */
+       int n_elts = VECTOR_CST_NELTS (arg1);
+       tree element_size = build_int_cst (unsigned_element_type,
+                                          128 / n_elts);
+       tree_vector_builder elts (unsigned_arg1_type, n_elts, 1);
+       for (int i = 0; i < n_elts; i++)
+         elts.safe_push (element_size);
+       tree modulo_tree = elts.build ();
+       /* Modulo the provided shift value against that vector.  */
+       gimple_seq stmts = NULL;
+       tree unsigned_arg1 = gimple_build (&stmts, VIEW_CONVERT_EXPR,
+                                          unsigned_arg1_type, arg1);
+       tree new_arg1 = gimple_build (&stmts, loc, TRUNC_MOD_EXPR,
+                                     unsigned_arg1_type, unsigned_arg1,
+                                     modulo_tree);
+       gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
+       /* And finally, do the shift.  */
+       g = gimple_build_assign (lhs, RSHIFT_EXPR, arg0, new_arg1);
+       gimple_set_location (g, loc);
+       gsi_replace (gsi, g, true);
+       return true;
+      }
    /* Flavors of vector shift left.
       builtin_altivec_vsl{b,h,w} -> vsl{b,h,w}.  */
     case ALTIVEC_BUILTIN_VSLB:
@@ -15795,14 +15819,34 @@ rs6000_gimple_fold_builtin (gimple_stmt_iterator *gsi)
        arg0 = gimple_call_arg (stmt, 0);
        arg1 = gimple_call_arg (stmt, 1);
        lhs = gimple_call_lhs (stmt);
+       tree arg1_type = TREE_TYPE (arg1);
+       tree unsigned_arg1_type = unsigned_type_for (TREE_TYPE (arg1));
+       tree unsigned_element_type = unsigned_type_for (TREE_TYPE (arg1_type));
+       location_t loc = gimple_location (stmt);
        gimple_seq stmts = NULL;
        /* Convert arg0 to unsigned.  */
        tree arg0_unsigned
          = gimple_build (&stmts, VIEW_CONVERT_EXPR,
                          unsigned_type_for (TREE_TYPE (arg0)), arg0);
+       /* Force arg1 into the range valid matching the arg0 type.  */
+       /* Build a vector consisting of the max valid bit-size values.  */
+       int n_elts = VECTOR_CST_NELTS (arg1);
+       tree element_size = build_int_cst (unsigned_element_type,
+                                          128 / n_elts);
+       tree_vector_builder elts (unsigned_arg1_type, n_elts, 1);
+       for (int i = 0; i < n_elts; i++)
+         elts.safe_push (element_size);
+       tree modulo_tree = elts.build ();
+       /* Modulo the provided shift value against that vector.  */
+       tree unsigned_arg1 = gimple_build (&stmts, VIEW_CONVERT_EXPR,
+                                          unsigned_arg1_type, arg1);
+       tree new_arg1 = gimple_build (&stmts, loc, TRUNC_MOD_EXPR,
+                                     unsigned_arg1_type, unsigned_arg1,
+                                     modulo_tree);
+       /* Do the shift.  */
        tree res
          = gimple_build (&stmts, RSHIFT_EXPR,
-                         TREE_TYPE (arg0_unsigned), arg0_unsigned, arg1);
+                         TREE_TYPE (arg0_unsigned), arg0_unsigned, new_arg1);
        /* Convert result back to the lhs type.  */
        res = gimple_build (&stmts, VIEW_CONVERT_EXPR, TREE_TYPE (lhs), res);
        gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
index 37af06ad0d96247471f6b2635afc2181aac08044..78aa1bc3c4c8cb30cc7e73d55423deb0c0609abe 100644 (file)
@@ -1,3 +1,9 @@
+2019-02-11  Bill Schmidt  <wschmidt@linux.ibm.com>
+
+       * gcc.target/powerpc/vec-sld-modulo.c: New.
+       * gcc.target/powerpc/vec-srad-modulo.c: New.
+       * gcc.target/powerpc/vec-srd-modulo.c: New.
+
 2019-02-11  Martin Liska  <mliska@suse.cz>
 
        PR ipa/89009
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-sld-modulo.c b/gcc/testsuite/gcc.target/powerpc/vec-sld-modulo.c
new file mode 100644 (file)
index 0000000..de7c045
--- /dev/null
@@ -0,0 +1,42 @@
+/* Test that using a character splat to set up a shift-left
+   for a doubleword vector works correctly after gimple folding.  */
+
+/* { dg-do run { target { vsx_hw } } } */
+/* { dg-options "-O2 -mvsx" } */
+
+#include <altivec.h>
+
+typedef __vector unsigned long long vui64_t;
+
+static inline vui64_t
+vec_sldi (vui64_t vra, const unsigned int shb)
+{
+  vui64_t lshift;
+  vui64_t result;
+
+  /* Note legitimate use of wrong-type splat due to expectation that only
+     lower 6-bits are read.  */
+  lshift = (vui64_t) vec_splat_s8 (shb);
+
+  /* Vector Shift Left Doublewords based on the lower 6-bits
+     of corresponding element of lshift.  */
+  result = vec_vsld (vra, lshift);
+
+  return result;
+}
+
+__attribute__ ((noinline)) vui64_t
+test_sldi_4 (vui64_t a)
+{
+  return vec_sldi (a, 4);
+}
+
+int
+main ()
+{
+  vui64_t x = {-256, 1025};
+  x = test_sldi_4 (x);
+  if (x[0] != -4096 || x[1] != 16400)
+    __builtin_abort ();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-srad-modulo.c b/gcc/testsuite/gcc.target/powerpc/vec-srad-modulo.c
new file mode 100644 (file)
index 0000000..f18049c
--- /dev/null
@@ -0,0 +1,43 @@
+/* Test that using a character splat to set up a shift-right algebraic
+   for a doubleword vector works correctly after gimple folding.  */
+
+/* { dg-do run { target { vsx_hw } } } */
+/* { dg-options "-O2 -mvsx" } */
+
+#include <altivec.h>
+
+typedef __vector unsigned long long vui64_t;
+typedef __vector long long vi64_t;
+
+static inline vi64_t
+vec_sradi (vi64_t vra, const unsigned int shb)
+{
+  vui64_t rshift;
+  vi64_t result;
+
+  /* Note legitimate use of wrong-type splat due to expectation that only
+     lower 6-bits are read.  */
+  rshift = (vui64_t) vec_splat_s8 (shb);
+
+  /* Vector Shift Right Algebraic Doublewords based on the lower 6-bits
+     of corresponding element of rshift.  */
+  result = vec_vsrad (vra, rshift);
+
+  return result;
+}
+
+__attribute__ ((noinline)) vi64_t
+test_sradi_4 (vi64_t a)
+{
+  return vec_sradi (a, 4);
+}
+
+int
+main ()
+{
+  vi64_t x = {-256, 1025};
+  x = test_sradi_4 (x);
+  if (x[0] != -16 || x[1] != 64)
+    __builtin_abort ();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-srd-modulo.c b/gcc/testsuite/gcc.target/powerpc/vec-srd-modulo.c
new file mode 100644 (file)
index 0000000..0370f15
--- /dev/null
@@ -0,0 +1,42 @@
+/* Test that using a character splat to set up a shift-right logical
+   for a doubleword vector works correctly after gimple folding.  */
+
+/* { dg-do run { target { vsx_hw } } } */
+/* { dg-options "-O2 -mvsx" } */
+
+#include <altivec.h>
+
+typedef __vector unsigned long long vui64_t;
+
+static inline vui64_t
+vec_srdi (vui64_t vra, const unsigned int shb)
+{
+  vui64_t rshift;
+  vui64_t result;
+
+  /* Note legitimate use of wrong-type splat due to expectation that only
+     lower 6-bits are read.  */
+  rshift = (vui64_t) vec_splat_s8 (shb);
+
+  /* Vector Shift Right [Logical] Doublewords based on the lower 6-bits
+     of corresponding element of rshift.  */
+  result = vec_vsrd (vra, rshift);
+
+  return result;
+}
+
+__attribute__ ((noinline)) vui64_t
+test_srdi_4 (vui64_t a)
+{
+  return vec_srdi (a, 4);
+}
+
+int
+main ()
+{
+  vui64_t x = {1992357, 1025};
+  x = test_srdi_4 (x);
+  if (x[0] != 124522 || x[1] != 64)
+    __builtin_abort ();
+  return 0;
+}