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