From: Stefan Schulze Frielinghaus <[email protected]>
When expand_mult handles a constant vector multiplier where the scalar
operand is a CONST_WIDE_INT, then also look through the vector mode
while determining the shift amount since here we need the scalar mode.
Note, when we call later on into expand_shift we need the vector mode,
i.e., only for the shift amount we need the scalar mode.
I guess it would have been sound to call unconditionally into
GET_MODE_INNER, i.e., even for scalars (kinda similar as for
GET_MODE_UNIT_BITSIZE from above), however, I think checking for
VECTOR_MODE_P here makes the intend explicit.
PR middle-end/127474
gcc/ChangeLog:
* expmed.cc (expand_mult): Look through vector mode.
gcc/testsuite/ChangeLog:
* gcc.target/s390/pr127474.c: New test.
---
Bootstrapped and regtested for
- aarch64-unknown-linux-gnu
- powerpc64le-unknown-linux-gnu
- s390x-ibm-linux-gnu
- x86_64-pc-linux-gnu
Ok for mainline?
gcc/expmed.cc | 4 +++-
gcc/testsuite/gcc.target/s390/pr127474.c | 11 +++++++++++
2 files changed, 14 insertions(+), 1 deletion(-)
create mode 100644 gcc/testsuite/gcc.target/s390/pr127474.c
diff --git a/gcc/expmed.cc b/gcc/expmed.cc
index c6494484251..b82c0bb10db 100644
--- a/gcc/expmed.cc
+++ b/gcc/expmed.cc
@@ -3633,7 +3633,9 @@ expand_mult (machine_mode mode, rtx op0, rtx op1, rtx
target,
else if (CONST_DOUBLE_AS_INT_P (scalar_op1))
#endif
{
- int shift = wi::exact_log2 (rtx_mode_t (scalar_op1, mode));
+ machine_mode scalar_mode = VECTOR_MODE_P (mode)
+ ? GET_MODE_INNER (mode) : mode;
+ int shift = wi::exact_log2 (rtx_mode_t (scalar_op1, scalar_mode));
/* Perfect power of 2 (other than 1, which is handled above). */
if (shift > 0)
return expand_shift (LSHIFT_EXPR, mode, op0,
diff --git a/gcc/testsuite/gcc.target/s390/pr127474.c
b/gcc/testsuite/gcc.target/s390/pr127474.c
new file mode 100644
index 00000000000..a5580ee3b6a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/pr127474.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=z17" } */
+
+/* Previously we ICE'd in expand_mult when dealing with a CONST_WIDE_INT. */
+
+typedef __int128 v1ti __attribute__ ((vector_size (16)));
+
+v1ti foo (v1ti x)
+{
+ return x * (v1ti){(__int128)123456789 << 64 | (__int128)123456789};
+}
--
2.55.0