diff options
author | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2011-07-11 16:57:25 +0000 |
---|---|---|
committer | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2011-07-11 16:57:25 +0000 |
commit | d89f182d5175ef56fcf5a8388c48d964b3c3aa74 (patch) | |
tree | 755f987ded70868d77d0a6f6d647ab846363e287 | |
parent | 1edb55c86493dbfd1f57a3e41536673fb66588d6 (diff) | |
download | ppe42-gcc-d89f182d5175ef56fcf5a8388c48d964b3c3aa74.tar.gz ppe42-gcc-d89f182d5175ef56fcf5a8388c48d964b3c3aa74.zip |
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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@176167 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/ChangeLog | 18 | ||||
-rw-r--r-- | gcc/dwarf2out.c | 172 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 3 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/guality/csttest.c | 63 |
4 files changed, 243 insertions, 13 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e7b4a592b07..4552b3df3d7 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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. diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 64695060c3b..f9a1e70e580 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -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)) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 36c375d7f20..6c76e33b934 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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. diff --git a/gcc/testsuite/gcc.dg/guality/csttest.c b/gcc/testsuite/gcc.dg/guality/csttest.c new file mode 100644 index 00000000000..4480c715e35 --- /dev/null +++ b/gcc/testsuite/gcc.dg/guality/csttest.c @@ -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; +} |