aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJim Wilson <wilson@gcc.gnu.org>1993-08-27 10:16:17 -0700
committerJim Wilson <wilson@gcc.gnu.org>1993-08-27 10:16:17 -0700
commit642a35f1b4db429d4f5c00e0af47cab74f112274 (patch)
tree0b34c8b9e140499373e04fb3465c8b213434cd71 /gcc
parent1875cc885952eed1ba9d7a7a12883d2f230573fe (diff)
downloadgcc-642a35f1b4db429d4f5c00e0af47cab74f112274.zip
gcc-642a35f1b4db429d4f5c00e0af47cab74f112274.tar.gz
gcc-642a35f1b4db429d4f5c00e0af47cab74f112274.tar.bz2
(TARGET_MINIMAL_TOC): New macro.
(TARGET_SWITCHES): Add -mminimal-toc and -mno-minimal-toc. (ELIMINABLE_REGS): Add elimination for r30. (CAN_ELIMINATE): Add case for r30. (INITIAL_ELIMINATION_OFFSET): Add case for r30. (toc_section): When TARET_MINIMAL_TOC, initialize toc_table. From-SVN: r5219
Diffstat (limited to 'gcc')
-rw-r--r--gcc/config/rs6000/rs6000.h53
1 files changed, 48 insertions, 5 deletions
diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h
index 8f90eb1..a7c6b15 100644
--- a/gcc/config/rs6000/rs6000.h
+++ b/gcc/config/rs6000/rs6000.h
@@ -70,6 +70,16 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#define TARGET_FP_IN_TOC (target_flags & 1)
+/* Flag to output only one TOC entry per module. Normally linking fails if
+ there are more than 16K unique variables/constants in an executable. With
+ this option, linking fails only if there are more than 16K modules, or
+ if there are more than 16K unique variables/constant in a single module.
+
+ This is at the cost of having 2 extra loads and one extra store per
+ function, and one less allocatable register. */
+
+#define TARGET_MINIMAL_TOC (target_flags & 2)
+
extern int target_flags;
/* Macro to define tables used to set the flags.
@@ -81,6 +91,8 @@ extern int target_flags;
#define TARGET_SWITCHES \
{{"fp-in-toc", 1}, \
{"no-fp-in-toc", -1}, \
+ {"minimal-toc", 2}, \
+ {"no-minimal-toc", -2}, \
{ "", TARGET_DEFAULT}}
#define TARGET_DEFAULT 1
@@ -884,7 +896,12 @@ struct rs6000_args {int words, fregno, nargs_prototype; };
We have two registers that can be eliminated on the RS/6000. First, the
frame pointer register can often be eliminated in favor of the stack
pointer register. Secondly, the argument pointer register can always be
- eliminated; it is replaced with either the stack or frame pointer. */
+ eliminated; it is replaced with either the stack or frame pointer.
+
+ In addition, we use the elimination mechanism to see if r30 is needed
+ Initially we assume that it isn't. If it is, we spill it. This is done
+ by making it an eliminable register. We replace it with itself so that
+ if it isn't needed, then existing uses won't be modified. */
/* This is an array of structures. Each structure initializes one pair
of eliminable registers. The "from" register number is given first,
@@ -893,17 +910,22 @@ struct rs6000_args {int words, fregno, nargs_prototype; };
#define ELIMINABLE_REGS \
{{ FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
{ ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
- { ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM} }
+ { ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM}, \
+ { 30, 30} }
/* Given FROM and TO register numbers, say whether this elimination is allowed.
Frame pointer elimination is automatically handled.
For the RS/6000, if frame pointer elimination is being done, we would like
- to convert ap into fp, not sp. */
+ to convert ap into fp, not sp.
+
+ We need r30 if -mmininal-toc was specified, and there are constant pool
+ references. */
#define CAN_ELIMINATE(FROM, TO) \
((FROM) == ARG_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM \
? ! frame_pointer_needed \
+ : (FROM) == 30 ? ! TARGET_MINIMAL_TOC || get_pool_size () == 0 \
: 1)
/* Define the offset between two registers, one to be eliminated, and the other
@@ -931,6 +953,8 @@ struct rs6000_args {int words, fregno, nargs_prototype; };
else \
(OFFSET) = 0; \
} \
+ else if ((FROM) == 30) \
+ (OFFSET) = 0; \
else \
abort (); \
}
@@ -1465,9 +1489,28 @@ read_only_private_data_section () \
void \
toc_section () \
{ \
- if (in_section != toc) \
- fprintf (asm_out_file, ".toc\n"); \
+ if (TARGET_MINIMAL_TOC) \
+ { \
+ static int toc_initialized = 0; \
\
+ /* toc_section is always called at least once from ASM_FILE_START, \
+ so this is guaranteed to always be defined once and only once \
+ in each file. */ \
+ if (! toc_initialized) \
+ { \
+ fprintf (asm_out_file, ".toc\nLCTOC..0:\n"); \
+ fprintf (asm_out_file, "\t.tc toc_table[TC],toc_table[RW]\n"); \
+ toc_initialized = 1; \
+ } \
+ \
+ if (in_section != toc) \
+ fprintf (asm_out_file, ".csect toc_table[RW]\n"); \
+ } \
+ else \
+ { \
+ if (in_section != toc) \
+ fprintf (asm_out_file, ".toc\n"); \
+ } \
in_section = toc; \
}