re PR debug/49676 (inefficiency: DW_AT_GNU_call_site_value calculates everything << 32)

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) <case CONST_INT>: 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.

	* gcc.dg/guality/csttest.c: New test.

From-SVN: r176167
This commit is contained in:
Jakub Jelinek 2011-07-11 18:57:25 +02:00 committed by Jakub Jelinek
parent 932ebb945f
commit 96ae7458c0
4 changed files with 243 additions and 13 deletions

View File

@ -1,3 +1,21 @@
2011-07-11 Jakub Jelinek <jakub@redhat.com>
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) <case CONST_INT>: 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.
2011-07-11 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
* config/i386/sol2.h [!USE_GLD] (CTORS_SECTION_ASM_OP): Define.

View File

@ -10135,6 +10135,21 @@ multiple_reg_loc_descriptor (rtx rtl, rtx regs,
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_INT i)
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 machine_mode mode,
|| 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 <XXX> vs.
DW_OP_GNU_const_type <XXX, 1, const>. */
&& 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 loc)
&& 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))

View File

@ -1,5 +1,8 @@
2011-07-11 Jakub Jelinek <jakub@redhat.com>
PR debug/49676
* gcc.dg/guality/csttest.c: New test.
PR fortran/49698
* gfortran.dg/pr49698.f90: New test.

View File

@ -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;
}