From b4a9ef2f4d68a5a10f4c87c9f416562bf5f59d35 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 12 Oct 2016 08:38:49 +0000 Subject: [PATCH] DWARF: space-optimize loc. descr. for integer literals on 32-bit targets This enhances location description generation so that the generated opcodes for integer literals are as space-efficient when HOST_WIDE_INT is 64-bits large than when it's 32-bits large. In particular, this reduces the size of the opcodes generated to produce big unsigned literals using small literal integers instead. gcc/ * dwarf2out.c (int_loc_descriptor): Generate opcodes for another equivalent 32-bit constant (modulo 2**32) when that yields smaller instructions. (size_of_int_loc_descriptor): Update accordingly. gcc/testsuite/ * gnat.dg/debug8.adb: New testcase. From-SVN: r241024 --- gcc/ChangeLog | 7 +++++++ gcc/dwarf2out.c | 29 ++++++++++++++++++++++++----- gcc/testsuite/ChangeLog | 4 ++++ gcc/testsuite/gnat.dg/debug8.adb | 29 +++++++++++++++++++++++++++++ 4 files changed, 64 insertions(+), 5 deletions(-) create mode 100644 gcc/testsuite/gnat.dg/debug8.adb diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b39089633f1..c5a982ee70f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2016-10-12 Pierre-Marie de Rodat + + * dwarf2out.c (int_loc_descriptor): Generate opcodes for another + equivalent 32-bit constant (modulo 2**32) when that yields + smaller instructions. + (size_of_int_loc_descriptor): Update accordingly. + 2016-10-12 Pierre-Marie de Rodat * dwarf2out.c (dwarf2out_early_global_decl): For nested diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index f03e9aa4f2f..b5787ef607c 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -11985,20 +11985,35 @@ int_loc_descriptor (HOST_WIDE_INT i) /* 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 (DWARF2_ADDR_SIZE == 4 && i > 0x7fffffff + && size_of_int_loc_descriptor ((HOST_WIDE_INT) (int32_t) i) + <= 4) + { + /* As i >= 2**31, the double cast above will yield a negative number. + Since wrapping is defined in DWARF expressions we can output big + positive integers as small negative ones, regardless of the size + of host wide ints. + + Here, since the evaluator will handle 32-bit values and since i >= + 2**31, we know it's going to be interpreted as a negative literal: + store it this way if we can do better than 5 bytes this way. */ + return int_loc_descriptor ((HOST_WIDE_INT) (int32_t) i); + } else if (HOST_BITS_PER_WIDE_INT == 32 || i <= 0xffffffff) op = DW_OP_const4u; + + /* Past this point, i >= 0x100000000 and thus DW_OP_constu will take at + least 6 bytes: see if we can do better before falling back to it. */ 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. */ + /* DW_OP_const1u X DW_OP_const1u Y DW_OP_shl takes just 5 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. */ + DW_OP_const2u X DW_OP_const1u Y DW_OP_shl takes 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 @@ -12223,6 +12238,10 @@ size_of_int_loc_descriptor (HOST_WIDE_INT i) && 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 (DWARF2_ADDR_SIZE == 4 && i > 0x7fffffff + && size_of_int_loc_descriptor ((HOST_WIDE_INT) (int32_t) i) + <= 4) + return size_of_int_loc_descriptor ((HOST_WIDE_INT) (int32_t) i); else if (HOST_BITS_PER_WIDE_INT == 32 || i <= 0xffffffff) return 5; s = size_of_uleb128 ((unsigned HOST_WIDE_INT) i); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 27d84131b0f..4a991d9ec43 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2016-10-12 Pierre-Marie de Rodat + + * gnat.dg/debug8.adb: New testcase. + 2016-10-12 Pierre-Marie de Rodat * gnat.dg/debug9.adb: New testcase. diff --git a/gcc/testsuite/gnat.dg/debug8.adb b/gcc/testsuite/gnat.dg/debug8.adb new file mode 100644 index 00000000000..fabcc22d06f --- /dev/null +++ b/gcc/testsuite/gnat.dg/debug8.adb @@ -0,0 +1,29 @@ +-- { dg-do compile } +-- { dg-options "-cargs -g -fgnat-encodings=minimal -dA" } +-- { dg-final { scan-assembler-not "DW_OP_const4u" } } +-- { dg-final { scan-assembler-not "DW_OP_const8u" } } + +-- The DW_AT_byte_size attribute DWARF expression for the +-- DW_TAG_structure_type DIE that describes Rec_Type contains the -4u literal. +-- Check that it is not created using an inefficient encoding (DW_OP_const1s +-- is expected). + +procedure Debug8 is + + type Rec_Type (I : Integer) is record + B : Boolean; + case I is + when 0 => + null; + when 1 .. 10 => + C : Character; + when others => + N : Natural; + end case; + end record; + + R : access Rec_Type := null; + +begin + null; +end Debug8; -- 2.30.2