Commit e6aecf8e by Bob Wilson Committed by Bob Wilson

xtensa.c (xtensa_copy_incoming_a7): Remove SUBREG on CQImode and CHImode…

xtensa.c (xtensa_copy_incoming_a7): Remove SUBREG on CQImode and CHImode incoming arguments in register a7.

	* config/xtensa/xtensa.c (xtensa_copy_incoming_a7): Remove SUBREG
	on CQImode and CHImode incoming arguments in register a7.
	(function_arg): Wrap BLKmode argument in register a7 in a PARALLEL.
	* config/xtensa/xtensa.h (BLOCK_REG_PADDING): Define.
	* config/xtensa/xtensa.md (movdi, movdf): Only call force_reg or
	xtensa_copy_incoming_a7 before reload.

From-SVN: r76742
parent 02307675
2004-01-27 Bob Wilson <bob.wilson@acm.org>
* config/xtensa/xtensa.c (xtensa_copy_incoming_a7): Remove SUBREG
on CQImode and CHImode incoming arguments in register a7.
(function_arg): Wrap BLKmode argument in register a7 in a PARALLEL.
* config/xtensa/xtensa.h (BLOCK_REG_PADDING): Define.
* config/xtensa/xtensa.md (movdi, movdf): Only call force_reg or
xtensa_copy_incoming_a7 before reload.
2004-01-27 J"orn Rennecke <joern.rennecke@superh.com> 2004-01-27 J"orn Rennecke <joern.rennecke@superh.com>
* coverage.c (get_coverage_counts): Give a different message * coverage.c (get_coverage_counts): Give a different message
......
...@@ -1327,7 +1327,27 @@ xtensa_copy_incoming_a7 (rtx *operands, enum machine_mode mode) ...@@ -1327,7 +1327,27 @@ xtensa_copy_incoming_a7 (rtx *operands, enum machine_mode mode)
if (a7_overlap_mentioned_p (operands[1]) if (a7_overlap_mentioned_p (operands[1])
&& !cfun->machine->incoming_a7_copied) && !cfun->machine->incoming_a7_copied)
{ {
rtx mov; rtx mov, src;
/* Despite defining SPLIT_COMPLEX_ARGS, complex function
arguments may still appear if they are wrapped in a struct.
For CQImode and CHImode arguments, this results in a move
with a source operand of the form: "(subreg:SI (reg:CHI a7)
0)". The subreg is later removed by the reload pass,
resulting in the RTL for a7 being regenerated using
hard_frame_pointer_rtx, and making it impossible for us to
distinguish the function argument. Detect this here when
generating the RTL and remove the subreg immediately so that
reload won't mess it up. */
src = operands[1];
if (GET_CODE (src) == SUBREG
&& GET_CODE (SUBREG_REG (src)) == REG
&& REGNO (SUBREG_REG (src)) == A7_REG
&& SUBREG_BYTE (src) == 0
&& (GET_MODE (SUBREG_REG (src)) == CHImode
|| GET_MODE (SUBREG_REG (src)) == CQImode))
operands[1] = gen_raw_REG (mode, A7_REG);
switch (mode) switch (mode)
{ {
case DFmode: case DFmode:
...@@ -1773,11 +1793,15 @@ function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type, ...@@ -1773,11 +1793,15 @@ function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
rtx that is not equal to hard_frame_pointer_rtx. For multi-word rtx that is not equal to hard_frame_pointer_rtx. For multi-word
modes for which we don't define move patterns, we can't control modes for which we don't define move patterns, we can't control
the expansion unless we explicitly list the individual registers the expansion unless we explicitly list the individual registers
in a PARALLEL. */ in a PARALLEL. Likewise, a single-word BLKmode argument passed
in a7 must be wrapped in a PARALLEL to avoid code that takes the
if (mode != DImode && mode != DFmode register number and builds a new REG. This is extremely fragile
&& regno < A7_REG but seems to be the best solution for now. */
&& regno + words > A7_REG)
if ((mode != DImode && mode != DFmode
&& regno < A7_REG
&& regno + words > A7_REG)
|| (mode == BLKmode && regno == A7_REG))
{ {
rtx result; rtx result;
int n; int n;
......
...@@ -799,6 +799,12 @@ typedef struct xtensa_args { ...@@ -799,6 +799,12 @@ typedef struct xtensa_args {
/* Pass complex arguments independently. */ /* Pass complex arguments independently. */
#define SPLIT_COMPLEX_ARGS 1 #define SPLIT_COMPLEX_ARGS 1
/* Because Xtensa's function_arg() wraps BLKmode arguments passed in
a7 inside a PARALLEL, BLOCK_REG_PADDING needs to be defined
to get emit_group_store to do the right thing. */
#define BLOCK_REG_PADDING(MODE, TYPE, FIRST) \
FUNCTION_ARG_PADDING (MODE, TYPE)
/* Profiling Xtensa code is typically done with the built-in profiling /* Profiling Xtensa code is typically done with the built-in profiling
feature of Tensilica's instruction set simulator, which does not feature of Tensilica's instruction set simulator, which does not
require any compiler support. Profiling code on a real (i.e., require any compiler support. Profiling code on a real (i.e.,
......
;; GCC machine description for Tensilica's Xtensa architecture. ;; GCC machine description for Tensilica's Xtensa architecture.
;; Copyright (C) 2001 Free Software Foundation, Inc. ;; Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
;; Contributed by Bob Wilson (bwilson@tensilica.com) at Tensilica. ;; Contributed by Bob Wilson (bwilson@tensilica.com) at Tensilica.
;; This file is part of GCC. ;; This file is part of GCC.
...@@ -803,12 +803,15 @@ ...@@ -803,12 +803,15 @@
if (CONSTANT_P (operands[1]) && !TARGET_CONST16) if (CONSTANT_P (operands[1]) && !TARGET_CONST16)
operands[1] = force_const_mem (DImode, operands[1]); operands[1] = force_const_mem (DImode, operands[1]);
if (!register_operand (operands[0], DImode) if (!(reload_in_progress | reload_completed))
&& !register_operand (operands[1], DImode)) {
operands[1] = force_reg (DImode, operands[1]); if (!register_operand (operands[0], DImode)
&& !register_operand (operands[1], DImode))
operands[1] = force_reg (DImode, operands[1]);
if (xtensa_copy_incoming_a7 (operands, DImode)) if (xtensa_copy_incoming_a7 (operands, DImode))
DONE; DONE;
}
}) })
(define_insn_and_split "movdi_internal" (define_insn_and_split "movdi_internal"
...@@ -1012,12 +1015,15 @@ ...@@ -1012,12 +1015,15 @@
if (CONSTANT_P (operands[1]) && !TARGET_CONST16) if (CONSTANT_P (operands[1]) && !TARGET_CONST16)
operands[1] = force_const_mem (DFmode, operands[1]); operands[1] = force_const_mem (DFmode, operands[1]);
if (!register_operand (operands[0], DFmode) if (!(reload_in_progress | reload_completed))
&& !register_operand (operands[1], DFmode)) {
operands[1] = force_reg (DFmode, operands[1]); if (!register_operand (operands[0], DFmode)
&& !register_operand (operands[1], DFmode))
operands[1] = force_reg (DFmode, operands[1]);
if (xtensa_copy_incoming_a7 (operands, DFmode)) if (xtensa_copy_incoming_a7 (operands, DFmode))
DONE; DONE;
}
}) })
(define_insn_and_split "movdf_internal" (define_insn_and_split "movdf_internal"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment