diff mbox

[RS6000] -mfp-in-toc

Message ID 20130606234000.GG6878@bubble.grove.modra.org
State New
Headers show

Commit Message

Alan Modra June 6, 2013, 11:40 p.m. UTC
On Tue, Jun 04, 2013 at 11:45:12PM +0930, Alan Modra wrote:
> This patch allows the user to specify -mfp-in-toc/-msum-in-toc options
> without being overridden when -fsection-anchors or -mcmodel != small
> is in effect.  I also change the default to -mno-fp-in-toc for
> -mcmodel=medium, because -mcmodel=medium ought to be able to address
> constants anywhere from the toc pointer, and putting them in their
> usual constant sections (.rodata.cst4 and .rodata.cst8) allow them to
> be merged at link time.  For -mcmodel=large we keep the default as
> -mfp-in-toc because large code model requires a toc entry to address
> any constant outside the TOC.
> 
> The patch also allows -mcmodel=medium toc relative addressing for
> CONSTANT_POOL_ADDRESS_P constants (the very sort we get from
> force_const_mem when -mno-fp-in-toc), and allows combine to merge the
> low-part of the address calculation with the load/store from memory.
> I'm not sure now why I had this disabled, perhaps there was a problem
> when we split toc refs early.  Bootstrapped and regression tested
> powerpc64-linux.  OK to apply?

Revised patch.  This one doesn't blindly trust CONSTANT_POOL_ADDRESS_P
constants are always sufficiently aligned.  There are modes where
alignment is less than size, CQI, CHI, CSI, CDI, CTI, SC, DC, TC, so
it might be the case that the imaginary part of a complex constant
crossed a 32k boundary.

I've also changed offsettable_ok_by_alignment to only check that the
particular access being considered doesn't cross a 32k boundary.
We'll only be offsetting within that access, so that is all that is
necessary.

	* config/rs6000/rs6000.c (rs6000_option_override_internal): Don't
	override user -mfp-in-toc.
	(offsettable_ok_by_alignment): Consider just the current access
	rather than the whole object, unless BLKmode.  Handle
	CONSTANT_POOL_ADDRESS_P constants that lack a decl too.
	(use_toc_relative_ref): Allow CONSTANT_POOL_ADDRESS_P constants
	for -mcmodel=medium.
	* config/rs6000/linux64.h (SUBSUBTARGET_OVERRIDE_OPTIONS): Don't
	override user -mfp-in-toc or -msum-in-toc.  Default to
	-mno-fp-in-toc for -mcmodel=medium.

Comments

David Edelsohn June 7, 2013, 1:16 a.m. UTC | #1
On Thu, Jun 6, 2013 at 7:40 PM, Alan Modra <amodra@gmail.com> wrote:
> On Tue, Jun 04, 2013 at 11:45:12PM +0930, Alan Modra wrote:
>> This patch allows the user to specify -mfp-in-toc/-msum-in-toc options
>> without being overridden when -fsection-anchors or -mcmodel != small
>> is in effect.  I also change the default to -mno-fp-in-toc for
>> -mcmodel=medium, because -mcmodel=medium ought to be able to address
>> constants anywhere from the toc pointer, and putting them in their
>> usual constant sections (.rodata.cst4 and .rodata.cst8) allow them to
>> be merged at link time.  For -mcmodel=large we keep the default as
>> -mfp-in-toc because large code model requires a toc entry to address
>> any constant outside the TOC.
>>
>> The patch also allows -mcmodel=medium toc relative addressing for
>> CONSTANT_POOL_ADDRESS_P constants (the very sort we get from
>> force_const_mem when -mno-fp-in-toc), and allows combine to merge the
>> low-part of the address calculation with the load/store from memory.
>> I'm not sure now why I had this disabled, perhaps there was a problem
>> when we split toc refs early.  Bootstrapped and regression tested
>> powerpc64-linux.  OK to apply?
>
> Revised patch.  This one doesn't blindly trust CONSTANT_POOL_ADDRESS_P
> constants are always sufficiently aligned.  There are modes where
> alignment is less than size, CQI, CHI, CSI, CDI, CTI, SC, DC, TC, so
> it might be the case that the imaginary part of a complex constant
> crossed a 32k boundary.
>
> I've also changed offsettable_ok_by_alignment to only check that the
> particular access being considered doesn't cross a 32k boundary.
> We'll only be offsetting within that access, so that is all that is
> necessary.
>
>         * config/rs6000/rs6000.c (rs6000_option_override_internal): Don't
>         override user -mfp-in-toc.
>         (offsettable_ok_by_alignment): Consider just the current access
>         rather than the whole object, unless BLKmode.  Handle
>         CONSTANT_POOL_ADDRESS_P constants that lack a decl too.
>         (use_toc_relative_ref): Allow CONSTANT_POOL_ADDRESS_P constants
>         for -mcmodel=medium.
>         * config/rs6000/linux64.h (SUBSUBTARGET_OVERRIDE_OPTIONS): Don't
>         override user -mfp-in-toc or -msum-in-toc.  Default to
>         -mno-fp-in-toc for -mcmodel=medium.

Okay.

It would have been helpful for reviewing the patch to submit the patch
in two stages that separate the re-organization of the code from the
modifications to the alignment test.

Thanks, David
diff mbox

Patch

Index: gcc/config/rs6000/linux64.h
===================================================================
--- gcc/config/rs6000/linux64.h	(revision 199718)
+++ gcc/config/rs6000/linux64.h	(working copy)
@@ -136,8 +136,11 @@  extern int dot_symbols;
 		SET_CMODEL (CMODEL_MEDIUM);			\
 	      if (rs6000_current_cmodel != CMODEL_SMALL)	\
 		{						\
-		  TARGET_NO_FP_IN_TOC = 0;			\
-		  TARGET_NO_SUM_IN_TOC = 0;			\
+		  if (!global_options_set.x_TARGET_NO_FP_IN_TOC) \
+		    TARGET_NO_FP_IN_TOC				\
+		      = rs6000_current_cmodel == CMODEL_MEDIUM;	\
+		  if (!global_options_set.x_TARGET_NO_SUM_IN_TOC) \
+		    TARGET_NO_SUM_IN_TOC = 0;			\
 		}						\
 	    }							\
 	}							\
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(revision 199718)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -3042,7 +3042,8 @@  rs6000_option_override_internal (bool global_init_
 
   /* Place FP constants in the constant pool instead of TOC
      if section anchors enabled.  */
-  if (flag_section_anchors)
+  if (flag_section_anchors
+      && !global_options_set.x_TARGET_NO_FP_IN_TOC)
     TARGET_NO_FP_IN_TOC = 1;
 
   if (TARGET_DEBUG_REG || TARGET_DEBUG_TARGET)
@@ -5474,91 +5475,102 @@  virtual_stack_registers_memory_p (rtx op)
 	  && regnum <= LAST_VIRTUAL_POINTER_REGISTER);
 }
 
-/* Return true if memory accesses to OP are known to never straddle
-   a 32k boundary.  */
+/* Return true if a MODE sized memory accesses to OP plus OFFSET
+   is known to not straddle a 32k boundary.  */
 
 static bool
 offsettable_ok_by_alignment (rtx op, HOST_WIDE_INT offset,
 			     enum machine_mode mode)
 {
   tree decl, type;
-  unsigned HOST_WIDE_INT dsize, dalign;
+  unsigned HOST_WIDE_INT dsize, dalign, lsb, mask;
 
   if (GET_CODE (op) != SYMBOL_REF)
     return false;
 
+  dsize = GET_MODE_SIZE (mode);
   decl = SYMBOL_REF_DECL (op);
   if (!decl)
     {
-      if (GET_MODE_SIZE (mode) == 0)
+      if (dsize == 0)
 	return false;
 
       /* -fsection-anchors loses the original SYMBOL_REF_DECL when
 	 replacing memory addresses with an anchor plus offset.  We
 	 could find the decl by rummaging around in the block->objects
 	 VEC for the given offset but that seems like too much work.  */
-      dalign = 1;
+      dalign = BITS_PER_UNIT;
       if (SYMBOL_REF_HAS_BLOCK_INFO_P (op)
 	  && SYMBOL_REF_ANCHOR_P (op)
 	  && SYMBOL_REF_BLOCK (op) != NULL)
 	{
 	  struct object_block *block = SYMBOL_REF_BLOCK (op);
-	  HOST_WIDE_INT lsb, mask;
 
-	  /* Given the alignment of the block..  */
 	  dalign = block->alignment;
-	  mask = dalign / BITS_PER_UNIT - 1;
-
-	  /* ..and the combined offset of the anchor and any offset
-	     to this block object..  */
 	  offset += SYMBOL_REF_BLOCK_OFFSET (op);
-	  lsb = offset & -offset;
+	}
+      else if (CONSTANT_POOL_ADDRESS_P (op))
+	{
+	  /* It would be nice to have get_pool_align()..  */
+	  enum machine_mode cmode = get_pool_mode (op);
 
-	  /* ..find how many bits of the alignment we know for the
-	     object.  */
-	  mask &= lsb - 1;
-	  dalign = mask + 1;
+	  dalign = GET_MODE_ALIGNMENT (cmode);
 	}
-      return dalign >= GET_MODE_SIZE (mode);
     }
-
-  if (DECL_P (decl))
+  else if (DECL_P (decl))
     {
-      if (TREE_CODE (decl) == FUNCTION_DECL)
-	return true;
+      dalign = DECL_ALIGN (decl);
 
-      if (!DECL_SIZE_UNIT (decl))
-	return false;
+      if (dsize == 0)
+	{
+	  /* Allow BLKmode when the entire object is known to not
+	     cross a 32k boundary.  */
+	  if (!DECL_SIZE_UNIT (decl))
+	    return false;
 
-      if (!host_integerp (DECL_SIZE_UNIT (decl), 1))
-	return false;
+	  if (!host_integerp (DECL_SIZE_UNIT (decl), 1))
+	    return false;
 
-      dsize = tree_low_cst (DECL_SIZE_UNIT (decl), 1);
-      if (dsize > 32768)
-	return false;
+	  dsize = tree_low_cst (DECL_SIZE_UNIT (decl), 1);
+	  if (dsize > 32768)
+	    return false;
 
-      dalign = DECL_ALIGN_UNIT (decl);
-      return dalign >= dsize;
+	  return dalign / BITS_PER_UNIT >= dsize;
+	}
     }
+  else
+    {
+      type = TREE_TYPE (decl);
 
-  type = TREE_TYPE (decl);
+      dalign = TYPE_ALIGN (type);
+      if (CONSTANT_CLASS_P (decl))
+	dalign = CONSTANT_ALIGNMENT (decl, dalign);
+      else
+	dalign = DATA_ALIGNMENT (decl, dalign);
 
-  if (TREE_CODE (decl) == STRING_CST)
-    dsize = TREE_STRING_LENGTH (decl);
-  else if (TYPE_SIZE_UNIT (type)
-	   && host_integerp (TYPE_SIZE_UNIT (type), 1))
-    dsize = tree_low_cst (TYPE_SIZE_UNIT (type), 1);
-  else
-    return false;
-  if (dsize > 32768)
-    return false;
+      if (dsize == 0)
+	{
+	  /* BLKmode, check the entire object.  */
+	  if (TREE_CODE (decl) == STRING_CST)
+	    dsize = TREE_STRING_LENGTH (decl);
+	  else if (TYPE_SIZE_UNIT (type)
+		   && host_integerp (TYPE_SIZE_UNIT (type), 1))
+	    dsize = tree_low_cst (TYPE_SIZE_UNIT (type), 1);
+	  else
+	    return false;
+	  if (dsize > 32768)
+	    return false;
 
-  dalign = TYPE_ALIGN (type);
-  if (CONSTANT_CLASS_P (decl))
-    dalign = CONSTANT_ALIGNMENT (decl, dalign);
-  else
-    dalign = DATA_ALIGNMENT (decl, dalign);
-  dalign /= BITS_PER_UNIT;
+	  return dalign / BITS_PER_UNIT >= dsize;
+	}
+    }
+
+  /* Find how many bits of the alignment we know for this access.  */
+  mask = dalign / BITS_PER_UNIT - 1;
+  lsb = offset & -offset;
+  mask &= lsb - 1;
+  dalign = mask + 1;
+
   return dalign >= dsize;
 }
 
@@ -6504,7 +6516,6 @@  use_toc_relative_ref (rtx sym)
 	   && ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (sym),
 					       get_pool_mode (sym)))
 	  || (TARGET_CMODEL == CMODEL_MEDIUM
-	      && !CONSTANT_POOL_ADDRESS_P (sym)
 	      && SYMBOL_REF_LOCAL_P (sym)));
 }