From: Sandra Loosemore Date: Fri, 16 Jan 2015 00:43:24 +0000 (-0500) Subject: re PR target/59710 (Nios2: Missing gprel optimization) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=56314783c33b58a03f7eee9d48b4a2628ee6e1f0;p=gcc.git re PR target/59710 (Nios2: Missing gprel optimization) 2015-01-15 Sandra Loosemore PR target/59710 gcc/ * doc/invoke.texi (Option Summary): Document new Nios II -mgpopt= syntax. (Nios II Options): Likewise. * config/nios2/nios2.opt: Add -mgpopt= option support. Modify existing -mgpopt and -mno-gpopt options to be aliases. * config/nios2/nios2-opts.h (enum nios2_gpopt_type): New. * config/nios2/nios2.c (nios2_option_override): Adjust -mgpopt defaulting. (nios2_in_small_data_p): Return true for explicit small data sections even with -G0. (nios2_symbol_ref_in_small_data_p): Adjust to handle new -mgpopt= option choices. gcc/testsuite/ * gcc.target/nios2/gpopt-all.c: New test case. * gcc.target/nios2/gpopt-local.c: New test case. * gcc.target/nios2/gpopt-global.c: New test case. * gcc.target/nios2/gpopt-data.c: New test case. * gcc.target/nios2/gpopt-none.c: New test case. From-SVN: r219700 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d2770f09144..62735a7a77e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,19 @@ +2015-01-15 Sandra Loosemore + + PR target/59710 + * doc/invoke.texi (Option Summary): Document new Nios II + -mgpopt= syntax. + (Nios II Options): Likewise. + * config/nios2/nios2.opt: Add -mgpopt= option support. + Modify existing -mgpopt and -mno-gpopt options to be aliases. + * config/nios2/nios2-opts.h (enum nios2_gpopt_type): New. + * config/nios2/nios2.c (nios2_option_override): Adjust + -mgpopt defaulting. + (nios2_in_small_data_p): Return true for explicit small data + sections even with -G0. + (nios2_symbol_ref_in_small_data_p): Adjust to handle new -mgpopt= + option choices. + 2015-01-15 Jan Hubicka PR ipa/64612 diff --git a/gcc/config/nios2/nios2-opts.h b/gcc/config/nios2/nios2-opts.h index 5523afdcbb2..91abdf6c7d9 100644 --- a/gcc/config/nios2/nios2-opts.h +++ b/gcc/config/nios2/nios2-opts.h @@ -20,6 +20,18 @@ along with GCC; see the file COPYING3. If not see #ifndef NIOS2_OPTS_H #define NIOS2_OPTS_H +/* Enumerate the possible -mgpopt choices. */ +enum nios2_gpopt_type +{ + gpopt_unspecified = -1, + gpopt_none, + gpopt_local, + gpopt_global, + gpopt_data, + gpopt_all +}; + + /* Enumeration of all FPU insn codes. */ #define N2FPU_ALL_CODES \ N2FPU_CODE(fadds) N2FPU_CODE(fsubs) N2FPU_CODE(fmuls) N2FPU_CODE(fdivs) \ diff --git a/gcc/config/nios2/nios2.c b/gcc/config/nios2/nios2.c index 06c9d007537..502314942cc 100644 --- a/gcc/config/nios2/nios2.c +++ b/gcc/config/nios2/nios2.c @@ -1038,9 +1038,14 @@ nios2_option_override (void) = (global_options_set.x_g_switch_value ? g_switch_value : NIOS2_DEFAULT_GVALUE); - /* Default to -mgpopt unless -fpic or -fPIC. */ - if (TARGET_GPOPT == -1 && flag_pic) - TARGET_GPOPT = 0; + if (nios2_gpopt_option == gpopt_unspecified) + { + /* Default to -mgpopt unless -fpic or -fPIC. */ + if (flag_pic) + nios2_gpopt_option = gpopt_none; + else + nios2_gpopt_option = gpopt_local; + } /* If we don't have mul, we don't have mulx either! */ if (!TARGET_HAS_MUL && TARGET_HAS_MULX) @@ -1657,8 +1662,7 @@ nios2_in_small_data_p (const_tree exp) if (DECL_SECTION_NAME (exp)) { const char *section = DECL_SECTION_NAME (exp); - if (nios2_section_threshold > 0 - && nios2_small_section_name_p (section)) + if (nios2_small_section_name_p (section)) return true; } else @@ -1681,19 +1685,63 @@ nios2_in_small_data_p (const_tree exp) bool nios2_symbol_ref_in_small_data_p (rtx sym) { + tree decl; + gcc_assert (GET_CODE (sym) == SYMBOL_REF); - return - (TARGET_GPOPT - /* GP-relative access cannot be used for externally defined symbols, - because the compilation unit that defines the symbol may place it - in a section that cannot be reached from GP. */ - && !SYMBOL_REF_EXTERNAL_P (sym) - /* True if a symbol is both small and not weak. */ - && SYMBOL_REF_SMALL_P (sym) - && !(SYMBOL_REF_DECL (sym) && DECL_WEAK (SYMBOL_REF_DECL (sym))) - /* TLS variables are not accessed through the GP. */ - && SYMBOL_REF_TLS_MODEL (sym) == 0); + decl = SYMBOL_REF_DECL (sym); + /* TLS variables are not accessed through the GP. */ + if (SYMBOL_REF_TLS_MODEL (sym) != 0) + return false; + + /* If the user has explicitly placed the symbol in a small data section + via an attribute, generate gp-relative addressing even if the symbol + is external, weak, or larger than we'd automatically put in the + small data section. OTOH, if the symbol is located in some + non-small-data section, we can't use gp-relative accesses on it + unless the user has requested gpopt_data or gpopt_all. */ + + switch (nios2_gpopt_option) + { + case gpopt_none: + /* Don't generate a gp-relative addressing mode if that's been + disabled. */ + return false; + + case gpopt_local: + /* Use GP-relative addressing for small data symbols that are + not external or weak, plus any symbols that have explicitly + been placed in a small data section. */ + if (decl && DECL_SECTION_NAME (decl)) + return nios2_small_section_name_p (DECL_SECTION_NAME (decl)); + return (SYMBOL_REF_SMALL_P (sym) + && !SYMBOL_REF_EXTERNAL_P (sym) + && !(decl && DECL_WEAK (decl))); + + case gpopt_global: + /* Use GP-relative addressing for small data symbols, even if + they are external or weak. Note that SYMBOL_REF_SMALL_P + is also true of symbols that have explicitly been placed + in a small data section. */ + return SYMBOL_REF_SMALL_P (sym); + + case gpopt_data: + /* Use GP-relative addressing for all data symbols regardless + of the object size, but not for code symbols. This option + is equivalent to the user asserting that the entire data + section is accessible from the GP. */ + return !SYMBOL_REF_FUNCTION_P (sym); + + case gpopt_all: + /* Use GP-relative addressing for everything, including code. + Effectively, the user has asserted that the entire program + fits within the 64K range of the GP offset. */ + return true; + + default: + /* We shouldn't get here. */ + return false; + } } /* Implement TARGET_SECTION_TYPE_FLAGS. */ diff --git a/gcc/config/nios2/nios2.opt b/gcc/config/nios2/nios2.opt index dad8fa8552f..071606387df 100644 --- a/gcc/config/nios2/nios2.opt +++ b/gcc/config/nios2/nios2.opt @@ -58,9 +58,36 @@ mcache-volatile Target Report RejectNegative Undocumented InverseMask(BYPASS_CACHE_VOLATILE) Volatile memory accesses do not use I/O load/store instructions +mgpopt= +Target RejectNegative Joined Enum(nios2_gpopt_type) Var(nios2_gpopt_option) Init(gpopt_unspecified) +Enable/disable GP-relative addressing. + +Enum +Name(nios2_gpopt_type) Type(enum nios2_gpopt_type) +Valid options for GP-relative addressing (for -mgpopt): + +EnumValue +Enum(nios2_gpopt_type) String(none) Value(gpopt_none) + +EnumValue +Enum(nios2_gpopt_type) String(local) Value(gpopt_local) + +EnumValue +Enum(nios2_gpopt_type) String(global) Value(gpopt_global) + +EnumValue +Enum(nios2_gpopt_type) String(data) Value(gpopt_data) + +EnumValue +Enum(nios2_gpopt_type) String(all) Value(gpopt_all) + mgpopt -Target Report Var(TARGET_GPOPT) Init(-1) -Use GP-relative addressing to access small data +Target Report RejectNegative Var(nios2_gpopt_option, gpopt_local) +Equivalent to -mgpopt=local. + +mno-gpopt +Target Report RejectNegative Var(nios2_gpopt_option, gpopt_none) +Equivalent to -mgpopt=none. meb Target Report RejectNegative Mask(BIG_ENDIAN) diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 510201acb24..12368e8e04a 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -869,7 +869,8 @@ Objective-C and Objective-C++ Dialects}. -mex9 -mctor-dtor -mrelax} @emph{Nios II Options} -@gccoptlist{-G @var{num} -mgpopt -mno-gpopt -mel -meb @gol +@gccoptlist{-G @var{num} -mgpopt=@var{option} -mgpopt -mno-gpopt @gol +-mel -meb @gol -mno-bypass-cache -mbypass-cache @gol -mno-cache-volatile -mcache-volatile @gol -mno-fast-sw-div -mfast-sw-div @gol @@ -19214,15 +19215,54 @@ Put global and static objects less than or equal to @var{num} bytes into the small data or BSS sections instead of the normal data or BSS sections. The default value of @var{num} is 8. +@item -mgpopt=@var{option} @item -mgpopt @itemx -mno-gpopt @opindex mgpopt @opindex mno-gpopt -Generate (do not generate) GP-relative accesses for objects in the -small data or BSS sections. The default is @option{-mgpopt} except -when @option{-fpic} or @option{-fPIC} is specified to generate -position-independent code. Note that the Nios II ABI does not permit -GP-relative accesses from shared libraries. +Generate (do not generate) GP-relative accesses. The following +@var{option} names are recognized: + +@table @samp + +@item none +Do not generate GP-relative accesses. + +@item local +Generate GP-relative accesses for small data objects that are not +external or weak. Also use GP-relative addressing for objects that +have been explicitly placed in a small data section via a @code{section} +attribute. + +@item global +As for @samp{local}, but also generate GP-relative accesses for +small data objects that are external or weak. If you use this option, +you must ensure that all parts of your program (including libraries) are +compiled with the same @option{-G} setting. + +@item data +Generate GP-relative accesses for all data objects in the program. If you +use this option, the entire data and BSS segments +of your program must fit in 64K of memory and you must use an appropriate +linker script to allocate them within the addressible range of the +global pointer. + +@item all +Generate GP-relative addresses for function pointers as well as data +pointers. If you use this option, the entire text, data, and BSS segments +of your program must fit in 64K of memory and you must use an appropriate +linker script to allocate them within the addressible range of the +global pointer. + +@end table + +@option{-mgpopt} is equivalent to @option{-mgpopt=local}, and +@option{-mno-gpopt} is equivalent to @option{-mgpopt=none}. + +The default is @option{-mgpopt} except when @option{-fpic} or +@option{-fPIC} is specified to generate position-independent code. +Note that the Nios II ABI does not permit GP-relative accesses from +shared libraries. You may need to specify @option{-mno-gpopt} explicitly when building programs that include large amounts of small data, including large diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 8a9f9271080..1ea322b0cce 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,12 @@ +2015-01-15 Sandra Loosemore + + PR target/59710 + * gcc.target/nios2/gpopt-all.c: New test case. + * gcc.target/nios2/gpopt-local.c: New test case. + * gcc.target/nios2/gpopt-global.c: New test case. + * gcc.target/nios2/gpopt-data.c: New test case. + * gcc.target/nios2/gpopt-none.c: New test case. + 2015-01-15 Jakub Jelinek * g++.dg/ubsan/vptr-1.C: New test. diff --git a/gcc/testsuite/gcc.target/nios2/gpopt-all.c b/gcc/testsuite/gcc.target/nios2/gpopt-all.c new file mode 100644 index 00000000000..1ea49094153 --- /dev/null +++ b/gcc/testsuite/gcc.target/nios2/gpopt-all.c @@ -0,0 +1,38 @@ +/* { dg-do compile } */ +/* { dg-options "-O -mgpopt=all" } */ + +extern int a __attribute__ ((section (".sdata"))); +static volatile int b __attribute__ ((section (".sdata"))) = 1; +extern int c __attribute__ ((section (".data"))); +static volatile int d __attribute__ ((section (".data"))) = 2; + +extern int e; +static volatile int f = 3; + +volatile int g __attribute__ ((weak)) = 4; + +extern int h[100]; +static int i[100]; +static int j[100] __attribute__ ((section (".sdata"))); + +typedef int (*ftype) (int); +extern int foo (int); + +extern int bar (int, int*, int*, int*, ftype); + +int baz (void) +{ + return bar (a + b + c + d + e + f + g, h, i, j, foo); +} + +/* { dg-final { scan-assembler "%gprel\\(a\\)" } } */ +/* { dg-final { scan-assembler "%gprel\\(b\\)" } } */ +/* { dg-final { scan-assembler "%gprel\\(c\\)" } } */ +/* { dg-final { scan-assembler "%gprel\\(d\\)" } } */ +/* { dg-final { scan-assembler "%gprel\\(e\\)" } } */ +/* { dg-final { scan-assembler "%gprel\\(f\\)" } } */ +/* { dg-final { scan-assembler "%gprel\\(g\\)" } } */ +/* { dg-final { scan-assembler "%gprel\\(h\\)" } } */ +/* { dg-final { scan-assembler "%gprel\\(i\\)" } } */ +/* { dg-final { scan-assembler "%gprel\\(j\\)" } } */ +/* { dg-final { scan-assembler "%gprel\\(foo\\)" } } */ diff --git a/gcc/testsuite/gcc.target/nios2/gpopt-data.c b/gcc/testsuite/gcc.target/nios2/gpopt-data.c new file mode 100644 index 00000000000..dba930f03a0 --- /dev/null +++ b/gcc/testsuite/gcc.target/nios2/gpopt-data.c @@ -0,0 +1,38 @@ +/* { dg-do compile } */ +/* { dg-options "-O -mgpopt=data" } */ + +extern int a __attribute__ ((section (".sdata"))); +static volatile int b __attribute__ ((section (".sdata"))) = 1; +extern int c __attribute__ ((section (".data"))); +static volatile int d __attribute__ ((section (".data"))) = 2; + +extern int e; +static volatile int f = 3; + +volatile int g __attribute__ ((weak)) = 4; + +extern int h[100]; +static int i[100]; +static int j[100] __attribute__ ((section (".sdata"))); + +typedef int (*ftype) (int); +extern int foo (int); + +extern int bar (int, int*, int*, int*, ftype); + +int baz (void) +{ + return bar (a + b + c + d + e + f + g, h, i, j, foo); +} + +/* { dg-final { scan-assembler "%gprel\\(a\\)" } } */ +/* { dg-final { scan-assembler "%gprel\\(b\\)" } } */ +/* { dg-final { scan-assembler "%gprel\\(c\\)" } } */ +/* { dg-final { scan-assembler "%gprel\\(d\\)" } } */ +/* { dg-final { scan-assembler "%gprel\\(e\\)" } } */ +/* { dg-final { scan-assembler "%gprel\\(f\\)" } } */ +/* { dg-final { scan-assembler "%gprel\\(g\\)" } } */ +/* { dg-final { scan-assembler "%gprel\\(h\\)" } } */ +/* { dg-final { scan-assembler "%gprel\\(i\\)" } } */ +/* { dg-final { scan-assembler "%gprel\\(j\\)" } } */ +/* { dg-final { scan-assembler-not "%gprel\\(foo\\)" } } */ diff --git a/gcc/testsuite/gcc.target/nios2/gpopt-global.c b/gcc/testsuite/gcc.target/nios2/gpopt-global.c new file mode 100644 index 00000000000..1bb608efa7f --- /dev/null +++ b/gcc/testsuite/gcc.target/nios2/gpopt-global.c @@ -0,0 +1,38 @@ +/* { dg-do compile } */ +/* { dg-options "-O -mgpopt=global" } */ + +extern int a __attribute__ ((section (".sdata"))); +static volatile int b __attribute__ ((section (".sdata"))) = 1; +extern int c __attribute__ ((section (".data"))); +static volatile int d __attribute__ ((section (".data"))) = 2; + +extern int e; +static volatile int f = 3; + +volatile int g __attribute__ ((weak)) = 4; + +extern int h[100]; +static int i[100]; +static int j[100] __attribute__ ((section (".sdata"))); + +typedef int (*ftype) (int); +extern int foo (int); + +extern int bar (int, int*, int*, int*, ftype); + +int baz (void) +{ + return bar (a + b + c + d + e + f + g, h, i, j, foo); +} + +/* { dg-final { scan-assembler "%gprel\\(a\\)" } } */ +/* { dg-final { scan-assembler "%gprel\\(b\\)" } } */ +/* { dg-final { scan-assembler-not "%gprel\\(c\\)" } } */ +/* { dg-final { scan-assembler-not "%gprel\\(d\\)" } } */ +/* { dg-final { scan-assembler "%gprel\\(e\\)" } } */ +/* { dg-final { scan-assembler "%gprel\\(f\\)" } } */ +/* { dg-final { scan-assembler "%gprel\\(g\\)" } } */ +/* { dg-final { scan-assembler-not "%gprel\\(h\\)" } } */ +/* { dg-final { scan-assembler-not "%gprel\\(i\\)" } } */ +/* { dg-final { scan-assembler "%gprel\\(j\\)" } } */ +/* { dg-final { scan-assembler-not "%gprel\\(foo\\)" } } */ diff --git a/gcc/testsuite/gcc.target/nios2/gpopt-local.c b/gcc/testsuite/gcc.target/nios2/gpopt-local.c new file mode 100644 index 00000000000..cf1174634aa --- /dev/null +++ b/gcc/testsuite/gcc.target/nios2/gpopt-local.c @@ -0,0 +1,38 @@ +/* { dg-do compile } */ +/* { dg-options "-O -mgpopt=local" } */ + +extern int a __attribute__ ((section (".sdata"))); +static volatile int b __attribute__ ((section (".sdata"))) = 1; +extern int c __attribute__ ((section (".data"))); +static volatile int d __attribute__ ((section (".data"))) = 2; + +extern int e; +static volatile int f = 3; + +volatile int g __attribute__ ((weak)) = 4; + +extern int h[100]; +static int i[100]; +static int j[100] __attribute__ ((section (".sdata"))); + +typedef int (*ftype) (int); +extern int foo (int); + +extern int bar (int, int*, int*, int*, ftype); + +int baz (void) +{ + return bar (a + b + c + d + e + f + g, h, i, j, foo); +} + +/* { dg-final { scan-assembler "%gprel\\(a\\)" } } */ +/* { dg-final { scan-assembler "%gprel\\(b\\)" } } */ +/* { dg-final { scan-assembler-not "%gprel\\(c\\)" } } */ +/* { dg-final { scan-assembler-not "%gprel\\(d\\)" } } */ +/* { dg-final { scan-assembler-not "%gprel\\(e\\)" } } */ +/* { dg-final { scan-assembler "%gprel\\(f\\)" } } */ +/* { dg-final { scan-assembler-not "%gprel\\(g\\)" } } */ +/* { dg-final { scan-assembler-not "%gprel\\(h\\)" } } */ +/* { dg-final { scan-assembler-not "%gprel\\(i\\)" } } */ +/* { dg-final { scan-assembler "%gprel\\(j\\)" } } */ +/* { dg-final { scan-assembler-not "%gprel\\(foo\\)" } } */ diff --git a/gcc/testsuite/gcc.target/nios2/gpopt-none.c b/gcc/testsuite/gcc.target/nios2/gpopt-none.c new file mode 100644 index 00000000000..c432f54041a --- /dev/null +++ b/gcc/testsuite/gcc.target/nios2/gpopt-none.c @@ -0,0 +1,38 @@ +/* { dg-do compile } */ +/* { dg-options "-O -mgpopt=none" } */ + +extern int a __attribute__ ((section (".sdata"))); +static volatile int b __attribute__ ((section (".sdata"))) = 1; +extern int c __attribute__ ((section (".data"))); +static volatile int d __attribute__ ((section (".data"))) = 2; + +extern int e; +static volatile int f = 3; + +volatile int g __attribute__ ((weak)) = 4; + +extern int h[100]; +static int i[100]; +static int j[100] __attribute__ ((section (".sdata"))); + +typedef int (*ftype) (int); +extern int foo (int); + +extern int bar (int, int*, int*, int*, ftype); + +int baz (void) +{ + return bar (a + b + c + d + e + f + g, h, i, j, foo); +} + +/* { dg-final { scan-assembler-not "%gprel\\(a\\)" } } */ +/* { dg-final { scan-assembler-not "%gprel\\(b\\)" } } */ +/* { dg-final { scan-assembler-not "%gprel\\(c\\)" } } */ +/* { dg-final { scan-assembler-not "%gprel\\(d\\)" } } */ +/* { dg-final { scan-assembler-not "%gprel\\(e\\)" } } */ +/* { dg-final { scan-assembler-not "%gprel\\(f\\)" } } */ +/* { dg-final { scan-assembler-not "%gprel\\(g\\)" } } */ +/* { dg-final { scan-assembler-not "%gprel\\(h\\)" } } */ +/* { dg-final { scan-assembler-not "%gprel\\(i\\)" } } */ +/* { dg-final { scan-assembler-not "%gprel\\(j\\)" } } */ +/* { dg-final { scan-assembler-not "%gprel\\(foo\\)" } } */