xtensa-protos.h (xtensa_copy_incoming_a7): Declare.

* config/xtensa/xtensa-protos.h (xtensa_copy_incoming_a7): Declare.
        * config/xtensa/xtensa.c (struct machine_function): Add
        incoming_a7_copied flag.
        (xtensa_copy_incoming_a7): Define.
        (xtensa_emit_move_sequence): Use xtensa_copy_incoming_a7.
        * config/xtensa/xtensa.md (movdi, movsf, movdf): Ditto.

From-SVN: r59382
This commit is contained in:
Bob Wilson 2002-11-22 19:27:42 +00:00 committed by Bob Wilson
parent b6bb8207c1
commit e1deeb725b
4 changed files with 87 additions and 57 deletions

View File

@ -1,3 +1,12 @@
2002-11-21 Bob Wilson <bob.wilson@acm.org>
* config/xtensa/xtensa-protos.h (xtensa_copy_incoming_a7): Declare.
* config/xtensa/xtensa.c (struct machine_function): Add
incoming_a7_copied flag.
(xtensa_copy_incoming_a7): Define.
(xtensa_emit_move_sequence): Use xtensa_copy_incoming_a7.
* config/xtensa/xtensa.md (movdi, movsf, movdf): Ditto.
2002-11-19 Release Manager
* GCC 3.2.1 Released.

View File

@ -70,6 +70,7 @@ extern int xtensa_expand_conditional_move PARAMS ((rtx *, int));
extern int xtensa_expand_scc PARAMS ((rtx *));
extern int xtensa_expand_block_move PARAMS ((rtx *));
extern int xtensa_emit_move_sequence PARAMS ((rtx *, enum machine_mode));
extern bool xtensa_copy_incoming_a7 PARAMS ((rtx *, enum machine_mode));
extern void xtensa_emit_block_move PARAMS ((rtx *, rtx *, int));
extern void xtensa_expand_nonlocal_goto PARAMS ((rtx *));
extern void xtensa_emit_loop_end PARAMS ((rtx, rtx *));

View File

@ -87,6 +87,7 @@ const char *xtensa_st_opcodes[(int) MAX_MACHINE_MODE];
struct machine_function
{
int accesses_prev_frame;
bool incoming_a7_copied;
};
/* Vector, indexed by hard register number, which contains 1 for a
@ -1262,45 +1263,8 @@ xtensa_emit_move_sequence (operands, mode)
if (!xtensa_valid_move (mode, operands))
operands[1] = force_reg (mode, operands[1]);
/* Check if this move is copying an incoming argument in a7. If
so, emit the move, followed by the special "set_frame_ptr"
unspec_volatile insn, at the very beginning of the function.
This is necessary because the register allocator will ignore
conflicts with a7 and may assign some other pseudo to a7. If
that pseudo was assigned prior to this move, it would clobber
the incoming argument in a7. By copying the argument out of
a7 as the very first thing, and then immediately following
that with an unspec_volatile to keep the scheduler away, we
should avoid any problems. */
if (a7_overlap_mentioned_p (operands[1]))
{
rtx mov;
switch (mode)
{
case SImode:
mov = gen_movsi_internal (operands[0], operands[1]);
break;
case HImode:
mov = gen_movhi_internal (operands[0], operands[1]);
break;
case QImode:
mov = gen_movqi_internal (operands[0], operands[1]);
break;
default:
abort ();
}
/* Insert the instructions before any other argument copies.
(The set_frame_ptr insn comes _after_ the move, so push it
out first.) */
push_topmost_sequence ();
emit_insn_after (gen_set_frame_ptr (), get_insns ());
emit_insn_after (mov, get_insns ());
pop_topmost_sequence ();
return 1;
}
if (xtensa_copy_incoming_a7 (operands, mode))
return 1;
}
/* During reload we don't want to emit (subreg:X (mem:Y)) since that
@ -1332,6 +1296,74 @@ fixup_subreg_mem (x)
}
/* Check if this move is copying an incoming argument in a7. If so,
emit the move, followed by the special "set_frame_ptr"
unspec_volatile insn, at the very beginning of the function. This
is necessary because the register allocator will ignore conflicts
with a7 and may assign some other pseudo to a7. If that pseudo was
assigned prior to this move, it would clobber the incoming argument
in a7. By copying the argument out of a7 as the very first thing,
and then immediately following that with an unspec_volatile to keep
the scheduler away, we should avoid any problems. */
bool
xtensa_copy_incoming_a7 (operands, mode)
rtx *operands;
enum machine_mode mode;
{
if (a7_overlap_mentioned_p (operands[1])
&& !cfun->machine->incoming_a7_copied)
{
rtx mov;
switch (mode)
{
case DFmode:
mov = gen_movdf_internal (operands[0], operands[1]);
break;
case SFmode:
mov = gen_movsf_internal (operands[0], operands[1]);
break;
case DImode:
mov = gen_movdi_internal (operands[0], operands[1]);
break;
case SImode:
mov = gen_movsi_internal (operands[0], operands[1]);
break;
case HImode:
mov = gen_movhi_internal (operands[0], operands[1]);
break;
case QImode:
mov = gen_movqi_internal (operands[0], operands[1]);
break;
default:
abort ();
}
/* Insert the instructions before any other argument copies.
(The set_frame_ptr insn comes _after_ the move, so push it
out first.) */
push_topmost_sequence ();
emit_insn_after (gen_set_frame_ptr (), get_insns ());
emit_insn_after (mov, get_insns ());
pop_topmost_sequence ();
/* Ideally the incoming argument in a7 would only be copied
once, since propagating a7 into the body of a function
will almost certainly lead to errors. However, there is
at least one harmless case (in GCSE) where the original
copy from a7 is changed to copy into a new pseudo. Thus,
we use a flag to only do this special treatment for the
first copy of a7. */
cfun->machine->incoming_a7_copied = true;
return 1;
}
return 0;
}
/* Try to expand a block move operation to an RTL block move instruction.
If not optimizing or if the block size is not a constant or if the
block is small, the expansion fails and GCC falls back to calling

View File

@ -929,12 +929,8 @@
&& !register_operand (operands[1], DImode))
operands[1] = force_reg (DImode, operands[1]);
if (a7_overlap_mentioned_p (operands[1]))
{
emit_insn (gen_movdi_internal (operands[0], operands[1]));
emit_insn (gen_set_frame_ptr ());
DONE;
}
if (xtensa_copy_incoming_a7 (operands, DImode))
DONE;
}
}")
@ -1107,12 +1103,8 @@
&& constantpool_mem_p (operands[1]))))
operands[1] = force_reg (SFmode, operands[1]);
if (a7_overlap_mentioned_p (operands[1]))
{
emit_insn (gen_movsf_internal (operands[0], operands[1]));
emit_insn (gen_set_frame_ptr ());
DONE;
}
if (xtensa_copy_incoming_a7 (operands, SFmode))
DONE;
}
}")
@ -1195,12 +1187,8 @@
&& !register_operand (operands[1], DFmode))
operands[1] = force_reg (DFmode, operands[1]);
if (a7_overlap_mentioned_p (operands[1]))
{
emit_insn (gen_movdf_internal (operands[0], operands[1]));
emit_insn (gen_set_frame_ptr ());
DONE;
}
if (xtensa_copy_incoming_a7 (operands, DFmode))
DONE;
}
}")