Bootstrapped and regtested on s390x-redhat-linux. After r265371 (S/390: Make "b" constraint match literal pool references), satisfies_constraint_b () started accepting memory references, whose addresses do not pass legitimate_address_p (). Specifically, literal pool accesses past the end of the entry they are based on are explicitly rejected by s390_decompose_address (). This leads to ICE in early_mach pass when trying to perform UNSPEC_LTREF substitution on such addresses.
s390_decompose_address () check does not apply to relative addresses. The reason it is even made is that larl_operand () does not accept literal pool references transformed into UNSPEC_LTREF. This patch makes larl_operand () treat plain and transformed literal pool references identically. gcc/ChangeLog: 2019-02-08 Ilya Leoshkevich <i...@linux.ibm.com> PR target/89233 * config/s390/predicates.md (larl_operand): Allow UNSPEC_LTREF. * config/s390/s390.c (s390_decompose_address): Update comment. (s390_loadrelative_operand_p): Allow UNSPEC_LTREF. gcc/testsuite/ChangeLog: 2019-02-08 Ilya Leoshkevich <i...@linux.ibm.com> PR target/89233 * gcc.target/s390/pr89233.c: New test. --- gcc/config/s390/predicates.md | 21 +++++++-------------- gcc/config/s390/s390.c | 8 ++++++-- gcc/testsuite/gcc.target/s390/pr89233.c | 11 +++++++++++ 3 files changed, 24 insertions(+), 16 deletions(-) create mode 100644 gcc/testsuite/gcc.target/s390/pr89233.c diff --git a/gcc/config/s390/predicates.md b/gcc/config/s390/predicates.md index 9a3d99e7897..1af505d156d 100644 --- a/gcc/config/s390/predicates.md +++ b/gcc/config/s390/predicates.md @@ -145,20 +145,11 @@ ;; Return true if OP a valid operand for the LARL instruction. (define_predicate "larl_operand" - (match_code "label_ref, symbol_ref, const") + (match_code "label_ref, symbol_ref, const, plus, unspec") { - /* Allow labels and local symbols. */ - if (GET_CODE (op) == LABEL_REF) - return true; - if (SYMBOL_REF_P (op)) - return (!SYMBOL_FLAG_NOTALIGN2_P (op) - && SYMBOL_REF_TLS_MODEL (op) == 0 - && s390_rel_address_ok_p (op)); - - /* Everything else must have a CONST, so strip it. */ - if (GET_CODE (op) != CONST) - return false; - op = XEXP (op, 0); + /* Strip CONST to unify SYMBOL_REF and UNSPEC_LTREF handling. */ + if (GET_CODE (op) == CONST) + op = XEXP (op, 0); /* Allow adding *even* in-range constants. */ if (GET_CODE (op) == PLUS) @@ -172,9 +163,11 @@ op = XEXP (op, 0); } - /* Labels and local symbols allowed here as well. */ + /* Allow labels and local symbols. */ if (GET_CODE (op) == LABEL_REF) return true; + if (GET_CODE (op) == UNSPEC && XINT (op, 1) == UNSPEC_LTREF) + op = XVECEXP (op, 0, 0); if (SYMBOL_REF_P (op)) return (!SYMBOL_FLAG_NOTALIGN2_P (op) && SYMBOL_REF_TLS_MODEL (op) == 0 diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index 6a571a3e054..8755f613d43 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -3019,8 +3019,9 @@ s390_decompose_address (rtx addr, struct s390_address *out) orig_disp = gen_rtx_CONST (Pmode, disp); if (offset) { - /* If we have an offset, make sure it does not - exceed the size of the constant pool entry. */ + /* If we have an offset, make sure it does not exceed the size of + the constant pool entry. Otherwise we might generate an + out-of-range displacement for the base register form. */ rtx sym = XVECEXP (disp, 0, 0); if (offset >= GET_MODE_SIZE (get_pool_mode (sym))) return false; @@ -3140,6 +3141,9 @@ s390_loadrelative_operand_p (rtx addr, rtx *symref, HOST_WIDE_INT *addend) addr = XEXP (addr, 0); } + if (GET_CODE (addr) == UNSPEC && XINT (addr, 1) == UNSPEC_LTREF) + addr = XVECEXP (addr, 0, 0); + if (GET_CODE (addr) == SYMBOL_REF || (GET_CODE (addr) == UNSPEC && (XINT (addr, 1) == UNSPEC_GOTENT diff --git a/gcc/testsuite/gcc.target/s390/pr89233.c b/gcc/testsuite/gcc.target/s390/pr89233.c new file mode 100644 index 00000000000..f572bfa08d8 --- /dev/null +++ b/gcc/testsuite/gcc.target/s390/pr89233.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-march=z13 -O1" } */ + +typedef int v4si __attribute__ ((vector_size (16))); + +int +f () +{ + v4si x = {0, 1, 2, 3}; + return x[4]; +} -- 2.20.1