https://gcc.gnu.org/g:b27fa6a7ca86a9b885cb4dbe8a55991e7fb666f0
commit r12-10967-gb27fa6a7ca86a9b885cb4dbe8a55991e7fb666f0 Author: Stefan Schulze Frielinghaus <stefa...@gcc.gnu.org> Date: Thu Feb 13 09:13:06 2025 +0100 s390: Fix s390_valid_shift_count() for TI mode [PR118835] 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 ...)). Thus, be more strict here and accept only CONST_INT operands. Done by replacing immediate_operand() with const_int_operand() which is enough since the former only additionally checks for LEGITIMATE_PIC_OPERAND_P and targetm.legitimate_constant_p which are always true for CONST_INT operands. 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. (cherry picked from commit ac9806dae30d07ab082ac341fe5646987753adcb) Diff: --- gcc/config/s390/s390.cc | 35 ++++++++++++++++++-------------- gcc/testsuite/gcc.target/s390/pr118835.c | 21 +++++++++++++++++++ 2 files changed, 41 insertions(+), 15 deletions(-) diff --git a/gcc/config/s390/s390.cc b/gcc/config/s390/s390.cc index a8f804ffe4f7..4e7a01ae6c9d 100644 --- a/gcc/config/s390/s390.cc +++ b/gcc/config/s390/s390.cc @@ -3216,26 +3216,31 @@ 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; + /* Accept only CONST_INT as immediates, i.e., 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_int_operand (imm, GET_MODE (imm))) + return false; - HOST_WIDE_INT val = INTVAL (imm); - if (implicit_mask > 0 - && (val & implicit_mask) != implicit_mask) - return false; + HOST_WIDE_INT val = INTVAL (imm); + if (implicit_mask > 0 + && (val & implicit_mask) != implicit_mask) + return false; - op = op1; - } + 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 000000000000..1ca6cd95543b --- /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; +}