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]

move expander rearrangement for powerpc



This patch rearranges the mov* expanders on powerpc, merging them into
a single function in rs6000.c.  It's not supposed to cause any
significant changes in what the functions actually do, although note
that the SFmode case was changed by eliminating some silly SUBREG
hacking (we now use true_regnum instead of reducing to a REG
ourselves).

The purpose behind this is that there were quite a number of bugs in
the DImode expander, for instance, and these were caused by that code
getting out of sync with the SImode expander.  So this patch prevents
this from ever happening again, and incidentally makes the existing
problems easier to spot and fix.

Please note the two FIXMEs.  The first is caused by bugs elsewhere in
the compiler, the second will go away in subsequent patches---I
thought it'd be better if I did something as error-prone as this in
stages.

-- 
- Geoffrey Keating <geoffk@cygnus.com>

===File ~/patches/cygnus/rs6000-move-2.patch================
Index: ChangeLog
===================================================================
RCS file: /cvs/gcc/egcs/gcc/ChangeLog,v
retrieving revision 1.7014
diff -p -u -u -p -r1.7014 ChangeLog
--- ChangeLog	2000/07/03 19:33:06	1.7014
+++ ChangeLog	2000/07/03 19:40:32
@@ -1,3 +1,15 @@
+2000-06-30  Geoff Keating  <geoffk@cygnus.com>
+
+	* config/rs6000/rs6000.c (rs6000_emit_move): New function.
+	* config/rs6000/rs6000-proto.h: Prototype rs6000_emit_move.
+	* config/rs6000/rs6000.md (movsi): Use rs6000_emit_move.
+	(movhi): Likewise.
+	(movqi): Likewise.
+	(movdf): Likewise.
+	(movsf): Likewise.
+	(movdi): Likewise.
+	(movti): Likewise.
+
 2000-07-03  Geoff Keating  <geoffk@cygnus.com>
 
 	* expmed.c (expand_mult_highpart): Use op1 instead of wide_op1 when
Index: config/rs6000/rs6000-protos.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/rs6000/rs6000-protos.h,v
retrieving revision 1.6
diff -p -u -u -p -r1.6 rs6000-protos.h
--- rs6000-protos.h	2000/06/12 19:58:57	1.6
+++ rs6000-protos.h	2000/07/03 19:40:33
@@ -97,6 +97,7 @@ extern int mtcrf_operation PARAMS ((rtx,
 extern int lmw_operation PARAMS ((rtx, enum machine_mode));
 extern struct rtx_def *create_TOC_reference PARAMS ((rtx));
 extern void rs6000_emit_eh_toc_restore PARAMS ((rtx));
+extern void rs6000_emit_move PARAMS ((rtx, rtx, enum machine_mode));
 extern rtx rs6000_legitimize_address PARAMS ((rtx, rtx, enum machine_mode));
 extern void rs6000_select_rtx_section PARAMS ((enum machine_mode, rtx));
 #endif /* RTX_CODE */
Index: config/rs6000/rs6000.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/rs6000/rs6000.c,v
retrieving revision 1.130
diff -p -u -u -p -r1.130 rs6000.c
--- rs6000.c	2000/06/14 21:45:43	1.130
+++ rs6000.c	2000/07/03 19:40:50
@@ -1458,8 +1458,277 @@ rs6000_legitimize_address (x, oldx, mode
   else
     return NULL_RTX;
 }
+
+/* Emit a move from SOURCE to DEST in mode MODE.  */
+void
+rs6000_emit_move (dest, source, mode)
+     rtx dest;
+     rtx source;
+     enum machine_mode mode;
+{
+  rtx operands[2];
+  operands[0] = dest;
+  operands[1] = source;
+  
+  /* Sanity checks.  Check that we get CONST_DOUBLE only when we should.  */
+  if (GET_CODE (operands[1]) == CONST_DOUBLE
+      && ! FLOAT_MODE_P (mode)
+      && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
+    {
+      /* FIXME.  This should never happen.  */
+      /* Since it seems that it does, do the safe thing and convert
+	 to a CONST_INT.  */
+      operands[1] = 
+	GEN_INT (trunc_int_for_mode (CONST_DOUBLE_LOW (operands[1]), mode));
+    }
+  if (GET_CODE (operands[1]) == CONST_DOUBLE
+      && ! FLOAT_MODE_P (mode)
+      && ((CONST_DOUBLE_HIGH (operands[1]) == 0
+	   && CONST_DOUBLE_LOW (operands[1]) >= 0)
+	  || (CONST_DOUBLE_HIGH (operands[1]) == -1
+	      && CONST_DOUBLE_LOW (operands[1]) < 0)))
+    abort ();
+  
+  if (! no_new_pseudos && GET_CODE (operands[0]) != REG)
+    operands[1] = force_reg (mode, operands[1]);
+  
+  if (mode == SFmode && ! TARGET_POWERPC && TARGET_HARD_FLOAT)
+    {
+      int regnum = true_regnum (operands[1]);
+      /* regnum may be -1 in which case the test below will fail.  */	
+      
+      /* If operands[1] is a register, on POWER it may have
+	 double-precision data in it, so truncate it to single
+	 precision.  */
+      if (FP_REGNO_P (regnum) || regnum >= FIRST_PSEUDO_REGISTER)
+	{
+	  rtx newreg;
+	  newreg = (no_new_pseudos ? operands[1] : gen_reg_rtx (mode));
+	  emit_insn (gen_aux_truncdfsf2 (newreg, operands[1]));
+	  operands[1] = newreg;
+	}
+    }
 
+  /* Only a tiny bit of handling for CONSTANT_P_RTX is necessary.  */
+  if (GET_CODE (operands[1]) == CONSTANT_P_RTX)
+    {
+      emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
+      return;
+    }
 
+  /* FIXME:  In the long term, this switch statement should go away
+     and be replaced by a sequence of tests based on things like
+     mode == Pmode.  */
+  switch (mode)
+    {
+    case HImode:
+    case QImode:
+      if (CONSTANT_P (operands[1])
+	  && GET_CODE (operands[1]) != CONST_INT)
+	{
+	  operands[1] = force_const_mem (mode, operands[1]);
+	  if (! memory_address_p (mode, XEXP (operands[1], 0))
+	      && ! reload_in_progress)
+	    operands[1] = change_address (operands[1], mode,
+					  XEXP (operands[1], 0));
+	}
+      break;
+
+    case DFmode:
+    case SFmode:
+      if (CONSTANT_P (operands[1]) 
+	  && ! easy_fp_constant (operands[1], mode))
+	{
+	  operands[1] = force_const_mem (mode, operands[1]);
+	  if (! memory_address_p (mode, XEXP (operands[1], 0))
+	      && ! reload_in_progress)
+	    operands[1] = change_address (operands[1], mode,
+					  XEXP (operands[1], 0));
+	}
+      break;
+      
+    case SImode:
+      /* Use default pattern for address of ELF small data */
+      if (TARGET_ELF
+	  && (DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS)
+	  && (GET_CODE (operands[1]) == SYMBOL_REF || GET_CODE (operands[1]) == CONST)
+	  && small_data_operand (operands[1], SImode))
+	{
+	  emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
+	  return;
+	}
+
+      if ((DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS)
+	  && flag_pic == 1 && got_operand (operands[1], SImode))
+	{
+	  emit_insn (gen_movsi_got (operands[0], operands[1]));
+	  return;
+	}
+
+      if (TARGET_ELF && TARGET_NO_TOC && ! TARGET_64BIT
+	  && ! flag_pic
+	  && CONSTANT_P (operands[1])
+	  && GET_CODE (operands[1]) != HIGH
+	  && GET_CODE (operands[1]) != CONST_INT)
+	{
+	  rtx target = (no_new_pseudos ? operands[0] : gen_reg_rtx (SImode));
+
+	  /* If this is a function address on -mcall-aixdesc,
+	     convert it to the address of the descriptor.  */
+	  if (DEFAULT_ABI == ABI_AIX
+	      && GET_CODE (operands[1]) == SYMBOL_REF
+	      && XSTR (operands[1], 0)[0] == '.')
+	    {
+	      const char *name = XSTR (operands[1], 0);
+	      rtx new_ref;
+	      while (*name == '.')
+		name++;
+	      new_ref = gen_rtx_SYMBOL_REF (Pmode, name);
+	      CONSTANT_POOL_ADDRESS_P (new_ref)
+		= CONSTANT_POOL_ADDRESS_P (operands[1]);
+	      SYMBOL_REF_FLAG (new_ref) = SYMBOL_REF_FLAG (operands[1]);
+	      SYMBOL_REF_USED (new_ref) = SYMBOL_REF_USED (operands[1]);
+	      operands[1] = new_ref;
+	    }
+
+	  emit_insn (gen_elf_high (target, operands[1]));
+	  emit_insn (gen_elf_low (operands[0], target, operands[1]));
+	  return;
+	}
+
+      if (CONSTANT_P (operands[1])
+	  && GET_CODE (operands[1]) != CONST_INT
+	  && GET_CODE (operands[1]) != HIGH
+	  && ! LEGITIMATE_CONSTANT_POOL_ADDRESS_P (operands[1])
+	  && ! TOC_RELATIVE_EXPR_P (operands[1]))
+	{
+	  /* Emit a USE operation so that the constant isn't deleted if
+	     expensive optimizations are turned on because nobody
+	     references it.  This should only be done for operands that
+	     contain SYMBOL_REFs with CONSTANT_POOL_ADDRESS_P set.
+	     This should not be done for operands that contain LABEL_REFs.
+	     For now, we just handle the obvious case.  */
+	  if (GET_CODE (operands[1]) != LABEL_REF)
+	    emit_insn (gen_rtx_USE (VOIDmode, operands[1]));
+
+      /* If we are to limit the number of things we put in the TOC and
+	 this is a symbol plus a constant we can add in one insn,
+	 just put the symbol in the TOC and add the constant.  Don't do
+	 this if reload is in progress.  */
+	  if (GET_CODE (operands[1]) == CONST
+	      && TARGET_NO_SUM_IN_TOC && ! reload_in_progress
+	      && GET_CODE (XEXP (operands[1], 0)) == PLUS
+	      && add_operand (XEXP (XEXP (operands[1], 0), 1), SImode)
+	      && (GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == LABEL_REF
+		  || GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == SYMBOL_REF)
+	      && ! side_effects_p (operands[0]))
+	    {
+	      rtx sym = force_const_mem (SImode, XEXP (XEXP (operands[1], 0), 0));
+	      rtx other = XEXP (XEXP (operands[1], 0), 1);
+
+	      emit_insn (gen_addsi3 (operands[0], force_reg (SImode, sym), other));
+	      return;
+	    }
+
+	  operands[1] = force_const_mem (SImode, operands[1]);
+
+	  if (TARGET_TOC 
+	      && CONSTANT_POOL_EXPR_P (XEXP (operands[1], 0))
+	      && ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (
+								     XEXP (operands[1], 0))))
+	    {
+	      operands[1] = gen_rtx_MEM (SImode,
+					 create_TOC_reference (XEXP (operands[1], 0)));
+	      MEM_ALIAS_SET (operands[1]) = get_TOC_alias_set ();	
+	      RTX_UNCHANGING_P (operands[1]) = 1;
+	    }
+
+	  if (! memory_address_p (SImode, XEXP (operands[1], 0))
+	      && ! reload_in_progress)
+	    operands[1] = change_address (operands[1], SImode,
+					  XEXP (operands[1], 0));
+	}
+      break;
+
+    case DImode:
+      if (TARGET_64BIT
+	  && CONSTANT_P (operands[1])
+#if HOST_BITS_PER_WIDE_INT == 32
+	  && GET_CODE (operands[1]) != CONST_INT
+#endif
+	  && ! easy_fp_constant (operands[1], DImode)
+	  && ! LEGITIMATE_CONSTANT_POOL_ADDRESS_P (operands[1])
+	  && ! TOC_RELATIVE_EXPR_P (operands[1]))
+	{
+	  /* Emit a USE operation so that the constant isn't deleted if
+	     expensive optimizations are turned on because nobody
+	     references it.  This should only be done for operands that
+	     contain SYMBOL_REFs with CONSTANT_POOL_ADDRESS_P set.
+	     This should not be done for operands that contain LABEL_REFs.
+	     For now, we just handle the obvious case.  */
+	  if (GET_CODE (operands[1]) != LABEL_REF)
+	    emit_insn (gen_rtx_USE (VOIDmode, operands[1]));
+
+	  /* If we are to limit the number of things we put in the TOC and
+	     this is a symbol plus a constant we can add in one insn,
+	     just put the symbol in the TOC and add the constant.  Don't do
+	     this if reload is in progress.  */
+	  if (GET_CODE (operands[1]) == CONST
+	      && TARGET_NO_SUM_IN_TOC && ! reload_in_progress
+	      && GET_CODE (XEXP (operands[1], 0)) == PLUS
+	      && add_operand (XEXP (XEXP (operands[1], 0), 1), DImode)
+	      && (GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == LABEL_REF
+		  || GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == SYMBOL_REF)
+	      && ! side_effects_p (operands[0]))
+	    {
+	      rtx sym = force_const_mem (DImode, XEXP (XEXP (operands[1], 0), 0));
+	      rtx other = XEXP (XEXP (operands[1], 0), 1);
+
+	      emit_insn (gen_adddi3 (operands[0], force_reg (DImode, sym), other));
+	      return;
+	    }
+
+	  operands[1] = force_const_mem (DImode, operands[1]);
+
+	  if (TARGET_TOC 
+	      && CONSTANT_POOL_EXPR_P (XEXP (operands[1], 0))
+	      && ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (
+								     XEXP (operands[1], 0))))
+	    {
+	      operands[1] = gen_rtx_MEM (DImode,
+					 create_TOC_reference (XEXP (operands[1], 0)));
+
+	      MEM_ALIAS_SET (operands[1]) = get_TOC_alias_set ();	
+	      RTX_UNCHANGING_P (operands[1]) = 1;
+	    }	
+
+	  if (! memory_address_p (DImode, XEXP (operands[1], 0))
+	      && ! reload_in_progress)
+	    operands[1] = change_address (operands[1], DImode,
+					  XEXP (operands[1], 0));
+	}
+      break;
+  
+    case TImode:
+      if (GET_CODE (operands[0]) == MEM
+	  && GET_CODE (XEXP (operands[0], 0)) != REG
+	  && ! reload_in_progress)
+	operands[0] = change_address (operands[0], TImode,
+				      copy_addr_to_reg (XEXP (operands[0], 0)));
+
+      if (GET_CODE (operands[1]) == MEM
+	  && GET_CODE (XEXP (operands[1], 0)) != REG
+	  && ! reload_in_progress)
+	operands[1] = change_address (operands[1], TImode,
+				      copy_addr_to_reg (XEXP (operands[1], 0)));
+      break;
+
+    default:
+      abort ();
+    }
+
+  emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
+}
 
 /* Initialize a variable CUM of type CUMULATIVE_ARGS
    for a call to a function whose data type is FNTYPE.
Index: config/rs6000/rs6000.md
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/rs6000/rs6000.md,v
retrieving revision 1.93
diff -p -u -u -p -r1.93 rs6000.md
--- rs6000.md	2000/06/12 19:58:57	1.93
+++ rs6000.md	2000/07/03 19:41:06
@@ -7434,124 +7434,8 @@
   [(set (match_operand:SI 0 "general_operand" "")
 	(match_operand:SI 1 "any_operand" ""))]
   ""
-  "
-{
-  if (! no_new_pseudos && GET_CODE (operands[0]) != REG)
-    operands[1] = force_reg (SImode, operands[1]);
-
-  /* Convert a move of a CONST_DOUBLE into a CONST_INT */
-  if (GET_CODE (operands[1]) == CONST_DOUBLE)
-    operands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
-
-  /* Only a tiny bit of handling for CONSTANT_P_RTX is necessary.  */
-  if (GET_CODE (operands[1]) == CONSTANT_P_RTX)
-    {
-      emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
-      DONE;
-    }
-
-  /* Use default pattern for address of ELF small data */
-  if (TARGET_ELF
-      && (DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS)
-      && (GET_CODE (operands[1]) == SYMBOL_REF || GET_CODE (operands[1]) == CONST)
-      && small_data_operand (operands[1], SImode))
-    {
-      emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
-      DONE;
-    }
-
-  if ((DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS)
-      && flag_pic == 1 && got_operand (operands[1], SImode))
-    {
-      emit_insn (gen_movsi_got (operands[0], operands[1]));
-      DONE;
-    }
-
-  if (TARGET_ELF && TARGET_NO_TOC && ! TARGET_64BIT
-      && ! flag_pic
-      && CONSTANT_P (operands[1])
-      && GET_CODE (operands[1]) != HIGH
-      && GET_CODE (operands[1]) != CONST_INT)
-    {
-      rtx target = (no_new_pseudos ? operands[0] : gen_reg_rtx (SImode));
-
-      /* If this is a function address on -mcall-aixdesc,
-	 convert it to the address of the descriptor.  */
-      if (DEFAULT_ABI == ABI_AIX
-	  && GET_CODE (operands[1]) == SYMBOL_REF
-	  && XSTR (operands[1], 0)[0] == '.')
-	{
-	  const char *name = XSTR (operands[1], 0);
-	  rtx new_ref;
-	  while (*name == '.')
-	    name++;
-	  new_ref = gen_rtx_SYMBOL_REF (Pmode, name);
-	  CONSTANT_POOL_ADDRESS_P (new_ref)
-	    = CONSTANT_POOL_ADDRESS_P (operands[1]);
-	  SYMBOL_REF_FLAG (new_ref) = SYMBOL_REF_FLAG (operands[1]);
-	  SYMBOL_REF_USED (new_ref) = SYMBOL_REF_USED (operands[1]);
-	  operands[1] = new_ref;
-	}
-
-      emit_insn (gen_elf_high (target, operands[1]));
-      emit_insn (gen_elf_low (operands[0], target, operands[1]));
-      DONE;
-    }
-
-  if (CONSTANT_P (operands[1])
-      && GET_CODE (operands[1]) != CONST_INT
-      && GET_CODE (operands[1]) != HIGH
-      && ! LEGITIMATE_CONSTANT_POOL_ADDRESS_P (operands[1])
-      && ! TOC_RELATIVE_EXPR_P (operands[1]))
-    {
-      /* Emit a USE operation so that the constant isn't deleted if
-	 expensive optimizations are turned on because nobody
-	 references it.  This should only be done for operands that
-	 contain SYMBOL_REFs with CONSTANT_POOL_ADDRESS_P set.
-	 This should not be done for operands that contain LABEL_REFs.
-	 For now, we just handle the obvious case.  */
-      if (GET_CODE (operands[1]) != LABEL_REF)
-	emit_insn (gen_rtx_USE (VOIDmode, operands[1]));
-
-      /* If we are to limit the number of things we put in the TOC and
-	 this is a symbol plus a constant we can add in one insn,
-	 just put the symbol in the TOC and add the constant.  Don't do
-	 this if reload is in progress.  */
-      if (GET_CODE (operands[1]) == CONST
-	  && TARGET_NO_SUM_IN_TOC && ! reload_in_progress
-	  && GET_CODE (XEXP (operands[1], 0)) == PLUS
-	  && add_operand (XEXP (XEXP (operands[1], 0), 1), SImode)
-	  && (GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == LABEL_REF
-	      || GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == SYMBOL_REF)
-	  && ! side_effects_p (operands[0]))
-	{
-	  rtx sym = force_const_mem (SImode, XEXP (XEXP (operands[1], 0), 0));
-	  rtx other = XEXP (XEXP (operands[1], 0), 1);
-
-	  emit_insn (gen_addsi3 (operands[0], force_reg (SImode, sym), other));
-	  DONE;
-	}
+  "{ rs6000_emit_move (operands[0], operands[1], SImode); DONE; }")
 
-      operands[1] = force_const_mem (SImode, operands[1]);
-
-      if (TARGET_TOC 
-	  && CONSTANT_POOL_EXPR_P (XEXP (operands[1], 0))
-	  && ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (
-		XEXP (operands[1], 0))))
-	{
-	  operands[1] = gen_rtx_MEM (SImode,
-			     create_TOC_reference (XEXP (operands[1], 0)));
-	  MEM_ALIAS_SET (operands[1]) = get_TOC_alias_set ();	
-	  RTX_UNCHANGING_P (operands[1]) = 1;
-	}
-
-      if (! memory_address_p (SImode, XEXP (operands[1], 0))
-	  && ! reload_in_progress)
-	operands[1] = change_address (operands[1], SImode,
-				      XEXP (operands[1], 0));
-    }
-}")
-
 (define_insn "*movsi_internal1"
   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,m,r,r,r,r,r,*q,*c*l,*h")
 	(match_operand:SI 1 "input_operand" "r,U,m,r,I,L,n,R,*h,r,r,0"))]
@@ -7620,21 +7504,7 @@
   [(set (match_operand:HI 0 "general_operand" "")
 	(match_operand:HI 1 "any_operand" ""))]
   ""
-  "
-{
-  if (! no_new_pseudos && GET_CODE (operands[0]) != REG)
-    operands[1] = force_reg (HImode, operands[1]);
-
-  if (CONSTANT_P (operands[1])
-      && GET_CODE (operands[1]) != CONST_INT)
-    {
-      operands[1] = force_const_mem (HImode, operands[1]);
-      if (! memory_address_p (HImode, XEXP (operands[1], 0))
-	  && ! reload_in_progress)
-	operands[1] = change_address (operands[1], HImode,
-				      XEXP (operands[1], 0));
-    }
-}")
+  "{ rs6000_emit_move (operands[0], operands[1], HImode); DONE; }")
 
 (define_insn ""
   [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r,r,*q,*c*l,*h")
@@ -7656,21 +7526,7 @@
   [(set (match_operand:QI 0 "general_operand" "")
 	(match_operand:QI 1 "any_operand" ""))]
   ""
-  "
-{
-  if (! no_new_pseudos && GET_CODE (operands[0]) != REG)
-    operands[1] = force_reg (QImode, operands[1]);
-
-  if (CONSTANT_P (operands[1])
-      && GET_CODE (operands[1]) != CONST_INT)
-    {
-      operands[1] = force_const_mem (QImode, operands[1]);
-      if (! memory_address_p (QImode, XEXP (operands[1], 0))
-	  && ! reload_in_progress)
-	operands[1] = change_address (operands[1], QImode,
-				      XEXP (operands[1], 0));
-    }
-}")
+  "{ rs6000_emit_move (operands[0], operands[1], QImode); DONE; }")
 
 (define_insn ""
   [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,m,r,r,*q,*c*l,*h")
@@ -7723,49 +7579,7 @@
   [(set (match_operand:SF 0 "nonimmediate_operand" "")
 	(match_operand:SF 1 "any_operand" ""))]
   ""
-  "
-{
-  /* If we are called from reload, we might be getting a SUBREG of a hard
-     reg.  So expand it.  */
-  if (GET_CODE (operands[0]) == SUBREG
-      && GET_CODE (SUBREG_REG (operands[0])) == REG
-      && REGNO (SUBREG_REG (operands[0])) < FIRST_PSEUDO_REGISTER
-      && (! REG_FUNCTION_VALUE_P (SUBREG_REG (operands[0]))
-	  || ! rtx_equal_function_value_matters))
-    operands[0] = alter_subreg (operands[0]);
-  if (GET_CODE (operands[1]) == SUBREG
-      && GET_CODE (SUBREG_REG (operands[1])) == REG
-      && REGNO (SUBREG_REG (operands[1])) < FIRST_PSEUDO_REGISTER)
-    operands[1] = alter_subreg (operands[1]);
-
-  if (GET_CODE (operands[0]) == MEM)
-    {
-      /* If operands[1] is a register, it may have double-precision data
-	 in it, so truncate it to single precision.  We need not do
-	 this for POWERPC.  */
-      if (! TARGET_POWERPC && TARGET_HARD_FLOAT
-	  && GET_CODE (operands[1]) == REG
-	  && (FP_REGNO_P (REGNO (operands[1]))
-	      || REGNO (operands[1]) >= FIRST_PSEUDO_REGISTER))
-	{
-	  rtx newreg = (no_new_pseudos ? operands[1] : gen_reg_rtx (SFmode));
-	  emit_insn (gen_aux_truncdfsf2 (newreg, operands[1]));
-	  operands[1] = newreg;
-	}
-
-      operands[1] = force_reg (SFmode, operands[1]);
-    }
-
-  if (CONSTANT_P (operands[1]) && TARGET_HARD_FLOAT
-      && ! easy_fp_constant (operands[1], SFmode))
-    {
-      operands[1] = force_const_mem (SFmode, operands[1]);
-      if (! memory_address_p (SFmode, XEXP (operands[1], 0))
-	  && ! reload_in_progress)
-	operands[1] = change_address (operands[1], SFmode,
-				      XEXP (operands[1], 0));
-    }
-}")
+  "{ rs6000_emit_move (operands[0], operands[1], SFmode); DONE; }")
 
 (define_split
   [(set (match_operand:SF 0 "gpc_reg_operand" "")
@@ -7831,21 +7645,8 @@
   [(set (match_operand:DF 0 "nonimmediate_operand" "")
 	(match_operand:DF 1 "any_operand" ""))]
   ""
-  "
-{
-  if (GET_CODE (operands[0]) != REG)
-    operands[1] = force_reg (DFmode, operands[1]);
+  "{ rs6000_emit_move (operands[0], operands[1], DFmode); DONE; }")
 
-  if (CONSTANT_P (operands[1]) && ! easy_fp_constant (operands[1], DFmode))
-    {
-      operands[1] = force_const_mem (DFmode, operands[1]);
-      if (! memory_address_p (DFmode, XEXP (operands[1], 0))
-	  && ! reload_in_progress)
-	operands[1] = change_address (operands[1], DFmode,
-				      XEXP (operands[1], 0));
-    }
-}")
-
 (define_split
   [(set (match_operand:DF 0 "gpc_reg_operand" "")
 	(match_operand:DF 1 "const_int_operand" ""))]
@@ -8100,88 +7901,8 @@
   [(set (match_operand:DI 0 "general_operand" "")
 	(match_operand:DI 1 "any_operand" ""))]
   ""
-  "
-{
-  if (! no_new_pseudos && GET_CODE (operands[0]) != REG)
-    operands[1] = force_reg (DImode, operands[1]);
+  "{ rs6000_emit_move (operands[0], operands[1], DImode); DONE; }")
 
-  /* Convert a move of a CONST_DOUBLE into a CONST_INT
-     only if sign-extended lower-half for 32-bit host.  */
-  if (GET_CODE (operands[1]) == CONST_DOUBLE
-#if HOST_BITS_PER_WIDE_INT == 32
-      && ((CONST_DOUBLE_HIGH (operands[1]) == 0
-	   && (CONST_DOUBLE_LOW (operands[1]) & 0x80000000) == 0)
-	  || (CONST_DOUBLE_HIGH (operands[1]) == (HOST_WIDE_INT) 0xffffffff
-	      && (CONST_DOUBLE_LOW (operands[1]) & 0x80000000) != 0))
-#endif
-	 )
-    operands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
-
-  /* Only a tiny bit of handling for CONSTANT_P_RTX is necessary.  */
-  if (GET_CODE (operands[1]) == CONSTANT_P_RTX)
-    {
-      emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
-      DONE;
-    }
-
-  if (TARGET_64BIT
-      && CONSTANT_P (operands[1])
-#if HOST_BITS_PER_WIDE_INT == 32
-      && GET_CODE (operands[1]) != CONST_INT
-#endif
-      && ! easy_fp_constant (operands[1], DImode)
-      && ! LEGITIMATE_CONSTANT_POOL_ADDRESS_P (operands[1])
-      && ! TOC_RELATIVE_EXPR_P (operands[1]))
-    {
-      /* Emit a USE operation so that the constant isn't deleted if
-	 expensive optimizations are turned on because nobody
-	 references it.  This should only be done for operands that
-	 contain SYMBOL_REFs with CONSTANT_POOL_ADDRESS_P set.
-	 This should not be done for operands that contain LABEL_REFs.
-	 For now, we just handle the obvious case.  */
-      if (GET_CODE (operands[1]) != LABEL_REF)
-	emit_insn (gen_rtx_USE (VOIDmode, operands[1]));
-
-      /* If we are to limit the number of things we put in the TOC and
-	 this is a symbol plus a constant we can add in one insn,
-	 just put the symbol in the TOC and add the constant.  Don't do
-	 this if reload is in progress.  */
-      if (GET_CODE (operands[1]) == CONST
-	  && TARGET_NO_SUM_IN_TOC && ! reload_in_progress
-	  && GET_CODE (XEXP (operands[1], 0)) == PLUS
-	  && add_operand (XEXP (XEXP (operands[1], 0), 1), DImode)
-	  && (GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == LABEL_REF
-	      || GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == SYMBOL_REF)
-	  && ! side_effects_p (operands[0]))
-	{
-	  rtx sym = force_const_mem (DImode, XEXP (XEXP (operands[1], 0), 0));
-	  rtx other = XEXP (XEXP (operands[1], 0), 1);
-
-	  emit_insn (gen_adddi3 (operands[0], force_reg (DImode, sym), other));
-	  DONE;
-	}
-
-      operands[1] = force_const_mem (DImode, operands[1]);
-
-      if (TARGET_TOC 
-	  && CONSTANT_POOL_EXPR_P (XEXP (operands[1], 0))
-	  && ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (
-		XEXP (operands[1], 0))))
-	{
-	  operands[1] = gen_rtx_MEM (DImode,
-			     create_TOC_reference (XEXP (operands[1], 0)));
-
-	  MEM_ALIAS_SET (operands[1]) = get_TOC_alias_set ();	
-	  RTX_UNCHANGING_P (operands[1]) = 1;
-	}	
-
-      if (! memory_address_p (DImode, XEXP (operands[1], 0))
-	  && ! reload_in_progress)
-	operands[1] = change_address (operands[1], DImode,
-				      XEXP (operands[1], 0));
-    }
-}")
-
 (define_insn "*movdi_internal32"
   [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,m,f,f,m,r,r,r,r,r")
 	(match_operand:DI 1 "input_operand" "r,m,r,f,m,f,IJK,n,G,H,F"))]
@@ -8526,23 +8247,7 @@ operands[2] = GEN_INT (INTVAL (operands[
 		   (match_operand:TI 1 "general_operand" ""))
 	      (clobber (scratch:SI))])]
   "TARGET_STRING || TARGET_POWERPC64"
-  "
-{
-  if (GET_CODE (operands[0]) == MEM)
-    operands[1] = force_reg (TImode, operands[1]);
-
-  if (GET_CODE (operands[0]) == MEM
-      && GET_CODE (XEXP (operands[0], 0)) != REG
-      && ! reload_in_progress)
-    operands[0] = change_address (operands[0], TImode,
-				  copy_addr_to_reg (XEXP (operands[0], 0)));
-
-  if (GET_CODE (operands[1]) == MEM
-      && GET_CODE (XEXP (operands[1], 0)) != REG
-      && ! reload_in_progress)
-    operands[1] = change_address (operands[1], TImode,
-				  copy_addr_to_reg (XEXP (operands[1], 0)));
-}")
+  "{ rs6000_emit_move (operands[0], operands[1], TImode); DONE; }")
 
 ;; We say that MQ is clobbered in the last alternative because the first
 ;; alternative would never get used otherwise since it would need a reload
============================================================

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