The original AltiVec manuals had the immediate lane number in the
splat instructions as a 5-bit number, but anything too big has no
defined meaning, and gas will choke on it too.  This patch disallows
it in the instruction patterns as well as in the builtins.  This
solves PR86987.

Tested on powerpc64-linux {-m32,-m64} and on powerpc64le-linux
(together with Will's recent patches).  Committing to trunk.


2018-09-25  Segher Boessenkool  <seg...@kernel.crashing.org>

        PR target/86987
        * config/rs6000/altivec.md (altivec_vspltb): Use
        const_0_to_15_operand instead of u5bit_cint_operand.
        (*altivec_vspltb_internal): Ditto.
        (altivec_vspltb_direct): Ditto.
        (altivec_vsplth): Use const_0_to_7_operand instead of
        u5bit_cint_operand.
        (*altivec_vsplth_internal): Ditto.
        (altivec_vsplth_direct): Ditto.
        (altivec_vspltw): Use const_0_to_3_operand instead of
        u5bit_cint_operand.
        (*altivec_vspltw_internal): Ditto.
        (altivec_vspltw_direct): Ditto.
        (altivec_vspltsf): Ditto.
        (*altivec_vspltsf_internal): Ditto.
        * config/rs6000/rs6000.c (rs6000_expand_binop_builtin): Handle the
        various splats with the proper size immediate.  Reorder the various
        cases by ascending size of immediate, and pout all such together.

---
 gcc/config/rs6000/altivec.md | 22 +++++++-------
 gcc/config/rs6000/rs6000.c   | 70 +++++++++++++++++++++++++++++++-------------
 2 files changed, 61 insertions(+), 31 deletions(-)

diff --git a/gcc/config/rs6000/altivec.md b/gcc/config/rs6000/altivec.md
index 1ddf580..345be09 100644
--- a/gcc/config/rs6000/altivec.md
+++ b/gcc/config/rs6000/altivec.md
@@ -1861,7 +1861,7 @@ (define_insn "altivec_vsumsws_direct"
 (define_expand "altivec_vspltb"
   [(use (match_operand:V16QI 0 "register_operand"))
    (use (match_operand:V16QI 1 "register_operand"))
-   (use (match_operand:QI 2 "u5bit_cint_operand"))]
+   (use (match_operand:QI 2 "const_0_to_15_operand"))]
   "TARGET_ALTIVEC"
 {
   rtvec v = gen_rtvec (1, operands[2]);
@@ -1877,7 +1877,7 @@ (define_insn "*altivec_vspltb_internal"
         (vec_duplicate:V16QI
         (vec_select:QI (match_operand:V16QI 1 "register_operand" "v")
                        (parallel
-                        [(match_operand:QI 2 "u5bit_cint_operand" "")]))))]
+                        [(match_operand:QI 2 "const_0_to_15_operand" "")]))))]
   "TARGET_ALTIVEC"
 {
   if (!BYTES_BIG_ENDIAN)
@@ -1890,7 +1890,7 @@ (define_insn "*altivec_vspltb_internal"
 (define_insn "altivec_vspltb_direct"
   [(set (match_operand:V16QI 0 "register_operand" "=v")
         (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
-                      (match_operand:QI 2 "u5bit_cint_operand" "i")]
+                      (match_operand:QI 2 "const_0_to_15_operand" "i")]
                       UNSPEC_VSPLT_DIRECT))]
   "TARGET_ALTIVEC"
   "vspltb %0,%1,%2"
@@ -1899,7 +1899,7 @@ (define_insn "altivec_vspltb_direct"
 (define_expand "altivec_vsplth"
   [(use (match_operand:V8HI 0 "register_operand"))
    (use (match_operand:V8HI 1 "register_operand"))
-   (use (match_operand:QI 2 "u5bit_cint_operand"))]
+   (use (match_operand:QI 2 "const_0_to_7_operand"))]
   "TARGET_ALTIVEC"
 {
   rtvec v = gen_rtvec (1, operands[2]);
@@ -1915,7 +1915,7 @@ (define_insn "*altivec_vsplth_internal"
        (vec_duplicate:V8HI
         (vec_select:HI (match_operand:V8HI 1 "register_operand" "v")
                        (parallel
-                        [(match_operand:QI 2 "u5bit_cint_operand" "")]))))]
+                        [(match_operand:QI 2 "const_0_to_7_operand" "")]))))]
   "TARGET_ALTIVEC"
 {
   if (!BYTES_BIG_ENDIAN)
@@ -1928,7 +1928,7 @@ (define_insn "*altivec_vsplth_internal"
 (define_insn "altivec_vsplth_direct"
   [(set (match_operand:V8HI 0 "register_operand" "=v")
         (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
-                      (match_operand:QI 2 "u5bit_cint_operand" "i")]
+                      (match_operand:QI 2 "const_0_to_7_operand" "i")]
                      UNSPEC_VSPLT_DIRECT))]
   "TARGET_ALTIVEC"
   "vsplth %0,%1,%2"
@@ -1937,7 +1937,7 @@ (define_insn "altivec_vsplth_direct"
 (define_expand "altivec_vspltw"
   [(use (match_operand:V4SI 0 "register_operand"))
    (use (match_operand:V4SI 1 "register_operand"))
-   (use (match_operand:QI 2 "u5bit_cint_operand"))]
+   (use (match_operand:QI 2 "const_0_to_3_operand"))]
   "TARGET_ALTIVEC"
 {
   rtvec v = gen_rtvec (1, operands[2]);
@@ -1953,7 +1953,7 @@ (define_insn "*altivec_vspltw_internal"
        (vec_duplicate:V4SI
         (vec_select:SI (match_operand:V4SI 1 "register_operand" "v")
                        (parallel
-                        [(match_operand:QI 2 "u5bit_cint_operand" "i")]))))]
+                        [(match_operand:QI 2 "const_0_to_3_operand" "i")]))))]
   "TARGET_ALTIVEC"
 {
   if (!BYTES_BIG_ENDIAN)
@@ -1966,7 +1966,7 @@ (define_insn "*altivec_vspltw_internal"
 (define_insn "altivec_vspltw_direct"
   [(set (match_operand:V4SI 0 "register_operand" "=v")
         (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
-                      (match_operand:QI 2 "u5bit_cint_operand" "i")]
+                      (match_operand:QI 2 "const_0_to_3_operand" "i")]
                      UNSPEC_VSPLT_DIRECT))]
   "TARGET_ALTIVEC"
   "vspltw %0,%1,%2"
@@ -1975,7 +1975,7 @@ (define_insn "altivec_vspltw_direct"
 (define_expand "altivec_vspltsf"
   [(use (match_operand:V4SF 0 "register_operand"))
    (use (match_operand:V4SF 1 "register_operand"))
-   (use (match_operand:QI 2 "u5bit_cint_operand"))]
+   (use (match_operand:QI 2 "const_0_to_3_operand"))]
   "TARGET_ALTIVEC"
 {
   rtvec v = gen_rtvec (1, operands[2]);
@@ -1991,7 +1991,7 @@ (define_insn "*altivec_vspltsf_internal"
        (vec_duplicate:V4SF
         (vec_select:SF (match_operand:V4SF 1 "register_operand" "v")
                        (parallel
-                        [(match_operand:QI 2 "u5bit_cint_operand" "i")]))))]
+                        [(match_operand:QI 2 "const_0_to_3_operand" "i")]))))]
   "VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
 {
   if (!BYTES_BIG_ENDIAN)
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 5c7ab2b..baa5851 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -13456,13 +13456,58 @@ rs6000_expand_binop_builtin (enum insn_code icode, 
tree exp, rtx target)
   if (arg0 == error_mark_node || arg1 == error_mark_node)
     return const0_rtx;
 
-  if (icode == CODE_FOR_altivec_vcfux
+  if (icode == CODE_FOR_unpackv1ti
+          || icode == CODE_FOR_unpackkf
+          || icode == CODE_FOR_unpacktf
+          || icode == CODE_FOR_unpackif
+          || icode == CODE_FOR_unpacktd)
+    {
+      /* Only allow 1-bit unsigned literals. */
+      STRIP_NOPS (arg1);
+      if (TREE_CODE (arg1) != INTEGER_CST
+         || !IN_RANGE (TREE_INT_CST_LOW (arg1), 0, 1))
+       {
+         error ("argument 2 must be a 1-bit unsigned literal");
+         return CONST0_RTX (tmode);
+       }
+    }
+  else if (icode == CODE_FOR_altivec_vspltw)
+    {
+      /* Only allow 2-bit unsigned literals.  */
+      STRIP_NOPS (arg1);
+      if (TREE_CODE (arg1) != INTEGER_CST
+         || TREE_INT_CST_LOW (arg1) & ~3)
+       {
+         error ("argument 2 must be a 2-bit unsigned literal");
+         return CONST0_RTX (tmode);
+       }
+    }
+  else if (icode == CODE_FOR_altivec_vsplth)
+    {
+      /* Only allow 3-bit unsigned literals.  */
+      STRIP_NOPS (arg1);
+      if (TREE_CODE (arg1) != INTEGER_CST
+         || TREE_INT_CST_LOW (arg1) & ~7)
+       {
+         error ("argument 2 must be a 3-bit unsigned literal");
+         return CONST0_RTX (tmode);
+       }
+    }
+  else if (icode == CODE_FOR_altivec_vspltb)
+    {
+      /* Only allow 4-bit unsigned literals.  */
+      STRIP_NOPS (arg1);
+      if (TREE_CODE (arg1) != INTEGER_CST
+         || TREE_INT_CST_LOW (arg1) & ~15)
+       {
+         error ("argument 2 must be a 4-bit unsigned literal");
+         return CONST0_RTX (tmode);
+       }
+    }
+  else if (icode == CODE_FOR_altivec_vcfux
       || icode == CODE_FOR_altivec_vcfsx
       || icode == CODE_FOR_altivec_vctsxs
-      || icode == CODE_FOR_altivec_vctuxs
-      || icode == CODE_FOR_altivec_vspltb
-      || icode == CODE_FOR_altivec_vsplth
-      || icode == CODE_FOR_altivec_vspltw)
+      || icode == CODE_FOR_altivec_vctuxs)
     {
       /* Only allow 5-bit unsigned literals.  */
       STRIP_NOPS (arg1);
@@ -13507,21 +13552,6 @@ rs6000_expand_binop_builtin (enum insn_code icode, 
tree exp, rtx target)
          return CONST0_RTX (tmode);
        }
     }
-  else if (icode == CODE_FOR_unpackv1ti
-          || icode == CODE_FOR_unpackkf
-          || icode == CODE_FOR_unpacktf
-          || icode == CODE_FOR_unpackif
-          || icode == CODE_FOR_unpacktd)
-    {
-      /* Only allow 1-bit unsigned literals. */
-      STRIP_NOPS (arg1);
-      if (TREE_CODE (arg1) != INTEGER_CST
-         || !IN_RANGE (TREE_INT_CST_LOW (arg1), 0, 1))
-       {
-         error ("argument 2 must be a 1-bit unsigned literal");
-         return CONST0_RTX (tmode);
-       }
-    }
 
   if (target == 0
       || GET_MODE (target) != tmode
-- 
1.8.3.1

Reply via email to