From 7eda7cda0a59d5f461936c1d131c534bb7a6c8a2 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 18 Aug 2004 23:12:12 -0700 Subject: [PATCH] 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 --- gcc/ChangeLog | 9 ++ gcc/config/xtensa/xtensa-protos.h | 1 - gcc/config/xtensa/xtensa.c | 192 ++++++++++-------------------- gcc/config/xtensa/xtensa.md | 19 --- 4 files changed, 70 insertions(+), 151 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 725fb34eca9..e1d71eeab28 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2004-08-18 Richard Henderson + + * 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 * config/mcore/mcore.c (mode_from_align): Remove DImode. diff --git a/gcc/config/xtensa/xtensa-protos.h b/gcc/config/xtensa/xtensa-protos.h index a300204e8ec..f50286d058f 100644 --- a/gcc/config/xtensa/xtensa-protos.h +++ b/gcc/config/xtensa/xtensa-protos.h @@ -69,7 +69,6 @@ extern int xtensa_expand_block_move (rtx *); extern void xtensa_split_operand_pair (rtx *, enum machine_mode); extern int xtensa_emit_move_sequence (rtx *, enum machine_mode); 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_emit_loop_end (rtx, rtx *); extern char *xtensa_emit_call (int, rtx *); diff --git a/gcc/config/xtensa/xtensa.c b/gcc/config/xtensa/xtensa.c index e91e943f57d..8d9a1b7fef8 100644 --- a/gcc/config/xtensa/xtensa.c +++ b/gcc/config/xtensa/xtensa.c @@ -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_conditional_move (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 bool xtensa_return_in_msb (tree); static void printx (FILE *, signed int); @@ -1439,19 +1438,35 @@ xtensa_copy_incoming_a7 (rtx opnd) int xtensa_expand_block_move (rtx *operands) { - rtx dest = operands[0]; - rtx src = operands[1]; - int bytes = INTVAL (operands[2]); - int align = XINT (operands[3], 0); + static const enum machine_mode mode_from_align[] = + { + VOIDmode, QImode, HImode, VOIDmode, SImode, + }; + + rtx dst_mem = operands[0]; + rtx src_mem = operands[1]; + HOST_WIDE_INT bytes, align; 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 (!optimize || (GET_CODE (operands[2]) != CONST_INT)) return 0; + bytes = INTVAL (operands[2]); + align = INTVAL (operands[3]); + /* Anything to move? */ if (bytes <= 0) - return 1; + return 0; if (align > MOVE_MAX) align = MOVE_MAX; @@ -1461,147 +1476,62 @@ xtensa_expand_block_move (rtx *operands) if (optimize > 2) move_ratio = LARGEST_MOVE_RATIO; num_pieces = (bytes / align) + (bytes % align); /* Close enough anyway. */ - if (num_pieces >= move_ratio) + if (num_pieces > move_ratio) return 0; - /* Make sure the memory addresses are valid. */ - operands[0] = validize_mem (dest); - 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; + x = XEXP (dst_mem, 0); + if (!REG_P (x)) + { + x = force_reg (Pmode, x); + dst_mem = replace_equiv_address (dst_mem, x); + } - ldinsns = (struct meminsnbuf *) - alloca (chunk_size * sizeof (struct meminsnbuf)); - stinsns = (struct meminsnbuf *) - alloca (chunk_size * sizeof (struct meminsnbuf)); + x = XEXP (src_mem, 0); + if (!REG_P (x)) + { + x = force_reg (Pmode, x); + src_mem = replace_equiv_address (src_mem, x); + } - 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]; + active[0] = active[1] = false; - while (bytes > 0) + do { - int n; + next = phase; + phase ^= 1; - for (n = 0; n < chunk_size; n++) + if (bytes > 0) { - rtx addr, mem; - - if (bytes == 0) - { - chunk_size = n; - break; - } - - if (bytes < item_size) - { - /* Find a smaller item_size which we can load & store. */ - 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. */ - addr = plus_constant (from_addr, offset); - 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. */ - addr = plus_constant (to_addr, offset); - mem = gen_rtx_MEM (mode, addr); - 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; - } + int next_amount; - /* Now output the loads followed by the stores. */ - for (n = 0; n < chunk_size; n++) - output_asm_insn (ldinsns[n].template, ldinsns[n].operands); - for (n = 0; n < chunk_size; n++) - output_asm_insn (stinsns[n].template, stinsns[n].operands); - } -} + next_amount = (bytes >= 4 ? 4 : (bytes >= 2 ? 2 : 1)); + next_amount = MIN (next_amount, align); + amount[next] = next_amount; + mode[next] = mode_from_align[next_amount]; + temp[next] = gen_reg_rtx (mode[next]); -static enum machine_mode -xtensa_find_mode_for_size (unsigned item_size) -{ - enum machine_mode mode, tmode; + x = adjust_address (src_mem, mode[next], offset_ld); + emit_insn (gen_rtx_SET (VOIDmode, temp[next], x)); - 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); + offset_ld += next_amount; + bytes -= next_amount; + active[next] = true; + } - if (xtensa_ld_opcodes[(int) mode] - && xtensa_st_opcodes[(int) mode]) - break; + if (active[phase]) + { + active[phase] = false; + + x = adjust_address (dst_mem, mode[phase], offset_st); + emit_insn (gen_rtx_SET (VOIDmode, x, temp[phase])); - /* Cannot load & store this mode; try something smaller. */ - item_size -= 1; + offset_st += amount[phase]; + } } + while (active[next]); - return mode; + return 1; } diff --git a/gcc/config/xtensa/xtensa.md b/gcc/config/xtensa/xtensa.md index a5421f04a12..448a892d744 100644 --- a/gcc/config/xtensa/xtensa.md +++ b/gcc/config/xtensa/xtensa.md @@ -1069,25 +1069,6 @@ 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. -- 2.30.2