xtensa.c (xtensa_expand_block_move): Expand block move to rtl completely.
authorRichard Henderson <rth@redhat.com>
Thu, 19 Aug 2004 06:12:12 +0000 (23:12 -0700)
committerRichard Henderson <rth@gcc.gnu.org>
Thu, 19 Aug 2004 06:12:12 +0000 (23:12 -0700)
        * 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
gcc/config/xtensa/xtensa-protos.h
gcc/config/xtensa/xtensa.c
gcc/config/xtensa/xtensa.md

index 725fb34eca932be81bd0994ddc637e1320aa2bfe..e1d71eeab2888e9bd8795358a6f69939e4991f14 100644 (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>
 
        * config/mcore/mcore.c (mode_from_align): Remove DImode.
index a300204e8ecf488cff46098cce4a5133c7bfcba6..f50286d058f844d6c1dc881b8b6daf6dea89618d 100644 (file)
@@ -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 *);
index e91e943f57db8178f340b41c4ad56bb083afcda7..8d9a1b7fef8a7a42f0acd8e2179232c7de676e6f 100644 (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_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;
 }
 
 
index a5421f04a12a1243be749c71fd8b0e5477684991..448a892d744535d7992213b8bc27fe36824e9178 100644 (file)
   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")])
-
 \f
 ;; Shift instructions.