optabs.c (expand_binop): Don't create a broadcast vector with a source element wider...
authorBill Schmidt <wschmidt@linux.vnet.ibm.com>
Thu, 3 Sep 2015 13:52:17 +0000 (13:52 +0000)
committerWilliam Schmidt <wschmidt@gcc.gnu.org>
Thu, 3 Sep 2015 13:52:17 +0000 (13:52 +0000)
[gcc]

2015-09-03  Bill Schmidt  <wschmidt@linux.vnet.ibm.com>

* optabs.c (expand_binop): Don't create a broadcast vector with a
source element wider than the inner mode.

[gcc/testsuite]

2015-09-03  Bill Schmidt  <wschmidt@linux.vnet.ibm.com>

* gcc.target/powerpc/vec-shift.c: New test.

From-SVN: r227444

gcc/ChangeLog
gcc/optabs.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/powerpc/vec-shift.c [new file with mode: 0644]

index a155a4a6eb8e5437c11741f62845c5f3f57248df..a3d521e43cb8dc5ae393335ef61c09dcf2197384 100644 (file)
@@ -1,3 +1,8 @@
+2015-09-03  Bill Schmidt  <wschmidt@linux.vnet.ibm.com>
+
+       * optabs.c (expand_binop): Don't create a broadcast vector with a
+       source element wider than the inner mode.
+
 2015-09-03  Richard Biener  <rguenther@suse.de>
 
        * varasm.c (output_constant): Use fold_convert instead of
index e533e6efb3612cf43e85fecb99f983b213d068ce..79c6f06b9913ba1c8076e3abad02b13192eac158 100644 (file)
@@ -1608,6 +1608,15 @@ expand_binop (machine_mode mode, optab binoptab, rtx op0, rtx op1,
 
       if (otheroptab && optab_handler (otheroptab, mode) != CODE_FOR_nothing)
        {
+         /* The scalar may have been extended to be too wide.  Truncate
+            it back to the proper size to fit in the broadcast vector.  */
+         machine_mode inner_mode = GET_MODE_INNER (mode);
+         if (!CONST_INT_P (op1)
+             && (GET_MODE_BITSIZE (inner_mode)
+                 < GET_MODE_BITSIZE (GET_MODE (op1))))
+           op1 = force_reg (inner_mode,
+                            simplify_gen_unary (TRUNCATE, inner_mode, op1,
+                                                GET_MODE (op1)));
          rtx vop1 = expand_vector_broadcast (mode, op1);
          if (vop1)
            {
index 191c22b325dc497a648fcc1930a90574ef64e737..4ca1b6a6e5aebf4ce465b319ac4071f1ffaedd4e 100644 (file)
@@ -1,3 +1,7 @@
+2015-09-03  Bill Schmidt  <wschmidt@linux.vnet.ibm.com>
+
+       * gcc.target/powerpc/vec-shift.c: New test.
+
 2015-09-03  Tom de Vries  <tom@codesourcery.com>
 
        PR tree-optimization/65637
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-shift.c b/gcc/testsuite/gcc.target/powerpc/vec-shift.c
new file mode 100644 (file)
index 0000000..80b59a2
--- /dev/null
@@ -0,0 +1,20 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-require-effective-target powerpc_altivec_ok } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power7" } } */
+/* { dg-options "-mcpu=power7 -O2" } */
+
+/* This used to ICE.  During gimplification, "i" is widened to an unsigned
+   int.  We used to fail at expand time as we tried to cram an SImode item
+   into a QImode memory slot.  This has been fixed to properly truncate the
+   shift amount when splatting it into a vector.  */
+
+typedef unsigned char v16ui __attribute__((vector_size(16)));
+
+v16ui vslb(v16ui v, unsigned char i)
+{
+       return v << i;
+}
+
+/* { dg-final { scan-assembler "vspltb" } } */
+/* { dg-final { scan-assembler "vslb" } } */