rtlopt merge part 4 - variable tracking pass

Jan Hubicka jh@suse.cz
Tue Jan 28 21:53:00 GMT 2003


> Hi,
> 
> this is a pass which computes where the variables are located at each
> position in code and generates notes (NOTE_INSN_VAR_LOCATION)
> which describe the location.
> 
> In final_scan_insn, var_location debug hook is called for each such a note.
> Currently all debug hooks are set to debug_nothing_rtx so no debug information
> is generated by this patch.
> 
> Variable tracking is run by default when compiling with optimization, debug info
> and if debug_hooks->var_location != debug_nothing_rtx,
> so when I was bootstrapping this patch I have enabled variable tracking to be
> run always.
> 
> Bootstrapped/regtested i386(athlon).
> 
> Josef
> 
> 2003-01-27  Josef Zlomek  <zlomekj@suse.cz>
> 
> 	* Makefile.in (var-tracking.o): New.
> 	* debug.h, dbxout.c, debug.c, dwarf2out.c, dwarfout.c, sdbout.c,
> 	vmsdbgout.c (struct gcc_debug_hooks): Added var_location debug hook.
> 	* final.c (final_scan_insn): Call var_location debug hook for each
> 	NOTE_INSN_VAR_LOCATION.
> 	* gengtype.c (adjust_field_rtx_def): NOTE_INSN_VAR_LOCATION was added.
> 	* print-rtl.c (print_rtx): Likewise.
> 	* rtl.c (note_insn_name): Likewise.
> 	* rtl.def (VAR_LOCATION): New.
> 	* rtl.h (NOTE_VAR_LOCATION): New.
> 	(NOTE_VAR_LOCATION_DECL): New.
> 	(NOTE_VAR_LOCATION_LOC): New.
> 	(insn_note): NOTE_INSN_VAR_LOCATION was added.
> 	(variable_tracking_main): New exported function.
> 	* timevar.def (TV_VAR_TRACKING): New.
> 	* toplev.c (DFI_vartrack): New.
> 	(dump_file): "vartrack" was added (-dV).
> 	(flag_var_tracking): New.
> 	(f_options): "var-tracking" was added.
> 	(rest_of_compilation): Run variable tracking.
> 	(process_options): If user has not specified flag_var_tracking
> 	set it according to optimize, debug_info_level and debug_hooks.
> 	* var-tracking.c: New file.
> 	* doc/invoke.texi: Added -dV and -fvar-tracking.
> 	* doc/passes.texi: Added variable tracking pass.
> 
Thanks for all the busy work!
Few comments (sorry for being so late)
> Index: var-tracking.c
> ===================================================================
> RCS file: var-tracking.c
> diff -N var-tracking.c
> *** /dev/null	1 Jan 1970 00:00:00 -0000
> --- var-tracking.c	27 Jan 2003 08:16:43 -0000
> ***************
> *** 0 ****
> --- 1,1643 ----
> + /* Variable tracking routines for the GNU compiler.
> +    Copyright (C) 2002, 2003 Free Software Foundation, Inc.
> + 
> +    This file is part of GCC.
> + 
> +    GCC is free software; you can redistribute it and/or modify it
> +    under the terms of the GNU General Public License as published by
> +    the Free Software Foundation; either version 2, or (at your option)
> +    any later version.
> + 
> +    GCC is distributed in the hope that it will be useful, but WITHOUT
> +    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
> +    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
> +    License for more details.
> + 
> +    You should have received a copy of the GNU General Public License
> +    along with GCC; see the file COPYING.  If not, write to the Free
> +    Software Foundation, 59 Temple Place - Suite 330, Boston, MA
> +    02111-1307, USA.  */

Some overall comment about how does the algorithm work would fit here
well.  It is quite nonobvious even for someone who understand how it
should work overall :)
It would also be nice to bring introduction to terminology - like what
is a attribute and so on.
> + /* The purpose that the location (REG or MEM) has in RTL.  */
> + enum location_type
> + {
> +   LT_PARAM,	/* Location is a parameter of instruction.  */

Maybe LT_USE is more common name, so it don't get confused with function
parameters.

> +   LT_SET_DEST,	/* Location is the destination of the SET.  */
> +   LT_CLOBBERED	/* Location is the "destination" of CLOBBER.  */
> + };
> + /* Insert the triplet DECL, OFFSET, LOC to the list *LISTP.  */
> + 
> + static void
> + attrs_list_insert (listp, decl, offset, loc)
> +      attrs_list *listp;
> +      tree decl;
> +      HOST_WIDE_INT offset;
> +      rtx loc;
> + {
> +   attrs_list list;
> + 
> +   list = xmalloc (sizeof (*list));
> +   list->loc = loc;
> +   list->decl = decl;
> +   list->offset = offset;
> +   list->next = *listp;

It may make sense to use Daniel's allocpool for attributes.
> + 
> + /* Scan rtx X for registers and memory references. Other parameters are
> +    in struct scan_for_locations_data passed in DATA.  */
> + 
> + static int
> + scan_for_locations (x, data)
> +      rtx *x;
> +      void *data;
> + {
> +   scan_for_locations_data *d = (scan_for_locations_data *) data;
> +   basic_block bb = BLOCK_FOR_INSN (d->insn);
> +   location *l;
> +   enum location_type old_type;
> + 
> +   switch (d->oper)
> +     {
> +       case SO_SKIP:	/* Do not process current rtx X.  */
> + 	/* Store the locations from subexpressions.  */
> + 	d->oper = SO_STORE;
> + 	return 0;
> + 
> +       case SO_COUNT:	/* Count the locations.  */
> + 	switch (GET_CODE (*x))
> + 	  {
> + 	    case REG:
> + #ifdef ENABLE_CHECKING
> + 	      if (REGNO (*x) >= FIRST_PSEUDO_REGISTER)
> + 		abort ();
> + #endif
> + 	      VTI (bb)->n_locs++;
> + 	      /* Continue traversing.  */
> + 	      return 0;
> + 
> + 	    case MEM:
> + 	      if (MEM_EXPR (*x) && track_expr_p (MEM_EXPR (*x)))
> + 		VTI (bb)->n_locs++;
> + 	      /* Continue traversing.  */
> + 	      return 0;
> + 
> + 	    default:
> + 	      /* Continue traversing.  */
> + 	      return 0;
> + 	  }
> + 	break;
> + 
> +       case SO_STORE:	/* Store the locations.  */
> + 	switch (GET_CODE (*x))
> + 	  {
> + 	    case SET:
> + 	      old_type = d->type;
> + 	      d->type = LT_PARAM;
> + 	      for_each_rtx (&SET_SRC (*x), scan_for_locations, data);
> + 	      d->type = LT_SET_DEST;
> + 	      for_each_rtx (&SET_DEST (*x), scan_for_locations, data);
> + 	      d->type = old_type;
> + 	      /* Do not traverse sub-expressions.  */
> + 	      return -1;
> + 
> + 	    case CLOBBER:
> + 	      old_type = d->type;
> + 	      d->type = LT_CLOBBERED;
> + 	      for_each_rtx (&SET_DEST (*x), scan_for_locations, data);
> + 	      d->type = old_type;
> + 	      /* Do not traverse sub-expressions.  */
> + 	      return -1;

This is somewhat unsafe, because SETs and CLOBBERs may contain uses in
bit non-obvious ways (such as zero_extract expression).  It would be
better to use note_stores to notice the outputs from instruction - you
will get called always to the toplevel construction (subreg, reg or mem
if I remmeber correctly).  Similarry we do have note_uses to get
expressions that are only reffered into.  You will get called always for
the outermost expression that is just used.

There are also expressions that are both used and stored into.  I
believe they counts as stores in this scheme.  I guess it is not major
problem for you, you can consider them to be just stores as well.
Geting this working perfectly is some work - se df.c for it.
(and of course you may just use it's analysis)
> +   n = VTI (bb)->n_locs;
> +   for (i = 0; i < n; i++)
> +     {
> +       rtx loc = VTI (bb)->locs[i].loc;
> + 
> +       if (GET_CODE (loc) == REG)
> + 	{
> + 	  attrs_list_clear (&out[REGNO (loc)]);
> + 	  if (VTI (bb)->locs[i].type == LT_PARAM
> + 	      || VTI (bb)->locs[i].type == LT_SET_DEST)
> + 	    {
> + 	      if (REG_EXPR (loc) && track_expr_p (REG_EXPR (loc)))
> + 		{
> + 		  attrs_list_insert (&out[REGNO (loc)], REG_EXPR (loc),
> + 				     REG_OFFSET (loc), loc);
> + 		}
> + 	    }
When you notice the store, where you actually invalidate the previous
value reigster did hold?
> + 	}
> +       else if (GET_CODE (loc) == MEM
> + 	       && MEM_EXPR (loc)
> + 	       && track_expr_p (MEM_EXPR (loc)))
> + 	{
> + 	  int j;
> + 	  tree decl = MEM_EXPR (loc);
> + 	  HOST_WIDE_INT offset = MEM_OFFSET (loc) ? INTVAL (MEM_OFFSET (loc)) : 0;
> + 
> + 	  attrs_htab_delete (VTI (bb)->mem_out, loc);
> + 	  if (VTI (bb)->locs[i].type == LT_PARAM
> + 	      || VTI (bb)->locs[i].type == LT_SET_DEST)
> + 	    {
> + 	      /* The variable is no longer in any register.  */
Why exactly?
> + 	      for (j = 0; j < FIRST_PSEUDO_REGISTER; j++)
> + 		attrs_list_delete (&out[j], decl, offset);
> + 	      attrs_htab_insert (VTI (bb)->mem_out, loc);

Honza



More information about the Gcc-patches mailing list