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]

[Xtensa] fix double-word moves


There was a problem with my previous change to the Xtensa port's movdi and 
movdf patterns.  This patch changes them to use post-reload split patterns, 
instead of trying to use the expand patterns to split up constant operands.  
Besides fixing the problem, I think this makes the code simpler and it should 
also generate slightly better code in some cases.  I tested this with the 
xtensa-elf target and committed it on the mainline.

2003-05-28  Bob Wilson  <bob.wilson@acm.org>

        * config/xtensa/xtensa-protos.h (smalloffset_double_mem_p): Delete.
        (xtensa_split_operand_pair): New proto.
        * config/xtensa/xtensa.c (move_operand): Handle DFmode and DImode.
        (smalloffset_double_mem_p): Delete.
        (gen_float_relational, printx, print_operand, xtensa_va_arg):
        Fix whitespace.
        (xtensa_split_operand_pair): New.
        (xtensa_dbx_register_number): Fix formatting.
        * config/xtensa/xtensa.h (EXTRA_CONSTRAINT): Remove 'S' constraint.
        * config/xtensa/xtensa.md (movdi, movdf): Force constants to memory
        instead of splitting them into single-word moves.  Remove unnecessary
        checks for reload_in_progress and reload_completed.
        (movdi_internal, movdf_internal): Change to post-reload split 
patterns.
        Add constraints to allow constant operands.
        (movsf_internal): Allow CONST_INT operands.

Index: xtensa-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/xtensa/xtensa-protos.h,v
retrieving revision 1.10
diff -c -3 -r1.10 xtensa-protos.h
*** xtensa-protos.h	14 May 2003 18:37:19 -0000	1.10
--- xtensa-protos.h	28 May 2003 23:37:31 -0000
***************
*** 54,60 ****
  extern int call_insn_operand PARAMS ((rtx, enum machine_mode));
  extern int move_operand PARAMS ((rtx, enum machine_mode));
  extern int smalloffset_mem_p PARAMS ((rtx));
- extern int smalloffset_double_mem_p PARAMS ((rtx));
  extern int constantpool_address_p PARAMS ((rtx));
  extern int constantpool_mem_p PARAMS ((rtx));
  extern int const_float_1_operand PARAMS ((rtx, enum machine_mode));
--- 54,59 ----
***************
*** 67,72 ****
--- 66,72 ----
  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 void xtensa_split_operand_pair PARAMS ((rtx *, enum machine_mode));
  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));
Index: xtensa.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/xtensa/xtensa.c,v
retrieving revision 1.34
diff -c -3 -r1.34 xtensa.c
*** xtensa.c	21 May 2003 21:23:03 -0000	1.34
--- xtensa.c	28 May 2003 23:37:31 -0000
***************
*** 599,617 ****
        || memory_operand (op, mode))
      return TRUE;
  
!   if (mode == SFmode)
!     return TARGET_CONST16 && CONSTANT_P (op);
  
!   /* Accept CONSTANT_P_RTX, since it will be gone by CSE1 and
!      result in 0/1.  */
!   if (GET_CODE (op) == CONSTANT_P_RTX)
!     return TRUE;
  
!   if (GET_CODE (op) == CONST_INT && xtensa_simm12b (INTVAL (op)))
!     return TRUE;
  
!   if (mode == SImode)
!     return TARGET_CONST16 && CONSTANT_P (op);
  
    return FALSE;
  }
--- 599,630 ----
        || memory_operand (op, mode))
      return TRUE;
  
!   switch (mode)
!     {
!     case DFmode:
!     case SFmode:
!       return TARGET_CONST16 && CONSTANT_P (op);
  
!     case DImode:
!     case SImode:
!       if (TARGET_CONST16)
! 	return CONSTANT_P (op);
!       /* fall through */
  
!     case HImode:
!     case QImode:
!       /* Accept CONSTANT_P_RTX, since it will be gone by CSE1 and
! 	 result in 0/1.  */
!       if (GET_CODE (op) == CONSTANT_P_RTX)
! 	return TRUE;
! 
!       if (GET_CODE (op) == CONST_INT && xtensa_simm12b (INTVAL (op)))
! 	return TRUE;
!       break;
  
!     default:
!       break;
!     }
  
    return FALSE;
  }
***************
*** 641,656 ****
  
  
  int
- smalloffset_double_mem_p (op)
-      rtx op;
- {
-   if (!smalloffset_mem_p (op))
-     return FALSE;
-   return smalloffset_mem_p (adjust_address (op, GET_MODE (op), 4));
- }
- 
- 
- int
  constantpool_address_p (addr)
       rtx addr;
  {
--- 654,659 ----
***************
*** 1014,1020 ****
      case GT: reverse_regs = 1; invert = 0; gen_fn = gen_slt_sf; break;
      case LT: reverse_regs = 0; invert = 0; gen_fn = gen_slt_sf; break;
      case GE: reverse_regs = 1; invert = 0; gen_fn = gen_sle_sf; break;
!     default: 
        fatal_insn ("bad test", gen_rtx (test_code, VOIDmode, cmp0, cmp1));
        reverse_regs = 0; invert = 0; gen_fn = 0; /* avoid compiler warnings */
      }
--- 1017,1023 ----
      case GT: reverse_regs = 1; invert = 0; gen_fn = gen_slt_sf; break;
      case LT: reverse_regs = 0; invert = 0; gen_fn = gen_slt_sf; break;
      case GE: reverse_regs = 1; invert = 0; gen_fn = gen_sle_sf; break;
!     default:
        fatal_insn ("bad test", gen_rtx (test_code, VOIDmode, cmp0, cmp1));
        reverse_regs = 0; invert = 0; gen_fn = 0; /* avoid compiler warnings */
      }
***************
*** 1207,1212 ****
--- 1210,1262 ----
  }
  
  
+ /* Split OP[1] into OP[2,3] and likewise for OP[0] into OP[0,1].  MODE is
+    for the output, i.e., the input operands are twice as big as MODE.  */
+ 
+ void
+ xtensa_split_operand_pair (operands, mode)
+      rtx operands[4];
+      enum machine_mode mode;
+ {
+   switch (GET_CODE (operands[1]))
+     {
+     case REG:
+       operands[3] = gen_rtx_REG (mode, REGNO (operands[1]) + 1);
+       operands[2] = gen_rtx_REG (mode, REGNO (operands[1]));
+       break;
+ 
+     case MEM:
+       operands[3] = adjust_address (operands[1], mode, GET_MODE_SIZE (mode));
+       operands[2] = adjust_address (operands[1], mode, 0);
+       break;
+ 
+     case CONST_INT:
+     case CONST_DOUBLE:
+       split_double (operands[1], &operands[2], &operands[3]);
+       break;
+ 
+     default:
+       abort ();
+     }
+ 
+   switch (GET_CODE (operands[0]))
+     {
+     case REG:
+       operands[1] = gen_rtx_REG (mode, REGNO (operands[0]) + 1);
+       operands[0] = gen_rtx_REG (mode, REGNO (operands[0]));
+       break;
+ 
+     case MEM:
+       operands[1] = adjust_address (operands[0], mode, GET_MODE_SIZE (mode));
+       operands[0] = adjust_address (operands[0], mode, 0);
+       break;
+ 
+     default:
+       abort ();
+     }
+ }
+ 
+ 
  /* Emit insns to move operands[1] into operands[0].
     Return 1 if we have written out everything that needs to be done to
     do the move.  Otherwise, return 0 and the caller will emit the move
***************
*** 1658,1681 ****
       int regno;
  {
    int first = -1;
!   
!   if (GP_REG_P (regno)) {
!     regno -= GP_REG_FIRST;
!     first = 0;
!   }
!   else if (BR_REG_P (regno)) {
!     regno -= BR_REG_FIRST;
!     first = 16;
!   }
!   else if (FP_REG_P (regno)) {
!     regno -= FP_REG_FIRST;
!     /* The current numbering convention is that TIE registers are
!        numbered in libcc order beginning with 256.  We can't guarantee
!        that the FP registers will come first, so the following is just
!        a guess.  It seems like we should make a special case for FP
!        registers and give them fixed numbers < 256.  */
!     first = 256;
!   }
    else if (ACC_REG_P (regno))
      {
        first = 0;
--- 1708,1734 ----
       int regno;
  {
    int first = -1;
! 
!   if (GP_REG_P (regno))
!     {
!       regno -= GP_REG_FIRST;
!       first = 0;
!     }
!   else if (BR_REG_P (regno))
!     {
!       regno -= BR_REG_FIRST;
!       first = 16;
!     }
!   else if (FP_REG_P (regno))
!     {
!       regno -= FP_REG_FIRST;
!       /* The current numbering convention is that TIE registers are
! 	 numbered in libcc order beginning with 256.  We can't guarantee
! 	 that the FP registers will come first, so the following is just
! 	 a guess.  It seems like we should make a special case for FP
! 	 registers and give them fixed numbers < 256.  */
!       first = 256;
!     }
    else if (ACC_REG_P (regno))
      {
        first = 0;
***************
*** 1885,1891 ****
     a null pointer for X and the punctuation character for CODE.
  
     'a', 'c', 'l', and 'n' are reserved.
!    
     The Xtensa specific codes are:
  
     'd'  CONST_INT, print as signed decimal
--- 1938,1944 ----
     a null pointer for X and the punctuation character for CODE.
  
     'a', 'c', 'l', and 'n' are reserved.
! 
     The Xtensa specific codes are:
  
     'd'  CONST_INT, print as signed decimal
***************
*** 2041,2047 ****
  	  print_operand (file, XEXP (XEXP (x, 0), 1), 0);
  	}
        else
! 	{ 
  	  output_addr_const (file, x);
  	  fputs (letter == 't' ? "@h" : "@l", file);
  	}
--- 2094,2100 ----
  	  print_operand (file, XEXP (XEXP (x, 0), 1), 0);
  	}
        else
! 	{
  	  output_addr_const (file, x);
  	  fputs (letter == 't' ? "@h" : "@l", file);
  	}
***************
*** 2608,2614 ****
  
    size = gen_reg_rtx (SImode);
    emit_move_insn (size, va_size);
!   
    if (BYTES_BIG_ENDIAN)
      {
        rtx lab_use_va_size = gen_label_rtx ();
--- 2661,2667 ----
  
    size = gen_reg_rtx (SImode);
    emit_move_insn (size, va_size);
! 
    if (BYTES_BIG_ENDIAN)
      {
        rtx lab_use_va_size = gen_label_rtx ();
Index: xtensa.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/xtensa/xtensa.h,v
retrieving revision 1.34
diff -c -3 -r1.34 xtensa.h
*** xtensa.h	21 May 2003 21:23:03 -0000	1.34
--- xtensa.h	28 May 2003 23:37:31 -0000
***************
*** 691,697 ****
     operand types.
  
     R = memory that can be accessed with a 4-bit unsigned offset
-    S = memory where the second word can be addressed with a 4-bit offset
     T = memory in a constant pool (addressable with a pc-relative load)
     U = memory *NOT* in a constant pool
  
--- 691,696 ----
***************
*** 713,719 ****
  	&& reload_in_progress && GET_CODE (OP) == REG			\
          && REGNO (OP) >= FIRST_PSEUDO_REGISTER)				\
     : ((CODE) == 'R') ? smalloffset_mem_p (OP)				\
-    : ((CODE) == 'S') ? smalloffset_double_mem_p (OP)			\
     : ((CODE) == 'T') ? !TARGET_CONST16 && constantpool_mem_p (OP)	\
     : ((CODE) == 'U') ? !constantpool_mem_p (OP)				\
     : FALSE)
--- 712,717 ----
Index: xtensa.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/xtensa/xtensa.md,v
retrieving revision 1.13
diff -c -3 -r1.13 xtensa.md
*** xtensa.md	21 May 2003 21:23:03 -0000	1.13
--- xtensa.md	28 May 2003 23:37:31 -0000
***************
*** 922,1004 ****
    ""
    "
  {
!   if (CONSTANT_P (operands[1])
!       && register_operand (operands[0], DImode))
!     {
!       rtx src0, src1, dst0, dst1;
!       dst0 = operand_subword (operands[0], 0, 1, DImode);
!       src0 = operand_subword (operands[1], 0, 1, DImode);
!       dst1 = operand_subword (operands[0], 1, 1, DImode);
!       src1 = operand_subword (operands[1], 1, 1, DImode);
!       if (!dst0 || !src0 || !dst1 || !src1)
!         abort ();
!       emit_insn (gen_movsi (dst0, src0));
!       emit_insn (gen_movsi (dst1, src1));
!       DONE;
!     }
  
!   if (!(reload_in_progress | reload_completed))
!     {
!       if (!register_operand (operands[0], DImode)
! 	  && !register_operand (operands[1], DImode))
! 	operands[1] = force_reg (DImode, operands[1]);
  
!       if (xtensa_copy_incoming_a7 (operands, DImode))
! 	DONE;
!     }
  }")
  
! (define_insn "movdi_internal"
!   [(set (match_operand:DI 0 "nonimmed_operand" "=D,D,S,a,a,U")
! 	(match_operand:DI 1 "nonimmed_operand" "d,S,d,r,U,r"))]
    "register_operand (operands[0], DImode)
     || register_operand (operands[1], DImode)"
!   "*
! {
!   rtx dstreg;
!   switch (which_alternative)
!     {
!     case 0: return \"mov.n\\t%0, %1\;mov.n\\t%D0, %D1\";
!     case 2: return \"%v0s32i.n\\t%1, %0\;s32i.n\\t%D1, %N0\";
!     case 3: return \"mov\\t%0, %1\;mov\\t%D0, %D1\";
!     case 5: return \"%v0s32i\\t%1, %0\;s32i\\t%D1, %N0\";
! 
!     case 1:
!     case 4:
!       /* Check if the first half of the destination register is used
! 	 in the source address.  If so, reverse the order of the loads
! 	 so that the source address doesn't get clobbered until it is
! 	 no longer needed. */
! 
!       dstreg = operands[0];
!       if (GET_CODE (dstreg) == SUBREG)
! 	dstreg = SUBREG_REG (dstreg);
!       if (GET_CODE (dstreg) != REG)
! 	abort();
! 
!       if (reg_mentioned_p (dstreg, operands[1]))
! 	{
! 	  switch (which_alternative)
! 	    {
! 	    case 1: return \"%v1l32i.n\\t%D0, %N1\;l32i.n\\t%0, %1\";
! 	    case 4: return \"%v1l32i\\t%D0, %N1\;l32i\\t%0, %1\";
! 	    }
! 	}
!       else
! 	{
! 	  switch (which_alternative)
! 	    {
! 	    case 1: return \"%v1l32i.n\\t%0, %1\;l32i.n\\t%D0, %N1\";
! 	    case 4: return \"%v1l32i\\t%0, %1\;l32i\\t%D0, %N1\";
! 	    }
! 	}
      }
!   abort ();
!   return \"\";
! }"
!   [(set_attr "type"	"move,load,store,move,load,store")
!    (set_attr "mode"	"DI")
!    (set_attr "length"	"4,4,4,6,6,6")])
  
  
  ;; 32-bit Integer moves
--- 922,956 ----
    ""
    "
  {
!   if (CONSTANT_P (operands[1]) && !TARGET_CONST16)
!     operands[1] = force_const_mem (DImode, operands[1]);
  
!   if (!register_operand (operands[0], DImode)
!       && !register_operand (operands[1], DImode))
!     operands[1] = force_reg (DImode, operands[1]);
  
!   if (xtensa_copy_incoming_a7 (operands, DImode))
!     DONE;
  }")
  
! (define_insn_and_split "movdi_internal"
!   [(set (match_operand:DI 0 "nonimmed_operand" "=a,W,a,a,U")
! 	(match_operand:DI 1 "move_operand" "r,i,T,U,r"))]
    "register_operand (operands[0], DImode)
     || register_operand (operands[1], DImode)"
!   "#"
!   "reload_completed"
!   [(set (match_dup 0) (match_dup 2))
!    (set (match_dup 1) (match_dup 3))]
! {
!   xtensa_split_operand_pair (operands, SImode);
!   if (reg_overlap_mentioned_p (operands[0], operands[3]))
!     {
!       rtx tmp;
!       tmp = operands[0], operands[0] = operands[1], operands[1] = tmp;
!       tmp = operands[2], operands[2] = operands[3], operands[3] = tmp;
      }
! })
  
  
  ;; 32-bit Integer moves
***************
*** 1122,1128 ****
  
  (define_insn "movsf_internal"
    [(set (match_operand:SF 0 "nonimmed_operand" "=f,f,U,D,D,R,a,f,a,W,a,a,U")
! 	(match_operand:SF 1 "move_operand" "f,U,f,d,R,d,r,r,f,F,T,U,r"))]
    "((register_operand (operands[0], SFmode)
       || register_operand (operands[1], SFmode))
      && !(FP_REG_P (xt_true_regnum (operands[0]))
--- 1074,1080 ----
  
  (define_insn "movsf_internal"
    [(set (match_operand:SF 0 "nonimmed_operand" "=f,f,U,D,D,R,a,f,a,W,a,a,U")
! 	(match_operand:SF 1 "move_operand" "f,U,f,d,R,d,r,r,f,iF,T,U,r"))]
    "((register_operand (operands[0], SFmode)
       || register_operand (operands[1], SFmode))
      && !(FP_REG_P (xt_true_regnum (operands[0]))
***************
*** 1187,1268 ****
    ""
    "
  {
!   if (CONSTANT_P (operands[1]))
!     {
!       rtx src0, src1, dst0, dst1;
!       dst0 = operand_subword (operands[0], 0, 1, DFmode);
!       src0 = operand_subword (operands[1], 0, 1, DFmode);
!       dst1 = operand_subword (operands[0], 1, 1, DFmode);
!       src1 = operand_subword (operands[1], 1, 1, DFmode);
!       if (!dst0 || !src0 || !dst1 || !src1)
!         abort ();
!       emit_insn (gen_movsi (dst0, src0));
!       emit_insn (gen_movsi (dst1, src1));
!       DONE;
!     }
  
!   if (!(reload_in_progress | reload_completed))
!     {
!       if (!register_operand (operands[0], DFmode)
! 	  && !register_operand (operands[1], DFmode))
! 	operands[1] = force_reg (DFmode, operands[1]);
  
!       if (xtensa_copy_incoming_a7 (operands, DFmode))
! 	DONE;
!     }
  }")
  
! (define_insn "movdf_internal"
!   [(set (match_operand:DF 0 "nonimmed_operand" "=D,D,S,a,a,U")
! 	(match_operand:DF 1 "nonimmed_operand" "d,S,d,r,U,r"))]
    "register_operand (operands[0], DFmode)
     || register_operand (operands[1], DFmode)"
!   "*
! {
!   rtx dstreg;
!   switch (which_alternative)
!     {
!     case 0: return \"mov.n\\t%0, %1\;mov.n\\t%D0, %D1\";
!     case 2: return \"%v0s32i.n\\t%1, %0\;s32i.n\\t%D1, %N0\";
!     case 3: return \"mov\\t%0, %1\;mov\\t%D0, %D1\";
!     case 5: return \"%v0s32i\\t%1, %0\;s32i\\t%D1, %N0\";
! 
!     case 1:
!     case 4:
!       /* Check if the first half of the destination register is used
! 	 in the source address.  If so, reverse the order of the loads
! 	 so that the source address doesn't get clobbered until it is
! 	 no longer needed.  */
! 
!       dstreg = operands[0];
!       if (GET_CODE (dstreg) == SUBREG)
! 	dstreg = SUBREG_REG (dstreg);
!       if (GET_CODE (dstreg) != REG)
! 	abort ();
! 
!       if (reg_mentioned_p (dstreg, operands[1]))
! 	{
! 	  switch (which_alternative)
! 	    {
! 	    case 1: return \"%v1l32i.n\\t%D0, %N1\;l32i.n\\t%0, %1\";
! 	    case 4: return \"%v1l32i\\t%D0, %N1\;l32i\\t%0, %1\";
! 	    }
! 	}
!       else
! 	{
! 	  switch (which_alternative)
! 	    {
! 	    case 1: return \"%v1l32i.n\\t%0, %1\;l32i.n\\t%D0, %N1\";
! 	    case 4: return \"%v1l32i\\t%0, %1\;l32i\\t%D0, %N1\";
! 	    }
! 	}
      }
!   abort ();
!   return \"\";
! }"
!   [(set_attr "type"	"move,load,store,move,load,store")
!    (set_attr "mode"	"DF")
!    (set_attr "length"	"4,4,4,6,6,6")])
  
  ;; Block moves
  
--- 1139,1174 ----
    ""
    "
  {
!   if (CONSTANT_P (operands[1]) && !TARGET_CONST16)
!     operands[1] = force_const_mem (DFmode, operands[1]);
  
!   if (!register_operand (operands[0], DFmode)
!       && !register_operand (operands[1], DFmode))
!     operands[1] = force_reg (DFmode, operands[1]);
  
!   if (xtensa_copy_incoming_a7 (operands, DFmode))
!     DONE;
  }")
  
! (define_insn_and_split "movdf_internal"
!   [(set (match_operand:DF 0 "nonimmed_operand" "=a,W,a,a,U")
! 	(match_operand:DF 1 "move_operand" "r,iF,T,U,r"))]
    "register_operand (operands[0], DFmode)
     || register_operand (operands[1], DFmode)"
!   "#"
!   "reload_completed"
!   [(set (match_dup 0) (match_dup 2))
!    (set (match_dup 1) (match_dup 3))]
! {
!   xtensa_split_operand_pair (operands, SFmode);
!   if (reg_overlap_mentioned_p (operands[0], operands[3]))
!     {
!       rtx tmp;
!       tmp = operands[0], operands[0] = operands[1], operands[1] = tmp;
!       tmp = operands[2], operands[2] = operands[3], operands[3] = tmp;
      }
! })
!  
  
  ;; Block moves
  

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