This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH] -fpic problems on PPC, a different approach
- To: Richard Henderson <rth at cygnus dot com>,law at cygnus dot com
- Subject: Re: [PATCH] -fpic problems on PPC, a different approach
- From: Franz Sirl <Franz dot Sirl-kernel at lauterbach dot com>
- Date: Wed, 9 Jun 1999 02:23:17 +0200
- Cc: Geoff Keating <geoffk at ozemail dot com dot au>,egcs-patches at egcs dot cygnus dot com
- References: <19990608005217.A30432@cygnus.com>
Am Tue, 08 Jun 1999 schrieb Richard Henderson:
>On Mon, Jun 07, 1999 at 07:26:50PM -0600, Jeffrey A Law wrote:
>> Keep track of whether or not you ever reference the pic register. If you
>> do, then you'll need to load it up at appropriate times. Else you ignore
>> it completely.
>
>You don't actually have to explicitly track this. Since there
>are no hidden uses of the pic register in the ppc port, you can
>simply check regs_ever_live[PIC_OFFSET_TABLE_REGNUM] when you
>generate the function's prologue.
>
>Ignore FINALIZE_PIC -- it is a red herring.
>
>Remove all references to GOT_TOC_REGNUM. Don't ever write to
>pic_offset_table_rtx; don't save and restore it in
>rs6000_save_machine_status.
>
>The movsi_got patterns can be streamlined; movsi_got_internal_mem
>can go away entirely.
Ok, here's my first try. Basically it should be OK, it at least compiles all
the troublesome -fpic testcases correctly. It turned out that simply checking
regs_ever_live[PIC_OFFSET_TABLE_REGNUM] is not enough, as this information
may no longer be correct after reload, if reload was the first instance to
produce pic_offset_table_rtx references. I've also marked some explicit uses of
r2, the old GOT_TOC_REGNUM, they might need some extra treatment now.
Is it possible to use something like "frame_pointer_needed ? 30 : 31" for
PIC_OFFSET_TABLE_REGNUM? This would make the unnecessary saving of r31 go away.
Franz.
Index: rs6000.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/config/rs6000/rs6000.c,v
retrieving revision 1.70.4.1
diff -u -p -r1.70.4.1 rs6000.c
--- rs6000.c 1999/05/28 02:41:43 1.70.4.1
+++ rs6000.c 1999/06/09 00:04:43
@@ -2397,142 +2411,15 @@ struct rtx_def *
rs6000_got_register (value)
rtx value;
{
- if (! current_function_uses_pic_offset_table || ! pic_offset_table_rtx)
- {
- if (no_new_pseudos)
- fatal_insn ("internal error -- needed new GOT register during reload phase to load:",
- value);
-
- current_function_uses_pic_offset_table = 1;
- pic_offset_table_rtx = gen_rtx_REG (Pmode, GOT_TOC_REGNUM);
- }
+ if (no_new_pseudos && !regs_ever_live[PIC_OFFSET_TABLE_REGNUM])
+ regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;
+ current_function_uses_pic_offset_table = 1;
return pic_offset_table_rtx;
}
-
-/* Replace all occurrences of register FROM with an new pseudo register in an insn X.
- Store the pseudo register used in REG.
- This is only safe during FINALIZE_PIC, since the registers haven't been setup
- yet. */
-
-static rtx
-rs6000_replace_regno (x, from, reg)
- rtx x;
- int from;
- rtx *reg;
-{
- register int i, j;
- register const char *fmt;
-
- /* Allow this function to make replacements in EXPR_LISTs. */
- if (!x)
- return x;
-
- switch (GET_CODE (x))
- {
- case SCRATCH:
- case PC:
- case CC0:
- case CONST_INT:
- case CONST_DOUBLE:
- case CONST:
- case SYMBOL_REF:
- case LABEL_REF:
- return x;
-
- case REG:
- if (REGNO (x) == from)
- {
- if (! *reg)
- *reg = pic_offset_table_rtx = gen_reg_rtx (Pmode);
-
- return *reg;
- }
-
- return x;
-
- default:
- break;
- }
-
- fmt = GET_RTX_FORMAT (GET_CODE (x));
- for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
- {
- if (fmt[i] == 'e')
- XEXP (x, i) = rs6000_replace_regno (XEXP (x, i), from, reg);
- else if (fmt[i] == 'E')
- for (j = XVECLEN (x, i) - 1; j >= 0; j--)
- XVECEXP (x, i, j) = rs6000_replace_regno (XVECEXP (x, i, j), from, reg);
- }
-
- return x;
-}
-
-
-/* By generating position-independent code, when two different
- programs (A and B) share a common library (libC.a), the text of
- the library can be shared whether or not the library is linked at
- the same address for both programs. In some of these
- environments, position-independent code requires not only the use
- of different addressing modes, but also special code to enable the
- use of these addressing modes.
-
- The `FINALIZE_PIC' macro serves as a hook to emit these special
- codes once the function is being compiled into assembly code, but
- not before. (It is not done before, because in the case of
- compiling an inline function, it would lead to multiple PIC
- prologues being included in functions which used inline functions
- and were compiled to assembly language.) */
-
-void
-rs6000_finalize_pic ()
-{
- /* Loop through all of the insns, replacing the special GOT_TOC_REGNUM
- with an appropriate pseudo register. If we find we need GOT/TOC,
- add the appropriate init code. */
- if (flag_pic && (DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS))
- {
- rtx insn = get_insns ();
- rtx reg = NULL_RTX;
- rtx first_insn;
- rtx last_insn = NULL_RTX;
-
- if (GET_CODE (insn) == NOTE)
- insn = next_nonnote_insn (insn);
-
- first_insn = insn;
- for ( ; insn != NULL_RTX; insn = NEXT_INSN (insn))
- {
- if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
- {
- PATTERN (insn) = rs6000_replace_regno (PATTERN (insn),
- GOT_TOC_REGNUM,
- ®);
-
- if (REG_NOTES (insn))
- REG_NOTES (insn) = rs6000_replace_regno (REG_NOTES (insn),
- GOT_TOC_REGNUM,
- ®);
- }
-
- if (GET_CODE (insn) != NOTE)
- last_insn = insn;
- }
-
- if (reg)
- {
- rtx init = gen_init_v4_pic (reg);
- emit_insn_before (init, first_insn);
- if (!optimize && last_insn)
- emit_insn_after (gen_rtx_USE (VOIDmode, reg), last_insn);
- }
- }
-}
-
-
/* Search for any occurrence of the GOT_TOC register marker that should
- have been eliminated, but may have crept back in. */
+ * have been eliminated, but may have crept back in. */
void
rs6000_reorg (insn)
@@ -2540,7 +2427,7 @@ rs6000_reorg (insn)
{
if (flag_pic && (DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS))
{
- rtx got_reg = gen_rtx_REG (Pmode, GOT_TOC_REGNUM);
+ rtx got_reg = gen_rtx_REG (Pmode, 2);
for ( ; insn != NULL_RTX; insn = NEXT_INSN (insn))
if (GET_RTX_CLASS (GET_CODE (insn)) == 'i'
&& reg_mentioned_p (got_reg, PATTERN (insn)))
@@ -2556,7 +2443,6 @@ struct machine_function
int save_toc_p;
int fpmem_size;
int fpmem_offset;
- rtx pic_offset_table_rtx;
};
/* Functions to save and restore rs6000_fpmem_size.
@@ -2574,7 +2460,6 @@ rs6000_save_machine_status (p)
machine->sysv_varargs_p = rs6000_sysv_varargs_p;
machine->fpmem_size = rs6000_fpmem_size;
machine->fpmem_offset = rs6000_fpmem_offset;
- machine->pic_offset_table_rtx = pic_offset_table_rtx;
}
void
@@ -2586,7 +2471,6 @@ rs6000_restore_machine_status (p)
rs6000_sysv_varargs_p = machine->sysv_varargs_p;
rs6000_fpmem_size = machine->fpmem_size;
rs6000_fpmem_offset = machine->fpmem_offset;
- pic_offset_table_rtx = machine->pic_offset_table_rtx;
free (machine);
p->machine = (struct machine_function *)0;
@@ -2601,7 +2485,6 @@ rs6000_init_expanders ()
rs6000_sysv_varargs_p = 0;
rs6000_fpmem_size = 0;
rs6000_fpmem_offset = 0;
- pic_offset_table_rtx = (rtx)0;
/* Arrange to save and restore machine status around nested functions. */
save_machine_status = rs6000_save_machine_status;
@@ -2646,7 +2529,7 @@ print_operand (file, x, code)
case '*':
/* Write the register number of the TOC register. */
- fputs (TARGET_MINIMAL_TOC ? reg_names[30] : reg_names[2], file);
+ fputs (TARGET_MINIMAL_TOC ? reg_names[30] : reg_names[2 /* PIC_OFFSET_TABLE_REGNUM? */ ], file);
return;
case '$':
@@ -3252,7 +3135,7 @@ print_operand_address (file, x)
;
#endif
else
- fprintf (file, "(%s)", reg_names[ TARGET_MINIMAL_TOC ? 30 : 2 ]);
+ fprintf (file, "(%s)", reg_names[ TARGET_MINIMAL_TOC ? 30 : 2 /* PIC_OFFSET_TABLE_REGNUM? */ ]);
}
else if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 1)) == REG)
{
@@ -4119,8 +4037,28 @@ output_prolog (file, size)
else
asm_fprintf (file, store_reg, reg_names[12], info->cr_save_offset + sp_offset,
reg_names[sp_reg]);
+ /* we save all the condition registers as if they are a single
+ register. The are physically, so this should work fine. */
+ if (dwarf2out_do_frame ())
+ {
+ SET_DWARF_LABEL (dw2_label);
+ dwarf2out_reg_save (dw2_label, 70, info->cr_save_offset);
+ }
}
+ /* If we need PIC_OFFSET_TABLE_REGNUM, initialize it now */
+ if (TARGET_ELF && flag_pic == 1 && current_function_uses_pic_offset_table)
+ {
+ if (!info->lr_save_p)
+ asm_fprintf (file, "\tmflr %s\n", reg_names[0]);
+
+ fputs ("\tbl _GLOBAL_OFFSET_TABLE_@local-4\n", file);
+ asm_fprintf (file, "\tmflr %s\n", reg_names[PIC_OFFSET_TABLE_REGNUM]);
+
+ if (!info->lr_save_p)
+ asm_fprintf (file, "\tmtlr %s\n", reg_names[0]);
+ }
+
/* NT needs us to probe the stack frame every 4k pages for large frames, so
do it here. */
if (DEFAULT_ABI == ABI_NT && info->total_size > 4096)
Index: rs6000.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/config/rs6000/rs6000.h,v
retrieving revision 1.49
diff -u -p -r1.49 rs6000.h
--- rs6000.h 1999/05/13 12:38:42 1.49
+++ rs6000.h 1999/06/09 00:07:35
@@ -884,15 +919,18 @@ extern int rs6000_debug_arg; /* debug a
64-bit AIX reserves GPR13 for thread-private data.
Conditionally disable FPRs. */
-#define CONDITIONAL_REGISTER_USAGE \
-{ \
- if (! TARGET_POWER) \
- fixed_regs[64] = 1; \
- if (TARGET_64BIT) \
- fixed_regs[13] = call_used_regs[13] = 1; \
- if (TARGET_SOFT_FLOAT) \
- for (i = 32; i < 64; i++) \
- fixed_regs[i] = call_used_regs[i] = 1; \
+#define CONDITIONAL_REGISTER_USAGE \
+{ \
+ if (! TARGET_POWER) \
+ fixed_regs[64] = 1; \
+ if (TARGET_64BIT) \
+ fixed_regs[13] = call_used_regs[13] = 1; \
+ if (TARGET_SOFT_FLOAT) \
+ for (i = 32; i < 64; i++) \
+ fixed_regs[i] = call_used_regs[i] = 1; \
+ if (TARGET_ELF && flag_pic == 1) \
+ fixed_regs[PIC_OFFSET_TABLE_REGNUM] \
+ = call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 1; \
}
/* Specify the registers used for certain standard purposes.
@@ -925,12 +963,6 @@ extern int rs6000_debug_arg; /* debug a
/* Special register that represents memory, used for float/int conversions. */
#define FPMEM_REGNUM 76
-/* Register to use as a placeholder for the GOT/allocated TOC register.
- FINALIZE_PIC will change all uses of this register to a an appropriate
- pseudo register when it adds the code to setup the GOT. We use r2
- because it is a reserved register in all of the ABI's. */
-#define GOT_TOC_REGNUM 2
-
/* Place that structure value return address is placed.
On the RS/6000, it is passed as an extra parameter. */
@@ -1146,12 +1178,21 @@ enum reg_class
On the RS/6000, we have to return NO_REGS when we want to reload a
floating-point CONST_DOUBLE to force it to be copied to memory. */
-
+/*
#define PREFERRED_RELOAD_CLASS(X,CLASS) \
((GET_CODE (X) == CONST_DOUBLE \
&& GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT) \
? NO_REGS : (CLASS))
+*/
+#define PREFERRED_RELOAD_CLASS(X,CLASS) \
+ (CONSTANT_P (X) \
+ && ((CLASS) == FLOAT_REGS \
+ || (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT \
+ && (HOST_FLOAT_FORMAT != IEEE_FLOAT_FORMAT \
+ || HOST_BITS_PER_INT != BITS_PER_WORD))) \
+ ? NO_REGS : (CLASS))
+
/* Return the register class of a scratch register needed to copy IN into
or out of a register in CLASS in MODE. If it can be done directly,
NO_REGS is returned. */
@@ -2105,7 +2151,7 @@ do {
this macro is not defined, it is up to the machine-dependent files
to allocate such a register (if necessary). */
-/* #define PIC_OFFSET_TABLE_REGNUM */
+#define PIC_OFFSET_TABLE_REGNUM 30
/* Define this macro if the register defined by
`PIC_OFFSET_TABLE_REGNUM' is clobbered by calls. Do not define
@@ -2128,7 +2174,7 @@ do {
prologues being included in functions which used inline functions
and were compiled to assembly language.) */
-#define FINALIZE_PIC rs6000_finalize_pic ()
+/* #define FINALIZE_PIC */
/* A C expression that is nonzero if X is a legitimate immediate
operand on the target machine when generating position independent
@@ -2143,11 +2189,8 @@ do {
/* In rare cases, correct code generation requires extra machine
dependent processing between the second jump optimization pass and
delayed branch scheduling. On those machines, define this macro
- as a C statement to act on the code starting at INSN.
+ as a C statement to act on the code starting at INSN. */
- On the RS/6000, we use it to make sure the GOT_TOC register marker
- that FINALIZE_PIC is supposed to remove actually got removed. */
-
#define MACHINE_DEPENDENT_REORG(INSN) rs6000_reorg (INSN)
Index: rs6000.md
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/config/rs6000/rs6000.md,v
retrieving revision 1.55
diff -u -p -r1.55 rs6000.md
--- rs6000.md 1999/05/13 12:38:44 1.55
+++ rs6000.md 1999/06/09 00:09:47
@@ -5809,21 +5809,6 @@
"{l|lwz} %0,%a1@got(%2)"
[(set_attr "type" "load")])
-;; Sometimes, though, the GOT `register' will be on the stack. Deal with
-;; this case specially.
-;; Force final to split this insn (if it hasn't been split already) to
-;; avoid having to create a suitable output template.
-(define_insn "*movsi_got_internal_mem"
- [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
- (unspec [(match_operand:SI 1 "got_no_const_operand" "")
- (match_operand:SI 2 "memory_operand" "m")] 8))]
- "(DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS)
- && flag_pic == 1
- && (reload_in_progress || reload_completed)"
- "#"
- [(set_attr "type" "load")
- (set_attr "length" "8")])
-
;; Used by sched, shorten_branches and final when the GOT pseudo reg
;; didn't get allocated to a hard register.
(define_split
@@ -8327,16 +8312,6 @@
[(unspec_volatile [(const_int 0)] 0)]
""
"")
-
-;; V.4 specific code to initialize the PIC register
-
-(define_insn "init_v4_pic"
- [(set (match_operand:SI 0 "register_operand" "=l")
- (unspec [(const_int 0)] 7))]
- "DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS"
- "bl _GLOBAL_OFFSET_TABLE_@local-4"
- [(set_attr "type" "branch")
- (set_attr "length" "4")])
;; Compare insns are next. Note that the RS/6000 has two types of compares,