From patchwork Fri Oct 21 18:01:29 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Kratochvil X-Patchwork-Id: 121047 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id 7A497B70ED for ; Sat, 22 Oct 2011 05:01:56 +1100 (EST) Received: (qmail 20389 invoked by alias); 21 Oct 2011 18:01:51 -0000 Received: (qmail 20375 invoked by uid 22791); 21 Oct 2011 18:01:48 -0000 X-SWARE-Spam-Status: No, hits=-6.8 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, SPF_HELO_PASS, TW_GD X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Fri, 21 Oct 2011 18:01:33 +0000 Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id p9LI1Xtw005607 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Fri, 21 Oct 2011 14:01:33 -0400 Received: from host1.jankratochvil.net (ovpn-116-16.ams2.redhat.com [10.36.116.16]) by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id p9LI1VkI002187 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Fri, 21 Oct 2011 14:01:32 -0400 Received: from host1.jankratochvil.net (localhost [127.0.0.1]) by host1.jankratochvil.net (8.14.4/8.14.4) with ESMTP id p9LI1UWP015747 for ; Fri, 21 Oct 2011 20:01:30 +0200 Received: (from jkratoch@localhost) by host1.jankratochvil.net (8.14.4/8.14.4/Submit) id p9LI1UM4015659 for gcc-patches@gcc.gnu.org; Fri, 21 Oct 2011 20:01:30 +0200 Date: Fri, 21 Oct 2011 20:01:29 +0200 From: Jan Kratochvil To: gcc-patches@gcc.gnu.org Subject: [patch] dwarf2out: Use DW_FORM_ref_udata (.debug -= 7.53%) Message-ID: <20111021180129.GA24486@host1.jankratochvil.net> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Hi, this is a standalone patch to replace DW_FORM_ref4 by DW_FORM_ref_udata (uleb128). It saves for libstdc++.so.debug: 5254792 -> 4859136 = 7.53% Tested with: -O2 -gdwarf-4 -fdebug-types-section The references are already intra-CU ones, they are never relocated, they are pre-computed by dwarf2out.c as plain numbers already. IIRC I got this idea after reading Google "Fission" but it does not deal with intra-CU refs. The change does not apply to CFI references, those are unchanged, generated by different code of dwarf2out.c. I had a draft patch to use DW_FORM_ref1, DW_FORM_ref2, DW_FORM_ref_udata and DW_FORM_ref4 which should be slightly smaller than just DW_FORM_ref_udata. But it produced larger files than just DW_FORM_ref_udata. Assuming it was due to multiplied abbrev definitions. One would need to decide when if it is worth to create a new smaller-sized abbrev but that seems too complicated for such kind of optimization. There exist other project(s) in development for DWARF optimizations as a post-processing tool, this patch is meant just as a very simple way to reduce the (possibly intermediate) DWARF files. It is incompatible with GNU binutils readelf, a pending simple fix is: [patch] Fix readelf for DW_FORM_ref_udata http://sourceware.org/ml/binutils/2011-10/msg00201.html No regressions on {x86_64,x86_64-m32,i686}-fedora16pre-linux-gnu (4.7.0 20111002). No changes in readelf -w output on libstdc++.so. My former DW_AT_sibling patch will be updated on top of this one: Re: [patch#2] dwarf2out: Drop the size + performance overhead of DW_AT_sibling http://gcc.gnu.org/ml/gcc-patches/2011-10/msg01869.html These two optimizations are not incremental to each other as both benefit primarily from common DW_AT_sibling. That size decrease 3.49% will be less after this patch; moreover when not all DW_AT_sibling attrs will be dropped. Thanks, Jan gcc/ 2011-10-21 Jan Kratochvil * dwarf2out.c (DW_FORM_ref): Remove. (size_of_die) : Use size_of_uleb128 for !AT_ref_external references. (calc_die_sizes_change): New variable. (calc_die_sizes): Permit die_offset incrementals. Set CALC_DIE_SIZES_CHANGE accordingly. (value_format) : Return DW_FORM_ref_udata for !AT_ref_external references. (output_die) : Use dw2_asm_output_data_uleb128 for !AT_ref_external references. (output_unit_prep): New function, call calc_die_sizes repeatedly based on CALC_DIE_SIZES_CHANGE. (output_comp_unit, output_comdat_type_unit): Move some code to output_unit_prep. --- gcc/dwarf2out.c +++ gcc/dwarf2out.c @@ -226,7 +226,6 @@ static GTY(()) rtx current_unit_personality; /* Data and reference forms for relocatable data. */ #define DW_FORM_data (DWARF_OFFSET_SIZE == 8 ? DW_FORM_data8 : DW_FORM_data4) -#define DW_FORM_ref (DWARF_OFFSET_SIZE == 8 ? DW_FORM_ref8 : DW_FORM_ref4) #ifndef DEBUG_FRAME_SECTION #define DEBUG_FRAME_SECTION ".debug_frame" @@ -7700,7 +7699,7 @@ size_of_die (dw_die_ref die) size += DWARF_OFFSET_SIZE; } else - size += DWARF_OFFSET_SIZE; + size += size_of_uleb128 (AT_ref (a)->die_offset); break; case dw_val_class_fde_ref: size += DWARF_OFFSET_SIZE; @@ -7735,6 +7734,10 @@ size_of_die (dw_die_ref die) return size; } +/* Has calc_die_sizes changed any DIE_OFFSET? */ + +static bool calc_die_sizes_change; + /* Size the debugging information associated with a given DIE. Visits the DIE's children recursively. Updates the global variable next_die_offset, on each time through. Uses the current value of next_die_offset to update the @@ -7745,9 +7748,12 @@ calc_die_sizes (dw_die_ref die) { dw_die_ref c; - gcc_assert (die->die_offset == 0 - || (unsigned long int) die->die_offset == next_die_offset); - die->die_offset = next_die_offset; + gcc_assert ((unsigned long int) die->die_offset <= next_die_offset); + if ((unsigned long int) die->die_offset != next_die_offset) + { + die->die_offset = next_die_offset; + calc_die_sizes_change = true; + } next_die_offset += size_of_die (die); FOR_EACH_CHILD (die, c, calc_die_sizes (c)); @@ -8018,7 +8024,7 @@ value_format (dw_attr_ref a) if (AT_ref_external (a)) return use_debug_types ? DW_FORM_ref_sig8 : DW_FORM_ref_addr; else - return DW_FORM_ref; + return DW_FORM_ref_udata; case dw_val_class_fde_ref: return DW_FORM_data; case dw_val_class_lbl_id: @@ -8397,8 +8403,7 @@ output_die (dw_die_ref die) else { gcc_assert (AT_ref (a)->die_offset); - dw2_asm_output_data (DWARF_OFFSET_SIZE, AT_ref (a)->die_offset, - "%s", name); + dw2_asm_output_data_uleb128 (AT_ref (a)->die_offset, "%s", name); } break; @@ -8496,6 +8501,28 @@ output_compilation_unit_header (void) dw2_asm_output_data (1, DWARF2_ADDR_SIZE, "Pointer Size (in bytes)"); } +/* Perform initializations common for .debug_info and .debug_types sections. */ + +static void +output_unit_prep (dw_die_ref die, unsigned long init_die_offset) +{ + /* First mark all the DIEs in this CU so we know which get local refs. */ + mark_dies (die); + + build_abbrev_table (die); + + /* The DIE sizes can increase, due to DW_FORM_ref_udata size increase + dependent on increases of other DIE_OFFSETs. */ + do + { + /* Initialize the beginning DIE offset - and calculate sizes/offsets. */ + next_die_offset = init_die_offset; + calc_die_sizes_change = false; + calc_die_sizes (die); + } + while (calc_die_sizes_change); +} + /* Output the compilation unit DIE and its children. */ static void @@ -8511,15 +8538,8 @@ output_comp_unit (dw_die_ref die, int output_if_empty) /* Even if there are no children of this DIE, we must output the information about the compilation unit. Otherwise, on an empty translation unit, we will generate a present, but empty, .debug_info section. IRIX 6.5 `nm' - will then complain when examining the file. First mark all the DIEs in - this CU so we know which get local refs. */ - mark_dies (die); - - build_abbrev_table (die); - - /* Initialize the beginning DIE offset - and calculate sizes/offsets. */ - next_die_offset = DWARF_COMPILE_UNIT_HEADER_SIZE; - calc_die_sizes (die); + will then complain when examining the file. */ + output_unit_prep (die, DWARF_COMPILE_UNIT_HEADER_SIZE); oldsym = die->die_id.die_symbol; if (oldsym) @@ -8563,14 +8583,7 @@ output_comdat_type_unit (comdat_type_node *node) tree comdat_key; #endif - /* First mark all the DIEs in this CU so we know which get local refs. */ - mark_dies (node->root_die); - - build_abbrev_table (node->root_die); - - /* Initialize the beginning DIE offset - and calculate sizes/offsets. */ - next_die_offset = DWARF_COMDAT_TYPE_UNIT_HEADER_SIZE; - calc_die_sizes (node->root_die); + output_unit_prep (node->root_die, DWARF_COMDAT_TYPE_UNIT_HEADER_SIZE); #if defined (OBJECT_FORMAT_ELF) secname = ".debug_types";