This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Basic infrastructure for substitution tracking


> 
> This seems to duplicate what DEBUG_STMTs do.  Can you convince me
> otherwise by providing an actual example and explaining what your code
> will do?

Yes, the tracking is sort of subset of what DEBUG_STMT does.  The main
difference is that tracking declare that "everywhere the variable was
defined, it is replaced by this expression" function wide. One don't
need duplicated declaration nor the statement and thus is a lot cheaper
and can handle common cases (plus tree-sra that seem to be bit difficult
to fit into debug-stmt code).

It is also bit more robust too, since debug_stmts inserted at the random
places of program (entry points of inlined functions) might drift away.

Lets take following expample "C++"

struct a{
  struct b {int a;} b;
  struct c{ int a;} c;
};

static void
t1 (struct b *a, int b)
{
  printf ("%i %i\n",a, b);
}
static void
t2 (struct c *a, char *msg)
{
  printf ("%i %s\n",a,msg);
}
static void
t3 (struct a *a)
{
  t1(&a->b, 1);
  t2(&a->c, "test");
}
struct a a={{0},{1}};
main()
{
  t3(&a);
}

Now what happens is that early inliner inlines t1+t2 into t3 and later
we inline t3 into main. With inline subtitution we can track these
changes as follows

;; Function t3 (t3)

Scope blocks after cleanups:

{ Scope block #0 

  { Scope block #2 t.c:20 Originating from :  static void t2 (struct c *, char *); 
    struct c * a = struct c *; [value-expr: &a->c ] (nonlocalized)
    char * msg = char *; [value-expr: &"test"[0] ] (nonlocalized)

    { Scope block #3 Originating from :#0 
      extern int printf (void); (nonlocalized)

    }

  }

  { Scope block #4 t.c:19 Originating from :  static void t1 (struct b *, int); 
    struct b * a = struct b *; [value-expr: &a->b ] (nonlocalized)
    int b = int; [value-expr: 1 ] (nonlocalized)

    { Scope block #5 Originating from :#0 
      extern int printf (void); (nonlocalized)

    }

  }

}
t3 (struct a * a)
{
  struct c * D.2721;
  struct b * D.2720;

<bb 2>:
  D.2720_2 = &a_1(D)->b;
  printf (&"%i %i\n"[0], D.2720_2, 1);
  D.2721_3 = &a_1(D)->c;
  printf (&"%i %s\n"[0], D.2721_3, &"test"[0]);
  return;

}

And later we get into main:

Scope blocks after cleanups:

{ Scope block #0 

  { Scope block #6 t.c:25 Originating from :  static void t3 (struct a *); 
    struct a * a = struct a *; [value-expr: &a ] (nonlocalized)

    { Scope block #7 Originating from :#0 

      { Scope block #8 t.c:20 Originating from :  static void t2 (struct c *, char *); 
        struct c * a = struct c *; [value-expr: &a.c ] (nonlocalized)
        char * msg = char *; [value-expr: &"test"[0] ] (nonlocalized)

        { Scope block #9 Originating from :#0 
          extern int printf (void); (nonlocalized)

        }

      }

      { Scope block #10 t.c:19 Originating from :  static void t1 (struct b *, int); 
        struct b * a = struct b *; [value-expr: &a.b ] (nonlocalized)
        int b = int; [value-expr: 1 ] (nonlocalized)

        { Scope block #11 Originating from :#0 
          extern int printf (void); (nonlocalized)

        }

      }

    }

  }

}

Now dwarf2out can annotate all the user vars

	.uleb128 0xf	# (DIE (0x166) DW_TAG_formal_parameter)
	.long	0x11f	# DW_AT_abstract_origin
	.quad	a	# DW_AT_const_value
	.uleb128 0x10	# (DIE (0x173) DW_TAG_inlined_subroutine)
	.long	0xd1	# DW_AT_abstract_origin
	.quad	.LBB13	# DW_AT_entry_pc
	.long	.Ldebug_ranges0+0x30	# DW_AT_ranges
	.byte	0x1	# DW_AT_call_file (t.c)
	.byte	0x14	# DW_AT_call_line
	.long	0x1b6	# DW_AT_sibling
	.uleb128 0x11	# (DIE (0x18a) DW_TAG_formal_parameter)
	.long	0xdd	# DW_AT_abstract_origin
	.byte	0xe	# DW_AT_location
	.byte	0x3	# DW_OP_addr
	.quad	a
	.byte	0x23	# DW_OP_plus_uconst
	.uleb128 0x4
	.byte	0x9f	# DW_OP_stack_value
	.byte	0x93	# DW_OP_piece
	.uleb128 0x8
	.uleb128 0x11	# (DIE (0x19e) DW_TAG_formal_parameter)
	.long	0xe6	# DW_AT_abstract_origin
	.byte	0xc	# DW_AT_location
	.byte	0x3	# DW_OP_addr
	.quad	.LC1
	.byte	0x9f	# DW_OP_stack_value
	.byte	0x93	# DW_OP_piece
	.uleb128 0x8
	.uleb128 0x12	# (DIE (0x1b0) DW_TAG_lexical_block)
	.long	.Ldebug_ranges0+0x60	# DW_AT_ranges
	.byte	0x0	# end of children of DIE 0x173
	.uleb128 0x13	# (DIE (0x1b6) DW_TAG_inlined_subroutine)
	.long	0x85	# DW_AT_abstract_origin
	.quad	.LBB16	# DW_AT_low_pc
	.quad	.LBE16	# DW_AT_high_pc
	.byte	0x1	# DW_AT_call_file (t.c)
	.byte	0x13	# DW_AT_call_line
	.uleb128 0x11	# (DIE (0x1cd) DW_TAG_formal_parameter)
	.long	0x91	# DW_AT_abstract_origin
	.byte	0xc	# DW_AT_location
	.byte	0x3	# DW_OP_addr
	.quad	a
	.byte	0x9f	# DW_OP_stack_value
	.byte	0x93	# DW_OP_piece
	.uleb128 0x8
	.uleb128 0x14	# (DIE (0x1df) DW_TAG_formal_parameter)
	.long	0x9a	# DW_AT_abstract_origin
	.byte	0x1	# DW_AT_const_value
	.uleb128 0x15	# (DIE (0x1e5) DW_TAG_lexical_block)
	.quad	.LBB17	# DW_AT_low_pc
	.quad	.LBE17	# DW_AT_high_pc
	.byte	0x0	# end of children of DIE 0x1b6
	.byte	0x0	# end of children of DIE 0x153
	.byte	0x0	# end of children of DIE 0x12f

And this happens with significandly less overhead than with debug
statements plus we can avoid building the statements when not
optimizing.  With -O2 -g I get 450MB->320MB of memory use for
integration and variable tracking goes from 40MB to 30MB. (with
producing 10 times more locations in debug info that we do on mainline)

Memory usage is 460->440 for generate-3.4.ii and 20K savings for
combine.c at -O3 (so the code really helps saving many debug statemetns
only with C++, but that is expected).

With GDB with inline tracking and DW_OP_stack_value support (I don't
have this one, but by combining current mainline and gdb with inline
tracking I can pretty much approximate this) I can single step through
the whole sequence and get proper values minus the fact that backtraces
are missing arguments since ipa-cp is not yet updated to record the
removed arguments for debug info.  With -fno-ipa-cp -O2 -g I get pretty
nice results and I plan to update ipa-cp shortly (it can even be
declared regression and is not too difficult to do: we just need to keep
track of arguments being removed and teach dwarf2out to re-build
original sequence when producing formal parameter list).

On current mainline we work hard enough to get all the DEBUG_INSNSs at
the place but for some reason we fail to produce useful debug info.  I
am looking it it now.

Honza


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]