aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/s390
diff options
context:
space:
mode:
authorStefan Schulze Frielinghaus <stefansf@gcc.gnu.org>2025-02-13 09:13:06 +0100
committerStefan Schulze Frielinghaus <stefansf@gcc.gnu.org>2025-02-13 09:13:06 +0100
commitac9806dae30d07ab082ac341fe5646987753adcb (patch)
tree22e951b14f866308d6e7fc21373ad7dfb33365ff /gcc/config/s390
parent77d01927bd7c989d431035251a5c196fe39bcec9 (diff)
downloadgcc-ac9806dae30d07ab082ac341fe5646987753adcb.zip
gcc-ac9806dae30d07ab082ac341fe5646987753adcb.tar.gz
gcc-ac9806dae30d07ab082ac341fe5646987753adcb.tar.bz2
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.
Diffstat (limited to 'gcc/config/s390')
-rw-r--r--gcc/config/s390/s390.cc35
1 files changed, 20 insertions, 15 deletions
diff --git a/gcc/config/s390/s390.cc b/gcc/config/s390/s390.cc
index 1d96df4..29aef50 100644
--- a/gcc/config/s390/s390.cc
+++ b/gcc/config/s390/s390.cc
@@ -3510,26 +3510,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);