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]

[RFC] PowerPC TImode splitters


	Hatmut Penner and I have expanded the splitters for vector values
in GPRs to handle TImode and 32-bit DImode.

	Previously TImode only was enabled when the POWER/PowerPC "string"
helper instructions were available for loading and storing multiple
registers.  This patch enables TImode uniformly.  I'm not sure if TImode
should have the restriction or not.  I am not going to commit this patch
immediately so that I can see if there are any comments first.

David


	* config/rs6000/rs6000.c (altivec_in_gprs_p): Rename to ...
	(gpr_or_gpr_p): Change to bool.
	(rs6000_split_altivec_in_gprs): Rename to ...
	(rs6000_split_multireg_move): Add support for update addressing.
	* config/rs6000/rs6000-protos.h: Same.
	* config/rs6000/altivec.md: Same.
	* config/rs6000/rs6000.md (movdi_internal32): Use new splitter for
	multiple GPRs.
	(movti): Remove TARGET_STRING || TARGET_POWERPC64 final condition.
	(movti_power): Use new splitter for multiple GPRs.
	(movti_string): Same.
	(movti_ppc64): Same.

Index: altivec.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/altivec.md,v
retrieving revision 1.8
diff -c -p -r1.8 altivec.md
*** altivec.md	30 Jun 2003 13:30:45 -0000	1.8
--- altivec.md	20 Sep 2003 21:22:57 -0000
***************
*** 114,137 ****
    [(set (match_operand:V4SI 0 "nonimmediate_operand" "")
          (match_operand:V4SI 1 "input_operand" ""))]
    "TARGET_ALTIVEC && reload_completed && TARGET_POWERPC64 
!    && altivec_in_gprs_p (operands[0], operands[1])"
    [(set (match_dup 2) (match_dup 4))
     (set (match_dup 3) (match_dup 5))]
  "{
!      rs6000_split_altivec_in_gprs (operands);
  }")
  
  (define_split
    [(set (match_operand:V4SI 0 "nonimmediate_operand" "")
          (match_operand:V4SI 1 "input_operand" ""))]
    "TARGET_ALTIVEC && reload_completed && !TARGET_POWERPC64 
!    && altivec_in_gprs_p (operands[0], operands[1])"
    [(set (match_dup 2) (match_dup 6))
     (set (match_dup 3) (match_dup 7))
     (set (match_dup 4) (match_dup 8))
     (set (match_dup 5) (match_dup 9))]
  "{
!      rs6000_split_altivec_in_gprs (operands);
  }")
  
  (define_split
--- 114,137 ----
    [(set (match_operand:V4SI 0 "nonimmediate_operand" "")
          (match_operand:V4SI 1 "input_operand" ""))]
    "TARGET_ALTIVEC && reload_completed && TARGET_POWERPC64 
!    && gpr_or_gpr_p (operands[0], operands[1])"
    [(set (match_dup 2) (match_dup 4))
     (set (match_dup 3) (match_dup 5))]
  "{
!      rs6000_split_multireg_move (operands);
  }")
  
  (define_split
    [(set (match_operand:V4SI 0 "nonimmediate_operand" "")
          (match_operand:V4SI 1 "input_operand" ""))]
    "TARGET_ALTIVEC && reload_completed && !TARGET_POWERPC64 
!    && gpr_or_gpr_p (operands[0], operands[1])"
    [(set (match_dup 2) (match_dup 6))
     (set (match_dup 3) (match_dup 7))
     (set (match_dup 4) (match_dup 8))
     (set (match_dup 5) (match_dup 9))]
  "{
!      rs6000_split_multireg_move (operands);
  }")
  
  (define_split
***************
*** 176,199 ****
    [(set (match_operand:V8HI 0 "nonimmediate_operand" "")
          (match_operand:V8HI 1 "input_operand" ""))]
    "TARGET_ALTIVEC && reload_completed && TARGET_POWERPC64 
!    && altivec_in_gprs_p (operands[0], operands[1])"
    [(set (match_dup 2) (match_dup 4))
     (set (match_dup 3) (match_dup 5))]
  "{
!      rs6000_split_altivec_in_gprs (operands);
  }")
  
  (define_split
    [(set (match_operand:V8HI 0 "nonimmediate_operand" "")
          (match_operand:V8HI 1 "input_operand" ""))]
    "TARGET_ALTIVEC && reload_completed && !TARGET_POWERPC64 
!    && altivec_in_gprs_p (operands[0], operands[1])"
    [(set (match_dup 2) (match_dup 6))
     (set (match_dup 3) (match_dup 7))
     (set (match_dup 4) (match_dup 8))
     (set (match_dup 5) (match_dup 9))]
  "{
!      rs6000_split_altivec_in_gprs (operands);
  }")
  
  (define_split
--- 176,199 ----
    [(set (match_operand:V8HI 0 "nonimmediate_operand" "")
          (match_operand:V8HI 1 "input_operand" ""))]
    "TARGET_ALTIVEC && reload_completed && TARGET_POWERPC64 
!    && gpr_or_gpr_p (operands[0], operands[1])"
    [(set (match_dup 2) (match_dup 4))
     (set (match_dup 3) (match_dup 5))]
  "{
!      rs6000_split_multireg_move (operands);
  }")
  
  (define_split
    [(set (match_operand:V8HI 0 "nonimmediate_operand" "")
          (match_operand:V8HI 1 "input_operand" ""))]
    "TARGET_ALTIVEC && reload_completed && !TARGET_POWERPC64 
!    && gpr_or_gpr_p (operands[0], operands[1])"
    [(set (match_dup 2) (match_dup 6))
     (set (match_dup 3) (match_dup 7))
     (set (match_dup 4) (match_dup 8))
     (set (match_dup 5) (match_dup 9))]
  "{
!      rs6000_split_multireg_move (operands);
  }")
  
  (define_split
***************
*** 238,261 ****
    [(set (match_operand:V16QI 0 "nonimmediate_operand" "")
          (match_operand:V16QI 1 "input_operand" ""))]
    "TARGET_ALTIVEC && reload_completed && TARGET_POWERPC64 
!    && altivec_in_gprs_p (operands[0], operands[1])"
    [(set (match_dup 2) (match_dup 4))
     (set (match_dup 3) (match_dup 5))]
  "{
!      rs6000_split_altivec_in_gprs (operands);
  }")
  
  (define_split
    [(set (match_operand:V16QI 0 "nonimmediate_operand" "")
          (match_operand:V16QI 1 "input_operand" ""))]
    "TARGET_ALTIVEC && reload_completed && !TARGET_POWERPC64 
!    && altivec_in_gprs_p (operands[0], operands[1])"
    [(set (match_dup 2) (match_dup 6))
     (set (match_dup 3) (match_dup 7))
     (set (match_dup 4) (match_dup 8))
     (set (match_dup 5) (match_dup 9))]
  "{
!      rs6000_split_altivec_in_gprs (operands);
  }")
  
  (define_split
--- 238,261 ----
    [(set (match_operand:V16QI 0 "nonimmediate_operand" "")
          (match_operand:V16QI 1 "input_operand" ""))]
    "TARGET_ALTIVEC && reload_completed && TARGET_POWERPC64 
!    && gpr_or_gpr_p (operands[0], operands[1])"
    [(set (match_dup 2) (match_dup 4))
     (set (match_dup 3) (match_dup 5))]
  "{
!      rs6000_split_multireg_move (operands);
  }")
  
  (define_split
    [(set (match_operand:V16QI 0 "nonimmediate_operand" "")
          (match_operand:V16QI 1 "input_operand" ""))]
    "TARGET_ALTIVEC && reload_completed && !TARGET_POWERPC64 
!    && gpr_or_gpr_p (operands[0], operands[1])"
    [(set (match_dup 2) (match_dup 6))
     (set (match_dup 3) (match_dup 7))
     (set (match_dup 4) (match_dup 8))
     (set (match_dup 5) (match_dup 9))]
  "{
!      rs6000_split_multireg_move (operands);
  }")
  
  (define_split
***************
*** 300,323 ****
    [(set (match_operand:V4SF 0 "nonimmediate_operand" "")
          (match_operand:V4SF 1 "input_operand" ""))]
    "TARGET_ALTIVEC && reload_completed && TARGET_POWERPC64 
!    && altivec_in_gprs_p (operands[0], operands[1])"
    [(set (match_dup 2) (match_dup 4))
     (set (match_dup 3) (match_dup 5))]
  "{
!      rs6000_split_altivec_in_gprs (operands);
  }")
  
  (define_split
    [(set (match_operand:V4SF 0 "nonimmediate_operand" "")
          (match_operand:V4SF 1 "input_operand" ""))]
    "TARGET_ALTIVEC && reload_completed && !TARGET_POWERPC64 
!    && altivec_in_gprs_p (operands[0], operands[1])"
    [(set (match_dup 2) (match_dup 6))
     (set (match_dup 3) (match_dup 7))
     (set (match_dup 4) (match_dup 8))
     (set (match_dup 5) (match_dup 9))]
  "{
!      rs6000_split_altivec_in_gprs (operands);
  }")
  
  (define_insn "get_vrsave_internal"
--- 300,323 ----
    [(set (match_operand:V4SF 0 "nonimmediate_operand" "")
          (match_operand:V4SF 1 "input_operand" ""))]
    "TARGET_ALTIVEC && reload_completed && TARGET_POWERPC64 
!    && gpr_or_gpr_p (operands[0], operands[1])"
    [(set (match_dup 2) (match_dup 4))
     (set (match_dup 3) (match_dup 5))]
  "{
!      rs6000_split_multireg_move (operands);
  }")
  
  (define_split
    [(set (match_operand:V4SF 0 "nonimmediate_operand" "")
          (match_operand:V4SF 1 "input_operand" ""))]
    "TARGET_ALTIVEC && reload_completed && !TARGET_POWERPC64 
!    && gpr_or_gpr_p (operands[0], operands[1])"
    [(set (match_dup 2) (match_dup 6))
     (set (match_dup 3) (match_dup 7))
     (set (match_dup 4) (match_dup 8))
     (set (match_dup 5) (match_dup 9))]
  "{
!      rs6000_split_multireg_move (operands);
  }")
  
  (define_insn "get_vrsave_internal"
Index: rs6000-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000-protos.h,v
retrieving revision 1.62
diff -c -p -r1.62 rs6000-protos.h
*** rs6000-protos.h	12 Sep 2003 19:00:45 -0000	1.62
--- rs6000-protos.h	20 Sep 2003 21:22:57 -0000
*************** extern int includes_rldic_lshift_p (rtx,
*** 100,115 ****
  extern int includes_rldicr_lshift_p (rtx, rtx);
  extern int registers_ok_for_quad_peep (rtx, rtx);
  extern int addrs_ok_for_quad_peep (rtx, rtx);
! extern int altivec_in_gprs_p (rtx, rtx);
  extern enum reg_class secondary_reload_class (enum reg_class,
! 						      enum machine_mode, rtx);
  extern int ccr_bit (rtx, int);
  extern int extract_MB (rtx);
  extern int extract_ME (rtx);
  extern void print_operand (FILE *, rtx, int);
  extern void print_operand_address (FILE *, rtx);
  extern enum rtx_code rs6000_reverse_condition (enum machine_mode,
! 						       enum rtx_code);
  extern void rs6000_emit_sCOND (enum rtx_code, rtx);
  extern void rs6000_emit_cbranch (enum rtx_code, rtx);
  extern char * output_cbranch (rtx, const char *, int, rtx);
--- 100,115 ----
  extern int includes_rldicr_lshift_p (rtx, rtx);
  extern int registers_ok_for_quad_peep (rtx, rtx);
  extern int addrs_ok_for_quad_peep (rtx, rtx);
! extern bool gpr_or_gpr_p (rtx, rtx);
  extern enum reg_class secondary_reload_class (enum reg_class,
! 					      enum machine_mode, rtx);
  extern int ccr_bit (rtx, int);
  extern int extract_MB (rtx);
  extern int extract_ME (rtx);
  extern void print_operand (FILE *, rtx, int);
  extern void print_operand_address (FILE *, rtx);
  extern enum rtx_code rs6000_reverse_condition (enum machine_mode,
! 					       enum rtx_code);
  extern void rs6000_emit_sCOND (enum rtx_code, rtx);
  extern void rs6000_emit_cbranch (enum rtx_code, rtx);
  extern char * output_cbranch (rtx, const char *, int, rtx);
*************** extern int mfcr_operation (rtx, enum mac
*** 125,131 ****
  extern int mtcrf_operation (rtx, enum machine_mode);
  extern int lmw_operation (rtx, enum machine_mode);
  extern struct rtx_def *create_TOC_reference (rtx);
! extern void rs6000_split_altivec_in_gprs (rtx *);
  extern void rs6000_emit_move (rtx, rtx, enum machine_mode);
  extern rtx rs6000_legitimize_address (rtx, rtx, enum machine_mode);
  extern rtx rs6000_legitimize_reload_address (rtx, enum machine_mode,
--- 125,131 ----
  extern int mtcrf_operation (rtx, enum machine_mode);
  extern int lmw_operation (rtx, enum machine_mode);
  extern struct rtx_def *create_TOC_reference (rtx);
! extern void rs6000_split_multireg_move (rtx *);
  extern void rs6000_emit_move (rtx, rtx, enum machine_mode);
  extern rtx rs6000_legitimize_address (rtx, rtx, enum machine_mode);
  extern rtx rs6000_legitimize_reload_address (rtx, enum machine_mode,
Index: rs6000.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.c,v
retrieving revision 1.519
diff -c -p -r1.519 rs6000.c
*** rs6000.c	15 Sep 2003 20:23:42 -0000	1.519
--- rs6000.c	20 Sep 2003 21:22:57 -0000
*************** small_data_operand (rtx op ATTRIBUTE_UNU
*** 2200,2217 ****
  #endif
  }
  
! /* Return 1 for all valid move insn operand combination involving altivec      
!    vectors in gprs.  */
  
! int
! altivec_in_gprs_p (rtx op0, rtx op1)
  {
!   if (REG_P (op0) && REGNO_REG_CLASS (REGNO (op0)) == GENERAL_REGS)
!     return 1;
! 
!   if (REG_P (op1) && REGNO_REG_CLASS (REGNO (op1)) == GENERAL_REGS) 
!     return 1;
!   return 0;
  }
  
  
--- 2200,2212 ----
  #endif
  }
  
! /* Return true if either operand is a general purpose register.  */
  
! bool
! gpr_or_gpr_p (rtx op0, rtx op1)
  {
!   return ((REG_P (op0) && INT_REGNO_P (REGNO (op0)))
! 	  || (REG_P (op1) && INT_REGNO_P (REGNO (op1))));
  }
  
  
*************** rs6000_emit_minmax (rtx dest, enum rtx_c
*** 9462,9475 ****
      emit_move_insn (dest, target);
  }
  
! /* Called by altivec splitter.
     Input: 
            operands[0] : Destination of move
            operands[1] : Source of move
! 	  noperands   : Size of operands vector
     Output:
! 	  operands[2-5] ([2-3] in 64 bit) : Destination slots
! 	  operands[6-9] ([4-5] in 64 bit) : Source slots
  
     Splits the move of operands[1] to operands[0].
     This is done, if GPRs are one of the operands.  In this case
--- 9457,9472 ----
      emit_move_insn (dest, target);
  }
  
! /* Called by splitter for multireg moves.
     Input: 
            operands[0] : Destination of move
            operands[1] : Source of move
! 
     Output:
! 	  operands[2-n] : Destination slots
! 	  operands[n-m] : Source slots
!    where n = 2 + HARD_REGNO_NREGS (reg, GET_MODE (operands[0]))
!          m = 2 + 2 * HARD_REGNO_NREGS (reg, GET_MODE (operands[0])) - 1
  
     Splits the move of operands[1] to operands[0].
     This is done, if GPRs are one of the operands.  In this case
*************** rs6000_emit_minmax (rtx dest, enum rtx_c
*** 9479,9488 ****
  */
  	  
  void
! rs6000_split_altivec_in_gprs (rtx *operands)
  {
!     int nregs, reg, i, j;
    enum machine_mode mode; 
  
    /* Calculate number to move (2/4 for 32/64 bit mode).  */ 
  
--- 9476,9488 ----
  */
  	  
  void
! rs6000_split_multireg_move (rtx *operands)
  {
!   int nregs, reg, i, j, used_update = 0;
    enum machine_mode mode; 
+   rtx dst = operands[0];
+   rtx src = operands[1];
+   rtx insn = 0;
  
    /* Calculate number to move (2/4 for 32/64 bit mode).  */ 
  
*************** rs6000_split_altivec_in_gprs (rtx *opera
*** 9500,9507 ****
        for (i = 0; i < nregs; i++)
          {
            j--;
!           operands[i + 2] = operand_subword (operands[0], j, 0, mode);
!           operands[i + 2 + nregs] = 
              operand_subword (operands[1], j, 0, mode);   
          }
      }     
--- 9500,9507 ----
        for (i = 0; i < nregs; i++)
          {
            j--;
!           operands[i+2] = operand_subword (operands[0], j, 0, mode);
!           operands[i+2+nregs] = 
              operand_subword (operands[1], j, 0, mode);   
          }
      }     
*************** rs6000_split_altivec_in_gprs (rtx *opera
*** 9512,9540 ****
        if (GET_CODE (operands[1]) == MEM)
          {
            rtx breg;
!           /* We have offsettable addresses only. If we use one of the
!              registers to address memory, we have change that register last.  */            
!           breg = GET_CODE (XEXP (operands[1], 0)) == PLUS ?
!               XEXP (XEXP (operands[1], 0), 0) :
!               XEXP (operands[1], 0);
! 
!           if (REGNO (breg) >= REGNO (operands[0]) 
!               && REGNO (breg) < REGNO (operands[0]) + nregs)
!               j = REGNO (breg) - REGNO (operands[0]);
          }
  
        for (i = 0; i < nregs; i++)
!         { 
!           /* Calculate index to next subword.  */
!           j++;
!           if (j == nregs) 
!             j = 0;
! 
!           operands[i + 2] = operand_subword (operands[0], j, 0, mode);
!           operands[i + 2 + nregs] = 
!             operand_subword (operands[1], j, 0, mode);
  
!         }
      }
  }
  
--- 9512,9598 ----
        if (GET_CODE (operands[1]) == MEM)
          {
            rtx breg;
! 
! 	  if (GET_CODE (XEXP (operands[1], 0)) == PRE_INC
! 	      || GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
! 	    {
! 	      rtx delta_rtx;
! 	      breg = XEXP (XEXP (operands[1], 0), 0);
! 	      delta_rtx =  GET_CODE (XEXP (operands[1], 0)) == PRE_INC 
! 		  ? GEN_INT (GET_MODE_SIZE (GET_MODE (operands[1]))) 
! 		  : GEN_INT (-GET_MODE_SIZE (GET_MODE (operands[1]))); 
! 	      insn = emit_insn (TARGET_32BIT
! 				? gen_addsi3 (breg, breg, delta_rtx)
! 				: gen_adddi3 (breg, breg, delta_rtx));
! 	      src = gen_rtx_MEM (mode, breg);
! 	    }
! 
! 	  /* We have now address involving an base register only.
! 	     If we use one of the registers to address memory, 
! 	     we have change that register last.  */
! 
! 	  breg = (GET_CODE (XEXP (src, 0)) == PLUS
! 		  ? XEXP (XEXP (src, 0), 0)
! 		  : XEXP (src, 0));
! 
! 	  if (!REG_P (breg))
! 	      abort();
! 
! 	  if (REGNO (breg) >= REGNO (dst) 
! 	      && REGNO (breg) < REGNO (dst) + nregs)
! 	    j = REGNO (breg) - REGNO (dst);
          }
  
+       if (GET_CODE (operands[0]) == MEM)
+ 	{
+ 	  rtx breg;
+ 
+ 	  if (GET_CODE (XEXP (operands[0], 0)) == PRE_INC
+ 	      || GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
+ 	    {
+ 	      rtx delta_rtx;
+ 	      breg = XEXP (XEXP (operands[0], 0), 0);
+ 	      delta_rtx = GET_CODE (XEXP (operands[0], 0)) == PRE_INC 
+ 		? GEN_INT (GET_MODE_SIZE (GET_MODE (operands[0]))) 
+ 		: GEN_INT (-GET_MODE_SIZE (GET_MODE (operands[0]))); 
+ 
+ 	      /* We have to update the breg before doing the store.
+ 		 Use store with update, if available.  */
+ 
+ 	      if (TARGET_UPDATE)
+ 		{
+ 		  insn = emit_insn (TARGET_32BIT
+ 				    ? gen_movsi_update (breg, breg, delta_rtx, 
+ 					operand_subword (src, 0, 0, mode))
+ 				    : gen_movdi_update (breg, breg, delta_rtx,
+ 					operand_subword (src, 0, 0, mode)));
+ 		  used_update = 1;
+ 		}
+ 	      else
+ 		  insn = emit_insn (TARGET_32BIT
+ 				    ? gen_addsi3 (breg, breg, delta_rtx)
+ 				    : gen_adddi3 (breg, breg, delta_rtx));
+ 	      dst = gen_rtx_MEM (mode, breg);
+ 	    }
+ 	}
+ 
        for (i = 0; i < nregs; i++)
! 	{  
! 	  /* Calculate index to next subword.  */
! 	  ++j;
! 	  if (j == nregs) 
! 	    j = 0;
  
! 	  operands[i+2] = operand_subword (dst, j, 0, mode);
! 	  operands[i+2+nregs] = operand_subword (src, j, 0, mode);
! 
! 	  if (j == 0 && used_update)
! 	    {
! 	      /* Already emited move of first word by 
! 		 store with update -> emit dead insn instead (r := r).  */
! 	      operands[i+2] = operands[i+2+nregs];
! 	    }
! 	}
      }
  }
  
Index: rs6000.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.md,v
retrieving revision 1.265
diff -c -p -r1.265 rs6000.md
*** rs6000.md	13 Aug 2003 17:05:19 -0000	1.265
--- rs6000.md	20 Sep 2003 21:22:57 -0000
***************
*** 8462,8486 ****
      default:
        abort ();
      case 0:
-       /* We normally copy the low-numbered register first.  However, if
- 	 the first register operand 0 is the same as the second register of
- 	 operand 1, we must copy in the opposite order.  */
-       if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
- 	return \"mr %L0,%L1\;mr %0,%1\";
-       else
- 	return \"mr %0,%1\;mr %L0,%L1\";
      case 1:
-       /* If the low-address word is used in the address, we must load it
- 	 last.  Otherwise, load it first.  Note that we cannot have
- 	 auto-increment in that case since the address register is known to be
- 	 dead.  */
-       if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
- 			     operands[1], 0))
- 	return \"{l|lwz} %L0,%L1\;{l|lwz} %0,%1\";
-       else
- 	return \"{l%U1|lwz%U1} %0,%1\;{l|lwz} %L0,%L1\";
      case 2:
!       return \"{st%U0|stw%U0} %1,%0\;{st|stw} %L1,%L0\";
      case 3:
        return \"fmr %0,%1\";
      case 4:
--- 8462,8470 ----
      default:
        abort ();
      case 0:
      case 1:
      case 2:
!       return \"#\";
      case 3:
        return \"fmr %0,%1\";
      case 4:
***************
*** 8495,8502 ****
        return \"#\";
      }
  }"
!   [(set_attr "type" "*,load,store,fp,fpload,fpstore,*,*,*,*,*")
!    (set_attr "length" "8,8,8,4,4,4,8,12,8,12,16")])
  
  (define_split
    [(set (match_operand:DI 0 "gpc_reg_operand" "")
--- 8479,8485 ----
        return \"#\";
      }
  }"
!   [(set_attr "type" "*,load,store,fp,fpload,fpstore,*,*,*,*,*")])
  
  (define_split
    [(set (match_operand:DI 0 "gpc_reg_operand" "")
***************
*** 8536,8541 ****
--- 8519,8535 ----
  }")
  
  (define_split
+   [(set (match_operand:DI 0 "nonimmediate_operand" "")
+         (match_operand:DI 1 "input_operand" ""))]
+   "reload_completed && !TARGET_POWERPC64 
+    && gpr_or_gpr_p (operands[0], operands[1])"
+   [(set (match_dup 2) (match_dup 4))
+    (set (match_dup 3) (match_dup 5))]
+ "{
+      rs6000_split_multireg_move (operands);
+ }")
+ 
+ (define_split
    [(set (match_operand:TI 0 "gpc_reg_operand" "")
  	(match_operand:TI 1 "const_double_operand" ""))]
    "TARGET_POWERPC64"
***************
*** 8677,8683 ****
    [(parallel [(set (match_operand:TI 0 "general_operand" "")
  		   (match_operand:TI 1 "general_operand" ""))
  	      (clobber (scratch:SI))])]
!   "TARGET_STRING || TARGET_POWERPC64"
    "{ rs6000_emit_move (operands[0], operands[1], TImode); DONE; }")
  
  ;; We say that MQ is clobbered in the last alternative because the first
--- 8671,8677 ----
    [(parallel [(set (match_operand:TI 0 "general_operand" "")
  		   (match_operand:TI 1 "general_operand" ""))
  	      (clobber (scratch:SI))])]
!   ""
    "{ rs6000_emit_move (operands[0], operands[1], TImode); DONE; }")
  
  ;; We say that MQ is clobbered in the last alternative because the first
***************
*** 8685,8695 ****
  ;; while the 2nd alternative would not.  We put memory cases first so they
  ;; are preferred.  Otherwise, we'd try to reload the output instead of
  ;; giving the SCRATCH mq.
  (define_insn "*movti_power"
    [(set (match_operand:TI 0 "reg_or_mem_operand" "=Q,m,????r,????r,????r")
  	(match_operand:TI 1 "reg_or_mem_operand" "r,r,r,Q,m"))
     (clobber (match_scratch:SI 2 "=q,q#X,X,X,X"))]
!   "TARGET_STRING && TARGET_POWER && ! TARGET_POWERPC64
     && (gpc_reg_operand (operands[0], TImode) || gpc_reg_operand (operands[1], TImode))"
    "*
  {
--- 8679,8690 ----
  ;; while the 2nd alternative would not.  We put memory cases first so they
  ;; are preferred.  Otherwise, we'd try to reload the output instead of
  ;; giving the SCRATCH mq.
+ 
  (define_insn "*movti_power"
    [(set (match_operand:TI 0 "reg_or_mem_operand" "=Q,m,????r,????r,????r")
  	(match_operand:TI 1 "reg_or_mem_operand" "r,r,r,Q,m"))
     (clobber (match_scratch:SI 2 "=q,q#X,X,X,X"))]
!   "TARGET_POWER && ! TARGET_POWERPC64
     && (gpc_reg_operand (operands[0], TImode) || gpc_reg_operand (operands[1], TImode))"
    "*
  {
***************
*** 8699,8716 ****
        abort ();
  
      case 0:
!       return \"{stsi|stswi} %1,%P0,16\";
      case 1:
!       return \"{st%U0|stw%U0} %1,%0\;{st|stw} %L1,%L0\;{st|stw} %Y1,%Y0\;{st|stw} %Z1,%Z0\";
      case 2:
!       /* Normally copy registers with lowest numbered register copied first.
! 	 But copy in the other order if the first register of the output
! 	 is the second, third, or fourth register in the input.  */
!       if (REGNO (operands[0]) >= REGNO (operands[1]) + 1
! 	  && REGNO (operands[0]) <= REGNO (operands[1]) + 3)
! 	return \"mr %Z0,%Z1\;mr %Y0,%Y1\;mr %L0,%L1\;mr %0,%1\";
!       else
! 	return \"mr %0,%1\;mr %L0,%L1\;mr %Y0,%Y1\;mr %Z0,%Z1\";
      case 3:
        /* If the address is not used in the output, we can use lsi.  Otherwise,
  	 fall through to generating four loads.  */
--- 8694,8705 ----
        abort ();
  
      case 0:
!       if (TARGET_STRING)
!         return \"{stsi|stswi} %1,%P0,16\";
      case 1:
!       return \"#\";
      case 2:
!       return \"#\";
      case 3:
        /* If the address is not used in the output, we can use lsi.  Otherwise,
  	 fall through to generating four loads.  */
***************
*** 8718,8746 ****
  	return \"{lsi|lswi} %0,%P1,16\";
        /* ... fall through ...  */
      case 4:
!       /* If the address register is the same as the register for the lowest-
! 	 addressed word, load it last.  Similarly for the next two words.
! 	 Otherwise load lowest address to highest.  */
!       if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
! 			     operands[1], 0))
! 	return \"{l|lwz} %L0,%L1\;{l|lwz} %Y0,%Y1\;{l|lwz} %Z0,%Z1\;{l|lwz} %0,%1\";
!       else if (refers_to_regno_p (REGNO (operands[0]) + 1,
! 				  REGNO (operands[0]) + 2, operands[1], 0))
! 	return \"{l|lwz} %0,%1\;{l|lwz} %Y0,%Y1\;{l|lwz} %Z0,%Z1\;{l|lwz} %L0,%L1\";
!       else if (refers_to_regno_p (REGNO (operands[0]) + 2,
! 				  REGNO (operands[0]) + 3, operands[1], 0))
! 	return \"{l|lwz} %0,%1\;{l|lwz} %L0,%L1\;{l|lwz} %Z0,%Z1\;{l|lwz} %Y0,%Y1\";
!       else
! 	return \"{l%U1|lwz%U1} %0,%1\;{l|lwz} %L0,%L1\;{l|lwz} %Y0,%Y1\;{l|lwz} %Z0,%Z1\";
      }
  }"
!   [(set_attr "type" "store,store,*,load,load")
!    (set_attr "length" "4,16,16,4,16")])
  
  (define_insn "*movti_string"
    [(set (match_operand:TI 0 "reg_or_mem_operand" "=Q,m,????r,????r,????r")
  	(match_operand:TI 1 "reg_or_mem_operand" "r,r,r,Q,m"))]
!   "TARGET_STRING && ! TARGET_POWER && ! TARGET_POWERPC64
     && (gpc_reg_operand (operands[0], TImode) || gpc_reg_operand (operands[1], TImode))"
    "*
  {
--- 8707,8721 ----
  	return \"{lsi|lswi} %0,%P1,16\";
        /* ... fall through ...  */
      case 4:
!       return \"#\";
      }
  }"
!   [(set_attr "type" "store,store,*,load,load")])
  
  (define_insn "*movti_string"
    [(set (match_operand:TI 0 "reg_or_mem_operand" "=Q,m,????r,????r,????r")
  	(match_operand:TI 1 "reg_or_mem_operand" "r,r,r,Q,m"))]
!   "! TARGET_POWER && ! TARGET_POWERPC64
     && (gpc_reg_operand (operands[0], TImode) || gpc_reg_operand (operands[1], TImode))"
    "*
  {
***************
*** 8748,8828 ****
      {
      default:
        abort ();
- 
      case 0:
!       return \"{stsi|stswi} %1,%P0,16\";
      case 1:
!       return \"{st%U0|stw%U0} %1,%0\;{st|stw} %L1,%L0\;{st|stw} %Y1,%Y0\;{st|stw} %Z1,%Z0\";
      case 2:
!       /* Normally copy registers with lowest numbered register copied first.
! 	 But copy in the other order if the first register of the output
! 	 is the second, third, or fourth register in the input.  */
!       if (REGNO (operands[0]) >= REGNO (operands[1]) + 1
! 	  && REGNO (operands[0]) <= REGNO (operands[1]) + 3)
! 	return \"mr %Z0,%Z1\;mr %Y0,%Y1\;mr %L0,%L1\;mr %0,%1\";
!       else
! 	return \"mr %0,%1\;mr %L0,%L1\;mr %Y0,%Y1\;mr %Z0,%Z1\";
      case 3:
        /* If the address is not used in the output, we can use lsi.  Otherwise,
  	 fall through to generating four loads.  */
!       if (! reg_overlap_mentioned_p (operands[0], operands[1]))
  	return \"{lsi|lswi} %0,%P1,16\";
        /* ... fall through ...  */
      case 4:
!       /* If the address register is the same as the register for the lowest-
! 	 addressed word, load it last.  Similarly for the next two words.
! 	 Otherwise load lowest address to highest.  */
!       if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
! 			     operands[1], 0))
! 	return \"{l|lwz} %L0,%L1\;{l|lwz} %Y0,%Y1\;{l|lwz} %Z0,%Z1\;{l|lwz} %0,%1\";
!       else if (refers_to_regno_p (REGNO (operands[0]) + 1,
! 				  REGNO (operands[0]) + 2, operands[1], 0))
! 	return \"{l|lwz} %0,%1\;{l|lwz} %Y0,%Y1\;{l|lwz} %Z0,%Z1\;{l|lwz} %L0,%L1\";
!       else if (refers_to_regno_p (REGNO (operands[0]) + 2,
! 				  REGNO (operands[0]) + 3, operands[1], 0))
! 	return \"{l|lwz} %0,%1\;{l|lwz} %L0,%L1\;{l|lwz} %Z0,%Z1\;{l|lwz} %Y0,%Y1\";
!       else
! 	return \"{l%U1|lwz%U1} %0,%1\;{l|lwz} %L0,%L1\;{l|lwz} %Y0,%Y1\;{l|lwz} %Z0,%Z1\";
      }
  }"
!   [(set_attr "type" "store,store,*,load,load")
!    (set_attr "length" "4,16,16,4,16")])
  
  (define_insn "*movti_ppc64"
!   [(set (match_operand:TI 0 "nonimmediate_operand" "=r,r,m")
! 	(match_operand:TI 1 "input_operand" "r,m,r"))]
    "TARGET_POWERPC64 && (gpc_reg_operand (operands[0], TImode)
     || gpc_reg_operand (operands[1], TImode))"
!   "*
! {
!   switch (which_alternative)
!     {
!     default:
!       abort ();
!     case 0:
!       /* We normally copy the low-numbered register first.  However, if
! 	 the first register operand 0 is the same as the second register of
! 	 operand 1, we must copy in the opposite order.  */
!       if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
! 	return \"mr %L0,%L1\;mr %0,%1\";
!       else
! 	return \"mr %0,%1\;mr %L0,%L1\";
!     case 1:
!       /* If the low-address word is used in the address, we must load it
! 	 last.  Otherwise, load it first.  Note that we cannot have
! 	 auto-increment in that case since the address register is known to be
! 	 dead.  */
!       if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
! 			     operands[1], 0))
! 	return \"ld %L0,%L1\;ld %0,%1\";
!       else
! 	return \"ld%U1 %0,%1\;ld %L0,%L1\";
!     case 2:
!       return \"std%U0 %1,%0\;std %L1,%L0\";
!     }
! }"
!   [(set_attr "type" "*,load,store")
!    (set_attr "length" "8,8,8")])
  
  (define_expand "load_multiple"
    [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
--- 8723,8784 ----
      {
      default:
        abort ();
      case 0:
!       if (TARGET_STRING)
!         return \"{stsi|stswi} %1,%P0,16\";
      case 1:
!       return \"#\";
      case 2:
!       return \"#\";
      case 3:
        /* If the address is not used in the output, we can use lsi.  Otherwise,
  	 fall through to generating four loads.  */
!       if (TARGET_STRING  
!           && ! reg_overlap_mentioned_p (operands[0], operands[1]))
  	return \"{lsi|lswi} %0,%P1,16\";
        /* ... fall through ...  */
      case 4:
!       return \"#\";
      }
  }"
!   [(set_attr "type" "store,store,*,load,load")])
  
  (define_insn "*movti_ppc64"
!   [(set (match_operand:TI 0 "nonimmediate_operand" "=r,m,r")
! 	(match_operand:TI 1 "input_operand" "r,r,o"))]
    "TARGET_POWERPC64 && (gpc_reg_operand (operands[0], TImode)
     || gpc_reg_operand (operands[1], TImode))"
!   "@
!    #	
!    #	
!    #"
!   [(set_attr "type" "*,load,store")])
! 
! (define_split
!   [(set (match_operand:TI 0 "nonimmediate_operand" "")
!         (match_operand:TI 1 "input_operand" ""))]
!   "reload_completed && TARGET_POWERPC64 
!    && gpr_or_gpr_p (operands[0], operands[1])"
!   [(set (match_dup 2) (match_dup 4))
!    (set (match_dup 3) (match_dup 5))]
! "{
!      rs6000_split_multireg_move (operands);
! }")
! 
! (define_split
!   [(set (match_operand:TI 0 "nonimmediate_operand" "")
!         (match_operand:TI 1 "input_operand" ""))]
!   "reload_completed && !TARGET_POWERPC64 
!    && gpr_or_gpr_p (operands[0], operands[1])"
!   [(set (match_dup 2) (match_dup 6))
!    (set (match_dup 3) (match_dup 7))
!    (set (match_dup 4) (match_dup 8))
!    (set (match_dup 5) (match_dup 9))]
! "{
!      rs6000_split_multireg_move (operands);
! }")
! 
! 
  
  (define_expand "load_multiple"
    [(match_par_dup 3 [(set (match_operand:SI 0 "" "")


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