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]
Other format: [Raw text]

[PATCH] First attempt at unwind epilogue support for s390{,x}


Hi!

So far only tested with a cross compiler.
The save_gprs changes are to avoid:
        stmg    %r6,%r15,48(%r15)
        lgr     %r14,%r15
        .cfi_offset 15, -40			<<<<< This line
        .cfi_offset 14, -48
        .cfi_offset 13, -56
        .cfi_offset 12, -64
        .cfi_offset 11, -72
        .cfi_offset 10, -80
        .cfi_offset 9, -88
        .cfi_offset 8, -96
        .cfi_offset 7, -104
        .cfi_offset 6, -112
As %r15 is the stack pointer (CFA is %r15 + (TARGET_64BIT ? 160 : 96)),
I believe having DW_CFA_offset/DW_CFA_restore for %r15 doesn't make sense,
the unwinders will restore %r15 from computing the CFA.  The rest is
to add epilogue unwind info.  Unfortunately, especially on 31-bit s390
current dwarf2out generates often unneeded
.cfi_remember_state/.cfi_restore_state.  Although that's just two
unnecessary bytes, it would be good to avoid that.  The reason for this is
the weird way how s390{,x} emits literal pool:
(jump_insn 125 124 126 aq.c:19 (parallel [
            (return)
            (use (reg:SI 4 %r4))
        ]) 570 {*return} (expr_list:REG_DEAD (reg:SI 4 %r4)
        (nil)))
(barrier 126 125 89)
(note 89 126 91 NOTE_INSN_DELETED)
(note 91 89 131 NOTE_INSN_DELETED)
(insn 131 91 132 (unspec_volatile [
            (const_int 4 [0x4])
        ] 202) -1 (nil))
(code_label 132 131 133 5 "" [0 uses])
(insn 133 132 134 (unspec_volatile:SI [
            (symbol_ref:SI ("bar3") [flags 0x41] <function_decl 0x7f826e315000 bar3>)
        ] 203) -1 (nil))
(code_label 134 133 135 4 "" [0 uses])
(insn 135 134 136 (unspec_volatile:SI [
            (symbol_ref:SI ("bar2") [flags 0x41] <function_decl 0x7f826e2fef00 bar2>)
        ] 203) -1 (nil))
(code_label 136 135 137 3 "" [0 uses])
(insn 137 136 138 (unspec_volatile:SI [
            (symbol_ref:SI ("bar") [flags 0x41] <function_decl 0x7f826e2fee00 bar>)
        ] 203) -1 (nil))
(insn 138 137 139 (unspec_volatile [
            (const_int 2 [0x2])
        ] 202) -1 (nil))
(barrier 139 138 0)

dwarf2out.c calls next_real_insn on the return insn (125 in this case)
to find out if there is some further basic block for which unwind info
needs to be provided and finds insn 131.  Can't s390 use some other rtx
for the literal pool stuff (e.g. NOTE)?  Or should dwarf2out.c search
for a label with non-0 uses and next_real_insn only after that?

2009-06-02  Jakub Jelinek  <jakub@redhat.com>

	* config/s390/s390.c (save_gprs): Don't tell unwinder when %r15
	is saved.
	(s390_emit_epilogue): Emit needed epilogue unwind info.

--- gcc/config/s390/s390.c.jj	2009-05-19 10:51:27.000000000 +0200
+++ gcc/config/s390/s390.c	2009-06-02 22:33:49.000000000 +0200
@@ -7447,7 +7447,8 @@ save_gprs (rtx base, int offset, int fir
       else
         insn = gen_movsi (addr, gen_rtx_REG (Pmode, first));
 
-      RTX_FRAME_RELATED_P (insn) = 1;
+      if (first != STACK_POINTER_REGNUM)
+	RTX_FRAME_RELATED_P (insn) = 1;
       return insn;
     }
 
@@ -7471,6 +7472,8 @@ save_gprs (rtx base, int offset, int fir
      However, we must not emit DWARF records for registers 2..5
      if they are stored for use by variable arguments ...
 
+     Don't emit DWARF records for 15 either, that's tracked as CFA.
+
      ??? Unfortunately, it is not enough to simply not the
      FRAME_RELATED flags for those SETs, because the first SET
      of the PARALLEL is always treated as if it had the flag
@@ -7482,7 +7485,8 @@ save_gprs (rtx base, int offset, int fir
       rtx pat = PATTERN (insn);
 
       for (i = 0; i < XVECLEN (pat, 0); i++)
-	if (GET_CODE (XVECEXP (pat, 0, i)) == SET)
+	if (GET_CODE (XVECEXP (pat, 0, i)) == SET
+	    && REGNO (SET_SRC (XVECEXP (pat, 0, i))) != STACK_POINTER_REGNUM)
 	  RTX_FRAME_RELATED_P (XVECEXP (pat, 0, i)) = 1;
 
       RTX_FRAME_RELATED_P (insn) = 1;
@@ -7492,7 +7496,8 @@ save_gprs (rtx base, int offset, int fir
       addr = plus_constant (base, offset + (6 - first) * UNITS_PER_WORD);
       note = gen_store_multiple (gen_rtx_MEM (Pmode, addr),
 				 gen_rtx_REG (Pmode, 6),
-				 GEN_INT (last - 6 + 1));
+				 GEN_INT (last - 6
+					  + (last != STACK_POINTER_REGNUM)));
       note = PATTERN (note);
 
       add_reg_note (insn, REG_FRAME_RELATED_EXPR, note);
@@ -7882,7 +7887,7 @@ s390_emit_prologue (void)
 void
 s390_emit_epilogue (bool sibcall)
 {
-  rtx frame_pointer, return_reg;
+  rtx frame_pointer, return_reg, cfa_restores = NULL_RTX;
   int area_bottom, area_top, offset = 0;
   int next_offset;
   rtvec p;
@@ -7924,11 +7929,13 @@ s390_emit_epilogue (bool sibcall)
     }
   else
     {
-      rtx insn, frame_off;
+      rtx insn, frame_off, cfa;
 
       offset = area_bottom < 0 ? -area_bottom : 0;
       frame_off = GEN_INT (cfun_frame_layout.frame_size - offset);
 
+      cfa = gen_rtx_SET (VOIDmode, frame_pointer,
+			 gen_rtx_PLUS (Pmode, frame_pointer, frame_off));
       if (DISP_IN_RANGE (INTVAL (frame_off)))
 	{
 	  insn = gen_rtx_SET (VOIDmode, frame_pointer,
@@ -7943,6 +7950,8 @@ s390_emit_epilogue (bool sibcall)
 	  insn = emit_insn (gen_add2_insn (frame_pointer, frame_off));
 	  annotate_constant_pool_refs (&PATTERN (insn));
 	}
+      add_reg_note (insn, REG_CFA_ADJUST_CFA, cfa);
+      RTX_FRAME_RELATED_P (insn) = 1;
     }
 
   /* Restore call saved fprs.  */
@@ -7958,6 +7967,9 @@ s390_emit_epilogue (bool sibcall)
 		{
 		  restore_fpr (frame_pointer,
 			       offset + next_offset, i);
+		  cfa_restores
+		    = alloc_reg_note (REG_CFA_RESTORE,
+				      gen_rtx_REG (DFmode, i), cfa_restores);
 		  next_offset += 8;
 		}
 	    }
@@ -7973,6 +7985,9 @@ s390_emit_epilogue (bool sibcall)
 	    {
 	      restore_fpr (frame_pointer,
 			   offset + next_offset, i);
+	      cfa_restores
+		= alloc_reg_note (REG_CFA_RESTORE,
+				  gen_rtx_REG (DFmode, i), cfa_restores);
 	      next_offset += 8;
 	    }
 	  else if (!TARGET_PACKED_STACK)
@@ -7999,6 +8014,11 @@ s390_emit_epilogue (bool sibcall)
 	   i <= cfun_frame_layout.last_restore_gpr;
 	   i++)
 	{
+	  if (i != STACK_POINTER_REGNUM)
+	    cfa_restores
+	      = alloc_reg_note (REG_CFA_RESTORE,
+				gen_rtx_REG (Pmode, i), cfa_restores);
+
 	  /* These registers are special and need to be
 	     restored in any case.  */
 	  if (i == STACK_POINTER_REGNUM
@@ -8051,7 +8071,11 @@ s390_emit_epilogue (bool sibcall)
 			   * UNITS_PER_WORD,
 			   cfun_frame_layout.first_restore_gpr,
 			   cfun_frame_layout.last_restore_gpr);
-      emit_insn (insn);
+      insn = emit_insn (insn);
+      REG_NOTES (insn) = cfa_restores;
+      add_reg_note (insn, REG_CFA_DEF_CFA,
+		    plus_constant (stack_pointer_rtx, STACK_POINTER_OFFSET));
+      RTX_FRAME_RELATED_P (insn) = 1;
     }
 
   if (! sibcall)

	Jakub


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