summaryrefslogtreecommitdiff
path: root/gcc/integrate.c
diff options
context:
space:
mode:
authorbwilson <bwilson@138bc75d-0d04-0410-961f-82ee72b054a4>2002-01-23 21:03:53 +0000
committerbwilson <bwilson@138bc75d-0d04-0410-961f-82ee72b054a4>2002-01-23 21:03:53 +0000
commitf6b7ba2b65b368412f985d9e5fef16185bf7a249 (patch)
tree474190a92649d5af6ccd7a6f3ed51d377009630f /gcc/integrate.c
parentf97f597e410e178e838560cf99b8e840478b3bcb (diff)
downloadgcc-f6b7ba2b65b368412f985d9e5fef16185bf7a249.tar.gz
* config/xtensa/elf.h: New file.
* config/xtensa/lib1funcs.asm: New file. * config/xtensa/lib2funcs.S: New file. * config/xtensa/linux.h: New file. * config/xtensa/t-xtensa: New file. * config/xtensa/xtensa-config.h: New file. * config/xtensa/xtensa-protos.h: New file. * config/xtensa/xtensa.c: New file. * config/xtensa/xtensa.h: New file. * config/xtensa/xtensa.md: New file. * config.gcc (xtensa-*-elf*): New target. (xtensa-*-linux*): New target. * cse.c (canon_hash): Compare rtx pointers instead of register numbers. This is required for the Xtensa port. * integrate.c (copy_insn_list): Handle case where the static chain is in memory and the memory address has to be copied to a register. * doc/invoke.texi (Option Summary): Add Xtensa options. (Xtensa Options): New node. * doc/md.texi (Machine Constraints): Add Xtensa machine constraints. * gcc.c-torture/compile/20001226-1.x: xfail for Xtensa. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@49155 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/integrate.c')
-rw-r--r--gcc/integrate.c50
1 files changed, 44 insertions, 6 deletions
diff --git a/gcc/integrate.c b/gcc/integrate.c
index b1fecc4788d..10d98f2f8a8 100644
--- a/gcc/integrate.c
+++ b/gcc/integrate.c
@@ -1318,6 +1318,7 @@ copy_insn_list (insns, map, static_chain_value)
#ifdef HAVE_cc0
rtx cc0_insn = 0;
#endif
+ rtx static_chain_mem = 0;
/* Copy the insns one by one. Do this in two passes, first the insns and
then their REG_NOTES. */
@@ -1381,25 +1382,62 @@ copy_insn_list (insns, map, static_chain_value)
&& REG_FUNCTION_VALUE_P (XEXP (pattern, 0)))
break;
- /* If this is setting the static chain rtx, omit it. */
+ /* Look for the address of the static chain slot. The
+ rtx_equal_p comparisons against the
+ static_chain_incoming_rtx below may fail if the static
+ chain is in memory and the address specified is not
+ "legitimate". This happens on Xtensa where the static
+ chain is at a negative offset from argp and where only
+ positive offsets are legitimate. When the RTL is
+ generated, the address is "legitimized" by copying it
+ into a register, causing the rtx_equal_p comparisons to
+ fail. This workaround looks for code that sets a
+ register to the address of the static chain. Subsequent
+ memory references via that register can then be
+ identified as static chain references. We assume that
+ the register is only assigned once, and that the static
+ chain address is only live in one register at a time. */
+
else if (static_chain_value != 0
&& set != 0
+ && GET_CODE (static_chain_incoming_rtx) == MEM
&& GET_CODE (SET_DEST (set)) == REG
- && rtx_equal_p (SET_DEST (set),
- static_chain_incoming_rtx))
+ && rtx_equal_p (SET_SRC (set),
+ XEXP (static_chain_incoming_rtx, 0)))
+ {
+ static_chain_mem =
+ gen_rtx_MEM (GET_MODE (static_chain_incoming_rtx),
+ SET_DEST (set));
+
+ /* emit the instruction in case it is used for something
+ other than setting the static chain; if it's not used,
+ it can always be removed as dead code */
+ copy = emit_insn (copy_rtx_and_substitute (pattern, map, 0));
+ }
+
+ /* If this is setting the static chain rtx, omit it. */
+ else if (static_chain_value != 0
+ && set != 0
+ && (rtx_equal_p (SET_DEST (set),
+ static_chain_incoming_rtx)
+ || (static_chain_mem
+ && rtx_equal_p (SET_DEST (set), static_chain_mem))))
break;
/* If this is setting the static chain pseudo, set it from
the value we want to give it instead. */
else if (static_chain_value != 0
&& set != 0
- && rtx_equal_p (SET_SRC (set),
- static_chain_incoming_rtx))
+ && (rtx_equal_p (SET_SRC (set),
+ static_chain_incoming_rtx)
+ || (static_chain_mem
+ && rtx_equal_p (SET_SRC (set), static_chain_mem))))
{
rtx newdest = copy_rtx_and_substitute (SET_DEST (set), map, 1);
copy = emit_move_insn (newdest, static_chain_value);
- static_chain_value = 0;
+ if (GET_CODE (static_chain_incoming_rtx) != MEM)
+ static_chain_value = 0;
}
/* If this is setting the virtual stack vars register, this must