summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorwschmidt <wschmidt@138bc75d-0d04-0410-961f-82ee72b054a4>2015-09-03 13:52:17 +0000
committerwschmidt <wschmidt@138bc75d-0d04-0410-961f-82ee72b054a4>2015-09-03 13:52:17 +0000
commitd5d0068c5af9095d2ef85d228264d99f845f788a (patch)
tree0dacf1cdc1177d00d75d9e223e6b76bc69512a66
parent3cdaf1fe3f8d2f692c064e5899878b0b72b15ce6 (diff)
downloadgcc-d5d0068c5af9095d2ef85d228264d99f845f788a.tar.gz
[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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@227444 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog5
-rw-r--r--gcc/optabs.c9
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-shift.c20
4 files changed, 38 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index a155a4a6eb8..a3d521e43cb 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/optabs.c b/gcc/optabs.c
index e533e6efb36..79c6f06b991 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -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)
{
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 191c22b325d..4ca1b6a6e5a 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 00000000000..80b59a2d3e7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/vec-shift.c
@@ -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" } } */