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]

optimize frame unwind data


The following reduces the size of frame unwind information by batching
register save data.  You don't absolutely have to describe a store
immediately, since the caller's data still exists in the register.  This
results in fewer pc advances.

When using gas (which re-codes .debug_frame/.eh_frame based on actual
instruction displacements), this doesn't turn out to help a whole lot.
I measure 2k savings in the resulting cc1.  But for other systems it
should be at least 6 times that.


r~



        * dwarf2out.c (queue_reg_save): New.
        (flush_queued_reg_saves, clobbers_queued_reg_save): New.
        (dwarf2out_frame_debug_expr): Call queue_reg_save instead of
        dwarf2out_reg_save.
        (dwarf2out_frame_debug): Call flush_queued_reg_saves when needed.
        (cfa, cfa_store, cfa_temp): Make static.
        * final.c (final_scan_insn): Always call dwarf2out_frame_debug.

Index: dwarf2out.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/dwarf2out.c,v
retrieving revision 1.254
diff -c -p -d -r1.254 dwarf2out.c
*** dwarf2out.c	2001/03/17 18:18:12	1.254
--- dwarf2out.c	2001/03/18 03:23:49
*************** static long stack_adjust_offset		PARAMS 
*** 241,246 ****
--- 241,249 ----
  static void output_cfi			PARAMS ((dw_cfi_ref, dw_fde_ref));
  static void output_call_frame_info	PARAMS ((int));
  static void dwarf2out_stack_adjust	PARAMS ((rtx));
+ static void queue_reg_save		PARAMS ((const char *, rtx, long));
+ static void flush_queued_reg_saves	PARAMS ((void));
+ static bool clobbers_queued_reg_save	PARAMS ((rtx));
  static void dwarf2out_frame_debug_expr	PARAMS ((rtx, const char *));
  
  /* Support for complex CFA locations.  */
*************** lookup_cfa (loc)
*** 594,604 ****
  }
  
  /* The current rule for calculating the DWARF2 canonical frame address.  */
! dw_cfa_location cfa;
  
  /* The register used for saving registers to the stack, and its offset
     from the CFA.  */
! dw_cfa_location cfa_store;
  
  /* The running total of the size of arguments pushed onto the stack.  */
  static long args_size;
--- 597,607 ----
  }
  
  /* The current rule for calculating the DWARF2 canonical frame address.  */
! static dw_cfa_location cfa;
  
  /* The register used for saving registers to the stack, and its offset
     from the CFA.  */
! static dw_cfa_location cfa_store;
  
  /* The running total of the size of arguments pushed onto the stack.  */
  static long args_size;
*************** dwarf2out_stack_adjust (insn)
*** 1020,1029 ****
    dwarf2out_args_size (label, args_size);
  }
  
  /* A temporary register holding an integral value used in adjusting SP
     or setting up the store_reg.  The "offset" field holds the integer
     value, not an offset.  */
! dw_cfa_location cfa_temp;
  
  /* Record call frame debugging information for an expression EXPR,
     which either sets SP or FP (adjusting how we calculate the frame
--- 1023,1092 ----
    dwarf2out_args_size (label, args_size);
  }
  
+ /* We delay emitting a register save until either (a) we reach the end
+    of the prologue or (b) the register is clobbered.  This clusters
+    register saves so that there are fewer pc advances.  */
+ 
+ struct queued_reg_save
+ {
+   struct queued_reg_save *next;
+   rtx reg;
+   long cfa_offset;
+ };
+ 
+ static struct queued_reg_save *queued_reg_saves;
+ static const char *last_reg_save_label;
+ 
+ static void
+ queue_reg_save (label, reg, offset)
+      const char *label;
+      rtx reg;
+      long offset;
+ {
+   struct queued_reg_save *q = (struct queued_reg_save *) xmalloc (sizeof (*q));
+ 
+   q->next = queued_reg_saves;
+   q->reg = reg;
+   q->cfa_offset = offset;
+   queued_reg_saves = q;
+ 
+   last_reg_save_label = label;
+ }
+ 
+ static void
+ flush_queued_reg_saves ()
+ {
+   struct queued_reg_save *q, *next;
+ 
+   for (q = queued_reg_saves; q ; q = next)
+     {
+       dwarf2out_reg_save (last_reg_save_label, REGNO (q->reg), q->cfa_offset);
+       next = q->next;
+       free (q);
+     }
+ 
+   queued_reg_saves = NULL;
+   last_reg_save_label = NULL;
+ }
+ 
+ static bool
+ clobbers_queued_reg_save (insn)
+      rtx insn;
+ {
+   struct queued_reg_save *q;
+ 
+   for (q = queued_reg_saves; q ; q = q->next)
+     if (modified_in_p (q->reg, insn))
+       return true;
+ 
+   return false;
+ }
+   
+ 
  /* A temporary register holding an integral value used in adjusting SP
     or setting up the store_reg.  The "offset" field holds the integer
     value, not an offset.  */
! static dw_cfa_location cfa_temp;
  
  /* Record call frame debugging information for an expression EXPR,
     which either sets SP or FP (adjusting how we calculate the frame
*************** dwarf2out_frame_debug_expr (expr, label)
*** 1440,1446 ****
  		 on the ARM.  */
  
  	      def_cfa_1 (label, &cfa);
! 	      dwarf2out_reg_save (label, STACK_POINTER_REGNUM, offset);
  	      break;
  	    }
  	  else
--- 1503,1509 ----
  		 on the ARM.  */
  
  	      def_cfa_1 (label, &cfa);
! 	      queue_reg_save (label, stack_pointer_rtx, offset);
  	      break;
  	    }
  	  else
*************** dwarf2out_frame_debug_expr (expr, label)
*** 1462,1468 ****
  	}
  
        def_cfa_1 (label, &cfa);
!       dwarf2out_reg_save (label, REGNO (src), offset);
        break;
  
      default:
--- 1525,1531 ----
  	}
  
        def_cfa_1 (label, &cfa);
!       queue_reg_save (label, src, offset);
        break;
  
      default:
*************** dwarf2out_frame_debug (insn)
*** 1483,1488 ****
--- 1546,1554 ----
  
    if (insn == NULL_RTX)
      {
+       /* Flush any queued register saves.  */
+       flush_queued_reg_saves ();
+ 
        /* Set up state for generating call frame debug info.  */
        lookup_cfa (&cfa);
        if (cfa.reg != (unsigned long) DWARF_FRAME_REGNUM (STACK_POINTER_REGNUM))
*************** dwarf2out_frame_debug (insn)
*** 1494,1502 ****
        return;
      }
  
    if (! RTX_FRAME_RELATED_P (insn))
      {
!       dwarf2out_stack_adjust (insn);
        return;
      }
  
--- 1560,1572 ----
        return;
      }
  
+   if (GET_CODE (insn) != INSN || clobbers_queued_reg_save (insn))
+     flush_queued_reg_saves ();
+ 
    if (! RTX_FRAME_RELATED_P (insn))
      {
!       if (!ACCUMULATE_OUTGOING_ARGS)
!         dwarf2out_stack_adjust (insn);
        return;
      }
  
Index: final.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/final.c,v
retrieving revision 1.161
diff -c -p -d -r1.161 final.c
*** final.c	2001/02/28 17:53:35	1.161
--- final.c	2001/03/18 03:23:49
*************** final_scan_insn (insn, file, optimize, p
*** 2324,2332 ****
  
      case BARRIER:
  #if defined (DWARF2_UNWIND_INFO)
!       /* If we push arguments, we need to check all insns for stack
! 	 adjustments.  */
!       if (!ACCUMULATE_OUTGOING_ARGS && dwarf2out_do_frame ())
  	dwarf2out_frame_debug (insn);
  #endif
        break;
--- 2324,2330 ----
  
      case BARRIER:
  #if defined (DWARF2_UNWIND_INFO)
!       if (dwarf2out_do_frame ())
  	dwarf2out_frame_debug (insn);
  #endif
        break;
*************** final_scan_insn (insn, file, optimize, p
*** 2936,2944 ****
  	current_output_insn = debug_insn = insn;
  
  #if defined (DWARF2_UNWIND_INFO)
! 	/* If we push arguments, we want to know where the calls are.  */
! 	if (!ACCUMULATE_OUTGOING_ARGS && GET_CODE (insn) == CALL_INSN
! 	    && dwarf2out_do_frame ())
  	  dwarf2out_frame_debug (insn);
  #endif
  
--- 2934,2940 ----
  	current_output_insn = debug_insn = insn;
  
  #if defined (DWARF2_UNWIND_INFO)
! 	if (GET_CODE (insn) == CALL_INSN && dwarf2out_do_frame ())
  	  dwarf2out_frame_debug (insn);
  #endif
  
*************** final_scan_insn (insn, file, optimize, p
*** 3006,3027 ****
  	output_asm_insn (template, recog_data.operand);
  
  #if defined (DWARF2_UNWIND_INFO)
- 	/* If we push arguments, we need to check all insns for stack
- 	   adjustments.  */
- 	if (!ACCUMULATE_OUTGOING_ARGS)
- 	  {
- 	    if (GET_CODE (insn) == INSN && dwarf2out_do_frame ())
- 	      dwarf2out_frame_debug (insn);
- 	  }
- 	else
- 	  {
  #if defined (HAVE_prologue)
! 	    /* If this insn is part of the prologue, emit DWARF v2
! 	       call frame info.  */
! 	    if (RTX_FRAME_RELATED_P (insn) && dwarf2out_do_frame ())
! 	      dwarf2out_frame_debug (insn);
  #endif
- 	  }
  #endif
  
  #if 0
--- 3002,3016 ----
  	output_asm_insn (template, recog_data.operand);
  
  #if defined (DWARF2_UNWIND_INFO)
  #if defined (HAVE_prologue)
! 	if (GET_CODE (insn) == INSN && dwarf2out_do_frame ())
! 	  dwarf2out_frame_debug (insn);
! #else
! 	if (!ACCUMULATE_OUTGOING_ARGS
! 	    && GET_CODE (insn) == INSN
! 	    && dwarf2out_do_frame ())
! 	  dwarf2out_frame_debug (insn);
  #endif
  #endif
  
  #if 0


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