> I tried to figure out why things had been done in this
> slightly convoluted manner and failed.  It seems to me that
> this is easily represented with the individual instructions.
> A comment indicated that there had been problems with the
> copy to %o7 being deleted.  Elsewhere we have successfully
> used a naked USE pattern to keep such things from being
> deleted.

I have 4 regressions in the C testsuite with -mflat on SPARC/Solaris:

FAIL: gcc.c-torture/execute/builtins/stpcpy-chk.c execution,  -O2 -flto
FAIL: gcc.c-torture/execute/nestfunc-4.c execution,  -Os
FAIL: gcc.c-torture/execute/pr19005.c execution,  -O2
FAIL: gcc.c-torture/execute/strncmp-1.c execution,  -O2 -flt

The problem is that the blockage isn't emitted if the frame pointer isn't used.
I have also fixed the swapping %o7/%i7 (despite the name, %o7 is the incoming 
return address register from GCC's viewpoint, and %i7 the register where you 
save the return address for the rest of the function).

Tested on SPARC/Solaris, applied on the mainline.


2011-06-26  Eric Botcazou  <ebotca...@adacore.com>

        * config/sparc/sparc.c (save_local_or_in_reg_p): Adjust comment.
        (emit_save_register_window): Likewise.
        (sparc_expand_prologue): Use SIZE_INT_RTX and SIZE_RTX variables.
        (sparc_flat_expand_prologue): Add comment.  Always emit blockage.
        Swap back %o7/%i7 in register naming.


-- 
Eric Botcazou
Index: config/sparc/sparc.c
===================================================================
--- config/sparc/sparc.c	(revision 175398)
+++ config/sparc/sparc.c	(working copy)
@@ -4149,7 +4149,7 @@ save_local_or_in_reg_p (unsigned int reg
   if (regno == RETURN_ADDR_REGNUM && return_addr_reg_needed_p (leaf_function))
     return true;
 
-  /* PIC register (%l7) if needed.  */
+  /* GOT register (%l7) if needed.  */
   if (regno == PIC_OFFSET_TABLE_REGNUM && crtl->uses_pic_offset_table)
     return true;
 
@@ -4600,11 +4600,12 @@ emit_save_register_window (rtx increment
   insn = emit_insn (gen_save_register_window_1 (increment));
   RTX_FRAME_RELATED_P (insn) = 1;
 
-  /* The return address (%i7) is saved in %o7.  */
+  /* The incoming return address (%o7) is saved in %i7.  */
   add_reg_note (insn, REG_CFA_REGISTER,
 		gen_rtx_SET (VOIDmode,
 			     gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM),
-			     gen_rtx_REG (Pmode, INCOMING_RETURN_ADDR_REGNUM)));
+			     gen_rtx_REG (Pmode,
+					  INCOMING_RETURN_ADDR_REGNUM)));
 
   /* The window save event.  */
   add_reg_note (insn, REG_CFA_WINDOW_SAVE, const0_rtx);
@@ -4688,8 +4689,10 @@ sparc_expand_prologue (void)
     ; /* do nothing.  */
   else if (sparc_leaf_function_p)
     {
+      rtx size_int_rtx = GEN_INT (-size);
+
       if (size <= 4096)
-	insn = emit_insn (gen_stack_pointer_inc (GEN_INT (-size)));
+	insn = emit_insn (gen_stack_pointer_inc (size_int_rtx));
       else if (size <= 8192)
 	{
 	  insn = emit_insn (gen_stack_pointer_inc (GEN_INT (-4096)));
@@ -4699,19 +4702,21 @@ sparc_expand_prologue (void)
 	}
       else
 	{
-	  rtx reg = gen_rtx_REG (Pmode, 1);
-	  emit_move_insn (reg, GEN_INT (-size));
-	  insn = emit_insn (gen_stack_pointer_inc (reg));
+	  rtx size_rtx = gen_rtx_REG (Pmode, 1);
+	  emit_move_insn (size_rtx, size_int_rtx);
+	  insn = emit_insn (gen_stack_pointer_inc (size_rtx));
 	  add_reg_note (insn, REG_FRAME_RELATED_EXPR,
-			gen_stack_pointer_inc (GEN_INT (-size)));
+			gen_stack_pointer_inc (size_int_rtx));
 	}
 
       RTX_FRAME_RELATED_P (insn) = 1;
     }
   else
     {
+      rtx size_int_rtx = GEN_INT (-size);
+
       if (size <= 4096)
-	emit_save_register_window (GEN_INT (-size));
+	emit_save_register_window (size_int_rtx);
       else if (size <= 8192)
 	{
 	  emit_save_register_window (GEN_INT (-4096));
@@ -4720,9 +4725,9 @@ sparc_expand_prologue (void)
 	}
       else
 	{
-	  rtx reg = gen_rtx_REG (Pmode, 1);
-	  emit_move_insn (reg, GEN_INT (-size));
-	  emit_save_register_window (reg);
+	  rtx size_rtx = gen_rtx_REG (Pmode, 1);
+	  emit_move_insn (size_rtx, size_int_rtx);
+	  emit_save_register_window (size_rtx);
 	}
     }
 
@@ -4783,6 +4788,10 @@ sparc_flat_expand_prologue (void)
 
       size_rtx = size_int_rtx = GEN_INT (-size);
 
+      /* We establish the frame (i.e. decrement the stack pointer) first, even
+	 if we use a frame pointer, because we cannot clobber any call-saved
+	 registers, including the frame pointer, if we haven't created a new
+	 register save area, for the sake of compatibility with the ABI.  */
       if (size <= 4096)
 	insn = emit_insn (gen_stack_pointer_inc (size_int_rtx));
       else if (size <= 8192 && !frame_pointer_needed)
@@ -4801,6 +4810,9 @@ sparc_flat_expand_prologue (void)
 	}
       RTX_FRAME_RELATED_P (insn) = 1;
 
+      /* Ensure nothing is scheduled until after the frame is established.  */
+      emit_insn (gen_blockage ());
+
       if (frame_pointer_needed)
 	{
 	  insn = emit_insn (gen_rtx_SET (VOIDmode, hard_frame_pointer_rtx,
@@ -4813,26 +4825,22 @@ sparc_flat_expand_prologue (void)
 			gen_rtx_SET (VOIDmode, hard_frame_pointer_rtx,
 				     plus_constant (stack_pointer_rtx,
 						    size)));
-
-	  /* Make sure nothing is scheduled until after the frame
-	     is established.  */
-	  emit_insn (gen_blockage ());
 	}
 
       if (return_addr_reg_needed_p (sparc_leaf_function_p))
 	{
-	  rtx i7 = gen_rtx_REG (Pmode, INCOMING_RETURN_ADDR_REGNUM);
-	  rtx o7 = gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM);
+	  rtx o7 = gen_rtx_REG (Pmode, INCOMING_RETURN_ADDR_REGNUM);
+	  rtx i7 = gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM);
 
-	  insn = emit_move_insn (o7, i7);
+	  insn = emit_move_insn (i7, o7);
 	  RTX_FRAME_RELATED_P (insn) = 1;
 
 	  add_reg_note (insn, REG_CFA_REGISTER,
-			gen_rtx_SET (VOIDmode, o7, i7));
+			gen_rtx_SET (VOIDmode, i7, o7));
 
 	  /* Prevent this instruction from ever being considered dead,
 	     even if this function has no epilogue.  */
-	  emit_insn (gen_rtx_USE (VOIDmode, o7));
+	  emit_insn (gen_rtx_USE (VOIDmode, i7));
 	}
     }
 

Reply via email to