summaryrefslogtreecommitdiff
path: root/gcc/dwarf2out.c
diff options
context:
space:
mode:
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2011-07-11 16:57:25 +0000
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2011-07-11 16:57:25 +0000
commitd89f182d5175ef56fcf5a8388c48d964b3c3aa74 (patch)
tree755f987ded70868d77d0a6f6d647ab846363e287 /gcc/dwarf2out.c
parent1edb55c86493dbfd1f57a3e41536673fb66588d6 (diff)
downloadgcc-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.c172
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))