Commit f5e336b1 by Claudiu Zissulescu Committed by Claudiu Zissulescu

[ARC] Use GOTOFFPC relocation for pc-relative accesses.

gcc/
2016-06-16  Claudiu Zissulescu  <claziss@synopsys.com>
	    Joern Rennecke  <joern.rennecke@embecosm.com>

	* config/arc/arc.c (arc_print_operand_address): Handle pc-relative
	addresses.
	(arc_needs_pcl_p): Add GOTOFFPC.
	(arc_legitimate_pic_addr_p): Likewise.
	(arc_output_pic_addr_const): Likewise.
	(arc_legitimize_pic_address): Generate a pc-relative address using
	GOTOFFPC.
	(arc_output_libcall): Use @pcl syntax.
	(arc_delegitimize_address_0): Delegitimize ARC_UNSPEC_GOTOFFPC.
	* config/arc/arc.md ("unspec"): Add ARC_UNSPEC_GOTOFFPC.
	(*movsi_insn): Use @pcl syntax.
	(doloop_begin_i): Likewise.

Co-Authored-By: Joern Rennecke <joern.rennecke@embecosm.com>

From-SVN: r237525
parent 7f7fa20f
2016-06-16 Claudiu Zissulescu <claziss@synopsys.com>
Joern Rennecke <joern.rennecke@embecosm.com>
* config/arc/arc.c (arc_print_operand_address): Handle pc-relative
addresses.
(arc_needs_pcl_p): Add GOTOFFPC.
(arc_legitimate_pic_addr_p): Likewise.
(arc_output_pic_addr_const): Likewise.
(arc_legitimize_pic_address): Generate a pc-relative address using
GOTOFFPC.
(arc_output_libcall): Use @pcl syntax.
(arc_delegitimize_address_0): Delegitimize ARC_UNSPEC_GOTOFFPC.
* config/arc/arc.md ("unspec"): Add ARC_UNSPEC_GOTOFFPC.
(*movsi_insn): Use @pcl syntax.
(doloop_begin_i): Likewise.
2016-06-16 Martin Liska <mliska@suse.cz> 2016-06-16 Martin Liska <mliska@suse.cz>
* predict.def: Define a new predictor. * predict.def: Define a new predictor.
......
...@@ -3528,7 +3528,8 @@ arc_print_operand_address (FILE *file , rtx addr) ...@@ -3528,7 +3528,8 @@ arc_print_operand_address (FILE *file , rtx addr)
|| XINT (c, 1) == UNSPEC_TLS_IE)) || XINT (c, 1) == UNSPEC_TLS_IE))
|| (GET_CODE (c) == PLUS || (GET_CODE (c) == PLUS
&& GET_CODE (XEXP (c, 0)) == UNSPEC && GET_CODE (XEXP (c, 0)) == UNSPEC
&& (XINT (XEXP (c, 0), 1) == UNSPEC_TLS_OFF))) && (XINT (XEXP (c, 0), 1) == UNSPEC_TLS_OFF
|| XINT (XEXP (c, 0), 1) == ARC_UNSPEC_GOTOFFPC)))
{ {
arc_output_pic_addr_const (file, c, 0); arc_output_pic_addr_const (file, c, 0);
break; break;
...@@ -4636,6 +4637,7 @@ arc_needs_pcl_p (rtx x) ...@@ -4636,6 +4637,7 @@ arc_needs_pcl_p (rtx x)
switch (XINT (x, 1)) switch (XINT (x, 1))
{ {
case ARC_UNSPEC_GOT: case ARC_UNSPEC_GOT:
case ARC_UNSPEC_GOTOFFPC:
case UNSPEC_TLS_GD: case UNSPEC_TLS_GD:
case UNSPEC_TLS_IE: case UNSPEC_TLS_IE:
return true; return true;
...@@ -4698,9 +4700,10 @@ arc_legitimate_pic_addr_p (rtx addr) ...@@ -4698,9 +4700,10 @@ arc_legitimate_pic_addr_p (rtx addr)
|| XVECLEN (addr, 0) != 1) || XVECLEN (addr, 0) != 1)
return false; return false;
/* Must be one of @GOT, @GOTOFF, @tlsgd, tlsie. */ /* Must be one of @GOT, @GOTOFF, @GOTOFFPC, @tlsgd, tlsie. */
if (XINT (addr, 1) != ARC_UNSPEC_GOT if (XINT (addr, 1) != ARC_UNSPEC_GOT
&& XINT (addr, 1) != ARC_UNSPEC_GOTOFF && XINT (addr, 1) != ARC_UNSPEC_GOTOFF
&& XINT (addr, 1) != ARC_UNSPEC_GOTOFFPC
&& XINT (addr, 1) != UNSPEC_TLS_GD && XINT (addr, 1) != UNSPEC_TLS_GD
&& XINT (addr, 1) != UNSPEC_TLS_IE) && XINT (addr, 1) != UNSPEC_TLS_IE)
return false; return false;
...@@ -4917,26 +4920,15 @@ arc_legitimize_pic_address (rtx orig, rtx oldx) ...@@ -4917,26 +4920,15 @@ arc_legitimize_pic_address (rtx orig, rtx oldx)
else if (!flag_pic) else if (!flag_pic)
return orig; return orig;
else if (CONSTANT_POOL_ADDRESS_P (addr) || SYMBOL_REF_LOCAL_P (addr)) else if (CONSTANT_POOL_ADDRESS_P (addr) || SYMBOL_REF_LOCAL_P (addr))
{ return gen_rtx_CONST (Pmode,
/* This symbol may be referenced via a displacement from the gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr),
PIC base address (@GOTOFF). */ ARC_UNSPEC_GOTOFFPC));
/* FIXME: if we had a way to emit pc-relative adds that /* This symbol must be referenced via a load from the Global
don't create a GOT entry, we could do without the use of Offset Table (@GOTPC). */
the gp register. */ pat = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), ARC_UNSPEC_GOT);
crtl->uses_pic_offset_table = 1; pat = gen_rtx_CONST (Pmode, pat);
pat = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), ARC_UNSPEC_GOTOFF); pat = gen_const_mem (Pmode, pat);
pat = gen_rtx_CONST (Pmode, pat);
pat = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, pat);
}
else
{
/* This symbol must be referenced via a load from the
Global Offset Table (@GOTPC). */
pat = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), ARC_UNSPEC_GOT);
pat = gen_rtx_CONST (Pmode, pat);
pat = gen_const_mem (Pmode, pat);
}
if (oldx == NULL) if (oldx == NULL)
oldx = gen_reg_rtx (Pmode); oldx = gen_reg_rtx (Pmode);
...@@ -4952,6 +4944,7 @@ arc_legitimize_pic_address (rtx orig, rtx oldx) ...@@ -4952,6 +4944,7 @@ arc_legitimize_pic_address (rtx orig, rtx oldx)
if (GET_CODE (addr) == UNSPEC) if (GET_CODE (addr) == UNSPEC)
{ {
/* Check that the unspec is one of the ones we generate? */ /* Check that the unspec is one of the ones we generate? */
return orig;
} }
else else
gcc_assert (GET_CODE (addr) == PLUS); gcc_assert (GET_CODE (addr) == PLUS);
...@@ -5105,6 +5098,9 @@ arc_output_pic_addr_const (FILE * file, rtx x, int code) ...@@ -5105,6 +5098,9 @@ arc_output_pic_addr_const (FILE * file, rtx x, int code)
case ARC_UNSPEC_GOTOFF: case ARC_UNSPEC_GOTOFF:
suffix = "@gotoff"; suffix = "@gotoff";
break; break;
case ARC_UNSPEC_GOTOFFPC:
suffix = "@pcl", pcrel = true;
break;
case ARC_UNSPEC_PLT: case ARC_UNSPEC_PLT:
suffix = "@plt"; suffix = "@plt";
break; break;
...@@ -5389,6 +5385,7 @@ arc_legitimate_constant_p (machine_mode mode, rtx x) ...@@ -5389,6 +5385,7 @@ arc_legitimate_constant_p (machine_mode mode, rtx x)
{ {
case ARC_UNSPEC_PLT: case ARC_UNSPEC_PLT:
case ARC_UNSPEC_GOTOFF: case ARC_UNSPEC_GOTOFF:
case ARC_UNSPEC_GOTOFFPC:
case ARC_UNSPEC_GOT: case ARC_UNSPEC_GOT:
case UNSPEC_TLS_GD: case UNSPEC_TLS_GD:
case UNSPEC_TLS_IE: case UNSPEC_TLS_IE:
...@@ -7648,7 +7645,7 @@ arc_output_libcall (const char *fname) ...@@ -7648,7 +7645,7 @@ arc_output_libcall (const char *fname)
|| (TARGET_MEDIUM_CALLS && arc_ccfsm_cond_exec_p ())) || (TARGET_MEDIUM_CALLS && arc_ccfsm_cond_exec_p ()))
{ {
if (flag_pic) if (flag_pic)
sprintf (buf, "add r12,pcl,@%s-(.&-4)\n\tjl%%!%%* [r12]", fname); sprintf (buf, "add r12,pcl,@%s@pcl\n\tjl%%!%%* [r12]", fname);
else else
sprintf (buf, "jl%%! @%s", fname); sprintf (buf, "jl%%! @%s", fname);
} }
...@@ -8578,13 +8575,21 @@ arc_legitimize_address (rtx orig_x, rtx oldx, machine_mode mode) ...@@ -8578,13 +8575,21 @@ arc_legitimize_address (rtx orig_x, rtx oldx, machine_mode mode)
static rtx static rtx
arc_delegitimize_address_0 (rtx x) arc_delegitimize_address_0 (rtx x)
{ {
rtx u, gp; rtx u, gp, p;
if (GET_CODE (x) == CONST && GET_CODE (u = XEXP (x, 0)) == UNSPEC) if (GET_CODE (x) == CONST && GET_CODE (u = XEXP (x, 0)) == UNSPEC)
{ {
if (XINT (u, 1) == ARC_UNSPEC_GOT) if (XINT (u, 1) == ARC_UNSPEC_GOT
|| XINT (u, 1) == ARC_UNSPEC_GOTOFFPC)
return XVECEXP (u, 0, 0); return XVECEXP (u, 0, 0);
} }
else if (GET_CODE (x) == CONST && GET_CODE (p = XEXP (x, 0)) == PLUS
&& GET_CODE (u = XEXP (p, 0)) == UNSPEC
&& (XINT (u, 1) == ARC_UNSPEC_GOT
|| XINT (u, 1) == ARC_UNSPEC_GOTOFFPC))
return gen_rtx_CONST
(GET_MODE (x),
gen_rtx_PLUS (GET_MODE (p), XVECEXP (u, 0, 0), XEXP (p, 1)));
else if (GET_CODE (x) == PLUS else if (GET_CODE (x) == PLUS
&& ((REG_P (gp = XEXP (x, 0)) && ((REG_P (gp = XEXP (x, 0))
&& REGNO (gp) == PIC_OFFSET_TABLE_REGNUM) && REGNO (gp) == PIC_OFFSET_TABLE_REGNUM)
......
...@@ -102,6 +102,7 @@ ...@@ -102,6 +102,7 @@
;; UNSPEC_GOT 4 symbol to be rerenced through the GOT ;; UNSPEC_GOT 4 symbol to be rerenced through the GOT
;; UNSPEC_GOTOFF 5 Local symbol.To be referenced relative to the ;; UNSPEC_GOTOFF 5 Local symbol.To be referenced relative to the
;; GOTBASE.(Referenced as @GOTOFF) ;; GOTBASE.(Referenced as @GOTOFF)
;; UNSPEC_GOTOFFPC 6 Local symbol. To be referenced pc-relative.
;; ---------------------------------------------------------------------------- ;; ----------------------------------------------------------------------------
(define_c_enum "unspec" [ (define_c_enum "unspec" [
...@@ -111,6 +112,7 @@ ...@@ -111,6 +112,7 @@
ARC_UNSPEC_PLT ARC_UNSPEC_PLT
ARC_UNSPEC_GOT ARC_UNSPEC_GOT
ARC_UNSPEC_GOTOFF ARC_UNSPEC_GOTOFF
ARC_UNSPEC_GOTOFFPC
UNSPEC_TLS_GD UNSPEC_TLS_GD
UNSPEC_TLS_LD UNSPEC_TLS_LD
UNSPEC_TLS_IE UNSPEC_TLS_IE
...@@ -725,7 +727,7 @@ ...@@ -725,7 +727,7 @@
* return INTVAL (operands[1]) & 0xffffff ? \"movbi.cl %0,%1 >> %p1,%p1,8;8\" : \"movbi.cl %0,%L1 >> 24,24,8;9\"; * return INTVAL (operands[1]) & 0xffffff ? \"movbi.cl %0,%1 >> %p1,%p1,8;8\" : \"movbi.cl %0,%L1 >> 24,24,8;9\";
mov%? %0,%1 ;10 mov%? %0,%1 ;10
add %0,%S1 ;11 add %0,%S1 ;11
* return arc_get_unalign () ? \"add %0,pcl,%1-.+2\" : \"add %0,pcl,%1-.\"; add %0,pcl,%1@pcl ;12
mov%? %0,%S1%& ;13 mov%? %0,%S1%& ;13
mov%? %0,%S1 ;14 mov%? %0,%S1 ;14
ld%? %0,%1%& ;15 ld%? %0,%1%& ;15
...@@ -5155,7 +5157,7 @@ ...@@ -5155,7 +5157,7 @@
/* ??? Can do better for when a scratch register /* ??? Can do better for when a scratch register
is known. But that would require extra testing. */ is known. But that would require extra testing. */
arc_clear_unalign (); arc_clear_unalign ();
return ".p2align 2\;push_s r0\;add r0,pcl,24\;sr r0,[2]; LP_START\;add r0,pcl,.L__GCC__LP%1-.+2\;sr r0,[3]; LP_END\;pop_s r0"; return ".p2align 2\;push_s r0\;add r0,pcl,24\;sr r0,[2]; LP_START\;add r0,pcl,.L__GCC__LP%1@pcl\;sr r0,[3]; LP_END\;pop_s r0";
} }
output_asm_insn ((size < 2048 output_asm_insn ((size < 2048
? "lp .L__GCC__LP%1" : "sr .L__GCC__LP%1,[3]; LP_END"), ? "lp .L__GCC__LP%1" : "sr .L__GCC__LP%1,[3]; LP_END"),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment