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] must-alias analysis


Given this code:

foo (int i)
{
  int *p = &i;

  if (*p == 10)
    return i--;

  *p = *p + 2;
  return *p;
}

This patch allows the compiler to convert it to:

foo (int i)
{
   if (i == 10)
     return 9;

   i = i + 2;
   return i;
}

Must-alias analysis works in four phases:

     1. While the program is renamed into SSA form, the renamer
        propagates instances of &VAR values into pointer dereferences,
        yielding *&VAR operands which are folded into VAR.
     2. The previous step exposes new variables which may not be in SSA
        form.  If this happens, the SSA pass is run once more on the new
        exposed variables.
     3. Right after the SSA pass, we run dead code elimination to remove
        statements of the form 'PTR = &VAR;'.
     4. The must-alias pass will then scan the program looking for
        variables whose address is not needed anymore.  Those that match
        are removed from alias lists and are renamed into SSA as regular
        non-addressable variables.  This exposes the variables to all
        the usual optimizations.


Despite the additional work we do in the SSA pass, compile times are
typically lower.  For instance, on the collection of C and C++ files I
have from the compiler and libstdc++,  Compile times are almost
identical.  There is an increase in the tree optimization passes, but we
typically get that time back from other passes (notably, parser and
varconst).

Phase                           Before  After   Speedup
 cfg construction                2.97    2.82   1.1
 life info update                8.25    7.83   1.1
 register scan                   2.57    2.39   1.1
 rebuild jump labels             1.15    1.29   0.9
 parser                         43.72   36.73   1.2
 tree CFG construction           1.86    1.76   1.1
 tree CFG cleanup                0.70    1.09   0.6
 tree alias analysis             2.42    2.71   0.9
 tree must-alias                 0.00    0.40   0.0
 tree PHI insertion              0.87    1.06   0.8
 tree SSA rewrite                3.20    3.48   0.9
 tree SSA other                 12.18   14.12   0.9
 tree SSA to normal              4.91    4.54   1.1
 tree DCE                        2.05    4.29   0.5
 dominance frontiers             0.26    0.28   0.9
 expand                         10.20   10.36   1.0
 varconst                        0.49    0.55   0.9
 loop analysis                   1.67    1.46   1.1
 bypass jumps                    3.93    4.17   0.9
 flow analysis                   0.73    0.47   1.6
 reload CSE regs                 8.74    8.16   1.1
 flow 2                          2.18    2.06   1.1
 if-conversion 2                 0.59    0.68   0.9
 rename registers                7.74    8.45   0.9
 reorder blocks                  1.36    1.47   0.9
 shorten branches                1.64    1.40   1.2
 rest of compilation             4.25    4.51   0.9
Total for tree optimizers       38.63   43.71   0.9
Total compile time              347.53  344.63  1.0

In the above table I've removed all passes that have identical times. 
Notice how the total compilation time is slightly lower despite the
increase in the compilation time over the tree passes.  In terms of code
size, there doesn't seem to be much difference.  But the new patch does
produce slightly smaller code.

In POOMA I found a larger difference.  Notably in LocalPatch.ii.  Not
only the new patch compiles faster, it produces significantly smaller
code.

Phase                           Before  After   Speedup
 garbage collection             15.41   11.89   1.3
 cfg construction                1.98    1.27   1.6
 cfg cleanup                     3.88    3.34   1.2
 trivially dead code             2.00    1.45   1.4
 life analysis                   6.21    5.84   1.1
 life info update                3.91    3.62   1.1
 alias analysis                  3.51    2.50   1.4
 register scan                   1.08    0.72   1.5
 rebuild jump labels             0.86    0.57   1.5
 preprocessing                   0.58    0.70   0.8
 parser                         16.39   12.91   1.3
 name lookup                     9.40    8.24   1.1
 integration                    44.78   36.40   1.2
 tree CFG construction           4.90    4.14   1.2
 tree CFG cleanup                2.15    1.45   1.5
 tree alias analysis             2.38    2.00   1.2
 tree PHI insertion             23.73   26.28   0.9
 tree SSA rewrite                3.92    3.93   1.0
 tree SSA other                  9.09   12.75   0.7
 tree SSA to normal              5.71    3.96   1.4
 tree CCP                        5.33    2.47   2.2
 tree COPYPROP                   6.79    4.70   1.4
 tree DCE                        3.09    4.46   0.7
 expand                          8.06    5.98   1.3
 varconst                       11.00    0.14   78.6
 jump                            3.41    2.82   1.2
 CSE                            14.45    8.53   1.7
 bypass jumps                    2.28    1.73   1.3
 CSE 2                           4.30    2.45   1.8
 branch prediction               4.96    4.47   1.1
 flow analysis                   0.12    0.11   1.1
 combiner                        3.18    2.13   1.5
 if-conversion                   0.35    0.32   1.1
 regmove                         1.41    1.10   1.3
 local alloc                     9.79   10.61   0.9
 global alloc                   19.09   24.44   0.8
 reload CSE regs                 2.55    1.88   1.4
 flow 2                          0.62    0.39   1.6
 if-conversion 2                 0.11    0.10   1.1
 peephole 2                      0.46    0.21   2.2
 rename registers                2.74    2.30   1.2
 scheduling 2                   11.64   10.74   1.1
 shorten branches                0.56    0.35   1.6
 reg stack                       0.35    0.25   1.4
 final                           0.76    0.61   1.2
 symout                          0.02    0.03   0.7
 rest of compilation             2.33    1.65   1.4
 TOTAL                         353.04  314.10   1,1

The code in LocalPatch.ii is very ADDR_EXPR happy.  Just the propagation
of ADDR_EXPR seems to have a significant effect on the code.  The final
.s file is about 30% smaller with this patch.

There are a few things that I'd like to fix in the current
implementation.

We now do a full DCE pass right after SSA construction just to get the
'PTR = &VAR' statements removed.  We could probably get by with a very
simplistic pass that just looked for these assignments.  It would be
less powerful, but it would catch most of the cases we are interested
in.
We currently do not propagate ADDR_EXPR values that have been type
casted.  So, things like 'PTR = (type *)&VAR' are not propagated.  The
problem with this is that we would need to fold instances of *PTR into
(type)VAR, which would produce non-GIMPLE code and confuse the
optimizers.  I'm not quite sure how to handle this one.  I think it's
important because right now we are not handling code like this (from Joe
Buck's sample code a while back):

struct complex {
    double re, im;
    complex(double r, double i) : re(r), im(i) {}
};

inline complex operator+(const complex& a, const complex& b) {
    return complex(a.re+b.re, a.im+b.im);
}

complex addone(const complex& arg) {
    return arg + complex(1,0);
}


When we inline operator+ into addone, we get code like this:

      struct complex * const this;

      this_2 = (struct complex * const)&<UV770>;
      r_3 = 1.0e+0;
      i_4 = 0.0;
      {
        this_2->re = 1.0e+0;
        this_2->im = 0.0;
        {
          (void)0
        }
      }

I would like to get rid of 'this_2' in this case.  But we don't because
of the type cast.

The patch does not seem to have a huge effect on SPEC either.  Some
tests are slightly faster, though.

The patch also fixes the regression in execute/20000603-1.c because it
can now disambiguate the pointer dereferences directly instead of
relying on may-alias information.

Before committing I would like to address the problems I mentioned and
fix a couple of regressions that it exposed on the C testsuite.  As it
is, the patch now bootstraps on x86, ppc, ia64 and amd64.

I'll finish these details after I deal with last week's merge.


Diego.




	Must alias analysis.  Allow the SSA rename pass to be done on a set
	of variables.

	* Makefile.in (OBJS): Add tree-must-alias.o.
	* flags.h (flag_tree_must_alias): Declare.
	* timevar.def (TV_TREE_MUST_ALIAS): Define.
	* toplev.c (flag_tree_must_alias): Declare.
	(f_options): Add entry for -ftree-must-alias.
	(parse_options_and_default_flags): Enable must-alias analysis at -O1.

	* tree-cfg.c (remove_useless_stmts_and_vars): Do not remove
	addressable variables.

	* tree-dfa.c (dump_file, dump_flags): New local variables to
	replace tree_ssa_dump_file and tree_ssa_dump_flags.  Update every
	user.
	(get_stmt_operands): Clear the array of virtual operands before
	scanning the statement.
	(get_expr_operands): Do not add an operand for ADDR_EXPR if the
	expression takes the address of a VAR_DECL or a PARM_DECL.  Instead
	add the variable to the list of variables whose address has been
	taken by the statement.
	Allow INDIRECT_REF expressions of the form *&VAR.  Convert them
	into an operand for VAR.
	When processing function calls, add a VUSE for .GLOBAL_VAR if the
	function is pure but not const.
	(add_stmt_operand): If the operand is an ADDR_EXPR, add the
	variable to the list of variables whose address has been taken by
	the statement.
	(add_vdef): If the statement had virtual definitions, try to find
	an existing VDEF for the variable, to preserve SSA information.  If
	none is found, create a new one.
	(add_vuse): Likewise.
	(remove_all_phi_nodes_for): New function.
	(get_call_flags): New function to replace call_may_clobber.  Update
	all callers.

	* tree-dump.c (dump_files): Add entry for -fdump-tree-mustalias.
	* tree-flow-inline.h (addresses_taken): New function.
	(is_unchanging_value): New function.

	* tree-flow.h (addresses_taken): Declare.
	(remove_all_phi_nodes): Declare.
	(init_tree_ssa): Declare.
	(propagate_copy): Declare.
	(is_unchanging_value): Declare.
	(tree_compute_must_alias): Declare.

	* tree-inline.c (copy_body_r): Fold instances of *&VAR.

	* tree-must-alias.c: New file.

	* tree-optimize.c (optimize_function_tree): Call init_tree_ssa and
	compute_may_aliases before calling rewrite_into_ssa.
	After the SSA pass, run dead code elimination and compute
	must-aliases.

	* tree-simple.c (is_gimple_call_expr): Add comment that
	is_gimple_* predicates should not have side effects.

	* tree-ssa-ccp.c: Replace calls to really_constant_p with
	is_unchanging_value everywhere.
	(fold_stmt): Don't fold if the RHS is already a constant.

	* tree-ssa-copyprop.c (copyprop_stmt): Remove unnecessary variable 'vuse'.
	Call propagate_copy to replace the operand with its new value.
	(copyprop_phi): Remove unnecessary variable 'vuse'.
	(get_original): Remove unused parameter 'vuse_p'.
	(propagate_copy): New function.

	* tree-ssa-dce.c (need_to_preserve_store): Update comments.

	* tree-ssa.c (dump_file, dump_flags): New local variables to
	replace globals tree_ssa_dump_file and tree_ssa_dump_flags.  Update
	all users.
	(addr_expr_propagated_p): New local variable.
	(vars_to_rename): New local variable.
	(check_for_new_variables): New local function.
	(rewrite_into_ssa): Add new argument VARS which is a bitmap
	representing all the variables that should be renamed into SSA.  If
	VARS is NULL, all the variables in the program are renamed.
	Don't call init_tree_ssa nor compute_may_aliases.
	Initialize all the local hash tables and bitmaps.
	Add support for repeating the SSA rename process more than once.
	If the dominator optimizations produced new symbols, repeat the
	process.
	(mark_def_sites): Ignore operands that are in SSA form already.
	(insert_phi_nodes): Only add PHI nodes for variables in the
	VARS_TO_RENAME bitmap.
	(rewrite_block): Ignore PHI nodes that have been renamed already.
	(rewrite_and_optimize_stmt): Ignore operands that are already in
	SSA form.
	When propagating ADDR_EXPR set addr_expr_propagated_p to 'true'.
	Call propagate_copy when doing copy propagation.
	Call is_unchanging_value to decide if the RHS of an assignment is a
	constant.
	(rewrite_stmt): Ignore operands that are already in SSA form.
	(init_tree_ssa): Make external.
	Move initialization of local hash tables and bitmaps to
	rewrite_into_ssa.
	(remove_annotations_r): Don't special case MODIFY_EXPR nodes.
	(lookup_avail_expr): Call is_unchanging_value.
	(get_eq_expr_value): Likewise.

	* tree.h (enum tree_dump_index): Add TDI_must_alias.

	* cp/optimize.c (optimize_function): Don't call the tree optimizers
	  if -fdisable-tree-ssa is given.

	* doc/invoke.texi: Add documentation for -ftree-must-alias.


Index: Makefile.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Makefile.in,v
retrieving revision 1.903.2.97
diff -d -u -p -r1.903.2.97 Makefile.in
-- Makefile.in	23 Jun 2003 02:03:41 -0000	1.903.2.97
+++ Makefile.in	11 Jul 2003 18:49:31 -0000
@@ -835,7 +835,7 @@ C_OBJS = c-parse.o c-lang.o $(C_AND_OBJC
 OBJS = tree-cfg.o tree-dfa.o tree-ssa.o tree-optimize.o tree-simple.o      \
  tree-alias-type.o gimplify.o tree-nomudflap.o tree-pretty-print.o         \
  tree-alias-common.o tree-ssa-ccp.o tree-browser.o @ANDER@ tree-ssa-dce.o  \
- tree-ssa-pre.o tree-ssa-copyprop.o tree-ssa-live.o 			   \
+ tree-ssa-pre.o tree-ssa-copyprop.o tree-ssa-live.o tree-must-alias.o	   \
  alias.o bb-reorder.o bitmap.o builtins.o caller-save.o calls.o	           \
  cfg.o cfganal.o cfgbuild.o cfgcleanup.o cfglayout.o cfgloop.o		   \
  cfgloopanal.o cfgloopmanip.o loop-init.o loop-unswitch.o loop-unroll.o	   \
@@ -1730,6 +1730,9 @@ tree-ssa-ccp.o : tree-ssa-ccp.c $(CONFIG
 tree-ssa-copyprop.o : tree-ssa-copyprop.c $(CONFIG_H) system.h errors.h \
     $(TREE_H) $(RTL_H) $(TM_P_H) $(TREE_FLOW_H) diagnostic.h $(TIMEVAR_H) \
     $(TREE_DUMP_H) coretypes.h $(TREE_SIMPLE_H) $(TM_H)
+tree-must-alias.o : tree-must-alias.c $(CONFIG_H) system.h errors.h \
+    $(TREE_H) $(RTL_H) $(TM_P_H) $(TREE_FLOW_H) diagnostic.h tree-inline.h \
+    $(TIMEVAR_H) $(TM_H) coretypes.h $(TREE_DUMP_H) $(TREE_SIMPLE_H)
 df.o : df.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
    insn-config.h $(RECOG_H) function.h $(REGS_H) alloc-pool.h hard-reg-set.h \
    $(BASIC_BLOCK_H) df.h $(FIBHEAP_H)
Index: flags.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/flags.h,v
retrieving revision 1.86.2.28
diff -d -u -p -r1.86.2.28 flags.h
-- flags.h	13 Jun 2003 19:00:16 -0000	1.86.2.28
+++ flags.h	11 Jul 2003 18:49:31 -0000
@@ -683,6 +683,9 @@ extern int flag_tree_dce;
 /* Enable dominator optimizations while re-writing into SSA form.  */
 extern int flag_tree_dom;
 
+/* Enable promotion of virtual to real operands in must-alias situations.  */
+extern int flag_tree_must_alias;
+
 /* Nonzero means put zero initialized data in the bss section.  */
 extern int flag_zero_initialized_in_bss;
 
Index: timevar.def
===================================================================
RCS file: /cvs/gcc/gcc/gcc/timevar.def,v
retrieving revision 1.14.2.14
diff -d -u -p -r1.14.2.14 timevar.def
-- timevar.def	17 Jun 2003 13:37:48 -0000	1.14.2.14
+++ timevar.def	11 Jul 2003 18:49:31 -0000
@@ -62,6 +62,7 @@ DEFTIMEVAR (TV_TREE_CFG		     , "tree CF
 DEFTIMEVAR (TV_TREE_CLEANUP_CFG	     , "tree CFG cleanup")
 DEFTIMEVAR (TV_TREE_PTA		     , "tree PTA")
 DEFTIMEVAR (TV_TREE_MAY_ALIAS        , "tree alias analysis")
+DEFTIMEVAR (TV_TREE_MUST_ALIAS       , "tree must-alias")
 DEFTIMEVAR (TV_TREE_INSERT_PHI_NODES , "tree PHI insertion")
 DEFTIMEVAR (TV_TREE_SSA_REWRITE_BLOCKS, "tree SSA rewrite")
 DEFTIMEVAR (TV_TREE_SSA_OTHER	     , "tree SSA other")
Index: toplev.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/toplev.c,v
retrieving revision 1.654.2.57
diff -d -u -p -r1.654.2.57 toplev.c
-- toplev.c	13 Jun 2003 19:00:17 -0000	1.654.2.57
+++ toplev.c	11 Jul 2003 18:49:32 -0000
@@ -927,6 +927,9 @@ int flag_tree_copyprop;
 /* Enable SSA-DCE on trees.  */
 int flag_tree_dce = 0;
 
+/* Enable promotion of virtual to real operands in must-alias situations.  */
+int flag_tree_must_alias = 0;
+
 /* Enable dominator optimizations while re-writing into SSA form.  */
 int flag_tree_dom = 0;
 
@@ -1269,7 +1272,9 @@ static const lang_independent_options f_
   { "tree-dce", &flag_tree_dce, 1,
    N_("Enable SSA dead code elimination optimization on trees") },
   { "tree-dominator-opts", &flag_tree_dom, 1,
-   N_("Enable dominator optimizations while re-writing into SSA form") }
+   N_("Enable dominator optimizations while re-writing into SSA form") },
+  { "tree-must-alias", &flag_tree_must_alias, 1,
+   N_("Detect must-alias relations to remove pointer de-references") }
 };
 
 /* Table of language-specific options.  */
@@ -5114,6 +5119,7 @@ parse_options_and_default_flags (argc, a
       flag_tree_dce = 1;
       flag_tree_copyprop = 1;
       flag_tree_dom = 1;
+      flag_tree_must_alias = 1;
     }
 
   if (optimize >= 2)
Index: tree-cfg.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-cfg.c,v
retrieving revision 1.1.4.126
diff -d -u -p -r1.1.4.126 tree-cfg.c
-- tree-cfg.c	8 Jul 2003 06:48:42 -0000	1.1.4.126
+++ tree-cfg.c	11 Jul 2003 18:49:32 -0000
@@ -1605,6 +1605,7 @@ remove_useless_stmts_and_vars (tree *fir
 		      && ! ann->may_aliases
 		      && ! ann->used
 		      && ! ann->has_hidden_use
+		      && ! TREE_ADDRESSABLE (vars)
 		      && (DECL_ARTIFICIAL (vars) || optimize >= 2))
 		    {
 		      /* Remove the variable from the BLOCK structures.  */
Index: tree-dfa.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-dfa.c,v
retrieving revision 1.1.4.126
diff -d -u -p -r1.1.4.126 tree-dfa.c
-- tree-dfa.c	1 Jul 2003 22:49:55 -0000	1.1.4.126
+++ tree-dfa.c	11 Jul 2003 18:49:32 -0000
@@ -107,11 +107,12 @@ static const int opf_is_def 	= 1 << 0;
 /* Consider the operand virtual, regardlessof aliasing information.  */
 static const int opf_force_vop	= 1 << 1;
 
+/* Debugging dumps.  */
+static FILE *dump_file;
+static int dump_flags;
 
 /* Data and functions shared with tree-ssa.c.  */
 struct dfa_stats_d dfa_stats;
-extern FILE *tree_ssa_dump_file;
-extern int tree_ssa_dump_flags;
 

 /* Local functions.  */
@@ -132,7 +133,7 @@ static void add_referenced_var (tree, st
 static tree get_memory_tag_for (tree);
 static void compute_immediate_uses_for (tree, int);
 static void add_may_alias (tree, tree);
-static bool call_may_clobber (tree);
+static int get_call_flags (tree);
 static void find_hidden_use_vars (tree);
 static tree find_hidden_use_vars_r (tree *, int *, void *);
 
@@ -183,14 +184,13 @@ get_stmt_operands (tree stmt)
   /* Remove any existing operands as they will be scanned again.  */
   ann->ops = NULL;
 
-  /* We cannot remove existing virtual operands because we would lose their
-     SSA versions.  Instead, we save them on PREV_VOPS.  When add_vdef and
-     add_vuse are called, they will do nothing if PREV_VOPS is set.
-     FIXME: This means that passes that modify virtual operands must
-            make the changes on their own.  */
+  /* Before removing existing virtual operands, save them in PREV_VOPS so 
+     that we can re-use their SSA versions.  */
   if (ann->vops)
     prev_vops = ann->vops;
 
+  ann->vops = NULL;
+
   code = TREE_CODE (stmt);
   switch (code)
     {
@@ -305,13 +305,20 @@ get_expr_operands (tree stmt, tree *expr
     {
       enum tree_code subcode = TREE_CODE (TREE_OPERAND (expr, 0));
 
+      /* Taking the address of a variable does not represent a
+	 reference to it, but the fact that STMT takes its address will be
+	 of interest to some passes (e.g. must-alias resolution).  */
+      if (SSA_VAR_P (TREE_OPERAND (expr, 0)))
+	{
+	  add_stmt_operand (expr_p, stmt, 0, NULL);
+	  return;
+	}
+
       /* Only a few specific types of ADDR_EXPR expressions are
        	 of interest.  */
       if (subcode != COMPONENT_REF
 	  && subcode != INDIRECT_REF
-	  && subcode != ARRAY_REF
-	  && subcode != PARM_DECL
-	  && subcode != VAR_DECL)
+	  && subcode != ARRAY_REF)
 	return;
 
       /* Avoid recursion.  */
@@ -357,7 +364,9 @@ get_expr_operands (tree stmt, tree *expr
       tree ptr = TREE_OPERAND (expr, 0);
 
 #if defined ENABLE_CHECKING
-      if (!SSA_VAR_P (ptr) && !TREE_CONSTANT (ptr))
+      if (!SSA_VAR_P (ptr)
+	  && !TREE_CONSTANT (ptr)
+	  && TREE_CODE (ptr) != ADDR_EXPR)
 	abort ();
 #endif
 
@@ -368,7 +377,23 @@ get_expr_operands (tree stmt, tree *expr
 	    add_stmt_operand (&ann->mem_tag, stmt, flags|opf_force_vop,
 			      prev_vops);
 	}
+      else if (TREE_CODE (ptr) == ADDR_EXPR)
+	{
+	  /* Fold *&VAR into VAR, add an operand for VAR and return.  */
+	  tree var = TREE_OPERAND (ptr, 0);
+	  *expr_p = var;
+
+	  /* If VAR is of type ARRAY_TYPE, we can't return VAR because
+	     this INDIRECT_REF node is actually VAR[0].  */
+	  if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
+	    *expr_p = build (ARRAY_REF, TREE_TYPE (expr), var,
+			     integer_zero_node);
+
+	  add_stmt_operand (&TREE_OPERAND (ptr, 0), stmt, flags, prev_vops);
+	  return;
+	}
 
+      /* Add a USE operand for the base pointer.  */
       get_expr_operands (stmt, &TREE_OPERAND (expr, 0), opf_none, prev_vops);
       return;
     }
@@ -419,7 +444,7 @@ get_expr_operands (tree stmt, tree *expr
   if (code == CALL_EXPR)
     {
       tree op;
-      bool may_clobber = call_may_clobber (expr);
+      int call_flags = get_call_flags (expr);
 
       /* Find uses in the called function.  */
       get_expr_operands (stmt, &TREE_OPERAND (expr, 0), opf_none, prev_vops);
@@ -427,14 +452,23 @@ get_expr_operands (tree stmt, tree *expr
       for (op = TREE_OPERAND (expr, 1); op; op = TREE_CHAIN (op))
 	add_stmt_operand (&TREE_VALUE (op), stmt, opf_none, prev_vops);
 
-      /* If the called function is neither pure nor const and there are
-	 call clobbered variables, create a definition of GLOBAL_VAR and
-	 mark the statement as a clobbering statement.  */
-      if (may_clobber && num_call_clobbered_vars > 0)
+      if (num_call_clobbered_vars > 0)
 	{
-	  stmt_ann (stmt)->makes_clobbering_call = may_clobber;
-	  add_stmt_operand (&global_var, stmt, opf_is_def|opf_force_vop,
-			    prev_vops);
+	  if (!(call_flags & (ECF_CONST | ECF_PURE | ECF_NORETURN)))
+	    {
+	      /* Functions that are not const, pure or never return may
+		 clobber call-clobbered variables.  Add a VDEF for
+		 .GLOBAL_VAR.  */
+	      stmt_ann (stmt)->makes_clobbering_call = true;
+	      add_stmt_operand (&global_var, stmt, opf_force_vop|opf_is_def,
+		                prev_vops);
+	    }
+	  else if (!(call_flags & (ECF_CONST | ECF_NORETURN)))
+	    {
+	      /* Otherwise, if the function is not pure, it may reference
+		 memory.  Add a VUSE for .GLOBAL_VAR.  */
+	      add_stmt_operand (&global_var, stmt, opf_force_vop, prev_vops);
+	    }
 	}
 
       return;
@@ -527,6 +561,22 @@ add_stmt_operand (tree *var_p, tree stmt
   var = *var_p;
   STRIP_NOPS (var);
 
+  s_ann = stmt_ann (stmt);
+
+  /* If the operand is an ADDR_EXPR, add its operand to the list of
+     variables that have had their address taken in this statement.  */
+  if (TREE_CODE (var) == ADDR_EXPR)
+    {
+      var = TREE_OPERAND (var, 0);
+      if (SSA_VAR_P (var))
+	{
+	  if (s_ann->addresses_taken == NULL)
+	    VARRAY_TREE_INIT (s_ann->addresses_taken, 2, "addresses_taken");
+	  VARRAY_PUSH_TREE (s_ann->addresses_taken, var);
+	}
+      return;
+    }
+
   /* If the original variable is not a scalar, it will be added to the list
      of virtual operands.  In that case, use its base symbol as the virtual
      variable representing it.  */
@@ -538,7 +588,6 @@ add_stmt_operand (tree *var_p, tree stmt
   if (var == NULL_TREE || !SSA_VAR_P (var))
     return;
 
-  s_ann = stmt_ann (stmt);
   v_ann = var_ann (TREE_CODE (var) == SSA_NAME ? SSA_NAME_VAR (var) : var);
 
   /* FIXME: Currently, global and local static variables are always treated as
@@ -690,12 +739,35 @@ add_vdef (tree var, tree stmt, voperands
   tree vdef;
   stmt_ann_t ann;
   size_t i;
+  bool found;
 
-  /* The statement already had virtual definitions.  Do nothing.  */
+  /* If the statement already had virtual definitions, see if any of the
+     existing VDEFs matches VAR.  If so, re-use it, otherwise add a new
+     VDEF for VAR.  */
+  found = false;
   if (prev_vops && prev_vops->vdef_ops)
-    return;
+    {
+      size_t i;
+
+      for (i = 0; i < VARRAY_ACTIVE_SIZE (prev_vops->vdef_ops); i++)
+	{
+	  tree t;
+	  vdef = VARRAY_TREE (prev_vops->vdef_ops, i);
+	  t = VDEF_RESULT (vdef);
+	  if (t == var
+	      || (TREE_CODE (t) == SSA_NAME
+		  && SSA_NAME_VAR (t) == var))
+	    {
+	      found = true;
+	      break;
+	    }
+	}
+    }
+
+  /* If no previous VDEF operand was found for VAR, create one now.  */
+  if (!found)
+    vdef = build_vdef_expr (var);
 
-  vdef = build_vdef_expr (var);
   ann = stmt_ann (stmt);
   if (ann->vops == NULL)
     {
@@ -725,10 +797,33 @@ add_vuse (tree var, tree stmt, voperands
 {
   stmt_ann_t ann;
   size_t i;
+  bool found;
+  tree vuse;
 
-  /* The statement already had virtual uses.  Do nothing.  */
+  /* If the statement already had virtual uses, see if any of the
+     existing VUSEs matches VAR.  If so, re-use it, otherwise add a new
+     VUSE for VAR.  */
+  found = false;
   if (prev_vops && prev_vops->vuse_ops)
-    return;
+    {
+      size_t i;
+
+      for (i = 0; i < VARRAY_ACTIVE_SIZE (prev_vops->vuse_ops); i++)
+	{
+	  vuse = VARRAY_TREE (prev_vops->vuse_ops, i);
+	  if (vuse == var
+	      || (TREE_CODE (vuse) == SSA_NAME
+		  && SSA_NAME_VAR (vuse) == var))
+	    {
+	      found = true;
+	      break;
+	    }
+	}
+    }
+
+  /* If VAR existed already in PREV_VOPS, re-use it.  */
+  if (found)
+    var = vuse;
 
   ann = stmt_ann (stmt);
   if (ann->vops == NULL)
@@ -912,6 +1007,43 @@ remove_phi_node (tree phi, tree prev, ba
 }
 

+/* Remove all the PHI nodes for variables in the VARS bitmap.  */
+
+void
+remove_all_phi_nodes_for (sbitmap vars)
+{
+  basic_block bb;
+
+  FOR_EACH_BB (bb)
+    {
+      /* Build a new PHI list for BB without variables in VARS.  */
+      tree phi, new_phi_list, tmp;
+      bb_ann_t ann = bb_ann (bb);
+
+      tmp = new_phi_list = NULL_TREE;
+      for (phi = ann->phi_nodes; phi; phi = TREE_CHAIN (phi))
+	{
+	  tree var = SSA_NAME_VAR (PHI_RESULT (phi));
+
+	  /* If the PHI node is for a variable in VARS, skip it.  */
+	  if (TEST_BIT (vars, var_ann (var)->uid))
+	    continue;
+
+	  if (new_phi_list == NULL_TREE)
+	    new_phi_list = tmp = phi;
+	  else
+	    {
+	      TREE_CHAIN (tmp) = phi;
+	      tmp = phi;
+	    }
+	}
+
+      ann->phi_nodes = new_phi_list;
+    }
+}
+
+
+
 /*--
 			Dataflow analysis (DFA) routines
 --*/
@@ -1703,10 +1835,12 @@ compute_alias_sets (void)
       }
 
   /* Debugging dumps.  */
-  if (tree_ssa_dump_file && tree_ssa_dump_flags & TDF_ALIAS)
+  dump_file = dump_begin (TDI_ssa, &dump_flags);
+  if (dump_file && dump_flags & TDF_ALIAS)
     {
-      dump_alias_info (tree_ssa_dump_file);
-      dump_referenced_vars (tree_ssa_dump_file);
+      dump_alias_info (dump_file);
+      dump_referenced_vars (dump_file);
+      dump_end (TDI_ssa, dump_file);
     }
 }
 
@@ -1986,8 +2120,7 @@ find_decl_location (tree decl, tree bloc
    the function.  */
 
 static tree
-find_vars_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
-	     void *data)
+find_vars_r (tree *tp, int *walk_subtrees, void *data)
 {
   tree t = *tp;
   struct walk_state *walk_state = (struct walk_state *)data;
@@ -2062,7 +2195,7 @@ find_vars_r (tree *tp, int *walk_subtree
   if (TREE_CODE (*tp) == CALL_EXPR)
     {
       tree op;
-      bool may_clobber = call_may_clobber (*tp);
+      int call_flags = get_call_flags (*tp);
 
       for (op = TREE_OPERAND (*tp, 1); op; op = TREE_CHAIN (op))
 	{
@@ -2075,16 +2208,15 @@ find_vars_r (tree *tp, int *walk_subtree
 	    }
 	}
 
-      /* If the function may clobber globals and addressable locals, add a
-	 reference to GLOBAL_VAR.  */
-      if (may_clobber)
-	{
-	  walk_state->is_store = 1;
-	  if (global_var == NULL_TREE)
-	    create_global_var ();
-	  add_referenced_var (global_var, walk_state);
-	}
+      if (global_var == NULL_TREE)
+	create_global_var ();
 
+      /* If the function may clobber globals and addressable locals,
+	 consider this call as a store operation to .GLOBAL_VAR.  */
+      if (!(call_flags & (ECF_CONST | ECF_PURE | ECF_NORETURN)))
+	walk_state->is_store = 1;
+
+      add_referenced_var (global_var, walk_state);
       walk_state->is_store = saved_is_store;
     }
 
@@ -2145,10 +2277,9 @@ add_referenced_var (tree var, struct wal
 	  VARRAY_PUSH_GENERIC_PTR (addressable_vars, (void *) alias_map);
 	}
 
-      /* If the variable is a writeable memory tag, a global or an
-	 addressable local, it may be clobbered by function calls.  */
-      if (!TREE_READONLY (var)
-	  && (is_addressable || v_ann->is_mem_tag))
+      /* Addressable variables and memory tags may be used or clobbered by
+	 function calls.  */
+      if (is_addressable || v_ann->is_mem_tag)
 	{
 	  add_call_clobbered_var (var);
 	  v_ann->is_call_clobbered = 1;
@@ -2273,21 +2404,21 @@ get_virtual_var (tree var)
 }
 

-/* Return true if EXPR is a CALL_EXPR tree to a function that may clobber
-   globals and local addressable variables.  */
+/* Return the ECF_ flags associated with the function called by the
+   CALL_EXPR node EXPR.  */
 
-static bool
-call_may_clobber (tree expr)
+static int
+get_call_flags (tree expr)
 {
   tree callee;
-  int flags;
 
+#if defined ENABLE_CHECKING
   if (TREE_CODE (expr) != CALL_EXPR)
-    return false;
+    abort ();
+#endif
 
   callee = get_callee_fndecl (expr);
-  flags = (callee) ? flags_from_decl_or_type (callee) : 0;
-  return (! (flags & (ECF_CONST | ECF_PURE | ECF_NORETURN)));
+  return (callee) ? flags_from_decl_or_type (callee) : 0;
 }
 

Index: tree-dump.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-dump.c,v
retrieving revision 1.6.2.28
diff -d -u -p -r1.6.2.28 tree-dump.c
-- tree-dump.c	13 Jun 2003 19:00:18 -0000	1.6.2.28
+++ tree-dump.c	11 Jul 2003 18:49:32 -0000
@@ -684,6 +684,7 @@ static struct dump_file_info dump_files[
   {".dot", "dump-tree-dot", 0, 0},
   {".pta", "dump-tree-pta", 0, 0},
   {".ssa", "dump-tree-ssa", 0, 0},
+  {".mustalias", "dump-tree-mustalias", 0, 0},
   {".predot", "dump-tree-predot", 0, 0},
   {".pre", "dump-tree-pre", 0, 0},
   {".ccp", "dump-tree-ccp", 0, 0},
Index: tree-flow-inline.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-flow-inline.h,v
retrieving revision 1.1.2.39
diff -d -u -p -r1.1.2.39 tree-flow-inline.h
-- tree-flow-inline.h	1 Jul 2003 22:49:55 -0000	1.1.2.39
+++ tree-flow-inline.h	11 Jul 2003 18:49:32 -0000
@@ -248,6 +248,14 @@ vuse_ops (stmt)
 }
 
 static inline varray_type
+addresses_taken (stmt)
+     tree stmt;
+{
+  stmt_ann_t ann = stmt_ann (stmt);
+  return ann ? ann->addresses_taken : NULL;
+}
+
+static inline varray_type
 immediate_uses (stmt)
      tree stmt;
 {
@@ -533,5 +541,19 @@ empty_bsi_stack (list)
   VARRAY_POP (stmt_stack);					\
   for ( ; VARRAY_ACTIVE_SIZE (stmt_stack) > 0 ; 		\
 	      stmt = VARRAY_TOP_TREE (stmt_stack), VARRAY_POP (stmt_stack))	
+
+
+static inline bool
+is_unchanging_value (tree val)
+{
+  /* FIXME: It should be possible to accept type-casted ADDR_EXPRs if we
+     made sure that the folded INDIRECT_REF kept the type-cast.  See for
+     instance, gcc.c-torture/compile/990203-1.c.  */
+  return ((TREE_CODE (val) == ADDR_EXPR
+	   && (TREE_CODE (TREE_OPERAND (val, 0)) == VAR_DECL
+	       || TREE_CODE (TREE_OPERAND (val, 0)) == PARM_DECL))
+          || ((TREE_CONSTANT (val) || really_constant_p (val))
+	      && is_gimple_val (val)));
+}
 
 #endif /* _TREE_FLOW_INLINE_H  */
Index: tree-flow.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-flow.h,v
retrieving revision 1.1.4.88
diff -d -u -p -r1.1.4.88 tree-flow.h
-- tree-flow.h	1 Jul 2003 04:04:31 -0000	1.1.4.88
+++ tree-flow.h	11 Jul 2003 18:49:32 -0000
@@ -223,6 +223,9 @@ struct stmt_ann_d GTY(())
   /* For nodes which can throw REACHABLE_EXCEPTION_HANDLERS contains a 
      tree list of all the directly reachable exception handlers.  */
   tree reachable_exception_handlers;
+
+  /* Array of variables that have had their address taken in the statement.  */
+  varray_type addresses_taken;
 };
 

@@ -260,6 +263,7 @@ static inline varray_type vdef_ops		PARA
 static inline varray_type vuse_ops		PARAMS ((tree));
 static inline varray_type use_ops		PARAMS ((tree));
 static inline tree *def_op			PARAMS ((tree));
+static inline varray_type addresses_taken	PARAMS ((tree));
 static inline varray_type immediate_uses	PARAMS ((tree));
 static inline varray_type reaching_defs		PARAMS ((tree));
 static inline bool has_hidden_use		PARAMS ((tree));
@@ -363,7 +367,6 @@ extern GTY(()) varray_type call_clobbere
 #define add_call_clobbered_var(v) VARRAY_PUSH_TREE (call_clobbered_vars, v)
 #define call_clobbered_var(i) VARRAY_TREE (call_clobbered_vars, i)
 
-
 /* Macros for showing usage statistics.  */
 #define SCALE(x) ((unsigned long) ((x) < 1024*10	\
 		  ? (x)					\
@@ -415,6 +418,7 @@ extern void add_phi_arg (tree, tree, edg
 extern void remove_phi_arg (tree, basic_block);
 extern void remove_phi_arg_num (tree, int);
 extern void remove_phi_node (tree, tree, basic_block);
+extern void remove_all_phi_nodes_for (sbitmap);
 extern void dump_dfa_stats (FILE *);
 extern void debug_dfa_stats (void);
 extern void debug_referenced_vars (void);
@@ -445,7 +449,8 @@ extern void create_global_var (void);
 

 /* In tree-ssa.c  */
-extern void rewrite_into_ssa (tree);
+extern void init_tree_ssa (void);
+extern void rewrite_into_ssa (tree, sbitmap);
 extern void rewrite_out_of_ssa (tree);
 extern void dump_reaching_defs (FILE *);
 extern void debug_reaching_defs (void);
@@ -469,11 +474,21 @@ void fold_stmt (tree);
 /* In tree-ssa-dce.c  */
 void tree_ssa_dce (tree);
 
+
 /* In tree-ssa-copyprop.c  */
 void tree_ssa_copyprop (tree);
+void propagate_copy (tree *, tree);
+
 
+/* In tree-flow-inline.h  */
 static inline int phi_arg_from_edge (tree, edge);
 static inline struct phi_arg_d *phi_element_for_edge (tree, edge);
+static inline bool is_unchanging_value (tree val);
+
+
+/* In tree-must-alias.c  */
+void tree_compute_must_alias (tree);
+
 
 #include "tree-flow-inline.h"
 
Index: tree-inline.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-inline.c,v
retrieving revision 1.26.2.33
diff -d -u -p -r1.26.2.33 tree-inline.c
-- tree-inline.c	13 Jun 2003 19:00:18 -0000	1.26.2.33
+++ tree-inline.c	11 Jul 2003 18:49:32 -0000
@@ -472,6 +472,25 @@ copy_body_r (tp, walk_subtrees, data)
 		}
 	    }
 	}
+      else if (TREE_CODE (*tp) == INDIRECT_REF)
+	{
+	  /* Get rid of *& from inline substitutions that can happen when a
+	     pointer argument is an ADDR_EXPR.  */
+	  tree decl = TREE_OPERAND (*tp, 0), value;
+	  splay_tree_node n;
+
+	  n = splay_tree_lookup (id->decl_map, (splay_tree_key) decl);
+	  if (n)
+	    {
+	      value = (tree) n->value;
+	      STRIP_NOPS (value);
+	      if (TREE_CODE (value) == ADDR_EXPR)
+		{
+		  *tp = (tree) n->value;
+		  return copy_body_r (tp, walk_subtrees, data);
+		}
+	    }
+	}
 
       copy_tree_r (tp, walk_subtrees, NULL);
 
Index: tree-must-alias.c
===================================================================
RCS file: tree-must-alias.c
diff -N tree-must-alias.c
-- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tree-must-alias.c	11 Jul 2003 18:49:32 -0000
@@ -0,0 +1,236 @@
+/* Promote virtual operands to real operands by converting may-alias
+   relations into must-alias relations.
+   Copyright (C) 2003 Free Software Foundation, Inc.
+   Contributed by Diego Novillo <dnovillo@redhat.com>
+
+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.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "errors.h"
+#include "ggc.h"
+#include "tree.h"
+
+/* These RTL headers are needed for basic-block.h.  */
+#include "rtl.h"
+#include "tm_p.h"
+#include "hard-reg-set.h"
+#include "basic-block.h"
+#include "diagnostic.h"
+#include "tree-inline.h"
+#include "tree-flow.h"
+#include "tree-simple.h"
+#include "tree-dump.h"
+#include "timevar.h"
+
+
+/* Local functions.  */
+static void find_addressable_vars (sbitmap);
+static void promote_var (tree, sbitmap);
+
+
+/* Local variables.  */
+static FILE *dump_file;
+static int dump_flags;
+
+
+/* This pass finds must-alias relations exposed by constant propagation of
+   ADDR_EXPR values into INDIRECT_REF expressions.  */
+
+void
+tree_compute_must_alias (tree fndecl)
+{
+  size_t i;
+  sbitmap addresses_needed, promoted_vars;
+
+  timevar_push (TV_TREE_MUST_ALIAS);
+
+  /* Initialize debugging dumps.  */
+  dump_file = dump_begin (TDI_mustalias, &dump_flags);
+
+  /* Initialize internal data structures.  */
+  promoted_vars = sbitmap_alloc (num_referenced_vars);
+  sbitmap_zero (promoted_vars);
+
+  addresses_needed = sbitmap_alloc (num_referenced_vars);
+  sbitmap_zero (addresses_needed);
+
+  /* Find variables that still need to have their address taken.  */
+  find_addressable_vars (addresses_needed);
+
+  /* Now traverse the original list of addressable variables and remove
+     those whose addresses are not needed anymore.  */
+  for (i = 0; i < VARRAY_ACTIVE_SIZE (call_clobbered_vars); i++)
+    {
+      tree var = VARRAY_TREE (call_clobbered_vars, i);
+      
+      /* We are only interested in disambiguating addressable locals.  */
+      if (TREE_ADDRESSABLE (var)
+	  /* FIXME Why exactly do we need to ignore pointers and arrays?  */
+	  && !POINTER_TYPE_P (TREE_TYPE (var))
+	  && TREE_CODE (TREE_TYPE (var)) != ARRAY_TYPE
+	  && decl_function_context (var) == current_function_decl
+	  && !TEST_BIT (addresses_needed, var_ann (var)->uid))
+	promote_var (var, promoted_vars);
+    }
+
+  /* Run the SSA pass again if we need to rename new variables.  */
+  if (sbitmap_first_set_bit (promoted_vars) >= 0)
+    {
+      /* Rename all variables in PROMOTED_VARS into SSA form.  */
+      remove_all_phi_nodes_for (promoted_vars);
+      rewrite_into_ssa (fndecl, promoted_vars);
+
+      /* FIXME  Also remove the disambiguated variables from
+	 CALL_CLOBBERED_VARS.  */
+    }
+
+  /* Free allocated memory.  */
+  sbitmap_free (addresses_needed);
+  sbitmap_free (promoted_vars);
+
+  /* Debugging dumps.  */
+  if (dump_file)
+    dump_end (TDI_mustalias, dump_file);
+  dump_function (TDI_mustalias, fndecl);
+
+  timevar_pop (TV_TREE_MUST_ALIAS);
+}
+
+
+/* Find all the variables that need to remain marked addressable and
+   variables that need to be renamed in a second SSA pass because of the
+   propagation of ADDR_EXPR values into INDIRECT_REF expressions.
+
+   Return a bitmap indexed by variable UID that will be set if for all
+   variables that still need to be addressable.  */
+
+static void
+find_addressable_vars (sbitmap addresses_needed)
+{
+  basic_block bb;
+
+  /* Since ADDR_EXPRs have been propagated into INDIRECT_REF expressions
+     and folded from '*&VAR' into 'VAR', some statements will have operands
+     that are not in SSA form.  Those variables are added to a list of
+     variables to be renamed in a second SSA pass.  */
+  FOR_EACH_BB (bb)
+    {
+      block_stmt_iterator si;
+
+      for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si))
+	{
+	  varray_type ops;
+	  size_t i;
+	  tree stmt = bsi_stmt (si);
+
+	  get_stmt_operands (stmt);
+
+	  ops = addresses_taken (stmt);
+	  if (ops)
+	    {
+	      for (i = 0; i < VARRAY_ACTIVE_SIZE (ops); i++)
+		{
+		  tree var = VARRAY_TREE (ops, i);
+		  SET_BIT (addresses_needed, var_ann (var)->uid);
+		}
+	    }
+	  else
+	    {
+	      /* The statement doesn't take the address of any variable,
+		 mark it modified so that any promoted variables in its
+		 operands are renamed again.  FIXME: We should only mark
+		 statements that have promoted variables, but at this point
+		 we still don't know which (if any) variables can be
+		 promoted.  */
+	      modify_stmt (stmt);
+	    }
+	}
+    }
+}
+
+
+/* Remove all the aliasing marks from variable VAR and mark it not
+   addressable.  If the variable was an alias tag for other variables,
+   remove it from those alias sets.  Finally, add VAR to the PROMOTED_VARS
+   bitmap.  */
+
+static void
+promote_var (tree var, sbitmap promoted_vars)
+{
+  var_ann_t ann = var_ann (var);
+
+  /* FIXME: Apparently we always need TREE_ADDRESSABLE for aggregate
+     types.  Is this a backend quirk or do we actually need these?  */
+  if (!AGGREGATE_TYPE_P (TREE_TYPE (var)))
+    TREE_ADDRESSABLE (var) = 0;
+
+  ann->may_aliases = NULL;
+  ann->is_call_clobbered = 0;
+  ann->may_alias_global_mem = 0;
+  ann->may_point_to_global_mem = 0;
+
+  /* If the variable was an alias tag, remove it from every variable that
+     had it in its may-alias set.  */
+  if (ann->is_alias_tag)
+    {
+      size_t i;
+
+      for (i = 0; i < num_call_clobbered_vars; i++)
+	{
+	  size_t j, len;
+	  tree aliased_var = call_clobbered_var (i);
+	  var_ann_t aliased_ann = var_ann (aliased_var);
+	  varray_type aliases = aliased_ann->may_aliases;
+
+	  if (aliases == NULL)
+	    continue;
+
+	  len = VARRAY_ACTIVE_SIZE (aliases);
+	  for (j = 0; j < len; j++)
+	    {
+	      if (var == VARRAY_TREE (aliases, j))
+		{
+		  if (j < len - 1)
+		    VARRAY_TREE (aliases, j) = VARRAY_TREE (aliases, len - 1);
+		  VARRAY_POP (aliases);
+		}
+	    }
+
+	  /* Completely remove the may-alias array if it's empty.  */
+	  if (VARRAY_ACTIVE_SIZE (aliases) == 0)
+	    aliased_ann->may_aliases = NULL;
+	}
+
+      /* Clear the alias-tag mark from VAR.  */
+      ann->is_alias_tag = 0;
+    }
+
+  /* Add VAR to the list of variables to rename.  */
+  SET_BIT (promoted_vars, var_ann (var)->uid);
+
+  /* Debugging dumps.  */
+  if (dump_file && (dump_flags & TDF_DETAILS))
+    {
+      fprintf (dump_file, "Promoting variable ");
+      print_generic_expr (dump_file, var, 0);
+      fprintf (dump_file, " from virtual to real operands.\n");
+    }
+}
Index: tree-optimize.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-optimize.c,v
retrieving revision 1.1.4.39
diff -d -u -p -r1.1.4.39 tree-optimize.c
-- tree-optimize.c	2 Jun 2003 18:49:54 -0000	1.1.4.39
+++ tree-optimize.c	11 Jul 2003 18:49:32 -0000
@@ -62,9 +62,28 @@ optimize_function_tree (fndecl)
   /* Begin analysis and optimization passes.  */
   if (n_basic_blocks > 0 && ! (errorcount || sorrycount))
     {
+      /* Initialize common SSA structures.  */
+      init_tree_ssa ();
+
+      /* Compute aliasing information for all the variables referenced in
+	 the function.  */
+      compute_may_aliases (fndecl);
+
       /* Rewrite the function into SSA form.  */
-      rewrite_into_ssa (fndecl);
-      
+      rewrite_into_ssa (fndecl, NULL);
+
+      if (flag_tree_dce)
+	{
+	  /* If the dominator optimizations propagated ADDR_EXPRs into
+	     INDIRECT_REF expressions, we may be able to promote may-alias
+	     into must-alias relations.  If DCE eliminated all the pointer
+	     assignments that were taking the address of a local variable X,
+	     we can now rename X as a non-aliased local.  */
+	  tree_ssa_dce (fndecl);
+	  if (flag_tree_dom && flag_tree_must_alias)
+	    tree_compute_must_alias (fndecl);
+	}
+
       if (flag_tree_pre)
 	tree_perform_ssapre (fndecl);
 
Index: tree-simple.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-simple.c,v
retrieving revision 1.1.4.43
diff -d -u -p -r1.1.4.43 tree-simple.c
-- tree-simple.c	1 Jul 2003 04:04:31 -0000	1.1.4.43
+++ tree-simple.c	11 Jul 2003 18:49:32 -0000
@@ -457,7 +457,8 @@ is_gimple_call_expr (t)
     {
       /* Mark the CALL_EXPR not gimplifiable so that optimizers don't
          assume anything about it.  Return nonzero to prevent any more
-	 gimplification on this expression.  */
+	 gimplification on this expression.  FIXME: is_gimple_* predicates
+	 should not have side effects.  */
       mark_not_gimple (&t);
       return 1;
     }
Index: tree-ssa-ccp.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa-ccp.c,v
retrieving revision 1.1.2.75
diff -d -u -p -r1.1.2.75 tree-ssa-ccp.c
-- tree-ssa-ccp.c	1 Jul 2003 04:04:32 -0000	1.1.2.75
+++ tree-ssa-ccp.c	11 Jul 2003 18:49:32 -0000
@@ -701,7 +701,7 @@ ccp_fold (tree stmt)
 	 replacement for an argument (as it would create non-gimple
 	 code).  But the new expression can still be used to derive
 	 other constants.  */
-      if (! retval && really_constant_p (op0))
+      if (! retval && is_unchanging_value (op0))
 	return build1 (code, TREE_TYPE (rhs), op0);
     }
 
@@ -750,8 +750,8 @@ ccp_fold (tree stmt)
 	 code).  But the new expression can still be used to derive
 	 other constants.  */
       if (! retval
-	  && really_constant_p (op0)
-	  && really_constant_p (op1))
+	  && is_unchanging_value (op0)
+	  && is_unchanging_value (op1))
 	return build (code, TREE_TYPE (rhs), op0, op1);
     }
 
@@ -819,7 +819,7 @@ evaluate_stmt (tree stmt)
   else
     simplified = NULL_TREE;
 
-  if (simplified && really_constant_p (simplified))
+  if (simplified && is_unchanging_value (simplified))
     {
       /* The statement produced a constant value.  */
       val.lattice_val = CONSTANT;
@@ -1138,7 +1138,7 @@ replace_uses_in (tree stmt)
       tree *use = VARRAY_GENERIC_PTR (uses, i);
       value *val = get_value (*use);
 
-      if (val->lattice_val == CONSTANT && is_gimple_val (val->const_val))
+      if (val->lattice_val == CONSTANT)
 	{
 	  *use = val->const_val;
 	  replaced = true;
@@ -1199,7 +1199,7 @@ fold_stmt (tree stmt)
   tree rhs, result;
 
   rhs = get_rhs (stmt);
-  if (rhs)
+  if (rhs && !TREE_CONSTANT (rhs))
     {
       result = fold (rhs);
       set_rhs (stmt, result);
@@ -1332,7 +1332,7 @@ get_default_value (tree var)
 
       if (TREE_READONLY (sym)
 	  && DECL_INITIAL (sym)
-	  && really_constant_p (DECL_INITIAL (sym)))
+	  && is_unchanging_value (DECL_INITIAL (sym)))
 	{
 	  val.lattice_val = CONSTANT;
 	  val.const_val = DECL_INITIAL (sym);
Index: tree-ssa-copyprop.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa-copyprop.c,v
retrieving revision 1.1.2.5
diff -d -u -p -r1.1.2.5 tree-ssa-copyprop.c
-- tree-ssa-copyprop.c	1 Jul 2003 04:04:32 -0000	1.1.2.5
+++ tree-ssa-copyprop.c	11 Jul 2003 18:49:32 -0000
@@ -44,7 +44,7 @@ static int dump_flags;
 /* Local functions.  */
 static void copyprop_stmt (tree);
 static void copyprop_phi (tree);
-static inline tree get_original (tree, tree *);
+static inline tree get_original (tree);
 

 /* Main entry point to the copy propagator.  The algorithm is a simple
@@ -108,9 +108,8 @@ copyprop_stmt (tree stmt)
   uses = use_ops (stmt);
   for (i = 0; uses && i < VARRAY_ACTIVE_SIZE (uses); i++)
     {
-      tree vuse;
       tree *use_p = (tree *) VARRAY_GENERIC_PTR (uses, i);
-      tree orig = get_original (*use_p, &vuse);
+      tree orig = get_original (*use_p);
 
       if (orig
 	  && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (*use_p)
@@ -125,9 +124,7 @@ copyprop_stmt (tree stmt)
 	      fprintf (dump_file, "\n");
 	    }
 
-	  *use_p = orig;
-	  if (vuse)
-	    add_vuse (vuse, stmt, NULL);
+	  propagate_copy (use_p, orig);
 	  modified = true;
 	}
     }
@@ -154,9 +151,8 @@ copyprop_phi (tree phi)
 
   for (i = 0; i < PHI_NUM_ARGS (phi); i++)
     {
-      tree vuse;
       tree arg = PHI_ARG_DEF (phi, i);
-      tree orig = get_original (arg, &vuse);
+      tree orig = get_original (arg);
 
       if (orig
 	  && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (arg)
@@ -184,12 +180,11 @@ copyprop_phi (tree phi)
    VAR = ORIG, return ORIG.  Otherwise, return NULL.  */
 
 static inline tree
-get_original (tree var, tree *vuse_p)
+get_original (tree var)
 {
   tree def_stmt;
 
   def_stmt = SSA_NAME_DEF_STMT (var);
-  *vuse_p = NULL_TREE;
 
   /* If VAR is not the LHS of its defining statement, it means that VAR is
      defined by a VDEF node.  This implies aliasing or structure updates.
@@ -207,4 +202,25 @@ get_original (tree var, tree *vuse_p)
     return TREE_OPERAND (def_stmt, 1);
 
   return NULL_TREE;
+}
+
+
+/* Replace the operand pointed to by OP_P with variable VAR.  If *OP_P is a
+   pointer, copy the memory tag used originally by *OP_P into VAR.  This is
+   needed in cases where VAR had never been dereferenced in the program.  */
+   
+void
+propagate_copy (tree *op_p, tree var)
+{
+  /* If VAR doesn't have a memory tag, copy the one from the original
+     operand.  */
+  if (POINTER_TYPE_P (TREE_TYPE (*op_p)))
+    {
+      var_ann_t new_ann = var_ann (SSA_NAME_VAR (var));
+      var_ann_t orig_ann = var_ann (SSA_NAME_VAR (*op_p));
+      if (new_ann->mem_tag == NULL_TREE)
+	new_ann->mem_tag = orig_ann->mem_tag;
+    }
+
+  *op_p = var;
 }
Index: tree-ssa-dce.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa-dce.c,v
retrieving revision 1.1.2.44
diff -d -u -p -r1.1.2.44 tree-ssa-dce.c
-- tree-ssa-dce.c	25 Jun 2003 02:37:31 -0000	1.1.2.44
+++ tree-ssa-dce.c	11 Jul 2003 18:49:32 -0000
@@ -201,10 +201,6 @@ need_to_preserve_store (tree var)
   if (decl_function_context (base_symbol) == NULL)
     return true;
   
-  /* Stores through parameter pointers must be preserved.
-     FIXME: We cannot detect this here anymore!  It needs to be done at the
-	    spot where we see the INDIRECT_REF itself.  */
-
   /* Static locals must be preserved as well.  */
   if (TREE_STATIC (base_symbol))
     return true;
@@ -213,10 +209,8 @@ need_to_preserve_store (tree var)
   if (may_alias_global_mem_p (sym))
     return true;
 
-  /* If SYM is used in some way we can not readily see in the IL, then
-     we need to preserve it.
-
-     Long term this needs to go away.  */
+  /* If SYM is used in some way that we can not readily see in the IL, then
+     we need to preserve it.  FIXME: Long term this needs to go away.  */
   if (has_hidden_use (sym))
     return true;
 
Index: tree-ssa.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa.c,v
retrieving revision 1.1.4.100
diff -d -u -p -r1.1.4.100 tree-ssa.c
-- tree-ssa.c	3 Jul 2003 18:28:25 -0000	1.1.4.100
+++ tree-ssa.c	11 Jul 2003 18:49:33 -0000
@@ -62,8 +62,8 @@ Boston, MA 02111-1307, USA.  */
 unsigned int next_ssa_version;
 
 /* Dump file and flags.  */
-FILE *tree_ssa_dump_file;
-int tree_ssa_dump_flags;
+static FILE *dump_file;
+static int dump_flags;
 
 /* Workstack for computing PHI node insertion points.  */
 static GTY (()) varray_type work_stack = NULL;
@@ -154,8 +154,15 @@ struct ssa_stats_d
 
 static struct ssa_stats_d ssa_stats;
 
+/* Bitmap representing variables that need to be renamed into SSA form.  */
+static sbitmap vars_to_rename;
+
+/* Flag to indicate whether the dominator optimizations propagated an
+   ADDR_EXPR.  If that happens, we may need to run another SSA pass because
+   new symbols may have been exposed.  */
+static bool addr_expr_propagated_p;
+
 /* Local functions.  */
-static void init_tree_ssa (void);
 static void delete_tree_ssa (tree);
 static void mark_def_sites (dominance_info, sbitmap);
 static void compute_global_livein (varray_type);
@@ -166,6 +173,7 @@ static void insert_phis_for_deferred_var
 static void rewrite_block (basic_block, tree);
 static int rewrite_and_optimize_stmt (block_stmt_iterator, varray_type *,
 				      varray_type *);
+static void check_for_new_variables (void);
 static void rewrite_stmt (block_stmt_iterator, varray_type *);
 static inline void rewrite_operand (tree *, bool);
 static void register_new_def (tree, tree, varray_type *, bool);
@@ -207,7 +215,11 @@ static inline void add_conflicts_if_vali
 static void replace_variable (var_map, tree *);
 
 /* Main entry point to the SSA builder.  FNDECL is the gimplified function
-   to convert.
+   to convert.  VARS is an sbitmap representing variables that need to be
+   renamed into SSA form.  A variable in REFERENCED_VARS will be renamed
+   into SSA if the element corresponding to the variable's UID is set in
+   VARS.  If VARS is NULL, all variables in REFERENCED_VARS will be
+   processed.
 
    Every statement has two different sets of operands: real and virtual.
    Real operands are those that use scalar, non-aliased variables.  Virtual
@@ -288,45 +300,115 @@ static void replace_variable (var_map, t
    increased compilation time.  */
 
 void
-rewrite_into_ssa (tree fndecl)
+rewrite_into_ssa (tree fndecl, sbitmap vars)
 {
   bitmap *dfs;
   sbitmap globals;
   dominance_info idom;
-  int i;
+  int i, rename_count;
+  bool compute_df;
   
   timevar_push (TV_TREE_SSA_OTHER);
 
-  /* Initialize common SSA structures.  */
-  init_tree_ssa ();
-
   /* Debugging dumps.  */
-  tree_ssa_dump_file = dump_begin (TDI_ssa, &tree_ssa_dump_flags);
+  dump_file = dump_begin (TDI_ssa, &dump_flags);
 
-  /* Compute aliasing information.  */
-  compute_may_aliases (fndecl);
+  /* Initialize the array of variables to rename.  */
+  if (vars == NULL)
+    {
+      vars_to_rename = sbitmap_alloc (num_referenced_vars);
+      sbitmap_ones (vars_to_rename);
+    }
+  else
+    vars_to_rename = vars;
+
+  /* Allocate memory for the DEF_BLOCKS hash table.  */
+  def_blocks = htab_create (VARRAY_ACTIVE_SIZE (referenced_vars),
+			    def_blocks_hash, def_blocks_eq, def_blocks_free);
+
+  /* Allocate memory for the CURRDEFS hash table.  */
+  currdefs = htab_create (VARRAY_ACTIVE_SIZE (referenced_vars),
+			  var_value_hash, var_value_eq, free);
+
+  /* Allocate memory for the AVAIL_EXPRS hash table.  */
+  avail_exprs = htab_create (1024, avail_expr_hash, avail_expr_eq, NULL);
+
+  /* Allocate memory for the CONST_AND_COPIES hash table.  */
+  const_and_copies = htab_create (1024, var_value_hash, var_value_eq, free);
 
+  /* Allocate memory for the GLOBALS bitmap which will indicate which
+     variables are live across basic block boundaries.  Note that this
+     bitmap is indexed by variable UID, so it must always be large enough
+     to accomodate all the variables referenced in the program, not just
+     the ones we are renaming.  */
   globals = sbitmap_alloc (num_referenced_vars);
   sbitmap_zero (globals);
 
-  /* Compute immediate dominators and dominance frontiers.  */
+  /* Initialize dominance frontier and immediate dominator bitmaps.  */
+  dfs = (bitmap *) xmalloc (n_basic_blocks * sizeof (bitmap *));
+  for (i = 0; i < n_basic_blocks; i++)
+    {
+      dfs[i] = BITMAP_XMALLOC ();
+      bb_ann (BASIC_BLOCK (i))->dom_children = NULL;
+    }
+
+  /* Compute immediate dominators.  */
   idom = calculate_dominance_info (CDI_DOMINATORS);
 
-  /* Find variable references and mark definition sites.  */
-  mark_def_sites (idom, globals);
+  /* Start the SSA rename process.  This may need to be repeated if the
+     dominator optimizations exposed more symbols to rename by propagating
+     ADDR_EXPR values into INDIRECT_REF expressions.  */
+  rename_count = 0;
+  compute_df = true;
+  addr_expr_propagated_p = false;
+  do
+    {
+      /* Find variable references and mark definition sites.  */
+      mark_def_sites (idom, globals);
 
-  dfs = (bitmap *) xmalloc (n_basic_blocks * sizeof (bitmap *));
-  for (i = 0; i < n_basic_blocks; i++)
-    dfs[i] = BITMAP_XMALLOC ();
-  compute_dominance_frontiers (dfs, idom);
+      /* Compute dominance frontiers (only once) and insert PHI nodes at
+	 dominance frontiers of definition blocks.  */
+      if (compute_df)
+	{
+	  compute_dominance_frontiers (dfs, idom);
+	  compute_df = false;
+	}
 
-  /* Insert PHI nodes at dominance frontiers of definition blocks.  */
-  insert_phi_nodes (dfs, globals);
+      insert_phi_nodes (dfs, globals);
 
-  /* Rewrite all the basic blocks in the program.  */
-  timevar_push (TV_TREE_SSA_REWRITE_BLOCKS);
-  rewrite_block (ENTRY_BLOCK_PTR, NULL_TREE);
-  timevar_pop (TV_TREE_SSA_REWRITE_BLOCKS);
+      /* Rewrite all the basic blocks in the program.  */
+      timevar_push (TV_TREE_SSA_REWRITE_BLOCKS);
+      sbitmap_zero (vars_to_rename);
+      rewrite_block (ENTRY_BLOCK_PTR, NULL_TREE);
+      timevar_pop (TV_TREE_SSA_REWRITE_BLOCKS);
+
+      /* If the dominator optimizations propagated ADDR_EXPRs, we may need
+	 to repeat the SSA renaming process for the new symbols that may
+	 have been exposed.  Re-scan the program for operands not in SSA
+	 form and if new symbols are added to VARS_TO_RENAME, repeat the
+	 process.  */
+      if (addr_expr_propagated_p)
+	{
+	  check_for_new_variables ();
+	  if (sbitmap_first_set_bit (vars_to_rename) >= 0)
+	    {
+	      /* Remove PHI nodes for the new symbols, clear the hash
+		 tables and bitmaps and run SSA again on the new exposed
+		 variables.  */
+	      remove_all_phi_nodes_for (vars_to_rename);
+	      htab_empty (def_blocks);
+	      htab_empty (currdefs);
+	      htab_empty (avail_exprs);
+	      htab_empty (const_and_copies);
+	      sbitmap_zero (globals);
+	    }
+	}
+
+      /* Sanity check, we shouldn't need to iterate more than twice.  */
+      if (rename_count++ > 1)
+	abort ();
+    }
+  while (sbitmap_first_set_bit (vars_to_rename) >= 0);
 
   /* Free allocated memory.  */
   for (i = 0; i < n_basic_blocks; i++)
@@ -338,18 +420,20 @@ rewrite_into_ssa (tree fndecl)
   htab_delete (currdefs);
   htab_delete (avail_exprs);
   htab_delete (const_and_copies);
+  if (vars == NULL)
+    sbitmap_free (vars_to_rename);
 
   /* Debugging dumps.  */
-  if (tree_ssa_dump_file)
+  if (dump_file)
     {
-      if (tree_ssa_dump_flags & TDF_STATS)
+      if (dump_flags & TDF_STATS)
 	{
-	  dump_dfa_stats (tree_ssa_dump_file);
-	  dump_tree_ssa_stats (tree_ssa_dump_file);
+	  dump_dfa_stats (dump_file);
+	  dump_tree_ssa_stats (dump_file);
 	}
 
-      dump_end (TDI_ssa, tree_ssa_dump_file);
-      tree_ssa_dump_file = NULL;
+      dump_end (TDI_ssa, dump_file);
+      dump_file = NULL;
     }
 
   dump_function (TDI_ssa, fndecl);
@@ -466,10 +550,13 @@ mark_def_sites (dominance_info idom, sbi
   block_stmt_iterator si;
   sbitmap kills;
 
+  /* Notice that this bitmap is indexed using variable UIDs, so it must be
+     large enough to accomodate all the variables referenced in the
+     function, not just the ones we are renaming.  */
   kills = sbitmap_alloc (num_referenced_vars);
 
-  /* Mark all the blocks that have definitions for each variable referenced
-     in the function.  */
+  /* Mark all the blocks that have definitions for each variable in the
+     VARS_TO_RENAME bitmap.  */
   FOR_EACH_BB (bb)
     {
       /* Add BB to the set of dominator children of BB's immediate
@@ -496,7 +583,13 @@ mark_def_sites (dominance_info idom, sbi
 	  for (i = 0; ops && i < VARRAY_ACTIVE_SIZE (ops); i++)
 	    {
 	      tree *use = VARRAY_GENERIC_PTR (ops, i);
-	      size_t uid = var_ann (*use)->uid;
+	      size_t uid;
+
+	      /* Ignore variables that have been renamed already.  */
+	      if (TREE_CODE (*use) == SSA_NAME)
+		continue;
+	      
+	      uid = var_ann (*use)->uid;
 
 	      if (! TEST_BIT (kills, uid))
 		{
@@ -510,7 +603,13 @@ mark_def_sites (dominance_info idom, sbi
 	  for (i = 0; ops && i < VARRAY_ACTIVE_SIZE (ops); i++)
 	    {
 	      tree use = VARRAY_TREE (ops, i);
-	      size_t uid = var_ann (use)->uid;
+	      size_t uid;
+
+	      /* Ignore variables that have been renamed already.  */
+	      if (TREE_CODE (use) == SSA_NAME)
+		continue;
+	      
+	      uid = var_ann (use)->uid;
 
 	      if (! TEST_BIT (kills, uid))
 	        {
@@ -523,13 +622,19 @@ mark_def_sites (dominance_info idom, sbi
 	     KILLED_VARS because a VDEF does not constitute a killing
 	     definition of the variable.  However, the operand of a virtual
 	     definitions is a use of the variable, so it may affect
-	     NONLOCAL_VARS.  */
+	     GLOBALS.  */
 	  ops = vdef_ops (stmt);
 	  for (i = 0; ops && i < VARRAY_ACTIVE_SIZE (ops); i++)
 	    {
 	      tree vdef = VARRAY_TREE (ops, i);
 	      tree vdef_op = VDEF_OP (vdef);
-	      size_t uid = var_ann (vdef_op)->uid;
+	      size_t uid;
+
+	      /* Ignore variables that have been renamed already.  */
+	      if (TREE_CODE (vdef_op) == SSA_NAME)
+		continue;
+
+	      uid = var_ann (vdef_op)->uid;
 
 	      set_def_block (VDEF_RESULT (vdef), bb);
 	      if (!TEST_BIT (kills, uid))
@@ -539,9 +644,10 @@ mark_def_sites (dominance_info idom, sbi
 		}
 	    }
 
-	  /* Now process the definition made by this statement.  */
+	  /* Now process the definition made by this statement.  If the
+	     definition has been renamed already, do nothing.  */
 	  dest = def_op (stmt);
-	  if (dest)
+	  if (dest && TREE_CODE (*dest) != SSA_NAME)
 	    {
 	      set_def_block (*dest, bb);
 	      SET_BIT (kills, var_ann (*dest)->uid);
@@ -610,9 +716,9 @@ set_livein_block (tree var, basic_block 
    definitions.  DFS contains the dominance frontier information for the
    flowgraph.
    
-   NONLOCAL_VARs is a bitmap representing the set of variables which are
-   live across basic block boundaries.  Only variables in NONLOCAL_VARs
-   need PHI nodes.  */
+   GLOBALS is a bitmap representing the set of variables which are live
+   across basic block boundaries.  Only variables in GLOBALS need PHI
+   nodes.  */
 
 static void
 insert_phi_nodes (bitmap *dfs, sbitmap globals)
@@ -628,19 +734,22 @@ insert_phi_nodes (bitmap *dfs, sbitmap g
      an assignment or PHI node will be pushed to this stack.  */
   VARRAY_BB_INIT (work_stack, last_basic_block, "work_stack");
 
-  /* Iterate over all referenced variables in the function.  For each
-     variable, add to the work list all the blocks that have a definition
-     for the variable.  PHI nodes will be added to the dominance frontier
-     blocks of each definition block.  */
-  for (i = 0; i < num_referenced_vars; i++)
+  /* Iterate over all variables in VARS_TO_RENAME.  For each variable, add
+     to the work list all the blocks that have a definition for the
+     variable.  PHI nodes will be added to the dominance frontier blocks of
+     each definition block.  */
+  EXECUTE_IF_SET_IN_SBITMAP (vars_to_rename, 0, i,
     {
+      tree var = referenced_var (i);
+      var_ann_t ann = var_ann (var);
+
       /* If we have queued enough variables, then drain the queue.  */
       if (VARRAY_ACTIVE_SIZE (def_maps) == HOST_BITS_PER_WIDE_INT)
 	insert_phis_for_deferred_variables (def_maps);
 
-      if (TEST_BIT (globals, i))
-	insert_phi_nodes_for (referenced_var (i), dfs, def_maps);
-    }
+      if (TEST_BIT (globals, ann->uid))
+	insert_phi_nodes_for (var, dfs, def_maps);
+    });
 
   if (VARRAY_ACTIVE_SIZE (def_maps) != 0)
     insert_phis_for_deferred_variables (def_maps);
@@ -723,8 +832,8 @@ rewrite_block (basic_block bb, tree eq_e
   if (flag_tree_dom)
     VARRAY_TREE_INIT (block_avail_exprs, 20, "block_avail_exprs");
 
-  if (tree_ssa_dump_file && (tree_ssa_dump_flags & TDF_DETAILS))
-    fprintf (tree_ssa_dump_file, "\n\nRenaming block #%d\n\n", bb->index);
+  if (dump_file && (dump_flags & TDF_DETAILS))
+    fprintf (dump_file, "\n\nRenaming block #%d\n\n", bb->index);
 
   /* If EQ_EXPR_VALUE (VAR == VALUE) is given and we are doing dominator
      optimizations, register the VALUE as a new value for VAR, so that
@@ -776,9 +885,15 @@ rewrite_block (basic_block bb, tree eq_e
 
       for (phi = phi_nodes (e->dest); phi; phi = TREE_CHAIN (phi))
 	{
+	  tree currdef;
+
+	  /* Ignore PHI nodes that have already been renamed.  */
+	  if (PHI_NUM_ARGS (phi) == PHI_ARG_CAPACITY (phi))
+	    continue;
+
 	  /* FIXME.  [UNSSA] If -ftree-dominator-opts, allow constants and
 	     copies to be propagated into PHI arguments.  */
-	  tree currdef = get_reaching_def (SSA_NAME_VAR (PHI_RESULT (phi)));
+	  currdef = get_reaching_def (SSA_NAME_VAR (PHI_RESULT (phi)));
 	  add_phi_arg (phi, currdef, e);
 	}
     }
@@ -890,14 +1005,14 @@ insert_copy_on_edge (edge e, tree dest, 
   tree copy;
 
   copy = build (MODIFY_EXPR, TREE_TYPE (dest), dest, src);
-  if (tree_ssa_dump_file && (tree_ssa_dump_flags & TDF_DETAILS))
+  if (dump_file && (dump_flags & TDF_DETAILS))
     {
-      fprintf (tree_ssa_dump_file,
+      fprintf (dump_file,
 	       "Inserting a copy on edge BB%d->BB%d :",
 	       e->src->index,
 	       e->dest->index);
-      print_generic_expr (tree_ssa_dump_file, copy, tree_ssa_dump_flags);
-      fprintf (tree_ssa_dump_file, "\n");
+      print_generic_expr (dump_file, copy, dump_flags);
+      fprintf (dump_file, "\n");
     }
   bsi_insert_on_edge (e, copy);
 }
@@ -1319,15 +1434,15 @@ coalesce_ssa_name (var_map map)
 	      abort ();
 	    }
 
-	  if (tree_ssa_dump_file && (tree_ssa_dump_flags & TDF_DETAILS))
+	  if (dump_file && (dump_flags & TDF_DETAILS))
 	    {
-	      fprintf (tree_ssa_dump_file, "Must coalesce ");
-	      print_generic_expr (tree_ssa_dump_file, 
+	      fprintf (dump_file, "Must coalesce ");
+	      print_generic_expr (dump_file, 
 				  partition_to_var (map, x), 
 				  TDF_SLIM);
-	      fprintf (tree_ssa_dump_file, " with the root variable ");
-	      print_generic_expr (tree_ssa_dump_file, var, TDF_SLIM);
-	      fprintf (tree_ssa_dump_file, ".\n");
+	      fprintf (dump_file, " with the root variable ");
+	      print_generic_expr (dump_file, var, TDF_SLIM);
+	      fprintf (dump_file, ".\n");
 	    }
 
 	  change_partition_var (map, var, x);
@@ -1393,18 +1508,18 @@ coalesce_ssa_name (var_map map)
 		    /* Now map the partitions back to their real variables.  */
 		    var = partition_to_var (map, x);
 		    tmp = partition_to_var (map, y);
-		    if (tree_ssa_dump_file 
-			&& (tree_ssa_dump_flags & TDF_DETAILS))
+		    if (dump_file 
+			&& (dump_flags & TDF_DETAILS))
 		      {
-			fprintf (tree_ssa_dump_file , "ABNORMAL: Coalescing ");
-			print_generic_expr (tree_ssa_dump_file, 
+			fprintf (dump_file , "ABNORMAL: Coalescing ");
+			print_generic_expr (dump_file, 
 					    var, 
 					    TDF_SLIM);
-			fprintf (tree_ssa_dump_file , " and ");
-			print_generic_expr (tree_ssa_dump_file, 
+			fprintf (dump_file , " and ");
+			print_generic_expr (dump_file, 
 					    tmp, 
 					    TDF_SLIM);
-			fprintf (tree_ssa_dump_file , " over abnormal edge.\n");
+			fprintf (dump_file , " over abnormal edge.\n");
 		      }
 		    var_union (map, var, tmp);
 		    conflict_graph_merge_regs (graph, x, y);
@@ -1425,9 +1540,9 @@ coalesce_ssa_name (var_map map)
 	      }
 	  }
 
-    if (tree_ssa_dump_file && (tree_ssa_dump_flags & TDF_DETAILS))
+    if (dump_file && (dump_flags & TDF_DETAILS))
       {
-        dump_var_map (tree_ssa_dump_file, map);
+        dump_var_map (dump_file, map);
       }
 

@@ -1489,11 +1604,11 @@ assign_vars (var_map map)
 	     the variable as assigned.  */
 	  ann = var_ann (var);
 	  ann->out_of_ssa_tag = 1;
-	  if (tree_ssa_dump_file && (tree_ssa_dump_flags & TDF_DETAILS))
+	  if (dump_file && (dump_flags & TDF_DETAILS))
 	    {
-	      fprintf(tree_ssa_dump_file, "partition %d has variable ", x);
-	      print_generic_expr (tree_ssa_dump_file, var, TDF_SLIM);
-	      fprintf(tree_ssa_dump_file, " assigned to it.\n");
+	      fprintf (dump_file, "partition %d has variable ", x);
+	      print_generic_expr (dump_file, var, TDF_SLIM);
+	      fprintf (dump_file, " assigned to it.\n");
 	    }
 
 	}
@@ -1519,23 +1634,23 @@ assign_vars (var_map map)
 	      continue;
 	    }
 
-	  if (tree_ssa_dump_file && (tree_ssa_dump_flags & TDF_DETAILS))
+	  if (dump_file && (dump_flags & TDF_DETAILS))
 	    {
-	      fprintf (tree_ssa_dump_file, "Overlap :  '");
-	      print_generic_expr (tree_ssa_dump_file, t, TDF_SLIM);
-	      fprintf (tree_ssa_dump_file, "'  conflicts with  '");
-	      print_generic_expr (tree_ssa_dump_file, var, TDF_SLIM);
+	      fprintf (dump_file, "Overlap :  '");
+	      print_generic_expr (dump_file, t, TDF_SLIM);
+	      fprintf (dump_file, "'  conflicts with  '");
+	      print_generic_expr (dump_file, var, TDF_SLIM);
 	    }
 
 	  var = create_temp (t);
 	  change_partition_var (map, var, i);
 	  ann = var_ann (var);
 
-	  if (tree_ssa_dump_file && (tree_ssa_dump_flags & TDF_DETAILS))
+	  if (dump_file && (dump_flags & TDF_DETAILS))
 	    {
-	      fprintf (tree_ssa_dump_file, "'     New temp:  '");
-	      print_generic_expr (tree_ssa_dump_file, var, TDF_SLIM);
-	      fprintf (tree_ssa_dump_file, "'\n");
+	      fprintf (dump_file, "'     New temp:  '");
+	      print_generic_expr (dump_file, var, TDF_SLIM);
+	      fprintf (dump_file, "'\n");
 	    }
 	}
     }
@@ -1587,10 +1702,10 @@ rewrite_out_of_ssa (tree fndecl)
 
   timevar_push (TV_TREE_SSA_TO_NORMAL);
 
-  tree_ssa_dump_file = dump_begin (TDI_optimized, &tree_ssa_dump_flags);
+  dump_file = dump_begin (TDI_optimized, &dump_flags);
 
-  if (tree_ssa_dump_file && (tree_ssa_dump_flags & TDF_DETAILS))
-    dump_tree_cfg (tree_ssa_dump_file, tree_ssa_dump_flags & ~TDF_DETAILS);
+  if (dump_file && (dump_flags & TDF_DETAILS))
+    dump_tree_cfg (dump_file, dump_flags & ~TDF_DETAILS);
 
   map = create_ssa_var_map ();
 
@@ -1598,15 +1713,15 @@ rewrite_out_of_ssa (tree fndecl)
      which have only one SSA version since there is nothing to coalesce.  */
   compact_var_map (map, VARMAP_NO_SINGLE_DEFS);
 
-  if (tree_ssa_dump_file && (tree_ssa_dump_flags & TDF_DETAILS))
-    dump_var_map (tree_ssa_dump_file, map);
+  if (dump_file && (dump_flags & TDF_DETAILS))
+    dump_var_map (dump_file, map);
 
   coalesce_ssa_name (map);
 
-  if (tree_ssa_dump_file && (tree_ssa_dump_flags & TDF_DETAILS))
+  if (dump_file && (dump_flags & TDF_DETAILS))
     {
-      fprintf(tree_ssa_dump_file, "After Coalescing:\n");
-      dump_var_map (tree_ssa_dump_file, map);
+      fprintf (dump_file, "After Coalescing:\n");
+      dump_var_map (dump_file, map);
     }
 
   /* This is the final var list, so assign real variables to the different
@@ -1615,10 +1730,10 @@ rewrite_out_of_ssa (tree fndecl)
   compact_var_map (map, VARMAP_NORMAL);
   assign_vars (map);
 
-  if (tree_ssa_dump_file && (tree_ssa_dump_flags & TDF_DETAILS))
+  if (dump_file && (dump_flags & TDF_DETAILS))
     {
-      fprintf(tree_ssa_dump_file, "After Root variable replacement:\n");
-      dump_var_map (tree_ssa_dump_file, map);
+      fprintf (dump_file, "After Root variable replacement:\n");
+      dump_var_map (dump_file, map);
     }
 
   g = new_elim_graph (map->num_partitions);
@@ -1687,8 +1802,8 @@ rewrite_out_of_ssa (tree fndecl)
   /* If any copies were inserted on edges, actually insert them now.  */
   bsi_commit_edge_inserts (0, NULL);
 
-  if (tree_ssa_dump_file && (tree_ssa_dump_flags & TDF_DETAILS))
-    dump_tree_cfg (tree_ssa_dump_file, tree_ssa_dump_flags & ~TDF_DETAILS);
+  if (dump_file && (dump_flags & TDF_DETAILS))
+    dump_tree_cfg (dump_file, dump_flags & ~TDF_DETAILS);
 
   /* Do some cleanups which reduce the amount of data the
      tree->rtl expanders deal with.  */
@@ -1707,8 +1822,8 @@ rewrite_out_of_ssa (tree fndecl)
   delete_var_map (map);
   timevar_pop (TV_TREE_SSA_TO_NORMAL);
 
-  if (tree_ssa_dump_file)
-    dump_end (TDI_optimized, tree_ssa_dump_file);
+  if (dump_file)
+    dump_end (TDI_optimized, dump_file);
 }
 

@@ -1918,7 +2033,6 @@ insert_phi_nodes_for (tree var, bitmap *
 
       VARRAY_POP (work_stack);
       
-
       EXECUTE_IF_SET_IN_BITMAP (dfs[bb_index], 0, bb_index,
 	{
           basic_block bb = BASIC_BLOCK (bb_index);
@@ -2031,11 +2145,11 @@ rewrite_and_optimize_stmt (block_stmt_it
   ann = stmt_ann (stmt);
   ssa_stats.num_stmts++;
 
-  if (tree_ssa_dump_file && (tree_ssa_dump_flags & TDF_DETAILS))
+  if (dump_file && (dump_flags & TDF_DETAILS))
     {
-      fprintf (tree_ssa_dump_file, "Renaming statement ");
-      print_generic_stmt (tree_ssa_dump_file, stmt, TDF_SLIM);
-      fprintf (tree_ssa_dump_file, "\n");
+      fprintf (dump_file, "Renaming statement ");
+      print_generic_stmt (dump_file, stmt, TDF_SLIM);
+      fprintf (dump_file, "\n");
     }
 
 #if defined ENABLE_CHECKING
@@ -2064,6 +2178,11 @@ rewrite_and_optimize_stmt (block_stmt_it
     {
       tree val;
       tree *op_p = (tree *) VARRAY_GENERIC_PTR (uses, i);
+
+      /* If the operand is already in SSA form, do nothing.  */
+      if (TREE_CODE (*op_p) == SSA_NAME)
+	continue;
+
       rewrite_operand (op_p, true);
 
       /* If the operand has a known constant value or it is known to be a
@@ -2074,30 +2193,41 @@ rewrite_and_optimize_stmt (block_stmt_it
       if (val)
 	{
 	  /* Gather statistics.  */
-	  if (TREE_CONSTANT (val))
+	  if (is_unchanging_value (val))
 	    ssa_stats.num_const_prop++;
 	  else
 	    ssa_stats.num_copy_prop++;
 
 	  /* Replace the operand with its known constant value or copy.  */
-	  if (tree_ssa_dump_file && (tree_ssa_dump_flags & TDF_DETAILS))
+	  if (dump_file && (dump_flags & TDF_DETAILS))
 	    {
-	      fprintf (tree_ssa_dump_file, "  Replaced '");
-	      print_generic_expr (tree_ssa_dump_file, *op_p, 0);
-	      fprintf (tree_ssa_dump_file, "' with %s '",
-		       TREE_CONSTANT (val) ? "constant" : "variable");
-	      print_generic_expr (tree_ssa_dump_file, val, 0);
-	      fprintf (tree_ssa_dump_file, "'\n");
+	      fprintf (dump_file, "  Replaced '");
+	      print_generic_expr (dump_file, *op_p, 0);
+	      fprintf (dump_file, "' with %s '",
+		       is_unchanging_value (val) ? "constant" : "variable");
+	      print_generic_expr (dump_file, val, 0);
+	      fprintf (dump_file, "'\n");
 	    }
 
-	  *op_p = val;
+	  /* If VAL is an ADDR_EXPR, notify that we may need to have a
+	     second SSA pass to rename variables exposed by the folding of
+	     *&VAR expressions.  */
+	  if (TREE_CODE (val) == ADDR_EXPR)
+	    addr_expr_propagated_p = true;
+
+	  if (TREE_CODE (val) == SSA_NAME)
+	    propagate_copy (op_p, val);
+	  else
+	    *op_p = val;
+
 	  ann->modified = 1;
 	}
     }
 
   /* Rewrite virtual uses in the statement.  */
   for (i = 0; vuses && i < VARRAY_ACTIVE_SIZE (vuses); i++)
-    rewrite_operand (&(VARRAY_TREE (vuses, i)), false);
+    if (TREE_CODE (VARRAY_TREE (vuses, i)) != SSA_NAME)
+      rewrite_operand (&(VARRAY_TREE (vuses, i)), false);
 
   /* If the statement has been modified with constant replacements,
       fold its RHS before checking for redundant computations.  */
@@ -2124,13 +2254,13 @@ rewrite_and_optimize_stmt (block_stmt_it
       ssa_stats.num_exprs_considered++;
       if (cached_lhs && TREE_TYPE (cached_lhs) == TREE_TYPE (*def_p))
 	{
-	  if (tree_ssa_dump_file && (tree_ssa_dump_flags & TDF_DETAILS))
+	  if (dump_file && (dump_flags & TDF_DETAILS))
 	    {
-	      fprintf (tree_ssa_dump_file, "  Replaced redundant expr '");
-	      print_generic_expr (tree_ssa_dump_file, TREE_OPERAND (stmt, 1), 0);
-	      fprintf (tree_ssa_dump_file, "' with '");
-	      print_generic_expr (tree_ssa_dump_file, cached_lhs, 0);
-	      fprintf (tree_ssa_dump_file, "'\n");
+	      fprintf (dump_file, "  Replaced redundant expr '");
+	      print_generic_expr (dump_file, TREE_OPERAND (stmt, 1), 0);
+	      fprintf (dump_file, "' with '");
+	      print_generic_expr (dump_file, cached_lhs, 0);
+	      fprintf (dump_file, "'\n");
 	    }
 
 	  if (cached_lhs && get_value_for (*def_p, currdefs) == cached_lhs)
@@ -2149,8 +2279,8 @@ rewrite_and_optimize_stmt (block_stmt_it
     }
 
   /* Step 3.  If the computation wasn't redundant, register its DEF and
-     VDEF operands.  */
-  if (def_p)
+     VDEF operands.  Do nothing if the definition is already in SSA form.  */
+  if (def_p && TREE_CODE (*def_p) != SSA_NAME)
     {
       tree rhs;
 
@@ -2162,8 +2292,7 @@ rewrite_and_optimize_stmt (block_stmt_it
       rhs = TREE_OPERAND (stmt, 1);
       if (may_optimize_p)
 	{
-	  if (TREE_CODE (rhs) == SSA_NAME
-	      || (TREE_CONSTANT (rhs) && is_gimple_val (rhs)))
+	  if (TREE_CODE (rhs) == SSA_NAME || is_unchanging_value (rhs))
 	    set_value_for (*def_p, rhs, const_and_copies);
 	}
     }
@@ -2172,7 +2301,12 @@ rewrite_and_optimize_stmt (block_stmt_it
   for (i = 0; vdefs && i < VARRAY_ACTIVE_SIZE (vdefs); i++)
     {
       tree vdef = VARRAY_TREE (vdefs, i);
+
+      if (TREE_CODE (VDEF_RESULT (vdef)) == SSA_NAME)
+	continue;
+
       rewrite_operand (&(VDEF_OP (vdef)), false);
+
       VDEF_RESULT (vdef) = make_ssa_name (VDEF_RESULT (vdef), stmt);
       register_new_def (SSA_NAME_VAR (VDEF_RESULT (vdef)), 
 			VDEF_RESULT (vdef), block_defs_p, false);
@@ -2182,6 +2316,60 @@ rewrite_and_optimize_stmt (block_stmt_it
 }
 

+/* Scan all the statements looking for symbols not in SSA form.  If any are
+   found, add them to VARS_TO_RENAME to trigger a second SSA pass.  */
+
+static void
+check_for_new_variables (void)
+{
+  basic_block bb;
+  
+  FOR_EACH_BB (bb)
+    {
+      block_stmt_iterator si;
+
+      for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si))
+	{
+	  varray_type ops;
+	  size_t i;
+	  tree *def_p;
+
+	  tree stmt = bsi_stmt (si);
+
+	  get_stmt_operands (stmt);
+
+	  def_p = def_op (stmt);
+	  if (def_p && DECL_P (*def_p))
+	    SET_BIT (vars_to_rename, var_ann (*def_p)->uid);
+
+	  ops = use_ops (stmt);
+	  for (i = 0; ops && i < VARRAY_ACTIVE_SIZE (ops); i++)
+	    {
+	      tree *use_p = VARRAY_GENERIC_PTR (ops, i);
+	      if (DECL_P (*use_p))
+		SET_BIT (vars_to_rename, var_ann (*use_p)->uid);
+	    }
+
+	  ops = vdef_ops (stmt);
+	  for (i = 0; ops && i < VARRAY_ACTIVE_SIZE (ops); i++)
+	    {
+	      tree var = VDEF_RESULT (VARRAY_TREE (ops, i));
+	      if (DECL_P (var))
+		SET_BIT (vars_to_rename, var_ann (var)->uid);
+	    }
+
+	  ops = vuse_ops (stmt);
+	  for (i = 0; ops && i < VARRAY_ACTIVE_SIZE (ops); i++)
+	    {
+	      tree var = VARRAY_TREE (ops, i);
+	      if (DECL_P (var))
+		SET_BIT (vars_to_rename, var_ann (var)->uid);
+	    }
+	}
+    }
+}
+
+
 /* Rewrite statement pointed by iterator SI into SSA form.  This is only
    used when not doing dominator optimizations (-ftree-dominator-opts), in
    which case rewrite_and_optimize_stmt is used.
@@ -2206,11 +2394,11 @@ rewrite_stmt (block_stmt_iterator si, va
   ann = stmt_ann (stmt);
   ssa_stats.num_stmts++;
 
-  if (tree_ssa_dump_file && (tree_ssa_dump_flags & TDF_DETAILS))
+  if (dump_file && (dump_flags & TDF_DETAILS))
     {
-      fprintf (tree_ssa_dump_file, "Renaming statement ");
-      print_generic_stmt (tree_ssa_dump_file, stmt, TDF_SLIM);
-      fprintf (tree_ssa_dump_file, "\n");
+      fprintf (dump_file, "Renaming statement ");
+      print_generic_stmt (dump_file, stmt, TDF_SLIM);
+      fprintf (dump_file, "\n");
     }
 
 #if defined ENABLE_CHECKING
@@ -2238,15 +2426,17 @@ rewrite_stmt (block_stmt_iterator si, va
   for (i = 0; uses && i < VARRAY_ACTIVE_SIZE (uses); i++)
     {
       tree *op_p = (tree *) VARRAY_GENERIC_PTR (uses, i);
-      rewrite_operand (op_p, true);
+      if (TREE_CODE (*op_p) != SSA_NAME)
+	rewrite_operand (op_p, true);
     }
 
   /* Rewrite virtual uses in the statement.  */
   for (i = 0; vuses && i < VARRAY_ACTIVE_SIZE (vuses); i++)
-    rewrite_operand (&(VARRAY_TREE (vuses, i)), false);
+    if (TREE_CODE (VARRAY_TREE (vuses, i)) != SSA_NAME)
+      rewrite_operand (&(VARRAY_TREE (vuses, i)), false);
 
   /* Step 2.  Register the statement's DEF and VDEF operands.  */
-  if (def_p)
+  if (def_p && TREE_CODE (*def_p) != SSA_NAME)
     {
       *def_p = make_ssa_name (*def_p, stmt);
       register_new_def (SSA_NAME_VAR (*def_p), *def_p, block_defs_p, true);
@@ -2256,7 +2446,12 @@ rewrite_stmt (block_stmt_iterator si, va
   for (i = 0; vdefs && i < VARRAY_ACTIVE_SIZE (vdefs); i++)
     {
       tree vdef = VARRAY_TREE (vdefs, i);
+
+      if (TREE_CODE (VDEF_RESULT (vdef)) == SSA_NAME)
+	continue;
+
       rewrite_operand (&(VDEF_OP (vdef)), false);
+
       VDEF_RESULT (vdef) = make_ssa_name (VDEF_RESULT (vdef), stmt);
       register_new_def (SSA_NAME_VAR (VDEF_RESULT (vdef)), 
 			VDEF_RESULT (vdef), block_defs_p, false);
@@ -2327,7 +2522,7 @@ register_new_def (tree var, tree def, va
 --*/
 /* Initialize DFA/SSA structures.  */
 
-static void
+void
 init_tree_ssa (void)
 {
   next_ssa_version = 1;
@@ -2335,20 +2530,6 @@ init_tree_ssa (void)
   VARRAY_TREE_INIT (call_clobbered_vars, 20, "call_clobbered_vars");
   memset ((void *) &ssa_stats, 0, sizeof (ssa_stats));
   global_var = NULL_TREE;
-
-  /* Allocate memory for the DEF_BLOCKS hash table.  */
-  def_blocks = htab_create (num_referenced_vars, def_blocks_hash,
-			    def_blocks_eq, def_blocks_free);
-
-  /* Allocate memory for the CURRDEFS hash table.  */
-  currdefs = htab_create (num_referenced_vars, var_value_hash, var_value_eq,
-			  free);
-
-  /* Allocate memory for the AVAIL_EXPRS hash table.  */
-  avail_exprs = htab_create (1024, avail_expr_hash, avail_expr_eq, NULL);
-
-  /* Allocate memory for the CONST_AND_COPIES hash table.  */
-  const_and_copies = htab_create (1024, var_value_hash, var_value_eq, free);
 }
 

@@ -2383,6 +2564,7 @@ remove_annotations_r (tree *tp, int *wal
   enum tree_code code = TREE_CODE (t);
 
   t->common.ann = NULL;
+
   /* If the node is not a container, then it has nothing interesting
      underneath it.  */
   if (code != LOOP_EXPR
@@ -2394,11 +2576,6 @@ remove_annotations_r (tree *tp, int *wal
       && code != BIND_EXPR
       && code != COMPOUND_EXPR)
     {
-      /* Ugh.  A MODIFY_EXPR has an annotation on its RHS for the
-         benefit of SSA-PRE.  See tree-dfa.c::create_stmt_ann.  */
-      if (code == MODIFY_EXPR)
-	TREE_OPERAND (t, 1)->common.ann = NULL;
-
       *walk_subtrees = 0;
       return NULL_TREE;
     }
@@ -2584,8 +2761,8 @@ lookup_avail_expr (tree stmt,
      Constants and copy operations are handled by the constant/copy propagator
      in rewrite_and_optimize_stmt.  */
   rhs = TREE_OPERAND (stmt, 1);
-  if (TREE_CONSTANT (rhs)
-      || TREE_CODE (rhs) == SSA_NAME)
+  if (TREE_CODE (rhs) == SSA_NAME
+      || is_unchanging_value (rhs))
     return NULL_TREE;
 
   slot = htab_find_slot (avail_exprs, stmt, INSERT);
@@ -2628,7 +2805,7 @@ get_eq_expr_value (tree if_stmt)
   /* If the conditional is of the form 'X == Y', return 'X = Y'.  */
   else if (TREE_CODE (cond) == EQ_EXPR
 	   && TREE_CODE (TREE_OPERAND (cond, 0)) == SSA_NAME
-	   && (TREE_CONSTANT (TREE_OPERAND (cond, 1))
+	   && (is_unchanging_value (TREE_OPERAND (cond, 1))
 	       || TREE_CODE (TREE_OPERAND (cond, 1)) == SSA_NAME))
     value = build (MODIFY_EXPR, TREE_TYPE (cond),
 		   TREE_OPERAND (cond, 0),
Index: tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.h,v
retrieving revision 1.342.2.75
diff -d -u -p -r1.342.2.75 tree.h
-- tree.h	3 Jul 2003 05:52:58 -0000	1.342.2.75
+++ tree.h	11 Jul 2003 18:49:33 -0000
@@ -3361,6 +3361,8 @@ enum tree_dump_index
   TDI_pta,                      /* dump points-to information for each
 				   function.  */
   TDI_ssa,                      /* dump SSA information for each function.  */
+  TDI_mustalias,		/* dump must-alias information for each
+				   function.  */
   TDI_predot,
   TDI_pre,                      /* dump SSA PRE information for each
 				   function.  */
Index: cp/optimize.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/optimize.c,v
retrieving revision 1.81.10.22
diff -d -u -p -r1.81.10.22 optimize.c
-- cp/optimize.c	13 Jun 2003 21:09:14 -0000	1.81.10.22
+++ cp/optimize.c	11 Jul 2003 18:49:33 -0000
@@ -88,7 +88,7 @@ optimize_function (tree fn)
       dump_function (TDI_gimple, fn);
 
       /* Invoke the SSA tree optimizer.  */
-      if (optimize >= 1)
+      if (optimize >= 1 && !flag_disable_tree_ssa)
 	optimize_function_tree (fn);
     }
 
Index: doc/invoke.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/invoke.texi,v
retrieving revision 1.152.2.45
diff -d -u -p -r1.152.2.45 invoke.texi
-- doc/invoke.texi	19 Jun 2003 18:58:35 -0000	1.152.2.45
+++ doc/invoke.texi	11 Jul 2003 18:49:34 -0000
@@ -248,6 +248,7 @@ in the following sections.
 -fdump-tree-ssa@r{[}-@var{n}@r{]} -fdump-tree-pre@r{[}-@var{n}@r{]} @gol
 -fdump-tree-ccp@r{[}-@var{n}@r{]} -fdump-tree-dce@r{[}-@var{n}@r{]} @gol
 -fdump-tree-gimple@r{[}-raw@r{]} -fdump-tree-mudflap@r{[}-@var{n}@r{]} @gol
+-fdump-tree-must-alias@r{[}-@var{n}@r{]} @gol
 -feliminate-dwarf2-dups -feliminate-unused-debug-types @gol
 -fmem-report -fprofile-arcs @gol
 -frandom-seed=@var{string} -fsched-verbose=@var{n} @gol
@@ -293,7 +294,7 @@ in the following sections.
 -funroll-all-loops  -funroll-loops  -fpeel-loops @gol
 -funswitch-loops  -fold-unroll-loops  -fold-unroll-all-loops @gol
 -fdisable-gimple  -ftree-pre  -ftree-ccp  -ftree-dce  -ftree-copyprop  @gol
--fdisable-tree-ssa -ftree-dominator-opts @gol
+-fdisable-tree-ssa -ftree-dominator-opts -ftree-must-alias @gol
 --param @var{name}=@var{value}
 -O  -O0  -O1  -O2  -O3  -Os}
 
@@ -3367,6 +3368,12 @@ appending @file{.dce} to the source file
 Dump each function after adding mudflap instrumentation.  The file name is
 made by appending @file{.mudflap} to the source file name.
 
+@item must-alias
+@opindex fdump-tree-must-alias
+Dump each function after computing must-alias information and promoting
+virtual operands to real operands.  The file name is made by appending
+@file{.must-alias} to the source file name.
+
 @item all
 @opindex fdump-tree-all
 Enable all the available tree dumps with the flags provided in this option.
@@ -4091,6 +4098,13 @@ default at -O and higher.
 @item -ftree-dominator-opts
 Perform dead code elimination (DCE) on trees.  This flag is enabled by
 default at -O and higher.
+
+@item -ftree-must-alias
+Perform must-alias analysis on trees.  This analysis will attempt to
+convert pointer dereferences into direct variable references when a
+must-alias relation is found between a pointer P and an addressable varible
+VAR whose address has been taken by P.  This flag is enabled by default at
+-O and higher.
 
 @item -ftracer
 @opindex ftracer


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