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:
parent
b6bb8207c1
commit
e1deeb725b
|
@ -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.
|
||||
|
|
|
@ -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 *));
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}")
|
||||
|
||||
|
|
Loading…
Reference in New Issue