public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
From: Bruno Haible <haible@ilog.fr>
To: egcs@cygnus.com
Subject: Reducing eh_frame table size
Date: Mon, 17 Nov 1997 14:21:00 -0000	[thread overview]
Message-ID: <199711172038.VAA16367@halles.ilog.fr> (raw)

Here is a patch which starts reducing the eh_table size. On a sample
C executable compiled with -fomit-frame-pointer, on i486-linux, I got
the following figures:

before patch:         text: 568920    eh_frame: 308732 (+ 54%)
after patch:          text: 568920    eh_frame: 173796 (+ 31%)

that is, a reduction of the eh_frame section by 44%.

The patch does the following:
  1. When there are two DW_CFA_advance_loc4 entries with no call between
     them, the latter one is removed. Recall that exceptions can only
     be thrown through function calls.
  2. When the tail of the CFIs (the ones after the last DW_CFA_advance_loc4)
     refers to a code section with no calls, it is removed.
  3. Introduce a short 1-byte opcode for a pretty common combination of
     DW_CFA_def_cfa_offset and DW_CFA_GNU_args_size.

*** testgcc-971111/frame.c.bak	Thu Nov 13 00:46:54 1997
--- testgcc-971111/frame.c	Sun Nov 16 18:12:44 1997
***************
*** 503,508 ****
--- 503,514 ----
        state->s.args_size = offset;
        break;
  
+     case DW_CFA_GNU_push_argword:
+       /* A combination of DW_CFA_def_cfa_offset and DW_CFA_GNU_args_size. */
+       state->s.cfa_offset += sizeof (long);
+       state->s.args_size += sizeof (long);
+       break;
+ 
      default:
        abort ();
      }
*** testgcc-971111/dwarf2.h.bak	Thu Nov  6 23:48:55 1997
--- testgcc-971111/dwarf2.h	Sun Nov 16 18:13:18 1997
***************
*** 500,506 ****
  
      /* GNU extensions */
      DW_CFA_GNU_window_save = 0x2d,
!     DW_CFA_GNU_args_size = 0x2e
    };
  
  #define DW_CIE_ID	  0xffffffff
--- 500,507 ----
  
      /* GNU extensions */
      DW_CFA_GNU_window_save = 0x2d,
!     DW_CFA_GNU_args_size = 0x2e,
!     DW_CFA_GNU_push_argword = 0x2f
    };
  
  #define DW_CIE_ID	  0xffffffff
*** testgcc-971111/dwarf2out.c.bak	Thu Nov  6 23:48:57 1997
--- testgcc-971111/dwarf2out.c	Sun Nov 16 18:17:12 1997
***************
*** 44,49 ****
--- 44,53 ----
  /* #define NDEBUG 1 */
  #include "assert.h"
  
+ #ifndef LONG_TYPE_SIZE
+ #define LONG_TYPE_SIZE BITS_PER_WORD
+ #endif
+ 
  /* Decide whether we want to emit frame unwind information for the current
     translation unit.  */
  
***************
*** 91,96 ****
--- 95,102 ----
    enum dwarf_call_frame_info dw_cfi_opc;
    dw_cfi_oprnd dw_cfi_oprnd1;
    dw_cfi_oprnd dw_cfi_oprnd2;
+   int dw_cfi_pushp : 1;
+   int dw_cfi_seen_call : 1;
  }
  dw_cfi_node;
  
***************
*** 104,109 ****
--- 110,116 ----
  {
    char *dw_fde_begin;
    char *dw_fde_current_label;
+   int dw_fde_seen_call;
    char *dw_fde_end;
    dw_cfi_ref dw_fde_cfi;
  }
***************
*** 637,642 ****
--- 653,660 ----
        return "DW_CFA_GNU_window_save";
      case DW_CFA_GNU_args_size:
        return "DW_CFA_GNU_args_size";
+     case DW_CFA_GNU_push_argword:
+       return "DW_CFA_GNU_push_argword";
  
      default:
        return "DW_CFA_<unknown>";
***************
*** 703,709 ****
  	label = dwarf2out_cfi_label ();
  
        if (fde->dw_fde_current_label == NULL
! 	  || strcmp (label, fde->dw_fde_current_label) != 0)
  	{
  	  register dw_cfi_ref xcfi;
  
--- 721,728 ----
  	label = dwarf2out_cfi_label ();
  
        if (fde->dw_fde_current_label == NULL
! 	  || strcmp (label, fde->dw_fde_current_label) != 0
! 	     && fde->dw_fde_seen_call)
  	{
  	  register dw_cfi_ref xcfi;
  
***************
*** 713,719 ****
--- 732,741 ----
  	  xcfi = new_cfi ();
  	  xcfi->dw_cfi_opc = DW_CFA_advance_loc4;
  	  xcfi->dw_cfi_oprnd1.dw_cfi_addr = label;
+ 	  xcfi->dw_cfi_seen_call = fde->dw_fde_seen_call;
  	  add_cfi (&fde->dw_fde_cfi, xcfi);
+ 
+ 	  fde->dw_fde_seen_call = 0;
  	}
  
        add_cfi (&fde->dw_fde_cfi, cfi);
***************
*** 814,819 ****
--- 836,843 ----
      {
        cfi->dw_cfi_opc = DW_CFA_def_cfa_offset;
        cfi->dw_cfi_oprnd1.dw_cfi_offset = offset;
+       cfi->dw_cfi_pushp =
+ 	(offset - old_offset == LONG_TYPE_SIZE / BITS_PER_UNIT);
      }
  
  #ifndef MIPS_DEBUGGING_INFO  /* SGI dbx thinks this means no offset.  */
***************
*** 1097,1102 ****
--- 1121,1132 ----
        return;
      }
  
+   /* Since exceptions can only occur through call instructions, when doing
+      for_eh we can remove advance_loc CFIs corresponding to ranges without
+      call instructions. */
+   if (GET_CODE (insn) == CALL_INSN)
+     fde_table[fde_table_in_use - 1].dw_fde_seen_call = 1;
+ 
    if (! RTX_FRAME_RELATED_P (insn))
      {
        dwarf2out_stack_adjust (insn);
***************
*** 1241,1246 ****
--- 1271,1317 ----
      }
  }
  
+ /* Combine adjacent CFIs, to reduce the size of the eh table. */
+ static void
+ peephole_fde (fde)
+     dw_fde_node *fde;
+ {
+   register dw_cfi_node *curr, **pcurr;
+   register dw_cfi_node *next;
+ 
+   for (pcurr = &fde->dw_fde_cfi; (curr = *pcurr); )
+     {
+       next = curr->dw_cfi_next;
+       if (curr->dw_cfi_opc == DW_CFA_advance_loc4
+           && ! curr->dw_cfi_seen_call)
+         {
+           *pcurr = next;
+           continue;
+         }
+       if (curr->dw_cfi_opc == DW_CFA_def_cfa_offset
+           && curr->dw_cfi_pushp
+           && next->dw_cfi_opc == DW_CFA_GNU_args_size)
+         {
+           curr->dw_cfi_opc = DW_CFA_GNU_push_argword;
+           curr->dw_cfi_next = next->dw_cfi_next;
+           continue;
+         }
+       pcurr = &curr->dw_cfi_next;
+     }
+ 
+   /* If there are no calls after the last advance, the trailing CFIs can
+      be removed. */
+   if (! fde->dw_fde_seen_call)
+     {
+       pcurr = &fde->dw_fde_cfi;
+       curr = *pcurr;
+       for (next = curr; next; next = next->dw_cfi_next)
+         if (next->dw_cfi_opc == DW_CFA_advance_loc4)
+           pcurr = &next->dw_cfi_next;
+       *pcurr = NULL;
+     }
+ }
+ 
  /* Return the size of an unsigned LEB128 quantity.  */
  
  static inline unsigned long
***************
*** 1453,1458 ****
--- 1527,1534 ----
  	  output_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_offset);
            fputc ('\n', asm_out_file);
  	  break;
+ 	case DW_CFA_GNU_push_argword:
+ 	  break;
  	default:
  	  break;
  	}
***************
*** 1601,1606 ****
--- 1677,1686 ----
      {
        fde = &fde_table[i];
  
+       /* Reduce the size of the CFI table. */
+       if (for_eh)
+ 	peephole_fde (fde);
+ 
        ASM_GENERATE_INTERNAL_LABEL (l1, FDE_AFTER_SIZE_LABEL, for_eh + i*2);
        ASM_GENERATE_INTERNAL_LABEL (l2, FDE_END_LABEL, for_eh + i*2);
        if (for_eh)
***************
*** 1693,1698 ****
--- 1773,1779 ----
    fde = &fde_table[fde_table_in_use++];
    fde->dw_fde_begin = xstrdup (label);
    fde->dw_fde_current_label = NULL;
+   fde->dw_fde_seen_call = 0;
    fde->dw_fde_end = NULL;
    fde->dw_fde_cfi = NULL;
  

             reply	other threads:[~1997-11-17 14:21 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
1997-11-17 14:21 Bruno Haible [this message]
  -- strict thread matches above, loose matches on Subject: below --
1997-11-17 13:49 Bruno Haible
1997-11-17 14:21 ` Ian Lance Taylor

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=199711172038.VAA16367@halles.ilog.fr \
    --to=haible@ilog.fr \
    --cc=egcs@cygnus.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).