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]

[tree-ssa] Don't rename INDIRECT_REF nodes [patch]


This implements the idea of not renaming memory that I proposed
in http://gcc.gnu.org/ml/gcc/2003-05/msg01411.html.  The main
changes are:

- Every time a pointer is dereferenced, the compiler creates an
  artificial variable, called "memory tag", of the type
  pointed-to by the pointer.  This variable is never used to
  generate code, it's only used to compute aliasing information.
  For instance, the following program:

	foo(int x)
	{
	  int a, *p;

	  p = &a;
	  *p = x + 3;
	  return a;
	}

  is renamed to:

	Alias information for foo: 1 sets

	Alias set #0:
	  Tag: MT.1, memory tag: p, is an alias tag, call clobbered, is stored
	  Aliases objects: { a }


	Referenced variables in foo: 5

	Variable: p, memory tag: MT.1, is stored

	Variable: a, may aliases: { MT.1 }, call clobbered

	Variable: MT.1, memory tag: p, is an alias tag, call clobbered,
	is stored

	Variable: x

	Variable: int, is stored


	;; Function foo (foo)

	foo (x)
	{
	  int a;
	  int * p;

	  #   VUSE <MT.1_1>;
	  p_2 = &a;

	  #   MT.1_4 = VDEF <MT.1_1>;
	  *p_2 = x_3 + 3;

	  #   int_6 = VDEF <int_5>;
	  #   VUSE <MT.1_4>;
	  return a;
	}

  Ignore the must-alias situation we have in this code.  The
  compiler should be smart enough to change *p with a (there are
  some ideas floating around about this, we'll see).
  The basic idea is essentially the same idea we used with
  INDIRECT_REFs.  The only change is that instead of having to
  handle INDIRECT_REF nodes everywhere, we deal with regular DECL
  nodes.


- There are new annotation bitflags to mark variables that are
  memory tags, alias tags and those that have never had a real
  reference.  The last bit is used by the SSA->normal pass to
  avoid dealing with variables that don't generate real code.
  The coalescer completely ignores variables that are never seen
  in a real operand.

- We can now allow pointers to be copy propagated because we
  don't have the headache of keeping track of the INDIRECT_REFs.

- Virtual operands are only scanned once.  Re-scanning virtual
  operands was not only slower, but it some times led to silly
  error situations.  For instance, if a pointer was copy
  propagated into another one inside an INDIRECT_REF node, the
  virtual operand that represented the indirect reference was now
  different.

  Since this change was typically done after/during the SSA
  rename pass, the operand scanner tried to preserve the SSA
  number of the virtual operand.  However, the new pointer was
  causing a different virtual operand to be referenced, and this
  virtual operand didn't have an SSA number.

  All this nonsense shouldn't be necessary.  After all, if we are
  copy propagating a pointer into another one.  They obviously
  alias each other, and so their memory tags should be the same.

  There are some potential inaccuracies with this scheme.  If for
  instance we fold a function call into its result, and the
  statement had a virtual operand for GLOBAL_VAR.  The operand
  will stay after folding the function.  Optimizers should be
  responsible from removing these virtual operands.  We'll
  probably need a few fixes to do this.


- Some changes to C++ that I need Jason to look over:

  a. In g++.oliva/template1.C the compiler is supposed to produce
     an error message for an undeclared identifier inside an
     array declarator.  This was causing an ICE because in
     grokdeclarator() the declarator was error_mark_node.  I told
     it to ignore error_mark_node, but I'm not sure if having
     error_mark_node means we have a bigger problem.

  b. In g++.dg/opt/cleanup1.C and g++.dg/opt/const1.C we were
     ICEing in the SSA rename pass because rewrite_operand was
     running into an already renamed operand.  That's a sign of
     tree sharing.  In this case, the inliner call in
     optimize.c:optimize_function was creating shared trees.
     
     I inserted a call to unshare_all_trees after inlining but
     that seems a bit heavy handed.  I thought the inliner used
     copy_tree_r to replicate trees.  It doesn't seem a
     widespread problem as it only happens in these two tests.


Bootstrapped and tested x86 and amd64.


Diego.

Attachment: 20030524-remove-indirect_ref-as-vars.diff.gz
Description: GNU Zip compressed data


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