xtensa.c (xtensa_expand_block_move): Expand block move to rtl completely.

* config/xtensa/xtensa.c (xtensa_expand_block_move): Expand block
        move to rtl completely.
        (struct meminsnbuf, xtensa_emit_block_move): Remove.
        (xtensa_find_mode_for_size): Remove.
        * config/xtensa/xtensa-protos.h (xtensa_emit_block_move): Remove.
        * config/xtensa/xtensa.md (movmemsi_internal): Remove.

From-SVN: r86235
This commit is contained in:
Richard Henderson 2004-08-18 23:12:12 -07:00 committed by Richard Henderson
parent 8804266301
commit 7eda7cda0a
4 changed files with 73 additions and 154 deletions

View File

@ -1,3 +1,12 @@
2004-08-18 Richard Henderson <rth@redhat.com>
* config/xtensa/xtensa.c (xtensa_expand_block_move): Expand block
move to rtl completely.
(struct meminsnbuf, xtensa_emit_block_move): Remove.
(xtensa_find_mode_for_size): Remove.
* config/xtensa/xtensa-protos.h (xtensa_emit_block_move): Remove.
* config/xtensa/xtensa.md (movmemsi_internal): Remove.
2004-08-18 Richard Henderson <rth@redhat.com> 2004-08-18 Richard Henderson <rth@redhat.com>
* config/mcore/mcore.c (mode_from_align): Remove DImode. * config/mcore/mcore.c (mode_from_align): Remove DImode.

View File

@ -69,7 +69,6 @@ extern int xtensa_expand_block_move (rtx *);
extern void xtensa_split_operand_pair (rtx *, enum machine_mode); extern void xtensa_split_operand_pair (rtx *, enum machine_mode);
extern int xtensa_emit_move_sequence (rtx *, enum machine_mode); extern int xtensa_emit_move_sequence (rtx *, enum machine_mode);
extern rtx xtensa_copy_incoming_a7 (rtx); extern rtx xtensa_copy_incoming_a7 (rtx);
extern void xtensa_emit_block_move (rtx *, rtx *, int);
extern void xtensa_expand_nonlocal_goto (rtx *); extern void xtensa_expand_nonlocal_goto (rtx *);
extern void xtensa_emit_loop_end (rtx, rtx *); extern void xtensa_emit_loop_end (rtx, rtx *);
extern char *xtensa_emit_call (int, rtx *); extern char *xtensa_emit_call (int, rtx *);

View File

@ -200,7 +200,6 @@ static rtx gen_int_relational (enum rtx_code, rtx, rtx, int *);
static rtx gen_float_relational (enum rtx_code, rtx, rtx); static rtx gen_float_relational (enum rtx_code, rtx, rtx);
static rtx gen_conditional_move (rtx); static rtx gen_conditional_move (rtx);
static rtx fixup_subreg_mem (rtx); static rtx fixup_subreg_mem (rtx);
static enum machine_mode xtensa_find_mode_for_size (unsigned);
static struct machine_function * xtensa_init_machine_status (void); static struct machine_function * xtensa_init_machine_status (void);
static bool xtensa_return_in_msb (tree); static bool xtensa_return_in_msb (tree);
static void printx (FILE *, signed int); static void printx (FILE *, signed int);
@ -1439,19 +1438,35 @@ xtensa_copy_incoming_a7 (rtx opnd)
int int
xtensa_expand_block_move (rtx *operands) xtensa_expand_block_move (rtx *operands)
{ {
rtx dest = operands[0]; static const enum machine_mode mode_from_align[] =
rtx src = operands[1]; {
int bytes = INTVAL (operands[2]); VOIDmode, QImode, HImode, VOIDmode, SImode,
int align = XINT (operands[3], 0); };
rtx dst_mem = operands[0];
rtx src_mem = operands[1];
HOST_WIDE_INT bytes, align;
int num_pieces, move_ratio; int num_pieces, move_ratio;
rtx temp[2];
enum machine_mode mode[2];
int amount[2];
bool active[2];
int phase = 0;
int next;
int offset_ld = 0;
int offset_st = 0;
rtx x;
/* If this is not a fixed size move, just call memcpy. */ /* If this is not a fixed size move, just call memcpy. */
if (!optimize || (GET_CODE (operands[2]) != CONST_INT)) if (!optimize || (GET_CODE (operands[2]) != CONST_INT))
return 0; return 0;
bytes = INTVAL (operands[2]);
align = INTVAL (operands[3]);
/* Anything to move? */ /* Anything to move? */
if (bytes <= 0) if (bytes <= 0)
return 1; return 0;
if (align > MOVE_MAX) if (align > MOVE_MAX)
align = MOVE_MAX; align = MOVE_MAX;
@ -1461,147 +1476,62 @@ xtensa_expand_block_move (rtx *operands)
if (optimize > 2) if (optimize > 2)
move_ratio = LARGEST_MOVE_RATIO; move_ratio = LARGEST_MOVE_RATIO;
num_pieces = (bytes / align) + (bytes % align); /* Close enough anyway. */ num_pieces = (bytes / align) + (bytes % align); /* Close enough anyway. */
if (num_pieces >= move_ratio) if (num_pieces > move_ratio)
return 0; return 0;
/* Make sure the memory addresses are valid. */ x = XEXP (dst_mem, 0);
operands[0] = validize_mem (dest); if (!REG_P (x))
operands[1] = validize_mem (src);
emit_insn (gen_movmemsi_internal (operands[0], operands[1],
operands[2], operands[3]));
return 1;
}
/* Emit a sequence of instructions to implement a block move, trying
to hide load delay slots as much as possible. Load N values into
temporary registers, store those N values, and repeat until the
complete block has been moved. N=delay_slots+1. */
struct meminsnbuf
{
char template[30];
rtx operands[2];
};
void
xtensa_emit_block_move (rtx *operands, rtx *tmpregs, int delay_slots)
{
rtx dest = operands[0];
rtx src = operands[1];
int bytes = INTVAL (operands[2]);
int align = XINT (operands[3], 0);
rtx from_addr = XEXP (src, 0);
rtx to_addr = XEXP (dest, 0);
int from_struct = MEM_IN_STRUCT_P (src);
int to_struct = MEM_IN_STRUCT_P (dest);
int offset = 0;
int chunk_size, item_size;
struct meminsnbuf *ldinsns, *stinsns;
const char *ldname, *stname;
enum machine_mode mode;
if (align > MOVE_MAX)
align = MOVE_MAX;
item_size = align;
chunk_size = delay_slots + 1;
ldinsns = (struct meminsnbuf *)
alloca (chunk_size * sizeof (struct meminsnbuf));
stinsns = (struct meminsnbuf *)
alloca (chunk_size * sizeof (struct meminsnbuf));
mode = xtensa_find_mode_for_size (item_size);
item_size = GET_MODE_SIZE (mode);
ldname = xtensa_ld_opcodes[(int) mode];
stname = xtensa_st_opcodes[(int) mode];
while (bytes > 0)
{ {
int n; x = force_reg (Pmode, x);
dst_mem = replace_equiv_address (dst_mem, x);
}
for (n = 0; n < chunk_size; n++) x = XEXP (src_mem, 0);
if (!REG_P (x))
{
x = force_reg (Pmode, x);
src_mem = replace_equiv_address (src_mem, x);
}
active[0] = active[1] = false;
do
{
next = phase;
phase ^= 1;
if (bytes > 0)
{ {
rtx addr, mem; int next_amount;
if (bytes == 0) next_amount = (bytes >= 4 ? 4 : (bytes >= 2 ? 2 : 1));
{ next_amount = MIN (next_amount, align);
chunk_size = n;
break;
}
if (bytes < item_size) amount[next] = next_amount;
{ mode[next] = mode_from_align[next_amount];
/* Find a smaller item_size which we can load & store. */ temp[next] = gen_reg_rtx (mode[next]);
item_size = bytes;
mode = xtensa_find_mode_for_size (item_size);
item_size = GET_MODE_SIZE (mode);
ldname = xtensa_ld_opcodes[(int) mode];
stname = xtensa_st_opcodes[(int) mode];
}
/* Record the load instruction opcode and operands. */ x = adjust_address (src_mem, mode[next], offset_ld);
addr = plus_constant (from_addr, offset); emit_insn (gen_rtx_SET (VOIDmode, temp[next], x));
mem = gen_rtx_MEM (mode, addr);
if (! memory_address_p (mode, addr))
abort ();
MEM_IN_STRUCT_P (mem) = from_struct;
ldinsns[n].operands[0] = tmpregs[n];
ldinsns[n].operands[1] = mem;
sprintf (ldinsns[n].template, "%s\t%%0, %%1", ldname);
/* Record the store instruction opcode and operands. */ offset_ld += next_amount;
addr = plus_constant (to_addr, offset); bytes -= next_amount;
mem = gen_rtx_MEM (mode, addr); active[next] = true;
if (! memory_address_p (mode, addr))
abort ();
MEM_IN_STRUCT_P (mem) = to_struct;
stinsns[n].operands[0] = tmpregs[n];
stinsns[n].operands[1] = mem;
sprintf (stinsns[n].template, "%s\t%%0, %%1", stname);
offset += item_size;
bytes -= item_size;
} }
/* Now output the loads followed by the stores. */ if (active[phase])
for (n = 0; n < chunk_size; n++) {
output_asm_insn (ldinsns[n].template, ldinsns[n].operands); active[phase] = false;
for (n = 0; n < chunk_size; n++)
output_asm_insn (stinsns[n].template, stinsns[n].operands); x = adjust_address (dst_mem, mode[phase], offset_st);
emit_insn (gen_rtx_SET (VOIDmode, x, temp[phase]));
offset_st += amount[phase];
}
} }
} while (active[next]);
return 1;
static enum machine_mode
xtensa_find_mode_for_size (unsigned item_size)
{
enum machine_mode mode, tmode;
while (1)
{
mode = VOIDmode;
/* Find mode closest to but not bigger than item_size. */
for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT);
tmode != VOIDmode; tmode = GET_MODE_WIDER_MODE (tmode))
if (GET_MODE_SIZE (tmode) <= item_size)
mode = tmode;
if (mode == VOIDmode)
abort ();
item_size = GET_MODE_SIZE (mode);
if (xtensa_ld_opcodes[(int) mode]
&& xtensa_st_opcodes[(int) mode])
break;
/* Cannot load & store this mode; try something smaller. */
item_size -= 1;
}
return mode;
} }

View File

@ -1069,25 +1069,6 @@
DONE; DONE;
}) })
(define_insn "movmemsi_internal"
[(set (match_operand:BLK 0 "memory_operand" "=U")
(match_operand:BLK 1 "memory_operand" "U"))
(use (match_operand:SI 2 "arith_operand" ""))
(use (match_operand:SI 3 "const_int_operand" ""))
(clobber (match_scratch:SI 4 "=&r"))
(clobber (match_scratch:SI 5 "=&r"))]
""
{
rtx tmpregs[2];
tmpregs[0] = operands[4];
tmpregs[1] = operands[5];
xtensa_emit_block_move (operands, tmpregs, 1);
return "";
}
[(set_attr "type" "multi")
(set_attr "mode" "none")
(set_attr "length" "300")])
;; Shift instructions. ;; Shift instructions.