This is the mail archive of the gcc@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]

Patch: Code Bloat g++


> I know what the problem may be.  We need a LBRAC/RBRAC eliminator.

I took a slightly different approach; the patch below avoids emitting
LBRAC/RBRAC pairs if the block has no locals (or only locals which
don't get debug info, such as __FUNCTION__).

It also reduces the size of the assembler file by using the function
begin label (if present), instead of the external symbol; this pays
off primarily in C++, where the external symbol is mangled.

In more detail, I did the following changes:
- Change dbxout functions to report whether they put anything out.
- Do not put out LBRAC/RBRAC if nothing was emitted.
- Move current_function_decl from the language front-ends to toplev.c,
  this also fixes a bug where current_function_decl was added as a GC
  root only in C.
- Add a new global current_function_func_begin_label. This is currently
  set only for DWARF2 output, but it could be extended to other formats
  as well.
- Use that to simplify LBRAC/RBRAC pairs. It could also be extended to
  do the same thing for SLINE stabs. This only reduces the size of the
  assembler file, not the object file size.

For LBRAC/RBRAC stabn removal, the labels indicating the basic blocks
are still emitted.

With this patch, I could reduce the assembler file size in Gerald's
example from 31867379 to 18570493. The object file size went down from
4692128 to 3684448. The patch passes the test suite; only limited
tests whether debuggers are still happy were performed.

The patch has really three independent parts (centralization of
current_function_decl, reducing debugging information, using function
start symbols). If desired, I can submit each feature separately.

Please let me know what you think.

Regards,
Martin

2000-02-19  Martin v. Löwis  <loewis@informatik.hu-berlin.de>

	* c-decl.c (current_function_decl): Move to toplev.c.
	(init_decl_processing): Don't add current_function_decl as a ggc
	root here.
	* dbxout.c (dbxout_symbol): Change return type to int.
	(dbxout_symbol_location, dbxout_syms): Likewise.
	(dbxout_block): Don't emit LBRAC/RBRAC pairs for blocks without
	any locals. Use current_function_func_begin_label if set.
	* dbxout.h (dbxout_symbol, dbxout_syms): Change return type.
	* dwarf2out.c (dwarf2out_begin_prologue): Set
	current_function_func_begin_label.
	* final.c (final_start_function): Reset it.
	* toplev.c (current_function_decl): Define it here.
	(current_function_func_begin_label): New variable.
	(main): Add both as ggc roots.
	* tree.h (current_function_func_begin_label): Declare.
	* ch/decl.c (current_function_decl): Move to toplev.c.
	* cp/decl.c (current_function_decl): Move to toplev.c.
	* f/com.c (current_function_decl): Move to toplev.c.
	* java/decl.c (current_function_decl): Move to toplev.c.
	
Index: c-decl.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/c-decl.c,v
retrieving revision 1.96
diff -u -p -r1.96 c-decl.c
--- c-decl.c	2000/01/31 03:31:26	1.96
+++ c-decl.c	2000/02/19 20:58:01
@@ -132,10 +132,6 @@ static tree shadowed_labels;
 
 static int c_function_varargs;
 
-/* The FUNCTION_DECL for the function currently being compiled,
-   or 0 if between functions.  */
-tree current_function_decl;
-
 /* Set to 0 at beginning of a function definition, set to 1 if
    a return statement that specifies a return value is seen.  */
 
@@ -3073,7 +3069,6 @@ init_decl_processing ()
   /* Record our roots.  */
 
   ggc_add_tree_root (c_global_trees, CTI_MAX);
-  ggc_add_tree_root (&current_function_decl, 1);
   ggc_add_tree_root (&named_labels, 1);
   ggc_add_tree_root (&shadowed_labels, 1);
   ggc_add_root (&current_binding_level, 1, sizeof current_binding_level,
Index: dbxout.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/dbxout.c,v
retrieving revision 1.44
diff -u -p -r1.44 dbxout.c
--- dbxout.c	2000/01/14 00:46:57	1.44
+++ dbxout.c	2000/02/19 20:58:04
@@ -335,7 +335,7 @@ static void dbxout_type			PARAMS ((tree,
 static void print_int_cst_octal		PARAMS ((tree));
 static void print_octal			PARAMS ((unsigned HOST_WIDE_INT, int));
 static void dbxout_type_name		PARAMS ((tree));
-static void dbxout_symbol_location	PARAMS ((tree, tree, const char *, rtx));
+static int dbxout_symbol_location	PARAMS ((tree, tree, const char *, rtx));
 static void dbxout_symbol_name		PARAMS ((tree, const char *, int));
 static void dbxout_prepare_symbol	PARAMS ((tree));
 static void dbxout_finish_symbol	PARAMS ((tree));
@@ -1702,15 +1702,17 @@ dbxout_type_name (type)
 /* Output a .stabs for the symbol defined by DECL,
    which must be a ..._DECL node in the normal namespace.
    It may be a CONST_DECL, a FUNCTION_DECL, a PARM_DECL or a VAR_DECL.
-   LOCAL is nonzero if the scope is less than the entire file.  */
+   LOCAL is nonzero if the scope is less than the entire file.
+   Return 1 if a stabs might have been emitted.  */
 
-void
+int
 dbxout_symbol (decl, local)
      tree decl;
      int local ATTRIBUTE_UNUSED;
 {
   tree type = TREE_TYPE (decl);
   tree context = NULL_TREE;
+  int result = 0;
 
   /* Cast avoids warning in old compilers.  */
   current_sym_code = (STAB_CODE_TYPE) 0;
@@ -1721,7 +1723,7 @@ dbxout_symbol (decl, local)
 
   if ((DECL_NAME (decl) == 0 && TREE_CODE (decl) != TYPE_DECL)
       || DECL_IGNORED_P (decl))
-    return;
+    return 0;
 
   dbxout_prepare_symbol (decl);
 
@@ -1739,7 +1741,7 @@ dbxout_symbol (decl, local)
 
     case FUNCTION_DECL:
       if (DECL_RTL (decl) == 0)
-	return;
+	return 0;
       if (DECL_EXTERNAL (decl))
 	break;
       /* Don't mention a nested function under its parent.  */
@@ -1754,6 +1756,7 @@ dbxout_symbol (decl, local)
       fprintf (asmfile, "%s \"%s:%c", ASM_STABS_OP,
 	       IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)),
 	       TREE_PUBLIC (decl) ? 'F' : 'f');
+      result = 1;
 
       current_sym_code = N_FUN;
       current_sym_addr = XEXP (DECL_RTL (decl), 0);
@@ -1785,15 +1788,15 @@ dbxout_symbol (decl, local)
 	 don't duplicate it.  */
       if (typevec[TYPE_SYMTAB_ADDRESS (type)].status == TYPE_DEFINED
 	  && TYPE_NAME (TREE_TYPE (decl)) == decl)
-	return;
+	return 0;
 #endif
       /* Don't output the same typedef twice.
          And don't output what language-specific stuff doesn't want output.  */
       if (TREE_ASM_WRITTEN (decl) || TYPE_DECL_SUPPRESS_DEBUG (decl))
-	return;
+	return 0;
 
       FORCE_TEXT;
-
+      result = 1;
       {
 	int tag_needed = 1;
 	int did_output = 0;
@@ -1925,7 +1928,7 @@ dbxout_symbol (decl, local)
       /* Named return value, treat like a VAR_DECL.  */
     case VAR_DECL:
       if (DECL_RTL (decl) == 0)
-	return;
+	return 0;
       /* Don't mention a variable that is external.
 	 Let the file that defines it describe it.  */
       if (DECL_EXTERNAL (decl))
@@ -1955,7 +1958,7 @@ dbxout_symbol (decl, local)
 		  fprintf (asmfile, HOST_WIDE_INT_PRINT_DEC, ival);
 		  fprintf (asmfile, "\",0x%x,0,0,0\n", N_LSYM);
 #endif
-		  return;
+		  return 1;
 		}
 	      else if (TREE_CODE (TREE_TYPE (decl)) == REAL_TYPE)
 		{
@@ -1972,20 +1975,22 @@ dbxout_symbol (decl, local)
 	leaf_renumber_regs_insn (DECL_RTL (decl));
 #endif
 
-      dbxout_symbol_location (decl, type, 0, DECL_RTL (decl));
+      result = dbxout_symbol_location (decl, type, 0, DECL_RTL (decl));
       break;
       
     default:
       break;
     }
+  return result;
 }
 
 /* Output the stab for DECL, a VAR_DECL, RESULT_DECL or PARM_DECL.
    Add SUFFIX to its name, if SUFFIX is not 0.
    Describe the variable as residing in HOME
-   (usually HOME is DECL_RTL (DECL), but not always).  */
+   (usually HOME is DECL_RTL (DECL), but not always).
+   Returns 1 if the stab was really emitted.  */
 
-static void
+static int
 dbxout_symbol_location (decl, type, suffix, home)
      tree decl, type;
      const char *suffix;
@@ -2004,7 +2009,7 @@ dbxout_symbol_location (decl, type, suff
     {
       regno = REGNO (home);
       if (regno >= FIRST_PSEUDO_REGISTER)
-	return;
+	return 0;
     }
   else if (GET_CODE (home) == SUBREG)
     {
@@ -2019,7 +2024,7 @@ dbxout_symbol_location (decl, type, suff
 	{
 	  regno = REGNO (value);
 	  if (regno >= FIRST_PSEUDO_REGISTER)
-	    return;
+	    return 0;
 	  regno += offset;
 	}
       alter_subreg (home);
@@ -2173,13 +2178,13 @@ dbxout_symbol_location (decl, type, suff
 	dbxout_symbol_location (decl, subtype, "$real", XEXP (home, 1));
       else
 	dbxout_symbol_location (decl, subtype, "$imag", XEXP (home, 1));
-      return;
+      return 1;
     }
   else
     /* Address might be a MEM, when DECL is a variable-sized object.
        Or it might be const0_rtx, meaning previous passes
        want us to ignore this variable.  */
-    return;
+    return 1;
 
   /* Ok, start a symtab entry and output the variable name.  */
   FORCE_TEXT;
@@ -2250,17 +2255,20 @@ dbxout_finish_symbol (sym)
 #endif
 }
 
-/* Output definitions of all the decls in a chain.  */
+/* Output definitions of all the decls in a chain. Return non-zero if
+   anything was output */
 
-void
+int
 dbxout_syms (syms)
      tree syms;
 {
+  int result = 0;
   while (syms)
     {
-      dbxout_symbol (syms, 1);
+      result += dbxout_symbol (syms, 1);
       syms = TREE_CHAIN (syms);
     }
+  return result;
 }
 
 /* The following two functions output definitions of function parameters.
@@ -2625,25 +2633,41 @@ dbxout_block (block, depth, args)
      tree args;
 {
   int blocknum = -1;
+  int ignored;
 
+#if DBX_BLOCKS_FUNCTION_RELATIVE
+  char *begin_label; 
+  if (current_function_func_begin_label != NULL_TREE)
+    begin_label = IDENTIFIER_POINTER (current_function_func_begin_label);
+  else
+    begin_label = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0);
+#endif
+
   while (block)
     {
       /* Ignore blocks never expanded or otherwise marked as real.  */
       if (TREE_USED (block))
 	{
 #ifndef DBX_LBRAC_FIRST
-	  /* In dbx format, the syms of a block come before the N_LBRAC.  */
+	  /* In dbx format, the syms of a block come before the N_LBRAC.
+	     If nothing is output, we don't need the N_LBRAC, either. */
+	  ignored = 1;
 	  if (debug_info_level != DINFO_LEVEL_TERSE || depth == 0)
-	    dbxout_syms (BLOCK_VARS (block));
+	    ignored = dbxout_syms (BLOCK_VARS (block)) == 0;
 	  if (args)
 	    dbxout_reg_parms (args);
+#else
+	  /* If the block has no locals, we don't need to tell the
+	     debugger about it.  */
+	  ignored = (debug_info_level == DINFO_LEVEL_TERSE
+		     || BLOCK_VARS (block) == NULL_TREE);
 #endif
 
 	  /* Now output an N_LBRAC symbol to represent the beginning of
 	     the block.  Use the block's tree-walk order to generate
 	     the assembler symbols LBBn and LBEn
 	     that final will define around the code in this block.  */
-	  if (depth > 0 && debug_info_level != DINFO_LEVEL_TERSE)
+	  if (depth > 0 && !ignored)
 	    {
 	      char buf[20];
 	      blocknum = next_block_number++;
@@ -2674,7 +2698,7 @@ dbxout_block (block, depth, args)
 	      assemble_name (asmfile, buf);
 #if DBX_BLOCKS_FUNCTION_RELATIVE
 	      fputc ('-', asmfile);
-	      assemble_name (asmfile, XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0));
+	      assemble_name (asmfile, begin_label);
 #endif
 	      fprintf (asmfile, "\n");
 #endif
@@ -2696,7 +2720,7 @@ dbxout_block (block, depth, args)
 	  dbxout_block (BLOCK_SUBBLOCKS (block), depth + 1, NULL_TREE);
 
 	  /* Refer to the marker for the end of the block.  */
-	  if (depth > 0 && debug_info_level != DINFO_LEVEL_TERSE)
+	  if (depth > 0 && !ignored)
 	    {
 	      char buf[20];
 	      ASM_GENERATE_INTERNAL_LABEL (buf, "LBE", blocknum);
@@ -2707,7 +2731,7 @@ dbxout_block (block, depth, args)
 	      assemble_name (asmfile, buf);
 #if DBX_BLOCKS_FUNCTION_RELATIVE
 	      fputc ('-', asmfile);
-	      assemble_name (asmfile, XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0));
+	      assemble_name (asmfile, begin_label);
 #endif
 	      fprintf (asmfile, "\n");
 #endif
Index: dbxout.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/dbxout.h,v
retrieving revision 1.6
diff -u -p -r1.6 dbxout.h
--- dbxout.h	2000/01/14 00:46:57	1.6
+++ dbxout.h	2000/02/19 20:58:04
@@ -27,10 +27,10 @@ extern void dbxout_resume_previous_sourc
 extern void dbxout_source_file		PARAMS ((FILE *, const char *));
 extern void dbxout_types		PARAMS ((tree));
 extern void dbxout_args			PARAMS ((tree));
-extern void dbxout_symbol		PARAMS ((tree, int));
+extern int dbxout_symbol		PARAMS ((tree, int));
 extern void dbxout_parms		PARAMS ((tree));
 extern void dbxout_reg_parms		PARAMS ((tree));
-extern void dbxout_syms			PARAMS ((tree));
+extern int dbxout_syms			PARAMS ((tree));
 extern void dbxout_function		PARAMS ((tree));
 extern void dbxout_source_line		PARAMS ((FILE *, const char *, int));
 extern void dbxout_begin_function	PARAMS ((tree));
Index: dwarf2out.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/dwarf2out.c,v
retrieving revision 1.150
diff -u -p -r1.150 dwarf2out.c
--- dwarf2out.c	2000/02/15 16:36:32	1.150
+++ dwarf2out.c	2000/02/19 20:58:13
@@ -1851,6 +1851,7 @@ dwarf2out_begin_prologue ()
   ASM_GENERATE_INTERNAL_LABEL (label, FUNC_BEGIN_LABEL,
 			       current_funcdef_number);
   ASM_OUTPUT_LABEL (asm_out_file, label);
+  current_function_func_begin_label = get_identifier (label);
 
   /* Expand the fde table if necessary.  */
   if (fde_table_in_use == fde_table_allocated)
Index: final.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/final.c,v
retrieving revision 1.108
diff -u -p -r1.108 final.c
--- final.c	2000/01/18 22:45:16	1.108
+++ final.c	2000/02/19 20:58:17
@@ -1628,6 +1628,8 @@ final_start_function (first, file, optim
   /* Output DWARF definition of the function.  */
   if (dwarf2out_do_frame ())
     dwarf2out_begin_prologue ();
+  else
+    current_function_func_begin_label = 0;
 #endif
 
   /* For SDB and XCOFF, the function beginning must be marked between
Index: toplev.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/toplev.c,v
retrieving revision 1.290
diff -u -p -r1.290 toplev.c
--- toplev.c	2000/02/16 07:54:53	1.290
+++ toplev.c	2000/02/19 20:58:30
@@ -306,6 +306,14 @@ int errorcount = 0;
 int warningcount = 0;
 int sorrycount = 0;
 
+/* The FUNCTION_DECL for the function currently being compiled,
+   or 0 if between functions.  */
+tree current_function_decl;
+
+/* Set to the FUNC_BEGIN label of the current function, or NULL_TREE
+   if none.  */
+tree current_function_func_begin_label;
+
 /* Pointer to function to compute the name to use to print a declaration.
    DECL is the declaration in question.
    VERBOSITY determines what information will be printed:
@@ -4554,6 +4562,8 @@ main (argc, argv)
   ggc_add_root (&input_file_stack, 1, sizeof input_file_stack,
 		mark_file_stack);
   ggc_add_rtx_root (&stack_limit_rtx, 1);
+  ggc_add_tree_root (&current_function_decl, 1);
+  ggc_add_tree_root (&current_function_func_begin_label, 1);
 
   /* Perform language-specific options intialization.  */
   lang_init_options ();
Index: tree.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/tree.h,v
retrieving revision 1.123
diff -u -p -r1.123 tree.h
--- tree.h	2000/02/18 06:32:01	1.123
+++ tree.h	2000/02/19 20:58:33
@@ -2050,6 +2050,9 @@ extern int immediate_size_expand;
 
 extern tree current_function_decl;
 
+/* Nonzero means a FUNC_BEGIN label was emitted.  */
+extern tree current_function_func_begin_label;
+
 /* Nonzero means all ..._TYPE nodes should be allocated permanently.  */
 
 extern int all_types_permanent;
Index: ch/decl.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/ch/decl.c,v
retrieving revision 1.18
diff -u -p -r1.18 decl.c
--- decl.c	2000/02/11 15:49:56	1.18
+++ decl.c	2000/02/19 20:58:38
@@ -374,10 +374,6 @@ static tree current_function_parms;
 
 static int c_function_varargs;
 
-/* The FUNCTION_DECL for the function currently being compiled,
-   or 0 if between functions.  */
-tree current_function_decl;
-
 /* These are irrelevant for Chill, but are referenced from from c-typeck.c. */
 int warn_format;
 int warn_traditional;
Index: cp/decl.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/decl.c,v
retrieving revision 1.546
diff -u -p -r1.546 decl.c
--- decl.c	2000/02/18 22:42:05	1.546
+++ decl.c	2000/02/19 20:59:15
@@ -313,10 +313,6 @@ static tree current_function_parm_tags;
 
 #define named_labels cp_function_chain->x_named_labels
 
-/* The FUNCTION_DECL for the function currently being compiled,
-   or 0 if between functions.  */
-tree current_function_decl;
-
 /* Set to 0 at beginning of a function definition, and whenever
    a label (case or named) is defined.  Set to value of expression
    returned from function when that value can be transformed into
Index: f/com.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/f/com.c,v
retrieving revision 1.75
diff -u -p -r1.75 com.c
--- com.c	2000/02/17 10:06:03	1.75
+++ com.c	2000/02/19 20:59:48
@@ -1,5 +1,5 @@
 /* com.c -- Implementation File (module.c template V1.0)
-   Copyright (C) 1995-1999 Free Software Foundation, Inc.
+   Copyright (C) 1995-2000 Free Software Foundation, Inc.
    Contributed by James Craig Burley.
 
 This file is part of GNU Fortran.
@@ -215,12 +215,6 @@ typedef struct { unsigned :16, :16, :16;
 /* Externals defined here.  */
 
 #if FFECOM_targetCURRENT == FFECOM_targetGCC
-
-/* tree.h declares a bunch of stuff that it expects the front end to
-   define.  Here are the definitions, which in the C front end are
-   found in the file c-decl.c.  */
-
-tree current_function_decl;
 
 /* ~~gcc/tree.h *should* declare this, because toplev.c and dwarfout.c
    reference it.  */
Index: java/decl.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/java/decl.c,v
retrieving revision 1.46
diff -u -p -r1.46 decl.c
--- decl.c	2000/02/09 20:38:02	1.46
+++ decl.c	2000/02/19 20:59:51
@@ -279,10 +279,6 @@ static int keep_next_level_flag;
 
 static int keep_next_if_subblocks;
   
-/* The FUNCTION_DECL for the function currently being compiled,
-   or 0 if between functions.  */
-tree current_function_decl;
-
 tree object_type_node;
 tree unqualified_object_id_node;
 tree object_ptr_type_node;

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