Hi, so far we were missing to use load relative when accessing GOT slots. Fixed with the attached patch.
Committed to mainline after tested on s390 and s390x. Bye, -Andreas- 2012-09-03 Andreas Krebbel <andreas.kreb...@de.ibm.com> * config/s390/s390.c (s390_loadrelative_operand_p): New function. (s390_check_qrst_address, print_operand_address): Use s390_loadrelative_operand_p instead of s390_symref_operand_p. (s390_check_symref_alignment): Accept pointer size alignment for GOT slots. (legitimize_pic_address): Use load relative on z10 or later. --- gcc/config/s390/s390.c | 36 +++++++++++++++++++++++-!!!!!!!!!!!! 1 file changed, 23 insertions(+), 1 deletion(-), 12 modifications(!) Index: gcc/config/s390/s390.c =================================================================== *** gcc/config/s390/s390.c.orig --- gcc/config/s390/s390.c *************** s390_symref_operand_p (rtx addr, rtx *sy *** 2123,2128 **** --- 2123,2144 ---- return true; } + /* Return TRUE if ADDR is an operand valid for a load/store relative + instructions. Be aware that the alignment of the operand needs to + be checked separately. */ + static bool + s390_loadrelative_operand_p (rtx addr) + { + if (GET_CODE (addr) == CONST) + addr = XEXP (addr, 0); + + /* Enable load relative for symbol@GOTENT. */ + if (GET_CODE (addr) == UNSPEC + && XINT (addr, 1) == UNSPEC_GOTENT) + return true; + + return s390_symref_operand_p (addr, NULL, NULL); + } /* Return true if the address in OP is valid for constraint letter C if wrapped in a MEM rtx. Set LIT_POOL_OK to true if it literal *************** s390_check_qrst_address (char c, rtx op, *** 2137,2143 **** /* This check makes sure that no symbolic address (except literal pool references) are accepted by the R or T constraints. */ ! if (s390_symref_operand_p (op, NULL, NULL)) return 0; /* Ensure literal pool references are only accepted if LIT_POOL_OK. */ --- 2153,2159 ---- /* This check makes sure that no symbolic address (except literal pool references) are accepted by the R or T constraints. */ ! if (s390_loadrelative_operand_p (op)) return 0; /* Ensure literal pool references are only accepted if LIT_POOL_OK. */ *************** s390_check_symref_alignment (rtx addr, H *** 2941,2946 **** --- 2957,2969 ---- HOST_WIDE_INT addend; rtx symref; + /* Accept symbol@GOTENT with pointer size alignment. */ + if (GET_CODE (addr) == CONST + && GET_CODE (XEXP (addr, 0)) == UNSPEC + && XINT (XEXP (addr, 0), 1) == UNSPEC_GOTENT + && alignment <= UNITS_PER_LONG) + return true; + if (!s390_symref_operand_p (addr, &symref, &addend)) return false; *************** legitimize_pic_address (rtx orig, rtx re *** 3398,3406 **** new_rtx = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOTENT); new_rtx = gen_rtx_CONST (Pmode, new_rtx); - emit_move_insn (temp, new_rtx); ! new_rtx = gen_const_mem (Pmode, temp); emit_move_insn (reg, new_rtx); new_rtx = reg; } --- 3421,3434 ---- new_rtx = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOTENT); new_rtx = gen_rtx_CONST (Pmode, new_rtx); ! if (!TARGET_Z10) ! { ! emit_move_insn (temp, new_rtx); ! new_rtx = gen_const_mem (Pmode, temp); ! } ! else ! new_rtx = gen_const_mem (GET_MODE (reg), new_rtx); emit_move_insn (reg, new_rtx); new_rtx = reg; } *************** print_operand_address (FILE *file, rtx a *** 5250,5256 **** { struct s390_address ad; ! if (s390_symref_operand_p (addr, NULL, NULL)) { if (!TARGET_Z10) { --- 5278,5284 ---- { struct s390_address ad; ! if (s390_loadrelative_operand_p (addr)) { if (!TARGET_Z10) {