From patchwork Mon Jul 11 16:33:00 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Jelinek X-Patchwork-Id: 104252 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 45EF8B6F77 for ; Tue, 12 Jul 2011 02:57:19 +1000 (EST) Received: (qmail 21974 invoked by alias); 11 Jul 2011 16:57:17 -0000 Received: (qmail 21963 invoked by uid 22791); 11 Jul 2011 16:57:14 -0000 X-SWARE-Spam-Status: No, hits=-6.5 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_HI, SPF_HELO_PASS, TW_CL, T_RP_MATCHES_RCVD 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; Mon, 11 Jul 2011 16:56:57 +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 p6BGubsc024367 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Mon, 11 Jul 2011 12:56:57 -0400 Received: from tyan-ft48-01.lab.bos.redhat.com (tyan-ft48-01.lab.bos.redhat.com [10.16.42.4]) by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id p6BGX1Lw012316 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Mon, 11 Jul 2011 12:33:02 -0400 Received: from tyan-ft48-01.lab.bos.redhat.com (localhost.localdomain [127.0.0.1]) by tyan-ft48-01.lab.bos.redhat.com (8.14.4/8.14.4) with ESMTP id p6BGX1Mj007059; Mon, 11 Jul 2011 18:33:01 +0200 Received: (from jakub@localhost) by tyan-ft48-01.lab.bos.redhat.com (8.14.4/8.14.4/Submit) id p6BGX0Td007057; Mon, 11 Jul 2011 18:33:00 +0200 Date: Mon, 11 Jul 2011 18:33:00 +0200 From: Jakub Jelinek To: Jason Merrill , Richard Henderson Cc: gcc-patches@gcc.gnu.org Subject: [PATCH] Create smaller DWARF ops for some int_loc_descriptor constants etc. (PR debug/49676) Message-ID: <20110711163300.GJ2687@tyan-ft48-01.lab.bos.redhat.com> Reply-To: Jakub Jelinek 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! While working on the last dwarf2out.c patch, I've noticed we can generate more compact DWARF location descriptions in several cases, e.g. DW_OP_constu 0xf80000000 is 7 byts long, while DW_OP_lit31 DW_OP_lit31 DW_OP_shl pushes the same value to the stack and is just 3 bytes long. The patch adjusts {,size_of_}int_loc_descriptor to generate those and similar sequences when shorter (for case of the same length prefers single op over several smaller ops though). In addition to that, it attempts to optimize DW_OP_GNU_const_type into int_loc_descriptor + DW_OP_GNU_convert when possible, and optimizes DW_OP_plus_uconst into int_loc_descriptor (const) DW_OP_plus if the latter is shorter. On the attached testcase .debug_info on x86_64 -m64 shrunk from 1092 bytes to 986 bytes (i.e. almost 10% reduction, though on artificial testcase), and for -m32 it shrunk from 1440 to 1295 bytes. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2011-07-11 Jakub Jelinek PR debug/49676 * dwarf2out.c (int_shift_loc_descriptor): New function. (int_loc_descriptor): If shorter, emit i as (i >> shift), shift, DW_OP_shl for suitable shift value. Similarly, try to optimize large negative values using DW_OP_neg of a positive value if shorter. (size_of_int_shift_loc_descriptor): New function. (size_of_int_loc_descriptor): Adjust to match int_loc_descriptor changes. (mem_loc_descriptor) : Emit zero-extended constants that fit into DWARF2_ADDR_SIZE bytes as int_loc_descriptor + DW_OP_GNU_convert instead of DW_OP_GNU_const_type if the former is shorter. (resolve_addr_in_expr): Optimize DW_OP_plus_uconst with a large addend as added DW_OP_plus if it is shorter. Jakub --- gcc/dwarf2out.c.jj 2011-07-11 10:39:50.000000000 +0200 +++ gcc/dwarf2out.c 2011-07-11 14:38:07.000000000 +0200 @@ -10135,6 +10135,21 @@ multiple_reg_loc_descriptor (rtx rtl, rt return loc_result; } +static unsigned long size_of_int_loc_descriptor (HOST_WIDE_INT); + +/* Return a location descriptor that designates a constant i, + as a compound operation from constant (i >> shift), constant shift + and DW_OP_shl. */ + +static dw_loc_descr_ref +int_shift_loc_descriptor (HOST_WIDE_INT i, int shift) +{ + dw_loc_descr_ref ret = int_loc_descriptor (i >> shift); + add_loc_descr (&ret, int_loc_descriptor (shift)); + add_loc_descr (&ret, new_loc_descr (DW_OP_shl, 0, 0)); + return ret; +} + /* Return a location descriptor that designates a constant. */ static dw_loc_descr_ref @@ -10146,15 +10161,45 @@ int_loc_descriptor (HOST_WIDE_INT i) defaulting to the LEB encoding. */ if (i >= 0) { + int clz = clz_hwi (i); + int ctz = ctz_hwi (i); if (i <= 31) op = (enum dwarf_location_atom) (DW_OP_lit0 + i); else if (i <= 0xff) op = DW_OP_const1u; else if (i <= 0xffff) op = DW_OP_const2u; - else if (HOST_BITS_PER_WIDE_INT == 32 - || i <= 0xffffffff) + else if (clz + ctz >= HOST_BITS_PER_WIDE_INT - 5 + && clz + 5 + 255 >= HOST_BITS_PER_WIDE_INT) + /* DW_OP_litX DW_OP_litY DW_OP_shl takes just 3 bytes and + DW_OP_litX DW_OP_const1u Y DW_OP_shl takes just 4 bytes, + while DW_OP_const4u is 5 bytes. */ + return int_shift_loc_descriptor (i, HOST_BITS_PER_WIDE_INT - clz - 5); + else if (clz + ctz >= HOST_BITS_PER_WIDE_INT - 8 + && clz + 8 + 31 >= HOST_BITS_PER_WIDE_INT) + /* DW_OP_const1u X DW_OP_litY DW_OP_shl takes just 4 bytes, + while DW_OP_const4u is 5 bytes. */ + return int_shift_loc_descriptor (i, HOST_BITS_PER_WIDE_INT - clz - 8); + else if (HOST_BITS_PER_WIDE_INT == 32 || i <= 0xffffffff) op = DW_OP_const4u; + else if (clz + ctz >= HOST_BITS_PER_WIDE_INT - 8 + && clz + 8 + 255 >= HOST_BITS_PER_WIDE_INT) + /* DW_OP_const1u X DW_OP_const1u Y DW_OP_shl takes just 5 bytes, + while DW_OP_constu of constant >= 0x100000000 takes at least + 6 bytes. */ + return int_shift_loc_descriptor (i, HOST_BITS_PER_WIDE_INT - clz - 8); + else if (clz + ctz >= HOST_BITS_PER_WIDE_INT - 16 + && clz + 16 + (size_of_uleb128 (i) > 5 ? 255 : 31) + >= HOST_BITS_PER_WIDE_INT) + /* DW_OP_const2u X DW_OP_litY DW_OP_shl takes just 5 bytes, + DW_OP_const2u X DW_OP_const1u Y DW_OP_shl takes 6 bytes, + while DW_OP_constu takes in this case at least 6 bytes. */ + return int_shift_loc_descriptor (i, HOST_BITS_PER_WIDE_INT - clz - 16); + else if (clz + ctz >= HOST_BITS_PER_WIDE_INT - 32 + && clz + 32 + 31 >= HOST_BITS_PER_WIDE_INT + && size_of_uleb128 (i) > 6) + /* DW_OP_const4u X DW_OP_litY DW_OP_shl takes just 7 bytes. */ + return int_shift_loc_descriptor (i, HOST_BITS_PER_WIDE_INT - clz - 32); else op = DW_OP_constu; } @@ -10164,35 +10209,88 @@ int_loc_descriptor (HOST_WIDE_INT i) op = DW_OP_const1s; else if (i >= -0x8000) op = DW_OP_const2s; - else if (HOST_BITS_PER_WIDE_INT == 32 - || i >= -0x80000000) - op = DW_OP_const4s; + else if (HOST_BITS_PER_WIDE_INT == 32 || i >= -0x80000000) + { + if (size_of_int_loc_descriptor (i) < 5) + { + dw_loc_descr_ref ret = int_loc_descriptor (-i); + add_loc_descr (&ret, new_loc_descr (DW_OP_neg, 0, 0)); + return ret; + } + op = DW_OP_const4s; + } else - op = DW_OP_consts; + { + if (size_of_int_loc_descriptor (i) + < (unsigned long) 1 + size_of_sleb128 (i)) + { + dw_loc_descr_ref ret = int_loc_descriptor (-i); + add_loc_descr (&ret, new_loc_descr (DW_OP_neg, 0, 0)); + return ret; + } + op = DW_OP_consts; + } } return new_loc_descr (op, i, 0); } +/* Return size_of_locs (int_shift_loc_descriptor (i, shift)) + without actually allocating it. */ + +static unsigned long +size_of_int_shift_loc_descriptor (HOST_WIDE_INT i, int shift) +{ + return size_of_int_loc_descriptor (i >> shift) + + size_of_int_loc_descriptor (shift) + + 1; +} + /* Return size_of_locs (int_loc_descriptor (i)) without actually allocating it. */ static unsigned long size_of_int_loc_descriptor (HOST_WIDE_INT i) { + unsigned long s; + if (i >= 0) { + int clz, ctz; if (i <= 31) return 1; else if (i <= 0xff) return 2; else if (i <= 0xffff) return 3; - else if (HOST_BITS_PER_WIDE_INT == 32 - || i <= 0xffffffff) + clz = clz_hwi (i); + ctz = ctz_hwi (i); + if (clz + ctz >= HOST_BITS_PER_WIDE_INT - 5 + && clz + 5 + 255 >= HOST_BITS_PER_WIDE_INT) + return size_of_int_shift_loc_descriptor (i, HOST_BITS_PER_WIDE_INT + - clz - 5); + else if (clz + ctz >= HOST_BITS_PER_WIDE_INT - 8 + && clz + 8 + 31 >= HOST_BITS_PER_WIDE_INT) + return size_of_int_shift_loc_descriptor (i, HOST_BITS_PER_WIDE_INT + - clz - 8); + else if (HOST_BITS_PER_WIDE_INT == 32 || i <= 0xffffffff) return 5; + s = size_of_uleb128 ((unsigned HOST_WIDE_INT) i); + if (clz + ctz >= HOST_BITS_PER_WIDE_INT - 8 + && clz + 8 + 255 >= HOST_BITS_PER_WIDE_INT) + return size_of_int_shift_loc_descriptor (i, HOST_BITS_PER_WIDE_INT + - clz - 8); + else if (clz + ctz >= HOST_BITS_PER_WIDE_INT - 16 + && clz + 16 + (s > 5 ? 255 : 31) >= HOST_BITS_PER_WIDE_INT) + return size_of_int_shift_loc_descriptor (i, HOST_BITS_PER_WIDE_INT + - clz - 16); + else if (clz + ctz >= HOST_BITS_PER_WIDE_INT - 32 + && clz + 32 + 31 >= HOST_BITS_PER_WIDE_INT + && s > 6) + return size_of_int_shift_loc_descriptor (i, HOST_BITS_PER_WIDE_INT + - clz - 32); else - return 1 + size_of_uleb128 ((unsigned HOST_WIDE_INT) i); + return 1 + s; } else { @@ -10200,11 +10298,27 @@ size_of_int_loc_descriptor (HOST_WIDE_IN return 2; else if (i >= -0x8000) return 3; - else if (HOST_BITS_PER_WIDE_INT == 32 - || i >= -0x80000000) - return 5; + else if (HOST_BITS_PER_WIDE_INT == 32 || i >= -0x80000000) + { + if (-(unsigned HOST_WIDE_INT) i != (unsigned HOST_WIDE_INT) i) + { + s = size_of_int_loc_descriptor (-i) + 1; + if (s < 5) + return s; + } + return 5; + } else - return 1 + size_of_sleb128 (i); + { + unsigned long r = 1 + size_of_sleb128 (i); + if (-(unsigned HOST_WIDE_INT) i != (unsigned HOST_WIDE_INT) i) + { + s = size_of_int_loc_descriptor (-i) + 1; + if (s < r) + return s; + } + return r; + } } } @@ -11818,8 +11932,27 @@ mem_loc_descriptor (rtx rtl, enum machin || GET_MODE_BITSIZE (mode) == 2 * HOST_BITS_PER_WIDE_INT)) { dw_die_ref type_die = base_type_for_mode (mode, 1); + enum machine_mode amode; if (type_die == NULL) return NULL; + amode = mode_for_size (DWARF2_ADDR_SIZE * BITS_PER_UNIT, + MODE_INT, 0); + if (INTVAL (rtl) >= 0 + && amode != BLKmode + && trunc_int_for_mode (INTVAL (rtl), amode) == INTVAL (rtl) + /* const DW_OP_GNU_convert vs. + DW_OP_GNU_const_type . */ + && size_of_int_loc_descriptor (INTVAL (rtl)) + 1 + 1 + < (unsigned long) 1 + 1 + 1 + GET_MODE_SIZE (mode)) + { + mem_loc_result = int_loc_descriptor (INTVAL (rtl)); + op0 = new_loc_descr (DW_OP_GNU_convert, 0, 0); + op0->dw_loc_oprnd1.val_class = dw_val_class_die_ref; + op0->dw_loc_oprnd1.v.val_die_ref.die = type_die; + op0->dw_loc_oprnd1.v.val_die_ref.external = 0; + add_loc_descr (&mem_loc_result, op0); + return mem_loc_result; + } mem_loc_result = new_loc_descr (DW_OP_GNU_const_type, 0, INTVAL (rtl)); mem_loc_result->dw_loc_oprnd1.val_class = dw_val_class_die_ref; @@ -20962,6 +21095,19 @@ resolve_addr_in_expr (dw_loc_descr_ref l && resolve_one_addr (&loc->dw_loc_oprnd1.v.val_addr, NULL)) return false; break; + case DW_OP_plus_uconst: + if (size_of_loc_descr (loc) + > size_of_int_loc_descriptor (loc->dw_loc_oprnd1.v.val_unsigned) + + 1 + && loc->dw_loc_oprnd1.v.val_unsigned > 0) + { + dw_loc_descr_ref repl + = int_loc_descriptor (loc->dw_loc_oprnd1.v.val_unsigned); + add_loc_descr (&repl, new_loc_descr (DW_OP_plus, 0, 0)); + add_loc_descr (&repl, loc->dw_loc_next); + *loc = *repl; + } + break; case DW_OP_implicit_value: if (loc->dw_loc_oprnd2.val_class == dw_val_class_addr && resolve_one_addr (&loc->dw_loc_oprnd2.v.val_addr, NULL)) --- gcc/testsuite/gcc.dg/guality/csttest.c.jj 2011-07-11 13:55:12.000000000 +0200 +++ gcc/testsuite/gcc.dg/guality/csttest.c 2011-07-11 14:20:00.000000000 +0200 @@ -0,0 +1,63 @@ +/* PR debug/49676 */ +/* { dg-do run { target lp64 } } */ +/* { dg-options "-g" } */ + +volatile int v; + +__attribute__((noinline, noclone)) +unsigned long long +foo (unsigned long long x) +{ + unsigned long long a = x * (0x17ULL << 31); /* { dg-final { gdb-test 29 "a" "(0x17ULL << 31)" } } */ + unsigned long long b = x * (0x7ULL << 33); /* { dg-final { gdb-test 29 "b" "(0x7ULL << 33)" } } */ + unsigned long long c = x * (0x1ULL << 35); /* { dg-final { gdb-test 29 "c" "(0x1ULL << 35)" } } */ + unsigned long long d = x * (0x17ULL << 15); /* { dg-final { gdb-test 29 "d" "(0x17ULL << 15)" } } */ + unsigned long long e = x * (0x17ULL << 50); /* { dg-final { gdb-test 29 "e" "(0x17ULL << 50)" } } */ + unsigned long long f = x * (0x37ULL << 31); /* { dg-final { gdb-test 29 "f" "(0x37ULL << 31)" } } */ + unsigned long long g = x * (0x37ULL << 50); /* { dg-final { gdb-test 29 "g" "(0x37ULL << 50)" } } */ + unsigned long long h = x * (0x1efULL << 33); /* { dg-final { gdb-test 29 "h" "(0x1efULL << 33)" } } */ + unsigned long long i = x * (0x1efULL << 50); /* { dg-final { gdb-test 29 "i" "(0x1efULL << 50)" } } */ + unsigned long long j = x * -(0x17ULL << 31); /* { dg-final { gdb-test 29 "j" "-(0x17ULL << 31)" } } */ + unsigned long long k = x * -(0x7ULL << 33); /* { dg-final { gdb-test 29 "k" "-(0x7ULL << 33)" } } */ + unsigned long long l = x * -(0x1ULL << 35); /* { dg-final { gdb-test 29 "l" "-(0x1ULL << 35)" } } */ + unsigned long long m = x * -(0x17ULL << 15); /* { dg-final { gdb-test 29 "m" "-(0x17ULL << 15)" } } */ + unsigned long long n = x * -(0x17ULL << 50); /* { dg-final { gdb-test 29 "n" "-(0x17ULL << 50)" } } */ + unsigned long long o = x * -(0x37ULL << 31); /* { dg-final { gdb-test 29 "o" "-(0x37ULL << 31)" } } */ + unsigned long long p = x * -(0x37ULL << 50); /* { dg-final { gdb-test 29 "p" "-(0x37ULL << 50)" } } */ + unsigned long long q = x * -(0x1efULL << 33); /* { dg-final { gdb-test 29 "q" "-(0x1efULL << 33)" } } */ + unsigned long long r = x * -(0x1efULL << 50); /* { dg-final { gdb-test 29 "r" "-(0x1efULL << 50)" } } */ + v++; + return x; +} + +__attribute__((noinline, noclone)) +unsigned long long +bar (unsigned long long x) +{ + unsigned long long a = (x & 255) + (0x17ULL << 31); /* { dg-final { gdb-test 55 "a" "(0x17ULL << 31)" } } */ + unsigned long long b = (x & 255) + (0x7ULL << 33); /* { dg-final { gdb-test 55 "b" "(0x7ULL << 33)" } } */ + unsigned long long c = (x & 255) + (0x1ULL << 35); /* { dg-final { gdb-test 55 "c" "(0x1ULL << 35)" } } */ + unsigned long long d = (x & 255) + (0x17ULL << 15); /* { dg-final { gdb-test 55 "d" "(0x17ULL << 15)" } } */ + unsigned long long e = (x & 255) + (0x17ULL << 50); /* { dg-final { gdb-test 55 "e" "(0x17ULL << 50)" } } */ + unsigned long long f = (x & 255) + (0x37ULL << 31); /* { dg-final { gdb-test 55 "f" "(0x37ULL << 31)" } } */ + unsigned long long g = (x & 255) + (0x37ULL << 50); /* { dg-final { gdb-test 55 "g" "(0x37ULL << 50)" } } */ + unsigned long long h = (x & 255) + (0x1efULL << 33); /* { dg-final { gdb-test 55 "h" "(0x1efULL << 33)" } } */ + unsigned long long i = (x & 255) + (0x1efULL << 50); /* { dg-final { gdb-test 55 "i" "(0x1efULL << 50)" } } */ + unsigned long long j = (x & 255) + -(0x17ULL << 31); /* { dg-final { gdb-test 55 "j" "-(0x17ULL << 31)" } } */ + unsigned long long k = (x & 255) + -(0x7ULL << 33); /* { dg-final { gdb-test 55 "k" "-(0x7ULL << 33)" } } */ + unsigned long long l = (x & 255) + -(0x1ULL << 35); /* { dg-final { gdb-test 55 "l" "-(0x1ULL << 35)" } } */ + unsigned long long m = (x & 255) + -(0x17ULL << 15); /* { dg-final { gdb-test 55 "m" "-(0x17ULL << 15)" } } */ + unsigned long long n = (x & 255) + -(0x17ULL << 50); /* { dg-final { gdb-test 55 "n" "-(0x17ULL << 50)" } } */ + unsigned long long o = (x & 255) + -(0x37ULL << 31); /* { dg-final { gdb-test 55 "o" "-(0x37ULL << 31)" } } */ + unsigned long long p = (x & 255) + -(0x37ULL << 50); /* { dg-final { gdb-test 55 "p" "-(0x37ULL << 50)" } } */ + unsigned long long q = (x & 255) + -(0x1efULL << 33); /* { dg-final { gdb-test 55 "q" "-(0x1efULL << 33)" } } */ + unsigned long long r = (x & 255) + -(0x1efULL << 50); /* { dg-final { gdb-test 55 "r" "-(0x1efULL << 50)" } } */ + v++; + return x; +} + +int +main () +{ + return foo (1) + bar (256) - 257; +}