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]

rs6000: jumbo move patch



This patch does all sorts of interesting things to the move expanders.

Firstly, it used to be that we would occasionally (in PIC mode, and on
AIX generally) generate constants that were smaller than a word.  This
is silly, because we are then going to generate a word-sized TOC entry
to point to them.  This also caused problems under some circumstances,
when reload asked us to move something into a register and we
couldn't.  So, now all constants are put in the TOC if they are
smaller than the size of a TOC entry; this includes SFmode values
even in 32-bit mode.  One consequence of this is that -mno-fp-in-toc
now does nothing useful in 64-bit mode (but I've kept it around for
when we get 128-bit floating constants).

Secondly, we weren't distinguishing between CONST_INTs of different
modes in the TOC hashing stuff.

Thirdly, rs6000_emit_move has a few minor bug fixes and a few major
cleanups.  It's now much cleaner, almost all the duplicated code is
gone.

Finally there are some small whitespace changes.

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

===File ~/patches/cygnus/rs6000-64bugs3-3-move.patch========
2000-07-17  Geoff Keating  <geoffk@cygnus.com>

	* config/rs6000/rs6000.h (ASM_OUTPUT_SPECIAL_POOL_ENTRY_P): All
	constants of size no larger than a pointer should go in the TOC.
	Add 'MODE' parameter.
	(LEGITIMIZE_RELOAD_ADDRESS): Add MODE parameter to
	ASM_OUTPUT_SPECIAL_POOL_ENTRY_P.
	(ASM_OUTPUT_SPECIAL_POOL_ENTRY): Likewise.
	* config/rs6000/aix.h (SELECT_RTX_SECTION): Likewise.
	* config/rs6000/netware.h (SELECT_RTX_SECTION): Likewise.
	* config/rs6000/rs6000.c (constant_pool_expr_1): Likewise.
	(rs6000_legitimize_address): Likewise.
	(rs6000_emit_move): Likewise.
	(rs6000_select_rtx_section): Likewise.
	(output_toc): Deal properly with outputting small constants like
	HImode, and SFmode in 32-bit mode, and DFmode in 64-bit mode.
	* config/rs6000/sysv4.h (ASM_OUTPUT_SPECIAL_POOL_ENTRY_P): Add
	MODE parameter.  Put small constants in the TOC.
	
	* config/rs6000/rs6000.c (easy_fp_constant_p): All constants are
	easy in SImode.
	(rs6000_emit_move): When reload calls us with an illegitimate
	address, exit early.  Move the change_address calls to one place
	at the end of the routine.  Merge the SImode and DImode expanders.
	When called by reload to put an integer into a FP register, force
	it to memory.

	* config/rs6000/rs6000.c (struct toc_hash_struct): Add 'key_mode'
	field.
	(rs6000_hash_constant): Hash mode too.
	(toc_hash_function): Allow for key_mode.
	(toc_hash_eq): Structures are different if key_mode differs.
	(output_toc): Add 'mode' parameter.  Save key_mode.
	* config/rs6000/rs6000.h (ASM_OUTPUT_SPECIAL_POOL_ENTRY):
	Pass 'mode' parameter.
	* config/rs6000/rs6000-protos.h (output_toc): Add 'mode' param.

Index: config/rs6000/aix.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/rs6000/aix.h,v
retrieving revision 1.5
diff -p -u -u -p -r1.5 aix.h
--- config/rs6000/aix.h	2000/07/04 11:14:13	1.5
+++ config/rs6000/aix.h	2000/07/18 16:06:13
@@ -100,14 +100,14 @@ Boston, MA 02111-1307, USA.  */
 /* Define the options for the binder: Start text at 512, align all segments
    to 512 bytes, and warn if there is text relocation.
 
- The -bhalt:4 option supposedly changes the level at which ld will abort,
+   The -bhalt:4 option supposedly changes the level at which ld will abort,
    but it also suppresses warnings about multiply defined symbols and is
    used by the AIX cc command.  So we use it here.
 
    -bnodelcsect undoes a poor choice of default relating to multiply-defined
    csects.  See AIX documentation for more information about this.
 
- -bM:SRE tells the linker that the output file is Shared REusable.  Note
+   -bM:SRE tells the linker that the output file is Shared REusable.  Note
    that to actually build a shared library you will also need to specify an
    export list with the -Wl,-bE option.  */
 
@@ -233,11 +233,11 @@ toc_section ()						\
    However, if this is being placed in the TOC it must be output as a
    toc entry.  */
 
-#define SELECT_RTX_SECTION(MODE, X)		\
-{ if (ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (X))	\
-    toc_section ();				\
-  else						\
-    read_only_private_data_section ();		\
+#define SELECT_RTX_SECTION(MODE, X)			\
+{ if (ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (X, MODE))	\
+    toc_section ();					\
+  else							\
+    read_only_private_data_section ();			\
 }
 
 /* Indicate that jump tables go in the text section.  */
Index: config/rs6000/netware.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/rs6000/netware.h,v
retrieving revision 1.5
diff -p -u -u -p -r1.5 netware.h
--- config/rs6000/netware.h	2000/03/16 03:16:40	1.5
+++ config/rs6000/netware.h	2000/07/18 16:06:14
@@ -162,11 +162,11 @@ toc_section ()								\
 /* Use the TOC section for TOC entries.  */
 
 #undef SELECT_RTX_SECTION
-#define SELECT_RTX_SECTION(MODE, X)		\
-{ if (ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (X))	\
-    toc_section ();				\
-  else						\
-    const_section ();				\
+#define SELECT_RTX_SECTION(MODE, X)			\
+{ if (ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (X, MODE))	\
+    toc_section ();					\
+  else							\
+    const_section ();					\
 }
 
 /* How to renumber registers for dbx and gdb.  */
Index: config/rs6000/rs6000-protos.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/rs6000/rs6000-protos.h,v
retrieving revision 1.7
diff -p -u -u -p -r1.7 rs6000-protos.h
--- config/rs6000/rs6000-protos.h	2000/07/03 20:00:44	1.7
+++ config/rs6000/rs6000-protos.h	2000/07/18 16:06:15
@@ -86,7 +86,7 @@ extern int ccr_bit PARAMS ((rtx, int));
 extern void print_operand PARAMS ((FILE *, rtx, int));
 extern void print_operand_address PARAMS ((FILE *, rtx));
 extern char * output_cbranch PARAMS ((rtx, const char *, int, rtx));
-extern void output_toc PARAMS ((FILE *, rtx, int));
+extern void output_toc PARAMS ((FILE *, rtx, int, enum machine_mode));
 extern int rs6000_adjust_cost PARAMS ((rtx, rtx, rtx, int));
 extern int rs6000_adjust_priority PARAMS ((rtx, int));
 extern void rs6000_initialize_trampoline PARAMS ((rtx, rtx, rtx));
Index: config/rs6000/rs6000.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/rs6000/rs6000.c,v
retrieving revision 1.132
diff -p -u -u -p -r1.132 rs6000.c
--- config/rs6000/rs6000.c	2000/07/08 12:42:09	1.132
+++ config/rs6000/rs6000.c	2000/07/18 16:06:39
@@ -119,6 +119,7 @@ static int rs6000_sr_alias_set;
 static void rs6000_add_gc_roots PARAMS ((void));
 static int num_insns_constant_wide PARAMS ((HOST_WIDE_INT));
 static rtx expand_block_move_mem PARAMS ((enum machine_mode, rtx, rtx));
+static void rs6000_maybe_dead PARAMS ((rtx));
 static void rs6000_emit_stack_tie PARAMS ((void));
 static void rs6000_frame_related PARAMS ((rtx, rtx, HOST_WIDE_INT, rtx, rtx));
 static void rs6000_emit_allocate_stack PARAMS ((HOST_WIDE_INT, int));
@@ -890,6 +891,8 @@ easy_fp_constant (op, mode)
 	     && GET_CODE (op) == CONST_DOUBLE && CONST_DOUBLE_LOW (op) == 0)
 	    || (num_insns_constant (op, DImode) <= 2));
 
+  else if (mode == SImode)
+    return 1;
   else
     abort ();
 }
@@ -1339,7 +1342,7 @@ constant_pool_expr_1 (op, have_sym, have
     case SYMBOL_REF:
 	if (CONSTANT_POOL_ADDRESS_P (op))
 	  {
-	   if (ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (op)))
+	   if (ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (op), Pmode))
 	     {
 	       *have_sym = 1;
 	       return 1;
@@ -1451,7 +1454,7 @@ rs6000_legitimize_address (x, oldx, mode
     }
   else if (TARGET_TOC 
 	   && CONSTANT_POOL_EXPR_P (x)
-	   && ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (x)))
+	   && ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (x), Pmode))
     {
       return create_TOC_reference (x);
     }
@@ -1491,7 +1494,7 @@ rs6000_emit_move (dest, source, mode)
   
   if (! no_new_pseudos && GET_CODE (operands[0]) != REG)
     operands[1] = force_reg (mode, operands[1]);
-  
+
   if (mode == SFmode && ! TARGET_POWERPC && TARGET_HARD_FLOAT
       && GET_CODE (operands[0]) == MEM)
     {
@@ -1516,13 +1519,16 @@ rs6000_emit_move (dest, source, mode)
 	}
     }
 
-  /* Only a tiny bit of handling for CONSTANT_P_RTX is necessary.  */
-  if (GET_CODE (operands[1]) == CONSTANT_P_RTX)
+  /* Handle the case where reload calls us with an invalid address;
+     and the case of CONSTANT_P_RTX.  */
+  if (! general_operand (operands[1], mode)
+      || ! nonimmediate_operand (operands[0], mode)
+      || 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.  */
@@ -1532,53 +1538,45 @@ rs6000_emit_move (dest, source, mode)
     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));
-	}
+	operands[1] = force_const_mem (mode, operands[1]);
       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));
-	}
+	operands[1] = force_const_mem (mode, operands[1]);
       break;
       
     case SImode:
+    case DImode:
       /* Use default pattern for address of ELF small data */
       if (TARGET_ELF
+	  && mode == Pmode
 	  && (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))
+	  && (GET_CODE (operands[1]) == SYMBOL_REF 
+	      || GET_CODE (operands[1]) == CONST)
+	  && small_data_operand (operands[1], mode))
 	{
 	  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))
+	  && mode == Pmode && mode == SImode
+	  && flag_pic == 1 && got_operand (operands[1], mode))
 	{
 	  emit_insn (gen_movsi_got (operands[0], operands[1]));
 	  return;
 	}
 
-      if (TARGET_ELF && TARGET_NO_TOC && ! TARGET_64BIT
-	  && ! flag_pic
+      if (TARGET_ELF && TARGET_NO_TOC && ! flag_pic
+	  && mode == Pmode
 	  && 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));
+	  rtx target = (no_new_pseudos ? operands[0] : gen_reg_rtx (mode));
 
 	  /* If this is a function address on -mcall-aixdesc,
 	     convert it to the address of the descriptor.  */
@@ -1603,70 +1601,30 @@ rs6000_emit_move (dest, source, mode)
 	  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]))
+      /* If this is a SYMBOL_REF that refers to a constant pool entry,
+	 and we have put it in the TOC, we just need to make a TOC-relative
+	 reference to it.  */
+      if (TARGET_TOC
+	  && GET_CODE (operands[1]) == SYMBOL_REF
+	  && CONSTANT_POOL_EXPR_P (operands[1])
+	  && ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (operands[1]),
+					      get_pool_mode (operands[1])))
+	{
+	  operands[1] = create_TOC_reference (operands[1]);
+	}
+      else if (mode == Pmode
+	       && CONSTANT_P (operands[1])
+ 	       && (((HOST_BITS_PER_WIDE_INT != 32 
+ 		     || GET_CODE (operands[1]) != CONST_INT)
+ 		    && ! easy_fp_constant (operands[1], mode))
+ 		   || (GET_CODE (operands[0]) == REG
+ 		       && FP_REGNO_P (REGNO (operands[0]))))
+	       && 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]));
+	  int special_constant_p = 0;
 
-      /* 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
@@ -1683,39 +1641,46 @@ rs6000_emit_move (dest, source, mode)
 	  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)
+	      && add_operand (XEXP (XEXP (operands[1], 0), 1), mode)
 	      && (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 sym = force_const_mem (mode, 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));
+	      sym = force_reg (mode, sym);
+	      if (mode == SImode)
+		emit_insn (gen_addsi3 (operands[0], sym, other));
+	      else
+		emit_insn (gen_adddi3 (operands[0], sym, other));
 	      return;
 	    }
 
-	  operands[1] = force_const_mem (DImode, operands[1]);
+	  operands[1] = force_const_mem (mode, 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))))
+	      && CONSTANT_POOL_EXPR_P (XEXP (operands[1], 0)))
 	    {
-	      operands[1] = gen_rtx_MEM (DImode,
-					 create_TOC_reference (XEXP (operands[1], 0)));
+	      rtx constant;
+	      enum machine_mode cmode;
+
+	      constant = get_pool_constant (XEXP (operands[1], 0));
+	      cmode = get_pool_mode (XEXP (operands[1], 0));
+	      special_constant_p = 
+		ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (constant, cmode);
+	    }
 
+	  if (special_constant_p)
+	    {
+	      operands[1] = gen_rtx_MEM (mode,
+					 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
@@ -1734,6 +1699,15 @@ rs6000_emit_move (dest, source, mode)
       abort ();
     }
 
+  /* Above, we may have called force_const_mem which may have returned
+     an invalid address.  If we can, fix this up; otherwise, reload will
+     have to deal with it.  */
+  if (GET_CODE (operands[1]) == MEM
+      && ! memory_address_p (mode, XEXP (operands[1], 0))
+      && ! reload_in_progress)
+    operands[1] = change_address (operands[1], mode,
+				  XEXP (operands[1], 0));
+
   emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
 }
 
@@ -6309,6 +6299,7 @@ struct toc_hash_struct 
   /* `key' will satisfy CONSTANT_P; in fact, it will satisfy
      ASM_OUTPUT_SPECIAL_POOL_ENTRY_P.  */
   rtx key;
+  enum machine_mode key_mode;
   int labelno;
 };
 
@@ -6320,7 +6311,7 @@ static unsigned
 rs6000_hash_constant (k)
      rtx k;
 {
-  unsigned result = GET_CODE (k);
+  unsigned result = (GET_CODE (k) << 3) ^ GET_MODE (k);
   const char *format = GET_RTX_FORMAT (GET_CODE (k));
   int flen = strlen (format);
   int fidx;
@@ -6377,8 +6368,9 @@ static unsigned
 toc_hash_function (hash_entry)
      const void * hash_entry;
 {
-  return rs6000_hash_constant (((const struct toc_hash_struct *) 
-				hash_entry)->key);
+  const struct toc_hash_struct *thc = 
+    (const struct toc_hash_struct *) hash_entry;
+  return rs6000_hash_constant (thc->key) ^ thc->key_mode;
 }
 
 /* Compare H1 and H2 for equivalence.  */
@@ -6391,6 +6383,10 @@ toc_hash_eq (h1, h2)
   rtx r1 = ((const struct toc_hash_struct *) h1)->key;
   rtx r2 = ((const struct toc_hash_struct *) h2)->key;
 
+  if (((const struct toc_hash_struct *) h1)->key_mode
+      != ((const struct toc_hash_struct *) h2)->key_mode)
+    return 0;
+
   /* Gotcha:  One of these const_doubles will be in memory.
      The other may be on the constant-pool chain.
      So rtx_equal_p will think they are different... */
@@ -6453,10 +6449,11 @@ toc_hash_mark_table (vht)
    being written.  */
 
 void
-output_toc (file, x, labelno)
+output_toc (file, x, labelno, mode)
      FILE *file;
      rtx x;
      int labelno;
+     enum machine_mode mode;
 {
   char buf[256];
   const char *name = buf;
@@ -6479,6 +6476,7 @@ output_toc (file, x, labelno)
       
       h = ggc_alloc (sizeof (*h));
       h->key = x;
+      h->key_mode = mode;
       h->labelno = labelno;
       
       found = htab_find_slot (toc_hash_table, h, 1);
@@ -6501,7 +6499,7 @@ output_toc (file, x, labelno)
      aligned properly when strict alignment is on.  */
   if (GET_CODE (x) == CONST_DOUBLE
       && STRICT_ALIGNMENT
-      && GET_MODE (x) == DFmode
+      && GET_MODE_BITSIZE (mode) >= 64
       && ! (TARGET_NO_FP_IN_TOC && ! TARGET_MINIMAL_TOC)) {
     ASM_OUTPUT_ALIGN (file, 3);
   }
@@ -6511,8 +6509,7 @@ output_toc (file, x, labelno)
   /* Handle FP constants specially.  Note that if we have a minimal
      TOC, things we put here aren't actually in the TOC, so we can allow
      FP constants.  */
-  if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == DFmode
-      && ! (TARGET_NO_FP_IN_TOC && ! TARGET_MINIMAL_TOC))
+  if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == DFmode)
     {
       REAL_VALUE_TYPE rv;
       long k[2];
@@ -6539,8 +6536,7 @@ output_toc (file, x, labelno)
 	  return;
 	}
     }
-  else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == SFmode
-	   && ! (TARGET_NO_FP_IN_TOC && ! TARGET_MINIMAL_TOC))
+  else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == SFmode)
     {
       REAL_VALUE_TYPE rv;
       long l;
@@ -6566,8 +6562,7 @@ output_toc (file, x, labelno)
 	}
     }
   else if (GET_MODE (x) == VOIDmode
-	   && (GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST_DOUBLE)
-	   && ! (TARGET_NO_FP_IN_TOC && ! TARGET_MINIMAL_TOC))
+	   && (GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST_DOUBLE))
     {
       HOST_WIDE_INT low;
       HOST_WIDE_INT high;
@@ -6590,6 +6585,18 @@ output_toc (file, x, labelno)
 	}
 #endif
 
+      /* TOC entries are always Pmode-sized, but since this
+	 is a bigendian machine then if we're putting smaller
+	 integer constants in the TOC we have to pad them.
+	 (This is still a win over putting the constants in
+	 a separate constant pool, because then we'd have
+	 to have both a TOC entry _and_ the actual constant.)  */
+      if (POINTER_SIZE < GET_MODE_BITSIZE (mode))
+	abort ();/* It would be easy to make this work, but it doesn't now.  */
+      if (mode != Pmode)
+	lshift_double (low, high, POINTER_SIZE - GET_MODE_BITSIZE (mode),
+		       POINTER_SIZE, &low, &high, 0);
+
       if (TARGET_64BIT)
 	{
 	  if (TARGET_MINIMAL_TOC)
@@ -7191,10 +7198,10 @@ rs6000_longcall_ref (call_ref)
 
 void
 rs6000_select_rtx_section (mode, x)
-     enum machine_mode mode ATTRIBUTE_UNUSED;
+     enum machine_mode mode;
      rtx x;
 {
-  if (ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (x))
+  if (ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (x, mode))
     toc_section ();
   else
     const_section ();
@@ -7219,7 +7226,7 @@ rs6000_select_section (decl, reloc)
       else
 	data_section ();
     }
-  else if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == CONSTRUCTOR)
+  else if (TREE_CODE (decl) == VAR_DECL)
     {
       if ((flag_pic && reloc)
 	  || ! TREE_READONLY (decl)
Index: config/rs6000/rs6000.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/rs6000/rs6000.h,v
retrieving revision 1.85
diff -p -u -u -p -r1.85 rs6000.h
--- config/rs6000/rs6000.h	2000/06/27 02:26:23	1.85
+++ config/rs6000/rs6000.h	2000/07/18 16:06:42
@@ -1920,55 +1934,55 @@ typedef struct rs6000_args
    register by splitting the addend across an addiu/addis and the mem insn.
    This cuts number of extra insns needed from 3 to 1.  */
    
-#define LEGITIMIZE_RELOAD_ADDRESS(X,MODE,OPNUM,TYPE,IND_LEVELS,WIN)     \
-do {                                                                    \
-  /* We must recognize output that we have already generated ourselves.  */ \
-  if (GET_CODE (X) == PLUS						\
-      && GET_CODE (XEXP (X, 0)) == PLUS					\
-      && GET_CODE (XEXP (XEXP (X, 0), 0)) == REG			\
-      && GET_CODE (XEXP (XEXP (X, 0), 1)) == CONST_INT			\
-      && GET_CODE (XEXP (X, 1)) == CONST_INT)				\
-    {									\
-      push_reload (XEXP (X, 0), NULL_RTX, &XEXP (X, 0), NULL_PTR,       \
-                   BASE_REG_CLASS, GET_MODE (X), VOIDmode, 0, 0,        \
-                   OPNUM, TYPE);                                        \
-      goto WIN;                                                         \
-    }									\
-  if (GET_CODE (X) == PLUS                                              \
-      && GET_CODE (XEXP (X, 0)) == REG                                  \
-      && REGNO (XEXP (X, 0)) < FIRST_PSEUDO_REGISTER                    \
-      && REG_MODE_OK_FOR_BASE_P (XEXP (X, 0), MODE)                     \
-      && GET_CODE (XEXP (X, 1)) == CONST_INT)                           \
-    {                                                                   \
-      HOST_WIDE_INT val = INTVAL (XEXP (X, 1));                         \
-      HOST_WIDE_INT low = ((val & 0xffff) ^ 0x8000) - 0x8000;           \
-      unsigned HOST_WIDE_INT high                                       \
-        = (((val - low) & 0xffffffffu) ^ 0x80000000u) - 0x80000000u;    \
-                                                                        \
-      /* Check for 32-bit overflow.  */                                 \
-      if (high + low != val)                                            \
-        break;                                                          \
-                                                                        \
-      /* Reload the high part into a base reg; leave the low part       \
-         in the mem directly.  */                                       \
-                                                                        \
-      X = gen_rtx_PLUS (GET_MODE (X),                                   \
-                        gen_rtx_PLUS (GET_MODE (X), XEXP (X, 0),        \
-                                      GEN_INT (high)),                  \
-                        GEN_INT (low));                                 \
-                                                                        \
-      push_reload (XEXP (X, 0), NULL_RTX, &XEXP (X, 0), NULL_PTR,       \
-                   BASE_REG_CLASS, GET_MODE (X), VOIDmode, 0, 0,        \
-                   OPNUM, TYPE);                                        \
-      goto WIN;                                                         \
-    }                                                                   \
-  else if (TARGET_TOC 							\
-	   && CONSTANT_POOL_EXPR_P (X)					\
-	   && ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (X)))	\
-    {									\
-      (X) = create_TOC_reference (X);					\
-      goto WIN;								\
-    }									\
+#define LEGITIMIZE_RELOAD_ADDRESS(X,MODE,OPNUM,TYPE,IND_LEVELS,WIN)	     \
+do {									     \
+  /* We must recognize output that we have already generated ourselves.  */  \
+  if (GET_CODE (X) == PLUS						     \
+      && GET_CODE (XEXP (X, 0)) == PLUS					     \
+      && GET_CODE (XEXP (XEXP (X, 0), 0)) == REG			     \
+      && GET_CODE (XEXP (XEXP (X, 0), 1)) == CONST_INT			     \
+      && GET_CODE (XEXP (X, 1)) == CONST_INT)				     \
+    {									     \
+      push_reload (XEXP (X, 0), NULL_RTX, &XEXP (X, 0), NULL_PTR,	     \
+                   BASE_REG_CLASS, GET_MODE (X), VOIDmode, 0, 0,	     \
+                   OPNUM, TYPE);					     \
+      goto WIN;								     \
+    }									     \
+  if (GET_CODE (X) == PLUS						     \
+      && GET_CODE (XEXP (X, 0)) == REG					     \
+      && REGNO (XEXP (X, 0)) < FIRST_PSEUDO_REGISTER			     \
+      && REG_MODE_OK_FOR_BASE_P (XEXP (X, 0), MODE)			     \
+      && GET_CODE (XEXP (X, 1)) == CONST_INT)				     \
+    {									     \
+      HOST_WIDE_INT val = INTVAL (XEXP (X, 1));				     \
+      HOST_WIDE_INT low = ((val & 0xffff) ^ 0x8000) - 0x8000;		     \
+      HOST_WIDE_INT high						     \
+        = (((val - low) & 0xffffffffu) ^ 0x80000000u) - 0x80000000u;	     \
+									     \
+      /* Check for 32-bit overflow.  */					     \
+      if (high + low != val)						     \
+        break;								     \
+									     \
+      /* Reload the high part into a base reg; leave the low part	     \
+         in the mem directly.  */					     \
+									     \
+      X = gen_rtx_PLUS (GET_MODE (X),					     \
+                        gen_rtx_PLUS (GET_MODE (X), XEXP (X, 0),	     \
+                                      GEN_INT (high)),			     \
+                        GEN_INT (low));					     \
+									     \
+      push_reload (XEXP (X, 0), NULL_RTX, &XEXP (X, 0), NULL_PTR,	     \
+                   BASE_REG_CLASS, GET_MODE (X), VOIDmode, 0, 0,	     \
+                   OPNUM, TYPE);					     \
+      goto WIN;								     \
+    }									     \
+  else if (TARGET_TOC							     \
+	   && CONSTANT_POOL_EXPR_P (X)					     \
+	   && ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (X), MODE)) \
+    {									     \
+      (X) = create_TOC_reference (X);					     \
+      goto WIN;								     \
+    }									     \
 } while (0)
 
 /* Go to LABEL if ADDR (a legitimate address expression)
@@ -2345,39 +2359,41 @@ extern int rs6000_trunc_used;
 /* Flag to say the TOC is initialized */
 extern int toc_initialized;
 
-/* Return non-zero if this entry is to be written into the constant pool
-   in a special way.  We do so if this is a SYMBOL_REF, LABEL_REF or a CONST
-   containing one of them.  If -mfp-in-toc (the default), we also do
-   this for floating-point constants.  We actually can only do this
-   if the FP formats of the target and host machines are the same, but
-   we can't check that since not every file that uses
-   GO_IF_LEGITIMATE_ADDRESS_P includes real.h.  */
+/* Return non-zero if this entry is to be written into the constant
+   pool in a special way.  We do so if this is a SYMBOL_REF, LABEL_REF
+   or a CONST containing one of them.  If -mfp-in-toc (the default),
+   we also do this for floating-point constants.  We actually can only
+   do this if the FP formats of the target and host machines are the
+   same, but we can't check that since not every file that uses
+   GO_IF_LEGITIMATE_ADDRESS_P includes real.h.  We also do this when
+   we can write the entry into the TOC and the entry is not larger
+   than a TOC entry.  */
 
-#define ASM_OUTPUT_SPECIAL_POOL_ENTRY_P(X)				\
+#define ASM_OUTPUT_SPECIAL_POOL_ENTRY_P(X, MODE)			\
   (TARGET_TOC								\
    && (GET_CODE (X) == SYMBOL_REF					\
        || (GET_CODE (X) == CONST && GET_CODE (XEXP (X, 0)) == PLUS	\
 	   && GET_CODE (XEXP (XEXP (X, 0), 0)) == SYMBOL_REF)		\
        || GET_CODE (X) == LABEL_REF					\
-       || (! (TARGET_NO_FP_IN_TOC && ! TARGET_MINIMAL_TOC)		\
-	   && GET_CODE (X) == CONST_DOUBLE				\
-	   && (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT		\
-	       || TARGET_POWERPC64))))
-#if 0
-	   && BITS_PER_WORD == HOST_BITS_PER_INT)))
-#endif
+       || (GET_CODE (X) == CONST_INT 					\
+	   && GET_MODE_BITSIZE (MODE) <= GET_MODE_BITSIZE (Pmode))	\
+       || (GET_CODE (X) == CONST_DOUBLE					\
+	   && (TARGET_POWERPC64						\
+	       || TARGET_MINIMAL_TOC					\
+	       || (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT		\
+		   && ! TARGET_NO_FP_IN_TOC)))))
 
 /* Macro to output a special constant pool entry.  Go to WIN if we output
    it.  Otherwise, it is written the usual way.
 
    On the RS/6000, toc entries are handled this way.  */
 
-#define ASM_OUTPUT_SPECIAL_POOL_ENTRY(FILE, X, MODE, ALIGN, LABELNO, WIN)  \
-{ if (ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (X))	\
-    {						\
-      output_toc (FILE, X, LABELNO);		\
-      goto WIN;					\
-    }						\
+#define ASM_OUTPUT_SPECIAL_POOL_ENTRY(FILE, X, MODE, ALIGN, LABELNO, WIN) \
+{ if (ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (X, MODE))			  \
+    {									  \
+      output_toc (FILE, X, LABELNO, MODE);				  \
+      goto WIN;								  \
+    }									  \
 }
 
 /* This is how we tell the assembler that two symbols have the same value.  */
Index: config/rs6000/sysv4.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/rs6000/sysv4.h,v
retrieving revision 1.31
diff -p -u -u -p -r1.31 sysv4.h
--- config/rs6000/sysv4.h	2000/06/27 02:26:23	1.31
+++ config/rs6000/sysv4.h	2000/07/18 16:06:47
@@ -563,12 +563,14 @@ fini_section ()								\
    allow floating point constants in the TOC if -mrelocatable.  */
 
 #undef	ASM_OUTPUT_SPECIAL_POOL_ENTRY_P
-#define	ASM_OUTPUT_SPECIAL_POOL_ENTRY_P(X)				\
+#define	ASM_OUTPUT_SPECIAL_POOL_ENTRY_P(X, MODE)			\
   (TARGET_TOC								\
    && (GET_CODE (X) == SYMBOL_REF					\
        || (GET_CODE (X) == CONST && GET_CODE (XEXP (X, 0)) == PLUS	\
 	   && GET_CODE (XEXP (XEXP (X, 0), 0)) == SYMBOL_REF)		\
        || GET_CODE (X) == LABEL_REF					\
+       || (GET_CODE (X) == CONST_INT 					\
+	   && GET_MODE_BITSIZE (MODE) <= GET_MODE_BITSIZE (Pmode))	\
        || (!TARGET_NO_FP_IN_TOC						\
 	   && !TARGET_RELOCATABLE					\
 	   && GET_CODE (X) == CONST_DOUBLE				\
============================================================

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