diff mbox

Fix PR target/46685

Message ID 201012022332.58316.ebotcazou@adacore.com
State New
Headers show

Commit Message

Eric Botcazou Dec. 2, 2010, 10:32 p.m. UTC
This fixes the recently introduced stack alignment failures with -fpic, on the 
SPARC side only.  The PA side will need another fix.  This is mostly Jakub's 
work, with an additional patchlet for sparc_file_end.

Tested on SPARC/Solaris and SPARC/Linux, applied on the mainline.


2010-11-02  Eric Botcazou  <ebotcazou@adacore.com>

	PR target/46685
	* config/sparc/sparc.c (can_use_mov_pic_label_ref): New predicate.
	(sparc_expand_move): Call it to decide whether to emit the special
	mov{si,di}_pic_label_ref patterns.
	(sparc_legitimize_pic_address): Call it to decide whether to emit
	the regular PIC sequence for labels.  Fix long line.
	(sparc_file_end): Set is_thunk for the PIC helper.


2010-11-02  Eric Botcazou  <ebotcazou@adacore.com>

	* gcc.dg/pr46685.c: New test.
diff mbox

Patch

Index: config/sparc/sparc.c
===================================================================
--- config/sparc/sparc.c	(revision 167352)
+++ config/sparc/sparc.c	(working copy)
@@ -1025,6 +1025,36 @@  fp_high_losum_p (rtx op)
   return 0;
 }
 
+/* Return true if the address of LABEL can be loaded by means of the
+   mov{si,di}_pic_label_ref patterns in PIC mode.  */
+
+static bool
+can_use_mov_pic_label_ref (rtx label)
+{
+  /* VxWorks does not impose a fixed gap between segments; the run-time
+     gap can be different from the object-file gap.  We therefore can't
+     assume X - _GLOBAL_OFFSET_TABLE_ is a link-time constant unless we
+     are absolutely sure that X is in the same segment as the GOT.
+     Unfortunately, the flexibility of linker scripts means that we
+     can't be sure of that in general, so assume that GOT-relative
+     accesses are never valid on VxWorks.  */
+  if (TARGET_VXWORKS_RTP)
+    return false;
+
+  /* Similarly, if the label is non-local, it might end up being placed
+     in a different section than the current one; now mov_pic_label_ref
+     requires the label and the code to be in the same section.  */
+  if (LABEL_REF_NONLOCAL_P (label))
+    return false;
+
+  /* Finally, if we are reordering basic blocks and partition into hot
+     and cold sections, this might happen for any label.  */
+  if (flag_reorder_blocks_and_partition)
+    return false;
+
+  return true;
+}
+
 /* Expand a move instruction.  Return true if all work is done.  */
 
 bool
@@ -1059,14 +1089,9 @@  sparc_expand_move (enum machine_mode mod
       if (pic_address_needs_scratch (operands[1]))
 	operands[1] = sparc_legitimize_pic_address (operands[1], NULL_RTX);
 
-      /* VxWorks does not impose a fixed gap between segments; the run-time
-	 gap can be different from the object-file gap.  We therefore can't
-	 assume X - _GLOBAL_OFFSET_TABLE_ is a link-time constant unless we
-	 are absolutely sure that X is in the same segment as the GOT.
-	 Unfortunately, the flexibility of linker scripts means that we
-	 can't be sure of that in general, so assume that _G_O_T_-relative
-	 accesses are never valid on VxWorks.  */
-      if (GET_CODE (operands[1]) == LABEL_REF && !TARGET_VXWORKS_RTP)
+      /* We cannot use the mov{si,di}_pic_label_ref patterns in all cases.  */
+      if (GET_CODE (operands[1]) == LABEL_REF
+	  && can_use_mov_pic_label_ref (operands[1]))
 	{
 	  if (mode == SImode)
 	    {
@@ -3425,7 +3450,7 @@  sparc_legitimize_pic_address (rtx orig,
 
   if (GET_CODE (orig) == SYMBOL_REF
       /* See the comment in sparc_expand_move.  */
-      || (TARGET_VXWORKS_RTP && GET_CODE (orig) == LABEL_REF))
+      || (GET_CODE (orig) == LABEL_REF && !can_use_mov_pic_label_ref (orig)))
     {
       rtx pic_ref, address;
       rtx insn;
@@ -3478,11 +3503,13 @@  sparc_legitimize_pic_address (rtx orig,
 	}
       else
 	{
-	  pic_ref = gen_const_mem (Pmode,
-				   gen_rtx_PLUS (Pmode,
-						 pic_offset_table_rtx, address));
+	  pic_ref
+	    = gen_const_mem (Pmode,
+			     gen_rtx_PLUS (Pmode,
+					   pic_offset_table_rtx, address));
 	  insn = emit_move_insn (reg, pic_ref);
 	}
+
       /* Put a REG_EQUAL note on this insn, so that it can be optimized
 	 by loop.  */
       set_unique_reg_note (insn, REG_EQUAL, orig);
@@ -3520,9 +3547,8 @@  sparc_legitimize_pic_address (rtx orig,
       return gen_rtx_PLUS (Pmode, base, offset);
     }
   else if (GET_CODE (orig) == LABEL_REF)
-    /* ??? Why do we do this?  */
-    /* Now movsi_pic_label_ref uses it, but we ought to be checking that
-       the register is live instead, in case it is eliminated.  */
+    /* ??? We ought to be checking that the register is live instead, in case
+       it is eliminated.  */
     crtl->uses_pic_offset_table = 1;
 
   return orig;
@@ -9453,6 +9479,7 @@  sparc_file_end (void)
 	  DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
 	  DECL_VISIBILITY_SPECIFIED (decl) = 1;
 	  allocate_struct_function (decl, true);
+	  cfun->is_thunk = 1;
 	  current_function_decl = decl;
 	  init_varasm_status ();
 	  assemble_start_function (decl, name);