Hi, the attached patch fixes a problem with literal pool relative references. Only if these themself reference literal pool slots using these values as displacement in addresses is valid. CSE sometimes tries to pull such values out of the literal pool. This patch rejects non-literal pool references as addresses in order to prevent that.
Bootstrapped on s390 and s390x. This together with [PATCH] recog.c: Fix RTX unsharing in change groups http://gcc.gnu.org/ml/gcc-patches/2011-03/msg00187.html fixes 54 testcases on s390. Committed to mainline. Bye, -Andreas- 2011-03-04 Andreas Krebbel <andreas.kreb...@de.ibm.com> * config/s390/s390.c (s390_decompose_address): Reject non-literal pool references in UNSPEC_LTREL_OFFSET. Index: gcc/config/s390/s390.c =================================================================== *** gcc/config/s390/s390.c.orig --- gcc/config/s390/s390.c *************** s390_decompose_address (rtx addr, struct *** 2065,2070 **** --- 2065,2080 ---- else if (GET_CODE (disp) == UNSPEC && XINT (disp, 1) == UNSPEC_LTREL_OFFSET) { + /* In case CSE pulled a non literal pool reference out of + the pool we have to reject the address. This is + especially important when loading the GOT pointer on non + zarch CPUs. In this case the literal pool contains an lt + relative offset to the _GLOBAL_OFFSET_TABLE_ label which + will most likely exceed the displacement. */ + if (GET_CODE (XVECEXP (disp, 0, 0)) != SYMBOL_REF + || !CONSTANT_POOL_ADDRESS_P (XVECEXP (disp, 0, 0))) + return false; + orig_disp = gen_rtx_CONST (Pmode, disp); if (offset) {