nios2.md (unspec): Add UNSPEC_PIC_GOTOFF_SYM enum.

2014-02-20  Chung-Lin Tang  <cltang@codesourcery.com>
	    Sandra Loosemore  <sandra@codesourcery.com>

	gcc/
	* config/nios2/nios2.md (unspec): Add UNSPEC_PIC_GOTOFF_SYM enum.
	* config/nios2/nios2.c (nios2_function_profiler):
	Add -fPIC (flag_pic == 2) support.
	(nios2_handle_custom_fpu_cfg): Fix warning parameter.
	(nios2_large_offset_p): New function.
	(nios2_unspec_reloc_p): Move up position, update to use
	nios2_large_offset_p.
	(nios2_unspec_address): Remove function.
	(nios2_unspec_offset): New function.
	(nios2_large_got_address): New function.
	(nios2_got_address): Add large offset support.
	(nios2_legitimize_tls_address): Update usage of removed and new
	functions.
	(nios2_symbol_binds_local_p): New function.
	(nios2_load_pic_address): Add -fPIC (flag_pic == 2) support.
	(nios2_legitimize_address): Update to use nios2_large_offset_p.
	(nios2_emit_move_sequence): Avoid legitimizing (const (unspec ...)).
	(nios2_print_operand): Merge H/L processing, add hiadj/lo
	processing for (const (unspec ...)).
	(nios2_unspec_reloc_name): Add UNSPEC_PIC_GOTOFF_SYM case.

	gcc/testsuite/
	* gcc.target/nios2/biggot-1.c: New.
	* gcc.target/nios2/biggot-2.c: New.

	libgcc/
	* config/nios2/t-nios2 (CRTSTUFF_T_CFLAGS): Add -mno-gpopt.
	* config/nios2/crti.S: Remove .file directive.
	* config/nios2/crtn.S: Likewise.

From-SVN: r207965
This commit is contained in:
Chung-Lin Tang 2014-02-20 16:35:10 +00:00
parent 4bbfc5fa4d
commit 95ce7613d5
10 changed files with 286 additions and 46 deletions

View file

@ -1,3 +1,27 @@
2014-02-20 Chung-Lin Tang <cltang@codesourcery.com>
Sandra Loosemore <sandra@codesourcery.com>
* config/nios2/nios2.md (unspec): Add UNSPEC_PIC_GOTOFF_SYM enum.
* config/nios2/nios2.c (nios2_function_profiler):
Add -fPIC (flag_pic == 2) support.
(nios2_handle_custom_fpu_cfg): Fix warning parameter.
(nios2_large_offset_p): New function.
(nios2_unspec_reloc_p): Move up position, update to use
nios2_large_offset_p.
(nios2_unspec_address): Remove function.
(nios2_unspec_offset): New function.
(nios2_large_got_address): New function.
(nios2_got_address): Add large offset support.
(nios2_legitimize_tls_address): Update usage of removed and new
functions.
(nios2_symbol_binds_local_p): New function.
(nios2_load_pic_address): Add -fPIC (flag_pic == 2) support.
(nios2_legitimize_address): Update to use nios2_large_offset_p.
(nios2_emit_move_sequence): Avoid legitimizing (const (unspec ...)).
(nios2_print_operand): Merge H/L processing, add hiadj/lo
processing for (const (unspec ...)).
(nios2_unspec_reloc_name): Add UNSPEC_PIC_GOTOFF_SYM case.
2014-02-20 Richard Biener <rguenther@suse.de>
* tree-cfg.c (replace_uses_by): Mark altered BBs before

View file

@ -664,7 +664,7 @@ void
nios2_function_profiler (FILE *file, int labelno ATTRIBUTE_UNUSED)
{
fprintf (file, "\tmov\tr8, ra\n");
if (flag_pic)
if (flag_pic == 1)
{
fprintf (file, "\tnextpc\tr2\n");
fprintf (file, "\t1: movhi\tr3, %%hiadj(_gp_got - 1b)\n");
@ -673,6 +673,18 @@ nios2_function_profiler (FILE *file, int labelno ATTRIBUTE_UNUSED)
fprintf (file, "\tldw\tr2, %%call(_mcount)(r2)\n");
fprintf (file, "\tcallr\tr2\n");
}
else if (flag_pic == 2)
{
fprintf (file, "\tnextpc\tr2\n");
fprintf (file, "\t1: movhi\tr3, %%hiadj(_gp_got - 1b)\n");
fprintf (file, "\taddi\tr3, r3, %%lo(_gp_got - 1b)\n");
fprintf (file, "\tadd\tr2, r2, r3\n");
fprintf (file, "\tmovhi\tr3, %%call_hiadj(_mcount)\n");
fprintf (file, "\taddi\tr3, %%call_lo(_mcount)\n");
fprintf (file, "\tadd\tr3, r2, r3\n");
fprintf (file, "\tldw\tr2, 0(r3)\n");
fprintf (file, "\tcallr\tr2\n");
}
else
fprintf (file, "\tcall\t_mcount\n");
fprintf (file, "\tmov\tra, r8\n");
@ -920,7 +932,7 @@ nios2_handle_custom_fpu_cfg (const char *cfgname, const char *endp,
}
else
warning (0, "ignoring unrecognized switch %<-mcustom-fpu-cfg%> "
"value %<%s%>", cfg);
"value %<%s%>", cfgname);
/* Guard against errors in the standard configurations. */
nios2_custom_check_insns ();
@ -1116,20 +1128,64 @@ nios2_call_tls_get_addr (rtx ti)
return ret;
}
static rtx
nios2_unspec_address (rtx loc, rtx base_reg, int unspec)
/* Return true for large offsets requiring hiadj/lo relocation pairs. */
static bool
nios2_large_offset_p (int unspec)
{
rtx unspec_offset =
gen_rtx_CONST (Pmode, gen_rtx_UNSPEC (Pmode, gen_rtvec (1, loc),
unspec));
return gen_rtx_PLUS (Pmode, base_reg, unspec_offset);
gcc_assert (nios2_unspec_reloc_name (unspec) != NULL);
if (flag_pic == 2
/* FIXME: TLS GOT offset relocations will eventually also get this
treatment, after binutils support for those are also completed. */
&& (unspec == UNSPEC_PIC_SYM || unspec == UNSPEC_PIC_CALL_SYM))
return true;
/* 'gotoff' offsets are always hiadj/lo. */
if (unspec == UNSPEC_PIC_GOTOFF_SYM)
return true;
return false;
}
/* Return true for conforming unspec relocations. Also used in
constraints.md and predicates.md. */
bool
nios2_unspec_reloc_p (rtx op)
{
return (GET_CODE (op) == CONST
&& GET_CODE (XEXP (op, 0)) == UNSPEC
&& ! nios2_large_offset_p (XINT (XEXP (op, 0), 1)));
}
/* Helper to generate unspec constant. */
static rtx
nios2_unspec_offset (rtx loc, int unspec)
{
return gen_rtx_CONST (Pmode, gen_rtx_UNSPEC (Pmode, gen_rtvec (1, loc),
unspec));
}
/* Generate GOT pointer based address with large offset. */
static rtx
nios2_large_got_address (rtx sym, rtx offset)
{
rtx addr = gen_reg_rtx (Pmode);
emit_insn (gen_add3_insn (addr, pic_offset_table_rtx,
force_reg (Pmode, offset)));
return addr;
}
/* Generate a GOT pointer based address. */
static rtx
nios2_got_address (rtx loc, int unspec)
{
rtx offset = nios2_unspec_offset (loc, unspec);
crtl->uses_pic_offset_table = 1;
return nios2_unspec_address (loc, pic_offset_table_rtx, unspec);
if (nios2_large_offset_p (unspec))
return nios2_large_got_address (loc, offset);
return gen_rtx_PLUS (Pmode, pic_offset_table_rtx, offset);
}
/* Generate the code to access LOC, a thread local SYMBOL_REF. The
@ -1151,8 +1207,8 @@ nios2_legitimize_tls_address (rtx loc)
case TLS_MODEL_LOCAL_DYNAMIC:
tmp = gen_reg_rtx (Pmode);
emit_move_insn (tmp, nios2_got_address (loc, UNSPEC_ADD_TLS_LDM));
return nios2_unspec_address (loc, nios2_call_tls_get_addr (tmp),
UNSPEC_ADD_TLS_LDO);
return gen_rtx_PLUS (Pmode, nios2_call_tls_get_addr (tmp),
nios2_unspec_offset (loc, UNSPEC_ADD_TLS_LDO));
case TLS_MODEL_INITIAL_EXEC:
tmp = gen_reg_rtx (Pmode);
@ -1163,8 +1219,8 @@ nios2_legitimize_tls_address (rtx loc)
case TLS_MODEL_LOCAL_EXEC:
tp = gen_rtx_REG (Pmode, TP_REGNO);
return nios2_unspec_address (loc, tp, UNSPEC_ADD_TLS_LE);
return gen_rtx_PLUS (Pmode, tp,
nios2_unspec_offset (loc, UNSPEC_ADD_TLS_LE));
default:
gcc_unreachable ();
}
@ -1599,6 +1655,15 @@ nios2_section_type_flags (tree decl, const char *name, int reloc)
return flags;
}
/* Return true if SYMBOL_REF X binds locally. */
static bool
nios2_symbol_binds_local_p (const_rtx x)
{
return (SYMBOL_REF_DECL (x)
? targetm.binds_local_p (SYMBOL_REF_DECL (x))
: SYMBOL_REF_LOCAL_P (x));
}
/* Position independent code related. */
@ -1616,8 +1681,13 @@ nios2_load_pic_register (void)
static rtx
nios2_load_pic_address (rtx sym, int unspec)
{
rtx gotaddr = nios2_got_address (sym, unspec);
return gen_const_mem (Pmode, gotaddr);
if (flag_pic == 2
&& GET_CODE (sym) == SYMBOL_REF
&& nios2_symbol_binds_local_p (sym))
/* Under -fPIC, generate a GOTOFF address for local symbols. */
return nios2_got_address (sym, UNSPEC_PIC_GOTOFF_SYM);
return gen_const_mem (Pmode, nios2_got_address (sym, unspec));
}
/* Nonzero if the constant value X is a legitimate general operand
@ -1626,6 +1696,11 @@ nios2_load_pic_address (rtx sym, int unspec)
bool
nios2_legitimate_pic_operand_p (rtx x)
{
if (GET_CODE (x) == CONST
&& GET_CODE (XEXP (x, 0)) == UNSPEC
&& nios2_large_offset_p (XINT (XEXP (x, 0), 1)))
return true;
return ! (GET_CODE (x) == SYMBOL_REF
|| GET_CODE (x) == LABEL_REF || GET_CODE (x) == CONST);
}
@ -1701,7 +1776,7 @@ nios2_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
rtx unspec, offset, reg = XEXP (x, 0);
split_const (XEXP (x, 1), &unspec, &offset);
if (GET_CODE (unspec) == UNSPEC
&& nios2_unspec_reloc_name (XINT (unspec, 1)) != NULL
&& !nios2_large_offset_p (XINT (unspec, 1))
&& offset != const0_rtx)
{
unspec = copy_rtx (unspec);
@ -1728,7 +1803,8 @@ nios2_emit_move_sequence (rtx *operands, enum machine_mode mode)
}
if (GET_CODE (from) == SYMBOL_REF || GET_CODE (from) == LABEL_REF
|| GET_CODE (from) == CONST)
|| (GET_CODE (from) == CONST
&& GET_CODE (XEXP (from, 0)) != UNSPEC))
from = nios2_legitimize_constant_address (from);
operands[0] = to;
@ -1845,20 +1921,23 @@ nios2_print_operand (FILE *file, rtx op, int letter)
output_addr_const (file, op);
return;
}
else if (letter == 'H')
{
fprintf (file, "%%hiadj(");
else if (letter == 'H' || letter == 'L')
{
fprintf (file, "%%");
if (GET_CODE (op) == CONST
&& GET_CODE (XEXP (op, 0)) == UNSPEC)
{
rtx unspec = XEXP (op, 0);
int unspec_reloc = XINT (unspec, 1);
gcc_assert (nios2_large_offset_p (unspec_reloc));
fprintf (file, "%s_", nios2_unspec_reloc_name (unspec_reloc));
op = XVECEXP (unspec, 0, 0);
}
fprintf (file, letter == 'H' ? "hiadj(" : "lo(");
output_addr_const (file, op);
fprintf (file, ")");
return;
}
else if (letter == 'L')
{
fprintf (file, "%%lo(");
output_addr_const (file, op);
fprintf (file, ")");
return;
}
}
break;
case SUBREG:
@ -1910,6 +1989,8 @@ nios2_unspec_reloc_name (int unspec)
return "got";
case UNSPEC_PIC_CALL_SYM:
return "call";
case UNSPEC_PIC_GOTOFF_SYM:
return "gotoff";
case UNSPEC_LOAD_TLS_IE:
return "tls_ie";
case UNSPEC_ADD_TLS_LE:
@ -1925,16 +2006,6 @@ nios2_unspec_reloc_name (int unspec)
}
}
/* Return true for conforming unspec relocations. Also used in
constraints.md and predicates.md. */
bool
nios2_unspec_reloc_p (rtx op)
{
return (GET_CODE (op) == CONST
&& GET_CODE (XEXP (op, 0)) == UNSPEC
&& nios2_unspec_reloc_name (XINT (XEXP (op, 0), 1)) != NULL);
}
/* Implement TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA. */
static bool
nios2_output_addr_const_extra (FILE *file, rtx op)

View file

@ -73,6 +73,7 @@
UNSPEC_LOAD_GOT_REGISTER
UNSPEC_PIC_SYM
UNSPEC_PIC_CALL_SYM
UNSPEC_PIC_GOTOFF_SYM
UNSPEC_TLS
UNSPEC_TLS_LDM
UNSPEC_LOAD_TLS_IE

View file

@ -1,3 +1,8 @@
2014-02-20 Sandra Loosemore <sandra@codesourcery.com>
* gcc.target/nios2/biggot-1.c: New.
* gcc.target/nios2/biggot-2.c: New.
2014-02-20 Martin Jambor <mjambor@suse.cz>
PR ipa/55260

View file

@ -0,0 +1,67 @@
/* Check that the GOT pointer is being initialized correctly to allow
access to the full 64K maximum GOT size for -fpic, rather than only 32K
(which would happen if the GOT pointer points to the base of the GOT,
as the GOT16 and CALL16 relocations are signed). */
/* { dg-options "-fpic" } */
/* { dg-do run { target nios2-*-linux-gnu } } */
extern void abort (void);
static int n = 0;
void
doit (int m)
{
if (m != n)
abort ();
n++;
}
#define X(N) \
void f_##N (void) { doit (0x##N); }
#define F(N) f_##N ();
#define A(N) \
X(N##0) X(N##1) X(N##2) X(N##3) X(N##4) X(N##5) X(N##6) X(N##7) \
X(N##8) X(N##9) X(N##a) X(N##b) X(N##c) X(N##d) X(N##e) X(N##f) \
void f_##N (void) { \
F(N##0) F(N##1) F(N##2) F(N##3) F(N##4) F(N##5) F(N##6) F(N##7) \
F(N##8) F(N##9) F(N##a) F(N##b) F(N##c) F(N##d) F(N##e) F(N##f) \
}
#define B(N) \
A(N##0) A(N##1) A(N##2) A(N##3) A(N##4) A(N##5) A(N##6) A(N##7) \
A(N##8) A(N##9) A(N##a) A(N##b) A(N##c) A(N##d) A(N##e) A(N##f) \
void f_##N (void) { \
F(N##0) F(N##1) F(N##2) F(N##3) F(N##4) F(N##5) F(N##6) F(N##7) \
F(N##8) F(N##9) F(N##a) F(N##b) F(N##c) F(N##d) F(N##e) F(N##f) \
}
#define C(N) \
B(N##0) B(N##1) B(N##2) B(N##3) B(N##4) B(N##5) B(N##6) B(N##7) \
B(N##8) B(N##9) B(N##a) B(N##b) B(N##c) B(N##d) B(N##e) B(N##f) \
void f_##N (void) { \
F(N##0) F(N##1) F(N##2) F(N##3) F(N##4) F(N##5) F(N##6) F(N##7) \
F(N##8) F(N##9) F(N##a) F(N##b) F(N##c) F(N##d) F(N##e) F(N##f) \
}
#define D(N) \
C(N##0) C(N##1) C(N##2) \
void f_##N (void) { \
F(N##0) F(N##1) F(N##2) \
}
/* This defines 16x16x16x3 leaf functions, requiring something over
48K of GOT space overall. */
D(0)
int
main (void)
{
f_0 ();
if (n != 16*16*16*3)
abort ();
return 0;
}

View file

@ -0,0 +1,68 @@
/* Check that a program that requires large-GOT support builds and
executes without error. This program defines a very large number
of leaf functions; compiled with -fPIC, they all require GOT
entries, which will overflow the range addressible by 16-bit -fpic
offsets by about a factor of 2. */
/* { dg-options "-fPIC" } */
/* { dg-do run { target nios2-*-linux-gnu } } */
extern void abort (void);
static int n = 0;
void
doit (int m)
{
if (m != n)
abort ();
n++;
}
#define X(N) \
void f_##N (void) { doit (0x##N); }
#define F(N) f_##N ();
#define A(N) \
X(N##0) X(N##1) X(N##2) X(N##3) X(N##4) X(N##5) X(N##6) X(N##7) \
X(N##8) X(N##9) X(N##a) X(N##b) X(N##c) X(N##d) X(N##e) X(N##f) \
void f_##N (void) { \
F(N##0) F(N##1) F(N##2) F(N##3) F(N##4) F(N##5) F(N##6) F(N##7) \
F(N##8) F(N##9) F(N##a) F(N##b) F(N##c) F(N##d) F(N##e) F(N##f) \
}
#define B(N) \
A(N##0) A(N##1) A(N##2) A(N##3) A(N##4) A(N##5) A(N##6) A(N##7) \
A(N##8) A(N##9) A(N##a) A(N##b) A(N##c) A(N##d) A(N##e) A(N##f) \
void f_##N (void) { \
F(N##0) F(N##1) F(N##2) F(N##3) F(N##4) F(N##5) F(N##6) F(N##7) \
F(N##8) F(N##9) F(N##a) F(N##b) F(N##c) F(N##d) F(N##e) F(N##f) \
}
#define C(N) \
B(N##0) B(N##1) B(N##2) B(N##3) B(N##4) B(N##5) B(N##6) B(N##7) \
B(N##8) B(N##9) B(N##a) B(N##b) B(N##c) B(N##d) B(N##e) B(N##f) \
void f_##N (void) { \
F(N##0) F(N##1) F(N##2) F(N##3) F(N##4) F(N##5) F(N##6) F(N##7) \
F(N##8) F(N##9) F(N##a) F(N##b) F(N##c) F(N##d) F(N##e) F(N##f) \
}
#define D(N) \
C(N##0) C(N##1) C(N##2) C(N##3) C(N##4) C(N##5) C(N##6) C(N##7) \
void f_##N (void) { \
F(N##0) F(N##1) F(N##2) F(N##3) F(N##4) F(N##5) F(N##6) F(N##7) \
}
/* This defines 16x16x16x8 leaf functions, requiring something over
128K of GOT space overall. */
D(0)
int
main (void)
{
f_0 ();
if (n != 16*16*16*8)
abort ();
return 0;
}

View file

@ -1,3 +1,10 @@
2014-02-20 Sandra Loosemore <sandra@codesourcery.com>
Chung-Lin Tang <cltang@codesourcery.com>
* config/nios2/t-nios2 (CRTSTUFF_T_CFLAGS): Add -mno-gpopt.
* config/nios2/crti.S: Remove .file directive.
* config/nios2/crtn.S: Likewise.
2014-02-18 Kai Tietz <ktietz@redhat.com>
Jonathan Schleifer <js@webkeks.org>

View file

@ -36,8 +36,6 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
See crt0.s for the code that calls init and fini. */
.file "crti.asm"
.section ".init"
.align 2
.global _init

View file

@ -23,12 +23,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
/* This file just makes sure that the .fini and .init sections do in
fact return. Users may put any desired instructions in those sections.
This file is the last thing linked into any executable.
*/
.file "crtn.asm"
fact return. Users may put any desired instructions in those sections.
This file is the last thing linked into any executable. */
.section ".init"
ldw ra, 44(sp)

View file

@ -3,3 +3,6 @@ LIB2ADD += $(srcdir)/config/nios2/lib2-divmod.c \
$(srcdir)/config/nios2/lib2-divtable.c \
$(srcdir)/config/nios2/lib2-mul.c \
$(srcdir)/config/nios2/tramp.c
# Disable use of GP-relative addressing in startup code.
CRTSTUFF_T_CFLAGS += -mno-gpopt