During combine we may end up with
(set (reg:DI 66 [ _6 ])
(ashift:DI (reg:DI 72 [ x ])
(subreg:QI (and:TI (reg:TI 67 [ _1 ])
(const_wide_int 0x0aaaaaaaaaaaaaabf))
15)))
where the shift count operand does not trivially fit the scheme of
address operands. Reject those operands, especially since
strip_address_mutations() expects expressions of the form
(and ... (const_int ...)) and fails for (and ... (const_wide_int ...)).
While on it, fix indentation of the if block.
gcc/ChangeLog:
PR target/118835
* config/s390/s390.cc (s390_valid_shift_count): Reject shift
count operands which do not trivially fit the scheme of
address operands.
gcc/testsuite/ChangeLog:
* gcc.target/s390/pr118835.c: New test.
---
Bootstrap and regtest are still running. Assuming they finish without
regressions and there are no further comments, I will push this.
gcc/config/s390/s390.cc | 37 ++++++++++++++----------
gcc/testsuite/gcc.target/s390/pr118835.c | 21 ++++++++++++++
2 files changed, 43 insertions(+), 15 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/s390/pr118835.c
diff --git a/gcc/config/s390/s390.cc b/gcc/config/s390/s390.cc
index 1d96df49fea..c2636c54613 100644
--- a/gcc/config/s390/s390.cc
+++ b/gcc/config/s390/s390.cc
@@ -3510,26 +3510,33 @@ s390_valid_shift_count (rtx op, HOST_WIDE_INT
implicit_mask)
/* Check for an and with proper constant. */
if (GET_CODE (op) == AND)
- {
- rtx op1 = XEXP (op, 0);
- rtx imm = XEXP (op, 1);
+ {
+ rtx op1 = XEXP (op, 0);
+ rtx imm = XEXP (op, 1);
- if (GET_CODE (op1) == SUBREG && subreg_lowpart_p (op1))
- op1 = XEXP (op1, 0);
+ if (GET_CODE (op1) == SUBREG && subreg_lowpart_p (op1))
+ op1 = XEXP (op1, 0);
- if (!(register_operand (op1, GET_MODE (op1)) || GET_CODE (op1) == PLUS))
- return false;
+ if (!(register_operand (op1, GET_MODE (op1)) || GET_CODE (op1) == PLUS))
+ return false;
- if (!immediate_operand (imm, GET_MODE (imm)))
- return false;
+ if (!immediate_operand (imm, GET_MODE (imm)))
+ return false;
- HOST_WIDE_INT val = INTVAL (imm);
- if (implicit_mask > 0
- && (val & implicit_mask) != implicit_mask)
- return false;
+ /* Reject shift count operands which do not trivially fit the scheme of
+ address operands. Especially since strip_address_mutations() expects
+ expressions of the form (and ... (const_int ...)) and fails for
+ (and ... (const_wide_int ...)). */
+ if (CONST_WIDE_INT_P (imm))
+ return false;
- op = op1;
- }
+ HOST_WIDE_INT val = INTVAL (imm);
+ if (implicit_mask > 0
+ && (val & implicit_mask) != implicit_mask)
+ return false;
+
+ op = op1;
+ }
/* Check the rest. */
return s390_decompose_addrstyle_without_index (op, NULL, NULL);
diff --git a/gcc/testsuite/gcc.target/s390/pr118835.c
b/gcc/testsuite/gcc.target/s390/pr118835.c
new file mode 100644
index 00000000000..1ca6cd95543
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/pr118835.c
@@ -0,0 +1,21 @@
+/* { dg-do compile { target int128 } } */
+/* { dg-options "-O2" } */
+
+/* During combine we may end up with patterns of the form
+
+ (set (reg:DI 66 [ _6 ])
+ (ashift:DI (reg:DI 72 [ x ])
+ (subreg:QI (and:TI (reg:TI 67 [ _1 ])
+ (const_wide_int 0x0aaaaaaaaaaaaaabf))
+ 15)))
+
+ which should be rejected since the shift count does not trivially fit the
+ scheme of address operands. */
+
+long
+test (long x, int y)
+{
+ __int128 z = 0xAAAAAAAAAAAAAABF;
+ z &= y;
+ return x << z;
+}
--
2.47.0