DWARF: space-optimize loc. descr. for integer literals on 32-bit targets
authorPierre-Marie de Rodat <derodat@adacore.com>
Wed, 12 Oct 2016 08:38:49 +0000 (08:38 +0000)
committerPierre-Marie de Rodat <pmderodat@gcc.gnu.org>
Wed, 12 Oct 2016 08:38:49 +0000 (08:38 +0000)
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
gcc/dwarf2out.c
gcc/testsuite/ChangeLog
gcc/testsuite/gnat.dg/debug8.adb [new file with mode: 0644]

index b390896..c5a982e 100644 (file)
@@ -1,5 +1,12 @@
 2016-10-12  Pierre-Marie de Rodat  <derodat@adacore.com>
 
+       * 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  <derodat@adacore.com>
+
        * dwarf2out.c (dwarf2out_early_global_decl): For nested
        functions, call dwarf2out_decl on the parent function first.
 
index f03e9aa..b5787ef 100644 (file)
@@ -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);
index 27d8413..4a991d9 100644 (file)
@@ -1,5 +1,9 @@
 2016-10-12  Pierre-Marie de Rodat  <derodat@adacore.com>
 
+       * gnat.dg/debug8.adb: New testcase.
+
+2016-10-12  Pierre-Marie de Rodat  <derodat@adacore.com>
+
        * gnat.dg/debug9.adb: New testcase.
 
 2016-10-12  Richard Biener  <rguenther@suse.de>
diff --git a/gcc/testsuite/gnat.dg/debug8.adb b/gcc/testsuite/gnat.dg/debug8.adb
new file mode 100644 (file)
index 0000000..fabcc22
--- /dev/null
@@ -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;