This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[nios2, committed] additional -mgpopt choices


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\\)" } } */

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]