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 /gcc/dwarf2out.c | |
parent | 1edb55c86493dbfd1f57a3e41536673fb66588d6 (diff) | |
download | gcc-d89f182d5175ef56fcf5a8388c48d964b3c3aa74.tar.gz |
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
Diffstat (limited to 'gcc/dwarf2out.c')
-rw-r--r-- | gcc/dwarf2out.c | 172 |
1 files changed, 159 insertions, 13 deletions
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)) |