re PR target/59710 (Nios2: Missing gprel optimization)
authorSandra Loosemore <sandra@codesourcery.com>
Fri, 16 Jan 2015 00:43:24 +0000 (19:43 -0500)
committerSandra Loosemore <sandra@gcc.gnu.org>
Fri, 16 Jan 2015 00:43:24 +0000 (19:43 -0500)
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.

From-SVN: r219700

gcc/ChangeLog
gcc/config/nios2/nios2-opts.h
gcc/config/nios2/nios2.c
gcc/config/nios2/nios2.opt
gcc/doc/invoke.texi
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/nios2/gpopt-all.c [new file with mode: 0644]
gcc/testsuite/gcc.target/nios2/gpopt-data.c [new file with mode: 0644]
gcc/testsuite/gcc.target/nios2/gpopt-global.c [new file with mode: 0644]
gcc/testsuite/gcc.target/nios2/gpopt-local.c [new file with mode: 0644]
gcc/testsuite/gcc.target/nios2/gpopt-none.c [new file with mode: 0644]

index d2770f0914422668a0eb85406afa600f114cdd41..62735a7a77e6d3f1a898b4427067b4f38ac7257e 100644 (file)
@@ -1,3 +1,19 @@
+2015-01-15  Sandra Loosemore  <sandra@codesourcery.com>
+
+       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  <hubicka@ucw.cz>
 
        PR ipa/64612
index 5523afdcbb20b9c0a393dd3c4124834db3abfead..91abdf6c7d951a913d4aaf6f94aa64aedcdb1a2c 100644 (file)
@@ -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) \
index 06c9d007537e46d08cc4a5a1e2d4c027cf7c3ae1..502314942ccd18d3b42d9371db4e2037ce0f8cd5 100644 (file)
@@ -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 dad8fa8552f30a852a2306a3c2432f2cf427ce45..071606387df9094d5c0536a49bcbf77defb9c51e 100644 (file)
@@ -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 510201acb2400ce349fd474f5e0525e54f1837e0..12368e8e04a3bcc1b0804e0439de728568f62929 100644 (file)
@@ -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
index 8a9f9271080e1f53ca086bc85b0b566745e4ac54..1ea322b0ccee088a83894e31123f88e04c1daec3 100644 (file)
@@ -1,3 +1,12 @@
+2015-01-15  Sandra Loosemore  <sandra@codesourcery.com>
+
+       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  <jakub@redhat.com>
 
        * 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 (file)
index 0000000..1ea4909
--- /dev/null
@@ -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 (file)
index 0000000..dba930f
--- /dev/null
@@ -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 (file)
index 0000000..1bb608e
--- /dev/null
@@ -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 (file)
index 0000000..cf11746
--- /dev/null
@@ -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 (file)
index 0000000..c432f54
--- /dev/null
@@ -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\\)" } } */