summaryrefslogtreecommitdiff
path: root/gcc/config/s390
diff options
context:
space:
mode:
authorkrebbel <krebbel@138bc75d-0d04-0410-961f-82ee72b054a4>2008-07-14 06:56:46 +0000
committerkrebbel <krebbel@138bc75d-0d04-0410-961f-82ee72b054a4>2008-07-14 06:56:46 +0000
commit08b5e26232fa08e766f268d46fad5c0714ae14b4 (patch)
tree248042c82d6c3e0c548673cd33a0225dc6bfff91 /gcc/config/s390
parent89768577114030eb69375ca94b7e749ae2428868 (diff)
downloadgcc-08b5e26232fa08e766f268d46fad5c0714ae14b4.tar.gz
2008-07-14 Andreas Krebbel <krebbel1@de.ibm.com>
PR target/36745 * config/s390/s390.c: (s390_secondary_reload): Add a secondary reload for symbol refs moved to r0 with -fPIC. (legitimize_pic_address): Use the target register as temporary reg if possible. (emit_symbolic_move): Adjust comment. * config/s390/s390.md (reloadsi_PIC_addr, reloaddi_PIC_addr): New expanders. 2008-07-14 Andreas Krebbel <krebbel1@de.ibm.com> PR target/36745 * g++.dg/torture/pr36745.C: New testcase. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@137777 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/s390')
-rw-r--r--gcc/config/s390/s390.c23
-rw-r--r--gcc/config/s390/s390.md10
2 files changed, 30 insertions, 3 deletions
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index b9f231729a6..936e0a0ead2 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -3026,6 +3026,14 @@ s390_secondary_reload (bool in_p, rtx x, enum reg_class class,
}
}
+ /* A scratch address register is needed when a symbolic constant is
+ copied to r0 compiling with -fPIC. In other cases the target
+ register might be used as temporary (see legitimize_pic_address). */
+ if (in_p && SYMBOLIC_CONST (x) && flag_pic == 2 && class != ADDR_REGS)
+ sri->icode = (TARGET_64BIT ?
+ CODE_FOR_reloaddi_PIC_addr :
+ CODE_FOR_reloadsi_PIC_addr);
+
/* Either scratch or no register needed. */
return NO_REGS;
}
@@ -3272,7 +3280,10 @@ legitimize_pic_address (rtx orig, rtx reg)
/* If the GOT offset might be >= 4k, we determine the position
of the GOT entry via a PC-relative LARL (@GOTENT). */
- rtx temp = gen_reg_rtx (Pmode);
+ rtx temp = reg ? reg : gen_reg_rtx (Pmode);
+
+ gcc_assert (REGNO (temp) >= FIRST_PSEUDO_REGISTER
+ || REGNO_REG_CLASS (REGNO (temp)) == ADDR_REGS);
new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOTENT);
new = gen_rtx_CONST (Pmode, new);
@@ -3287,7 +3298,10 @@ legitimize_pic_address (rtx orig, rtx reg)
/* If the GOT offset might be >= 4k, we have to load it
from the literal pool (@GOT). */
- rtx temp = gen_reg_rtx (Pmode);
+ rtx temp = reg ? reg : gen_reg_rtx (Pmode);
+
+ gcc_assert (REGNO (temp) >= FIRST_PSEUDO_REGISTER
+ || REGNO_REG_CLASS (REGNO (temp)) == ADDR_REGS);
if (reload_in_progress || reload_completed)
df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
@@ -3707,7 +3721,10 @@ legitimize_tls_address (rtx addr, rtx reg)
return new;
}
-/* Emit insns to move operands[1] into operands[0]. */
+/* Emit insns making the address in operands[1] valid for a standard
+ move to operands[0]. operands[1] is replaced by an address which
+ should be used instead of the former RTX to emit the move
+ pattern. */
void
emit_symbolic_move (rtx *operands)
diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md
index d33cc5c3267..ec5b7532977 100644
--- a/gcc/config/s390/s390.md
+++ b/gcc/config/s390/s390.md
@@ -1175,6 +1175,16 @@
DONE;
})
+(define_expand "reload<mode>_PIC_addr"
+ [(parallel [(match_operand 0 "register_operand" "=d")
+ (match_operand 1 "larl_operand" "")
+ (match_operand:P 2 "register_operand" "=a")])]
+ ""
+{
+ rtx new = legitimize_pic_address (operands[1], operands[2]);
+ emit_move_insn (operands[0], new);
+})
+
;
; movdi instruction pattern(s).
;