From: Andreas Krebbel <krebbel@linux.vnet.ibm.com>
To: gcc-patches@gcc.gnu.org
Subject: [Committed] S/390: Fix PR55718: Handle GOTENT + constant for pic addresses
Date: Thu, 10 Jan 2013 08:19:00 -0000 [thread overview]
Message-ID: <20130110081941.GA11578@bart> (raw)
Hi,
I've committed the attached patch which fixes PR 55718 by adding
support for GOTENT + constant to legitimize_pic_address in the S/390
backend.
The patch also does some rearrangements of the whole function in order
to avoid some duplicate code.
Bye,
-Andreas-
2013-01-10 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
PR target/55718
* config/s390/s390.c (s390_symref_operand_p)
(s390_loadrelative_operand_p): Merge the two functions.
(s390_check_qrst_address, print_operand_address): Add parameters
to s390_loadrelative_operand_p invokation.
(s390_check_symref_alignment): Use s390_loadrelative_operand_p.
(s390_reload_larl_operand, s390_secondary_reload): Use
s390_loadrelative_operand_p instead of s390_symref_operand_p.
(legitimize_pic_address): Handle @GOTENT and @PLT + addend.
---
gcc/config/s390/s390.c | 474 ++-!!!!!!!!!!!!!!!!!!!!!!!!!!!!
gcc/testsuite/gcc.target/s390/pr55718.c | 29 +
2 files changed, 65 insertions(+), 10 deletions(-), 428 modifications(!)
Index: gcc/config/s390/s390.c
===================================================================
*** gcc/config/s390/s390.c.orig
--- gcc/config/s390/s390.c
*************** s390_legitimate_address_without_index_p
*** 2148,2160 ****
}
! /* Return true if ADDR is of kind symbol_ref or symbol_ref + const_int
! and return these parts in SYMREF and ADDEND. You can pass NULL in
! SYMREF and/or ADDEND if you are not interested in these values.
! Literal pool references are *not* considered symbol references. */
static bool
! s390_symref_operand_p (rtx addr, rtx *symref, HOST_WIDE_INT *addend)
{
HOST_WIDE_INT tmpaddend = 0;
--- 2148,2164 ----
}
! /* Return TRUE if ADDR is an operand valid for a load/store relative
! instruction. Be aware that the alignment of the operand needs to
! be checked separately.
! Valid addresses are single references or a sum of a reference and a
! constant integer. Return these parts in SYMREF and ADDEND. You can
! pass NULL in REF and/or ADDEND if you are not interested in these
! values. Literal pool references are *not* considered symbol
! references. */
static bool
! s390_loadrelative_operand_p (rtx addr, rtx *symref, HOST_WIDE_INT *addend)
{
HOST_WIDE_INT tmpaddend = 0;
*************** s390_symref_operand_p (rtx addr, rtx *sy
*** 2163,2205 ****
if (GET_CODE (addr) == PLUS)
{
! if (GET_CODE (XEXP (addr, 0)) == SYMBOL_REF
! && !CONSTANT_POOL_ADDRESS_P (XEXP (addr, 0))
! && CONST_INT_P (XEXP (addr, 1)))
! {
! tmpaddend = INTVAL (XEXP (addr, 1));
! addr = XEXP (addr, 0);
! }
! else
return false;
- }
- else
- if (GET_CODE (addr) != SYMBOL_REF || CONSTANT_POOL_ADDRESS_P (addr))
- return false;
-
- if (symref)
- *symref = addr;
- if (addend)
- *addend = tmpaddend;
! 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
--- 2167,2192 ----
if (GET_CODE (addr) == PLUS)
{
! if (!CONST_INT_P (XEXP (addr, 1)))
return false;
! tmpaddend = INTVAL (XEXP (addr, 1));
! addr = XEXP (addr, 0);
! }
! if ((GET_CODE (addr) == SYMBOL_REF && !CONSTANT_POOL_ADDRESS_P (addr))
! || (GET_CODE (addr) == UNSPEC
! && (XINT (addr, 1) == UNSPEC_GOTENT
! || (TARGET_CPU_ZARCH && XINT (addr, 1) == UNSPEC_PLT))))
! {
! if (symref)
! *symref = addr;
! if (addend)
! *addend = tmpaddend;
! return true;
! }
! return false;
}
/* Return true if the address in OP is valid for constraint letter C
*************** s390_check_qrst_address (char c, rtx op,
*** 2215,2221 ****
/* 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. */
--- 2202,2208 ----
/* 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, NULL, NULL))
return 0;
/* Ensure literal pool references are only accepted if LIT_POOL_OK. */
*************** s390_check_symref_alignment (rtx addr, H
*** 3022,3039 ****
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;
! return (!SYMBOL_REF_NOT_NATURALLY_ALIGNED_P (symref)
! && !(addend & (alignment - 1)));
}
/* ADDR is moved into REG using larl. If ADDR isn't a valid larl
--- 3009,3029 ----
HOST_WIDE_INT addend;
rtx symref;
! if (!s390_loadrelative_operand_p (addr, &symref, &addend))
! return false;
! if (addend & (alignment - 1))
return false;
! if (GET_CODE (symref) == SYMBOL_REF
! && !SYMBOL_REF_NOT_NATURALLY_ALIGNED_P (symref))
! return true;
!
! if (GET_CODE (symref) == UNSPEC
! && alignment <= UNITS_PER_LONG)
! return true;
!
! return false;
}
/* ADDR is moved into REG using larl. If ADDR isn't a valid larl
*************** s390_reload_larl_operand (rtx reg, rtx a
*** 3046,3052 ****
HOST_WIDE_INT addend;
rtx symref;
! if (!s390_symref_operand_p (addr, &symref, &addend))
gcc_unreachable ();
if (!(addend & 1))
--- 3036,3042 ----
HOST_WIDE_INT addend;
rtx symref;
! if (!s390_loadrelative_operand_p (addr, &symref, &addend))
gcc_unreachable ();
if (!(addend & 1))
*************** s390_secondary_reload (bool in_p, rtx x,
*** 3132,3138 ****
/* On z10 several optimizer steps may generate larl operands with
an odd addend. */
if (in_p
! && s390_symref_operand_p (x, &symref, &offset)
&& mode == Pmode
&& !SYMBOL_REF_ALIGN1_P (symref)
&& (offset & 1) == 1)
--- 3122,3128 ----
/* On z10 several optimizer steps may generate larl operands with
an odd addend. */
if (in_p
! && s390_loadrelative_operand_p (x, &symref, &offset)
&& mode == Pmode
&& !SYMBOL_REF_ALIGN1_P (symref)
&& (offset & 1) == 1)
*************** s390_secondary_reload (bool in_p, rtx x,
*** 3144,3150 ****
or if the symref addend of a SI or DI move is not aligned to the
width of the access. */
if (MEM_P (x)
! && s390_symref_operand_p (XEXP (x, 0), NULL, NULL)
&& (mode == QImode || mode == TImode || FLOAT_MODE_P (mode)
|| (!TARGET_ZARCH && mode == DImode)
|| ((mode == HImode || mode == SImode || mode == DImode)
--- 3134,3140 ----
or if the symref addend of a SI or DI move is not aligned to the
width of the access. */
if (MEM_P (x)
! && s390_loadrelative_operand_p (XEXP (x, 0), NULL, NULL)
&& (mode == QImode || mode == TImode || FLOAT_MODE_P (mode)
|| (!TARGET_ZARCH && mode == DImode)
|| ((mode == HImode || mode == SImode || mode == DImode)
*************** rtx
*** 3419,3470 ****
legitimize_pic_address (rtx orig, rtx reg)
{
rtx addr = orig;
rtx new_rtx = orig;
- rtx base;
gcc_assert (!TLS_SYMBOLIC_CONST (addr));
! if (GET_CODE (addr) == LABEL_REF
! || (GET_CODE (addr) == SYMBOL_REF && SYMBOL_REF_LOCAL_P (addr)))
{
! /* This is a local symbol. */
! if (TARGET_CPU_ZARCH && larl_operand (addr, VOIDmode))
! {
! /* Access local symbols PC-relative via LARL.
! This is the same as in the non-PIC case, so it is
! handled automatically ... */
! }
else
! {
! /* Access local symbols relative to the GOT. */
! rtx temp = reg? reg : gen_reg_rtx (Pmode);
if (reload_in_progress || reload_completed)
df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
! addr = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOTOFF);
! addr = gen_rtx_CONST (Pmode, addr);
! addr = force_const_mem (Pmode, addr);
emit_move_insn (temp, addr);
! new_rtx = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, temp);
! if (reg != 0)
! {
! s390_load_address (reg, new_rtx);
! new_rtx = reg;
! }
! }
}
! else if (GET_CODE (addr) == SYMBOL_REF)
{
if (reg == 0)
reg = gen_reg_rtx (Pmode);
! if (flag_pic == 1)
{
! /* Assume GOT offset < 4k. This is handled the same way
! in both 31- and 64-bit code (@GOT). */
if (reload_in_progress || reload_completed)
df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
--- 3409,3533 ----
legitimize_pic_address (rtx orig, rtx reg)
{
rtx addr = orig;
+ rtx addend = const0_rtx;
rtx new_rtx = orig;
gcc_assert (!TLS_SYMBOLIC_CONST (addr));
! if (GET_CODE (addr) == CONST)
! addr = XEXP (addr, 0);
!
! if (GET_CODE (addr) == PLUS)
{
! addend = XEXP (addr, 1);
! addr = XEXP (addr, 0);
! }
!
! if ((GET_CODE (addr) == LABEL_REF
! || (GET_CODE (addr) == SYMBOL_REF && SYMBOL_REF_LOCAL_P (addr))
! || (GET_CODE (addr) == UNSPEC &&
! (XINT (addr, 1) == UNSPEC_GOTENT
! || (TARGET_CPU_ZARCH && XINT (addr, 1) == UNSPEC_PLT))))
! && GET_CODE (addend) == CONST_INT)
! {
! /* This can be locally addressed. */
!
! /* larl_operand requires UNSPECs to be wrapped in a const rtx. */
! rtx const_addr = (GET_CODE (addr) == UNSPEC ?
! gen_rtx_CONST (Pmode, addr) : addr);
!
! if (TARGET_CPU_ZARCH
! && larl_operand (const_addr, VOIDmode)
! && INTVAL (addend) < (HOST_WIDE_INT)1 << 31
! && INTVAL (addend) >= -((HOST_WIDE_INT)1 << 31))
! {
! if (INTVAL (addend) & 1)
! {
! /* LARL can't handle odd offsets, so emit a pair of LARL
! and LA. */
! rtx temp = reg? reg : gen_reg_rtx (Pmode);
!
! if (!DISP_IN_RANGE (INTVAL (addend)))
! {
! HOST_WIDE_INT even = INTVAL (addend) - 1;
! addr = gen_rtx_PLUS (Pmode, addr, GEN_INT (even));
! addr = gen_rtx_CONST (Pmode, addr);
! addend = const1_rtx;
! }
!
! emit_move_insn (temp, addr);
! new_rtx = gen_rtx_PLUS (Pmode, temp, addend);
!
! if (reg != 0)
! {
! s390_load_address (reg, new_rtx);
! new_rtx = reg;
! }
! }
! else
! {
! /* If the offset is even, we can just use LARL. This
! will happen automatically. */
! }
! }
else
! {
! /* No larl - Access local symbols relative to the GOT. */
! rtx temp = reg? reg : gen_reg_rtx (Pmode);
if (reload_in_progress || reload_completed)
df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
! addr = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOTOFF);
! if (addend != const0_rtx)
! addr = gen_rtx_PLUS (Pmode, addr, addend);
! addr = gen_rtx_CONST (Pmode, addr);
! addr = force_const_mem (Pmode, addr);
emit_move_insn (temp, addr);
! new_rtx = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, temp);
! if (reg != 0)
! {
! s390_load_address (reg, new_rtx);
! new_rtx = reg;
! }
! }
}
! else if (GET_CODE (addr) == SYMBOL_REF && addend == const0_rtx)
{
+ /* A non-local symbol reference without addend.
+
+ The symbol ref is wrapped into an UNSPEC to make sure the
+ proper operand modifier (@GOT or @GOTENT) will be emitted.
+ This will tell the linker to put the symbol into the GOT.
+
+ Additionally the code dereferencing the GOT slot is emitted here.
+
+ An addend to the symref needs to be added afterwards.
+ legitimize_pic_address calls itself recursively to handle
+ that case. So no need to do it here. */
+
if (reg == 0)
reg = gen_reg_rtx (Pmode);
! if (TARGET_Z10)
! {
! /* Use load relative if possible.
! lgrl <target>, sym@GOTENT */
! new_rtx = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOTENT);
! new_rtx = gen_rtx_CONST (Pmode, new_rtx);
! new_rtx = gen_const_mem (GET_MODE (reg), new_rtx);
!
! emit_move_insn (reg, new_rtx);
! new_rtx = reg;
! }
! else if (flag_pic == 1)
{
! /* Assume GOT offset is a valid displacement operand (< 4k
! or < 512k with z990). This is handled the same way in
! both 31- and 64-bit code (@GOT).
! lg <target>, sym@GOT(r12) */
if (reload_in_progress || reload_completed)
df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
*************** legitimize_pic_address (rtx orig, rtx re
*** 3479,3485 ****
else if (TARGET_CPU_ZARCH)
{
/* If the GOT offset might be >= 4k, we determine the position
! of the GOT entry via a PC-relative LARL (@GOTENT). */
rtx temp = reg ? reg : gen_reg_rtx (Pmode);
--- 3542,3550 ----
else if (TARGET_CPU_ZARCH)
{
/* If the GOT offset might be >= 4k, we determine the position
! of the GOT entry via a PC-relative LARL (@GOTENT).
! larl temp, sym@GOTENT
! lg <target>, 0(temp) */
rtx temp = reg ? reg : gen_reg_rtx (Pmode);
*************** legitimize_pic_address (rtx orig, rtx re
*** 3488,3508 ****
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;
}
else
{
/* If the GOT offset might be >= 4k, we have to load it
! from the literal pool (@GOT). */
rtx temp = reg ? reg : gen_reg_rtx (Pmode);
--- 3553,3573 ----
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;
}
else
{
/* If the GOT offset might be >= 4k, we have to load it
! from the literal pool (@GOT).
!
! lg temp, lit-litbase(r13)
! lg <target>, 0(temp)
! lit: .long sym@GOT */
rtx temp = reg ? reg : gen_reg_rtx (Pmode);
*************** legitimize_pic_address (rtx orig, rtx re
*** 3523,3697 ****
new_rtx = reg;
}
}
! else
{
! if (GET_CODE (addr) == CONST)
{
! addr = XEXP (addr, 0);
! if (GET_CODE (addr) == UNSPEC)
! {
! gcc_assert (XVECLEN (addr, 0) == 1);
! switch (XINT (addr, 1))
! {
! /* If someone moved a GOT-relative UNSPEC
! out of the literal pool, force them back in. */
! case UNSPEC_GOTOFF:
! case UNSPEC_PLTOFF:
! new_rtx = force_const_mem (Pmode, orig);
! break;
!
! /* @GOT is OK as is if small. */
! case UNSPEC_GOT:
! if (flag_pic == 2)
! new_rtx = force_const_mem (Pmode, orig);
! break;
!
! /* @GOTENT is OK as is. */
! case UNSPEC_GOTENT:
! break;
!
! /* @PLT is OK as is on 64-bit, must be converted to
! GOT-relative @PLTOFF on 31-bit. */
! case UNSPEC_PLT:
! if (!TARGET_CPU_ZARCH)
! {
! rtx temp = reg? reg : gen_reg_rtx (Pmode);
!
! if (reload_in_progress || reload_completed)
! df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
!
! addr = XVECEXP (addr, 0, 0);
! addr = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr),
! UNSPEC_PLTOFF);
! addr = gen_rtx_CONST (Pmode, addr);
! addr = force_const_mem (Pmode, addr);
! emit_move_insn (temp, addr);
!
! new_rtx = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, temp);
! if (reg != 0)
! {
! s390_load_address (reg, new_rtx);
! new_rtx = reg;
! }
! }
! break;
!
! /* Everything else cannot happen. */
! default:
! gcc_unreachable ();
! }
! }
! else
! gcc_assert (GET_CODE (addr) == PLUS);
! }
! if (GET_CODE (addr) == PLUS)
! {
! rtx op0 = XEXP (addr, 0), op1 = XEXP (addr, 1);
! gcc_assert (!TLS_SYMBOLIC_CONST (op0));
! gcc_assert (!TLS_SYMBOLIC_CONST (op1));
! /* Check first to see if this is a constant offset
! from a local symbol reference. */
! if ((GET_CODE (op0) == LABEL_REF
! || (GET_CODE (op0) == SYMBOL_REF && SYMBOL_REF_LOCAL_P (op0)))
! && GET_CODE (op1) == CONST_INT)
! {
! if (TARGET_CPU_ZARCH
! && larl_operand (op0, VOIDmode)
! && INTVAL (op1) < (HOST_WIDE_INT)1 << 31
! && INTVAL (op1) >= -((HOST_WIDE_INT)1 << 31))
! {
! if (INTVAL (op1) & 1)
! {
! /* LARL can't handle odd offsets, so emit a
! pair of LARL and LA. */
! rtx temp = reg? reg : gen_reg_rtx (Pmode);
!
! if (!DISP_IN_RANGE (INTVAL (op1)))
! {
! HOST_WIDE_INT even = INTVAL (op1) - 1;
! op0 = gen_rtx_PLUS (Pmode, op0, GEN_INT (even));
! op0 = gen_rtx_CONST (Pmode, op0);
! op1 = const1_rtx;
! }
!
! emit_move_insn (temp, op0);
! new_rtx = gen_rtx_PLUS (Pmode, temp, op1);
!
! if (reg != 0)
! {
! s390_load_address (reg, new_rtx);
! new_rtx = reg;
! }
! }
! else
! {
! /* If the offset is even, we can just use LARL.
! This will happen automatically. */
! }
! }
! else
! {
! /* Access local symbols relative to the GOT. */
!
! rtx temp = reg? reg : gen_reg_rtx (Pmode);
!
! if (reload_in_progress || reload_completed)
! df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
!
! addr = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op0),
! UNSPEC_GOTOFF);
! addr = gen_rtx_PLUS (Pmode, addr, op1);
! addr = gen_rtx_CONST (Pmode, addr);
! addr = force_const_mem (Pmode, addr);
! emit_move_insn (temp, addr);
!
! new_rtx = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, temp);
! if (reg != 0)
! {
! s390_load_address (reg, new_rtx);
! new_rtx = reg;
! }
! }
! }
!
! /* Now, check whether it is a GOT relative symbol plus offset
! that was pulled out of the literal pool. Force it back in. */
!
! else if (GET_CODE (op0) == UNSPEC
! && GET_CODE (op1) == CONST_INT
! && XINT (op0, 1) == UNSPEC_GOTOFF)
! {
! gcc_assert (XVECLEN (op0, 0) == 1);
! new_rtx = force_const_mem (Pmode, orig);
! }
! /* Otherwise, compute the sum. */
! else
! {
! base = legitimize_pic_address (XEXP (addr, 0), reg);
! new_rtx = legitimize_pic_address (XEXP (addr, 1),
! base == reg ? NULL_RTX : reg);
! if (GET_CODE (new_rtx) == CONST_INT)
! new_rtx = plus_constant (Pmode, base, INTVAL (new_rtx));
! else
{
! if (GET_CODE (new_rtx) == PLUS && CONSTANT_P (XEXP (new_rtx, 1)))
! {
! base = gen_rtx_PLUS (Pmode, base, XEXP (new_rtx, 0));
! new_rtx = XEXP (new_rtx, 1);
! }
! new_rtx = gen_rtx_PLUS (Pmode, base, new_rtx);
}
! if (GET_CODE (new_rtx) == CONST)
! new_rtx = XEXP (new_rtx, 0);
! new_rtx = force_operand (new_rtx, 0);
}
}
}
return new_rtx;
}
--- 3588,3681 ----
new_rtx = reg;
}
}
! else if (GET_CODE (addr) == UNSPEC && GET_CODE (addend) == CONST_INT)
{
! gcc_assert (XVECLEN (addr, 0) == 1);
! switch (XINT (addr, 1))
{
! /* These address symbols (or PLT slots) relative to the GOT
! (not GOT slots!). In general this will exceed the
! displacement range so these value belong into the literal
! pool. */
! case UNSPEC_GOTOFF:
! case UNSPEC_PLTOFF:
! new_rtx = force_const_mem (Pmode, orig);
! break;
! /* For -fPIC the GOT size might exceed the displacement
! range so make sure the value is in the literal pool. */
! case UNSPEC_GOT:
! if (flag_pic == 2)
! new_rtx = force_const_mem (Pmode, orig);
! break;
! /* For @GOTENT larl is used. This is handled like local
! symbol refs. */
! case UNSPEC_GOTENT:
! gcc_unreachable ();
! break;
! /* @PLT is OK as is on 64-bit, must be converted to
! GOT-relative @PLTOFF on 31-bit. */
! case UNSPEC_PLT:
! if (!TARGET_CPU_ZARCH)
! {
! rtx temp = reg? reg : gen_reg_rtx (Pmode);
!
! if (reload_in_progress || reload_completed)
! df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
!
! addr = XVECEXP (addr, 0, 0);
! addr = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr),
! UNSPEC_PLTOFF);
! if (addend != const0_rtx)
! addr = gen_rtx_PLUS (Pmode, addr, addend);
! addr = gen_rtx_CONST (Pmode, addr);
! addr = force_const_mem (Pmode, addr);
! emit_move_insn (temp, addr);
! new_rtx = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, temp);
! if (reg != 0)
{
! s390_load_address (reg, new_rtx);
! new_rtx = reg;
}
+ }
+ else
+ /* On 64 bit larl can be used. This case is handled like
+ local symbol refs. */
+ gcc_unreachable ();
+ break;
+
+ /* Everything else cannot happen. */
+ default:
+ gcc_unreachable ();
+ }
+ }
+ else if (addend != const0_rtx)
+ {
+ /* Otherwise, compute the sum. */
! rtx base = legitimize_pic_address (addr, reg);
! new_rtx = legitimize_pic_address (addend,
! base == reg ? NULL_RTX : reg);
! if (GET_CODE (new_rtx) == CONST_INT)
! new_rtx = plus_constant (Pmode, base, INTVAL (new_rtx));
! else
! {
! if (GET_CODE (new_rtx) == PLUS && CONSTANT_P (XEXP (new_rtx, 1)))
! {
! base = gen_rtx_PLUS (Pmode, base, XEXP (new_rtx, 0));
! new_rtx = XEXP (new_rtx, 1);
}
+ new_rtx = gen_rtx_PLUS (Pmode, base, new_rtx);
}
+
+ if (GET_CODE (new_rtx) == CONST)
+ new_rtx = XEXP (new_rtx, 0);
+ new_rtx = force_operand (new_rtx, 0);
}
+
return new_rtx;
}
*************** print_operand_address (FILE *file, rtx a
*** 5350,5356 ****
{
struct s390_address ad;
! if (s390_loadrelative_operand_p (addr))
{
if (!TARGET_Z10)
{
--- 5334,5340 ----
{
struct s390_address ad;
! if (s390_loadrelative_operand_p (addr, NULL, NULL))
{
if (!TARGET_Z10)
{
Index: gcc/testsuite/gcc.target/s390/pr55718.c
===================================================================
*** /dev/null
--- gcc/testsuite/gcc.target/s390/pr55718.c
***************
*** 0 ****
--- 1,29 ----
+ /* PR target/55717 */
+
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -march=z10 -fPIC" } */
+
+ extern char temp[];
+ short ansi_value[256];
+ void terminal_state(void)
+ {
+ static const char *puc[] = { "", "<", "=", ">", "?", 0};
+ int i, j, k, l, modes_found;
+ char buf[256];
+ k = (int) __builtin_strlen(temp);
+ for (j = l = 0; j < 255 && j - l < 50; j++)
+ {
+ __builtin_sprintf(temp, "\033[%s%d$p", puc[i], j);
+ if (ansi_value[1])
+ {
+ l = j;
+ buf[k] = '\0';
+ put_crlf();
+ ptextln(buf);
+ buf[k++] = ' ';
+ k = (int) __builtin_strlen(temp);
+ }
+ }
+ for (i = j = 0; j < modes_found; j = ++i >> 1)
+ ;
+ }
reply other threads:[~2013-01-10 8:19 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20130110081941.GA11578@bart \
--to=krebbel@linux.vnet.ibm.com \
--cc=gcc-patches@gcc.gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).