This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Xtensa port, part 3: patches to other files
- From: Bob Wilson <bwilson at tensilica dot com>
- To: gcc-patches <gcc-patches at gcc dot gnu dot org>
- Date: Fri, 30 Nov 2001 11:31:46 -0800
- Subject: Xtensa port, part 3: patches to other files
- Organization: Tensilica, Inc.
This file contains 3 patches to the processor-independent pieces of GCC.
I figure they deserve some explanation:
(1) gcc/cse.c
The Xtensa calling convention uses all available registers for either
incoming or outgoing registers. This forces us to use one of the
incoming argument registers as the hard frame pointer register. We
need to keep GCC from treating the incoming argument as if it were the
frame pointer. This is no problem in most cases where the frame pointer
is detected by checking the rtx pointer: gen_rtx_REG always uses the
same rtx for the frame pointer, so we can distinguish the incoming
argument by calling gen_rtx directly to create a different rtx with the
same register number. The patch to cse.c fixes one place where the
frame pointer check is done based on the register number.
(2) gcc/integrate.c
This patch fixes a problem where the inlining code assumes that
the static chain is in a register, or at least that the address of the
static chain is "legitimate" if the static chain is in memory. This
is not true for Xtensa processors, where the static chain is passed in
memory at a negative offset from the stack pointer and where only
positive memory offsets are supported by the processor. The comments
in the patch explain the details. In any case, the patch should only
affect ports where the static chain is in memory (only "romp" and Xtensa).
(3) gcc/varasm.c
This patch adds another hook to assemble_end_function(). We want to use
a "standard" definition for ASM_DECLARE_FUNCTION_SIZE (the existing
hook), but we also need to emit a bit of extra assembly at the end of
some functions.
Changelog for part 3:
* cse.c (canon_hash): Compare rtx pointers instead of register
numbers.
* 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.
* varasm.c (assemble_end_function): Add ASM_OUTPUT_FUNCTION_END
hook.
Index: gcc/cse.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cse.c,v
retrieving revision 1.174.2.6
diff -c -3 -p -r1.174.2.6 cse.c
*** cse.c 2001/09/12 20:55:19 1.174.2.6
--- cse.c 2001/11/30 17:41:04
*************** canon_hash (x, mode)
*** 2277,2286 ****
&& (global_regs[regno]
|| (SMALL_REGISTER_CLASSES
&& ! fixed_regs[regno]
! && regno != FRAME_POINTER_REGNUM
! && regno != HARD_FRAME_POINTER_REGNUM
! && regno != ARG_POINTER_REGNUM
! && regno != STACK_POINTER_REGNUM
&& GET_MODE_CLASS (GET_MODE (x)) != MODE_CC)))
{
do_not_record = 1;
--- 2277,2286 ----
&& (global_regs[regno]
|| (SMALL_REGISTER_CLASSES
&& ! fixed_regs[regno]
! && x != frame_pointer_rtx
! && x != hard_frame_pointer_rtx
! && x != arg_pointer_rtx
! && x != stack_pointer_rtx
&& GET_MODE_CLASS (GET_MODE (x)) != MODE_CC)))
{
do_not_record = 1;
Index: gcc/integrate.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/integrate.c,v
retrieving revision 1.126.4.11
diff -c -3 -p -r1.126.4.11 integrate.c
*** integrate.c 2001/06/08 22:55:35 1.126.4.11
--- integrate.c 2001/11/30 17:41:06
*************** copy_insn_list (insns, map, static_chain
*** 1225,1230 ****
--- 1225,1231 ----
#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. */
*************** copy_insn_list (insns, map, static_chain
*** 1288,1312 ****
&& REG_FUNCTION_VALUE_P (XEXP (pattern, 0)))
break;
! /* If this is setting the static chain rtx, omit it. */
else if (static_chain_value != 0
&& set != 0
&& GET_CODE (SET_DEST (set)) == REG
! && rtx_equal_p (SET_DEST (set),
! static_chain_incoming_rtx))
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 newdest = copy_rtx_and_substitute (SET_DEST (set), map, 1);
copy = emit_move_insn (newdest, static_chain_value);
! static_chain_value = 0;
}
/* If this is setting the virtual stack vars register, this must
--- 1289,1350 ----
&& REG_FUNCTION_VALUE_P (XEXP (pattern, 0)))
break;
! /* 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_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)
! || (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);
! if (GET_CODE (static_chain_incoming_rtx) != MEM)
! static_chain_value = 0;
}
/* If this is setting the virtual stack vars register, this must
Index: gcc/varasm.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/varasm.c,v
retrieving revision 1.161.2.17
diff -c -3 -p -r1.161.2.17 varasm.c
*** varasm.c 2001/09/22 01:33:20 1.161.2.17
--- varasm.c 2001/11/30 17:41:08
*************** assemble_end_function (decl, fnname)
*** 1012,1017 ****
--- 1012,1020 ----
#ifdef ASM_DECLARE_FUNCTION_SIZE
ASM_DECLARE_FUNCTION_SIZE (asm_out_file, fnname, decl);
#endif
+ #ifdef ASM_OUTPUT_FUNCTION_END
+ ASM_OUTPUT_FUNCTION_END (asm_out_file, fnname, decl);
+ #endif
if (! CONSTANT_POOL_BEFORE_FUNCTION)
{
output_constant_pool (fnname, decl);