This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[nios2, committed] additional -mgpopt choices
- From: Sandra Loosemore <sandra at codesourcery dot com>
- To: GCC Patches <gcc-patches at gcc dot gnu dot org>
- Date: Thu, 15 Jan 2015 17:45:14 -0700
- Subject: [nios2, committed] additional -mgpopt choices
- Authentication-results: sourceware.org; auth=none
This patch is for PR 59710. As noted in that issue, the nios2 backend
only uses GP-relative addressing on objects defined locally to the
translation unit, where it knows definitely that the object is assigned
to the small data section under the current -G setting. Some other
backends also use GP-relative addressing on externally-defined objects
with the assumption that the entire program will be compiled at the same
-G setting. While that can be a Good Thing, it seemed to me that
changing the behavior of -mgpopt incompatibly might cause problems
(especially since it's enabled by default in most cases), so I added an
additional state (-mgpopt=global) to control the new behavior.
While I was at it, I added two more states to -mgpopt= that tell the
compiler to use GP-relative addressing for all data, or for the whole
program (including text). These fell out of a discussion we've been
having internally about producing tighter code for very small programs,
like a bootloader that's guaranteed to have to fit into a 64K internal
memory segment. This was trivial to implement once the -mgpopt option
syntax support for multiple choices was there.
I've committed this after regression-testing on nios2-elf. Sorry to get
this in so late in stage 3; I was hoping to make stage 1 but mainline
trunk builds were broken for a long time by PR64377.
-Sandra
2015-01-15 Sandra Loosemore <sandra@codesourcery.com>
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.
Index: gcc/doc/invoke.texi
===================================================================
--- gcc/doc/invoke.texi (revision 219696)
+++ gcc/doc/invoke.texi (working copy)
@@ -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
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
Index: gcc/config/nios2/nios2.opt
===================================================================
--- gcc/config/nios2/nios2.opt (revision 219696)
+++ gcc/config/nios2/nios2.opt (working copy)
@@ -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)
Index: gcc/config/nios2/nios2-opts.h
===================================================================
--- gcc/config/nios2/nios2-opts.h (revision 219696)
+++ gcc/config/nios2/nios2-opts.h (working copy)
@@ -20,6 +20,18 @@ along with GCC; see the file COPYING3.
#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) \
Index: gcc/config/nios2/nios2.c
===================================================================
--- gcc/config/nios2/nios2.c (revision 219696)
+++ gcc/config/nios2/nios2.c (working copy)
@@ -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. */
Index: gcc/testsuite/gcc.target/nios2/gpopt-all.c
===================================================================
--- gcc/testsuite/gcc.target/nios2/gpopt-all.c (revision 0)
+++ gcc/testsuite/gcc.target/nios2/gpopt-all.c (revision 0)
@@ -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\\)" } } */
Index: gcc/testsuite/gcc.target/nios2/gpopt-local.c
===================================================================
--- gcc/testsuite/gcc.target/nios2/gpopt-local.c (revision 0)
+++ gcc/testsuite/gcc.target/nios2/gpopt-local.c (revision 0)
@@ -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\\)" } } */
Index: gcc/testsuite/gcc.target/nios2/gpopt-global.c
===================================================================
--- gcc/testsuite/gcc.target/nios2/gpopt-global.c (revision 0)
+++ gcc/testsuite/gcc.target/nios2/gpopt-global.c (revision 0)
@@ -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\\)" } } */
Index: gcc/testsuite/gcc.target/nios2/gpopt-data.c
===================================================================
--- gcc/testsuite/gcc.target/nios2/gpopt-data.c (revision 0)
+++ gcc/testsuite/gcc.target/nios2/gpopt-data.c (revision 0)
@@ -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\\)" } } */
Index: gcc/testsuite/gcc.target/nios2/gpopt-none.c
===================================================================
--- gcc/testsuite/gcc.target/nios2/gpopt-none.c (revision 0)
+++ gcc/testsuite/gcc.target/nios2/gpopt-none.c (revision 0)
@@ -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\\)" } } */