re PR debug/49676 (inefficiency: DW_AT_GNU_call_site_value calculates everything...
authorJakub Jelinek <jakub@redhat.com>
Mon, 11 Jul 2011 16:57:25 +0000 (18:57 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Mon, 11 Jul 2011 16:57:25 +0000 (18:57 +0200)
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.

From-SVN: r176167

gcc/ChangeLog
gcc/dwarf2out.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/guality/csttest.c [new file with mode: 0644]

index e7b4a592b07dfdcb1969b0ab90270d60a26a64a3..4552b3df3d70d83799a9a22395190177956c48ac 100644 (file)
@@ -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.
index 64695060c3b0a9b18c1b81601bdde01dab47a43c..f9a1e70e58010af8e9199bebab9b3b289611bd19 100644 (file)
@@ -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))
index 36c375d7f202ca5fa20d7d920ec53a66afcb5e0b..6c76e33b934f5f2305b5e63eeacae35c782a33ff 100644 (file)
@@ -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 (file)
index 0000000..4480c71
--- /dev/null
@@ -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;
+}