This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

rewrite xtensa block move


"Rewrite" in this case meaning "copy from mcore", since I just
got finished tidying that version wrt aliasing.

The rtl emitted is basically the same as the assembly that
xtensa_emit_block_move was trying to generate.  Lightly tested,
but committed anyway.


r~


        * 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.

Index: config/xtensa/xtensa-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/xtensa/xtensa-protos.h,v
retrieving revision 1.17
diff -c -p -d -r1.17 xtensa-protos.h
*** config/xtensa/xtensa-protos.h	9 Jul 2004 10:13:16 -0000	1.17
--- config/xtensa/xtensa-protos.h	19 Aug 2004 06:09:51 -0000
*************** extern int xtensa_expand_block_move (rtx
*** 69,75 ****
  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 *);
--- 69,74 ----
Index: config/xtensa/xtensa.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/xtensa/xtensa.c,v
retrieving revision 1.67
diff -c -p -d -r1.67 xtensa.c
*** config/xtensa/xtensa.c	15 Aug 2004 15:45:19 -0000	1.67
--- config/xtensa/xtensa.c	19 Aug 2004 06:09:52 -0000
*************** static rtx gen_int_relational (enum rtx_
*** 200,206 ****
  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);
--- 200,205 ----
*************** xtensa_copy_incoming_a7 (rtx opnd)
*** 1439,1457 ****
  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);
    int num_pieces, move_ratio;
  
    /* If this is not a fixed size move, just call memcpy.  */
    if (!optimize || (GET_CODE (operands[2]) != CONST_INT))
      return 0;
  
    /* Anything to move?  */
    if (bytes <= 0)
!     return 1;
  
    if (align > MOVE_MAX)
      align = MOVE_MAX;
--- 1438,1472 ----
  int
  xtensa_expand_block_move (rtx *operands)
  {
!   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 0;
  
    if (align > MOVE_MAX)
      align = MOVE_MAX;
*************** xtensa_expand_block_move (rtx *operands)
*** 1461,1607 ****
    if (optimize > 2)
      move_ratio = LARGEST_MOVE_RATIO;
    num_pieces = (bytes / align) + (bytes % align); /* Close enough anyway.  */
!   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;
  
!   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;
  
!       for (n = 0; n < chunk_size; n++)
  	{
! 	  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;
  	}
  
!       /* 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);
!     }
! }
! 
! 
! 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;
  }
  
  
--- 1476,1537 ----
    if (optimize > 2)
      move_ratio = LARGEST_MOVE_RATIO;
    num_pieces = (bytes / align) + (bytes % align); /* Close enough anyway.  */
!   if (num_pieces > move_ratio)
      return 0;
  
!   x = XEXP (dst_mem, 0);
!   if (!REG_P (x))
!     {
!       x = force_reg (Pmode, x);
!       dst_mem = replace_equiv_address (dst_mem, x);
!     }
  
!   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)
  	{
! 	  int next_amount;
  
! 	  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]);
  
! 	  x = adjust_address (src_mem, mode[next], offset_ld);
! 	  emit_insn (gen_rtx_SET (VOIDmode, temp[next], x));
  
! 	  offset_ld += next_amount;
! 	  bytes -= next_amount;
! 	  active[next] = true;
  	}
  
!       if (active[phase])
! 	{
! 	  active[phase] = false;
! 	  
! 	  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;
  }
  
  
Index: config/xtensa/xtensa.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/xtensa/xtensa.md,v
retrieving revision 1.21
diff -c -p -d -r1.21 xtensa.md
*** config/xtensa/xtensa.md	7 Jul 2004 19:24:56 -0000	1.21
--- config/xtensa/xtensa.md	19 Aug 2004 06:09:52 -0000
***************
*** 1069,1093 ****
    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.
  
--- 1069,1074 ----


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]