public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* integrated immediate uses - alpha patch
@ 2004-10-14 20:40 Andrew MacLeod
  2004-10-15  3:07 ` Giovanni Bajo
  0 siblings, 1 reply; 6+ messages in thread
From: Andrew MacLeod @ 2004-10-14 20:40 UTC (permalink / raw)
  To: gcc-patches, Zdenek Dvorak

[-- Attachment #1: Type: text/plain, Size: 3302 bytes --]


OK, here's the mythical patch for integrated immediate_uses. It
bootstraps and is based off the immuse-rewrite-branch where I have
checked it in..

There is much more followup work to be done, but this is the most
difficult initial part.

The rewrite branch was updated to mainline as of last thursday or
friday,. so there likely isnt a whole lot different right now.

The interface is quite simple, there are two macros:

FOR_EACH_IMM_USE_FAST (use_p, iter, ssa_var)
  {
  }

    and

FOR_EACH_IMM_USE_SAFE (use_p, iter, ssa_var)
  {
  }

The only difference is that the SAFE loop allows you to delete and
modify stmts, its just a bit slower because it links a guard into the
list and moves the guard along as you iterate thorugh the list.  The
presence of the guard requires you to use 

    BREAK_FROM_SAFE_IMM_USE(iter);

instead of 

    break;  

when you wish to exit the loop early, otherwise the guard will remain
linked in. If the loop finishes its natural progression to the end on
its own, it will automatically remove the guard node.  THere are no such
issues with thr FAST loop, just dont try deletiung anything.

And once you do a SET_USE, or update_stmt(), or bsi_remove() or
something like that, forget about using the use_p variable. You've
invalidated it since the use you were pointing to may not even exist any
more.  Its a one shot deal for modifications.


The 3 parameters are:
  use_operand_p use_p 	: A use pointer for each immediate use of ssa_var.
  imm_use_iterator iter	: the iterator structure
  tree ssa_var		: The SSA variable you want the immediate uses of.


Another change is that modify_stmt is being replaced. It exists in a few
places right now, but many places have been replaced with 

  update_stmt()

  which is the equivilent of 

    modify_stmt() ;
    get_stmt_operands();


In order for immediate uses to be accurate, all the stmt must be up to
date, so verify_ssa now checks that there are no modified stmts at the
end of a pass.


Im sure there are a few other tidbits, but thats the gist of it.

This patch is by no means ready for primetime, there are cleanups yet to
be done, the conversion to update_stmt is not finished, redundant
get_stmt_operand() calsl have not bene removed, and its not as
bulletproof as I intend to get it.

but it fundamentally works for now, and others wanted to be able to fool
with the interface, so here is the current snapshot. (there isnt even a
changelog :-)


Overall compilation time is typically a little bit slower, somewhere in
the ballpark of 3% or so. There is pending operand work which should
remove that when I am done. I ran tramp3d to check memory usage.. user
time was up about 3%, but overall run time was down 2% presumably due to
the improved memory situation:

Mainline report:
Total allocations and overheads during the compilation process
Total Overhead:                         224747369
Total Allocated:                       1600543224

immuse patch report:
Total allocations and overheads during the compilation process
Total Overhead:                         159146391
Total Allocated:                       1443969316


so total memory usage is down.

Anyway, this is what there is right now for those that wanted a
snapshot. It bootstraps and shows no regressions on x86-linux. 


Andrew



[-- Attachment #2: immuse-alpha.diff --]
[-- Type: text/plain, Size: 147016 bytes --]


Index: lambda-code.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/lambda-code.c,v
retrieving revision 2.12.6.1
diff -c -p -r2.12.6.1 lambda-code.c
*** lambda-code.c	8 Oct 2004 20:20:18 -0000	2.12.6.1
--- lambda-code.c	14 Oct 2004 19:24:35 -0000
*************** lambda_loopnest_to_gcc_loopnest (struct 
*** 1904,1910 ****
        COND_EXPR_COND (exitcond) = build (testtype,
  					 boolean_type_node,
  					 ivvarinced, newupperbound);
!       modify_stmt (exitcond);
        VEC_replace (tree, new_ivs, i, ivvar);
  
        i++;
--- 1904,1910 ----
        COND_EXPR_COND (exitcond) = build (testtype,
  					 boolean_type_node,
  					 ivvarinced, newupperbound);
!       update_stmt (exitcond);
        VEC_replace (tree, new_ivs, i, ivvar);
  
        i++;
*************** lambda_loopnest_to_gcc_loopnest (struct 
*** 1916,1927 ****
    temp = old_loopnest;
    for (i = 0; i < VEC_length (tree, old_ivs); i++)
      {
!       int j;
        tree oldiv = VEC_index (tree, old_ivs, i);
!       dataflow_t imm = get_immediate_uses (SSA_NAME_DEF_STMT (oldiv));
!       for (j = 0; j < num_immediate_uses (imm); j++)
  	{
! 	  tree stmt = immediate_use (imm, j);
  	  use_operand_p use_p;
  	  ssa_op_iter iter;
  	  FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_USE)
--- 1916,1933 ----
    temp = old_loopnest;
    for (i = 0; i < VEC_length (tree, old_ivs); i++)
      {
!       imm_use_iterator imm_iter;
!       use_operand_p imm_use;
!       tree oldiv_def;
        tree oldiv = VEC_index (tree, old_ivs, i);
!       tree oldiv_stmt = SSA_NAME_DEF_STMT (oldiv);
! 
!       gcc_assert (NUM_DEFS (STMT_DEF_OPS (oldiv_stmt)) == 1);
!       oldiv_def = DEF_OP (STMT_DEF_OPS (oldiv_stmt), 0);
! 
!       FOR_EACH_IMM_USE_SAFE (imm_use, imm_iter, oldiv_def)
  	{
! 	  tree stmt = USE_STMT (imm_use);
  	  use_operand_p use_p;
  	  ssa_op_iter iter;
  	  FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_USE)
*************** lambda_loopnest_to_gcc_loopnest (struct 
*** 1942,1948 ****
  		     expression.  */
  		  bsi_insert_before (&bsi, stmts, BSI_SAME_STMT);
  		  propagate_value (use_p, newiv);
! 		  modify_stmt (stmt);
  		  
  		}
  	    }
--- 1948,1954 ----
  		     expression.  */
  		  bsi_insert_before (&bsi, stmts, BSI_SAME_STMT);
  		  propagate_value (use_p, newiv);
! 		  update_stmt (stmt);
  		  
  		}
  	    }
*************** stmt_is_bumper_for_loop (struct loop *lo
*** 2029,2044 ****
    tree use;
    tree def;
    def_optype defs = STMT_DEF_OPS (stmt);
!   dataflow_t imm;
!   int i;
    
    if (NUM_DEFS (defs) != 1)
      return false;
    def = DEF_OP (defs, 0);
!   imm = get_immediate_uses (stmt);
!   for (i = 0; i < num_immediate_uses (imm); i++)
      {
!       use = immediate_use (imm, i);
        if (TREE_CODE (use) == PHI_NODE)
  	{
  	  if (phi_loop_edge_uses_def (loop, use, def))
--- 2035,2049 ----
    tree use;
    tree def;
    def_optype defs = STMT_DEF_OPS (stmt);
!   imm_use_iterator iter;
!   use_operand_p use_p;
    
    if (NUM_DEFS (defs) != 1)
      return false;
    def = DEF_OP (defs, 0);
!   FOR_EACH_IMM_USE_FAST (use_p, iter, def)
      {
!       use = USE_FROM_PTR (use_p);
        if (TREE_CODE (use) == PHI_NODE)
  	{
  	  if (phi_loop_edge_uses_def (loop, use, def))
Index: predict.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/predict.c,v
retrieving revision 1.128
diff -c -p -r1.128 predict.c
*** predict.c	28 Sep 2004 07:59:48 -0000	1.128
--- predict.c	14 Oct 2004 19:24:35 -0000
*************** strip_builtin_expect (void)
*** 1010,1016 ****
  	      && TREE_CHAIN (arglist))
  	    {
  	      TREE_OPERAND (stmt, 1) = TREE_VALUE (arglist);
! 	      modify_stmt (stmt);
  	    }
  	}
      }
--- 1010,1016 ----
  	      && TREE_CHAIN (arglist))
  	    {
  	      TREE_OPERAND (stmt, 1) = TREE_VALUE (arglist);
! 	      update_stmt (stmt);
  	    }
  	}
      }
Index: tree-cfg.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-cfg.c,v
retrieving revision 2.69.2.1
diff -c -p -r2.69.2.1 tree-cfg.c
*** tree-cfg.c	8 Oct 2004 20:20:19 -0000	2.69.2.1
--- tree-cfg.c	14 Oct 2004 19:24:36 -0000
*************** stmt_for_bsi (tree stmt)
*** 2650,2655 ****
--- 2650,2675 ----
    gcc_unreachable ();
  }
  
+ /* Mark statement T as modified, and update it.  */
+ static inline void
+ update_new_stmt (tree t)
+ {
+   if (TREE_CODE (t) == STATEMENT_LIST)
+     {
+       tree_stmt_iterator i;
+       tree stmt;
+       for (i = tsi_start (t); !tsi_end_p (i); tsi_next (&i))
+         {
+ 	  stmt = tsi_stmt (i);
+ 	  if (stmt_modified_p (stmt))
+ 	    get_stmt_operands (stmt);
+ 	}
+     }
+   else
+     if (stmt_modified_p (t))
+       get_stmt_operands (t);
+ }
+ 
  /* Insert statement (or statement list) T before the statement
     pointed-to by iterator I.  M specifies how to update iterator I
     after insertion (see enum bsi_iterator_update).  */
*************** void
*** 2658,2665 ****
  bsi_insert_before (block_stmt_iterator *i, tree t, enum bsi_iterator_update m)
  {
    set_bb_for_stmt (t, i->bb);
    tsi_link_before (&i->tsi, t, m);
-   modify_stmt (t);
  }
  
  
--- 2678,2685 ----
  bsi_insert_before (block_stmt_iterator *i, tree t, enum bsi_iterator_update m)
  {
    set_bb_for_stmt (t, i->bb);
+   update_new_stmt (t);
    tsi_link_before (&i->tsi, t, m);
  }
  
  
*************** void
*** 2671,2678 ****
  bsi_insert_after (block_stmt_iterator *i, tree t, enum bsi_iterator_update m)
  {
    set_bb_for_stmt (t, i->bb);
    tsi_link_after (&i->tsi, t, m);
-   modify_stmt (t);
  }
  
  
--- 2691,2698 ----
  bsi_insert_after (block_stmt_iterator *i, tree t, enum bsi_iterator_update m)
  {
    set_bb_for_stmt (t, i->bb);
+   update_new_stmt (t);
    tsi_link_after (&i->tsi, t, m);
  }
  
  
*************** bsi_remove (block_stmt_iterator *i)
*** 2684,2690 ****
--- 2704,2712 ----
  {
    tree t = bsi_stmt (*i);
    set_bb_for_stmt (t, NULL);
+   delink_stmt_imm_use (t);
    tsi_delink (&i->tsi);
+   mark_stmt_modified (t);
  }
  
  
*************** bsi_replace (const block_stmt_iterator *
*** 2748,2754 ****
      }
  
    *bsi_stmt_ptr (*bsi) = stmt;
!   modify_stmt (stmt);
  }
  
  
--- 2770,2776 ----
      }
  
    *bsi_stmt_ptr (*bsi) = stmt;
!   update_new_stmt (stmt);
  }
  
  
Index: tree-dfa.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-dfa.c,v
retrieving revision 2.36
diff -c -p -r2.36 tree-dfa.c
*** tree-dfa.c	30 Sep 2004 14:09:37 -0000	2.36
--- tree-dfa.c	14 Oct 2004 19:24:36 -0000
*************** struct walk_state
*** 76,86 ****
  /* Local functions.  */
  static void collect_dfa_stats (struct dfa_stats_d *);
  static tree collect_dfa_stats_r (tree *, int *, void *);
- static void add_immediate_use (tree, tree);
  static tree find_vars_r (tree *, int *, void *);
  static void add_referenced_var (tree, struct walk_state *);
- static void compute_immediate_uses_for_phi (tree, bool (*)(tree));
- static void compute_immediate_uses_for_stmt (tree, int, bool (*)(tree));
  
  
  /* Global declarations.  */
--- 76,83 ----
*************** struct tree_opt_pass pass_referenced_var
*** 141,395 ****
  };
  
  
- /* Compute immediate uses.
- 
-    CALC_FOR is an optional function pointer which indicates whether
-       immediate uses information should be calculated for a given SSA
-       variable.  If NULL, then information is computed for all
-       variables.
- 
-    FLAGS is one of {TDFA_USE_OPS, TDFA_USE_VOPS}.  It is used by
-       compute_immediate_uses_for_stmt to determine whether to look at
-       virtual and/or real operands while computing def-use chains.  */
- 
- void
- compute_immediate_uses (int flags, bool (*calc_for)(tree))
- {
-   basic_block bb;
-   block_stmt_iterator si;
- 
-   FOR_EACH_BB (bb)
-     {
-       tree phi;
- 
-       for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
- 	{
- 	  if (is_gimple_reg (PHI_RESULT (phi)))
- 	    {
- 	      if (!(flags & TDFA_USE_OPS))
- 		continue;
- 	    }
- 	  else
- 	    {
- 	      if (!(flags & TDFA_USE_VOPS))
- 		continue;
- 	    }
- 
- 	  compute_immediate_uses_for_phi (phi, calc_for);
- 	}
- 
-       for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si))
-         {
- 	  tree stmt = bsi_stmt (si);
- 	  get_stmt_operands (stmt);
- 	  compute_immediate_uses_for_stmt (stmt, flags, calc_for);
- 	}
-     }
- }
- 
- 
- /* Invalidates dataflow information for a statement STMT.   */
- 
- void
- free_df_for_stmt (tree stmt)
- {
-   dataflow_t *df;
- 
-   if (TREE_CODE (stmt) == PHI_NODE)
-     df = &PHI_DF (stmt);
-   else
-     {
-       stmt_ann_t ann = stmt_ann (stmt);
- 
-       if (!ann)
- 	return;
- 
-       df = &ann->df;
-     }
- 
-   if (!*df)
-     return;
-       
-   /* If we have a varray of immediate uses, then go ahead and release
-      it for re-use.  */
-   if ((*df)->immediate_uses)
-     ggc_free ((*df)->immediate_uses);
- 
-   /* Similarly for the main dataflow structure.  */
-   ggc_free (*df);
-   *df = NULL;
- }
- 
- 
- /* Invalidate dataflow information for the whole function. 
- 
-    Note this only invalidates dataflow information on statements and
-    PHI nodes which are reachable.
- 
-    A deleted statement may still have attached dataflow information
-    on it.  */
- 
- void
- free_df (void)
- {
-   basic_block bb;
-   block_stmt_iterator si;
- 
-   FOR_EACH_BB (bb)
-     {
-       tree phi;
- 
-       for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
- 	free_df_for_stmt (phi);
- 
-       for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si))
-         {
- 	  tree stmt = bsi_stmt (si);
- 	  free_df_for_stmt (stmt);
- 	}
-     }
- }
- 
- 
- /* Helper for compute_immediate_uses.  Check all the USE and/or VUSE
-    operands in phi node PHI and add a def-use edge between their
-    defining statement and PHI.  CALC_FOR is as in
-    compute_immediate_uses.
- 
-    PHI nodes are easy, we only need to look at their arguments.  */
- 
- static void
- compute_immediate_uses_for_phi (tree phi, bool (*calc_for)(tree))
- {
-   int i;
- 
-   gcc_assert (TREE_CODE (phi) == PHI_NODE);
- 
-   for (i = 0; i < PHI_NUM_ARGS (phi); i++)
-     {
-       tree arg = PHI_ARG_DEF (phi, i);
- 
-       if (TREE_CODE (arg) == SSA_NAME && (!calc_for || calc_for (arg)))
- 	{
- 	  tree imm_rdef_stmt = SSA_NAME_DEF_STMT (PHI_ARG_DEF (phi, i));
- 	  if (!IS_EMPTY_STMT (imm_rdef_stmt))
- 	    add_immediate_use (imm_rdef_stmt, phi);
- 	}
-     }
- }
- 
- 
- /* Another helper for compute_immediate_uses.  Depending on the value
-    of FLAGS, check all the USE and/or VUSE operands in STMT and add a
-    def-use edge between their defining statement and STMT.  CALC_FOR
-    is as in compute_immediate_uses.  */
- 
- static void
- compute_immediate_uses_for_stmt (tree stmt, int flags, bool (*calc_for)(tree))
- {
-   tree use;
-   ssa_op_iter iter;
- 
-   /* PHI nodes are handled elsewhere.  */
-   gcc_assert (TREE_CODE (stmt) != PHI_NODE);
- 
-   /* Look at USE_OPS or VUSE_OPS according to FLAGS.  */
-   if (flags & TDFA_USE_OPS)
-     {
-       FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE)
- 	{
- 	  tree imm_stmt = SSA_NAME_DEF_STMT (use);
- 	  if (!IS_EMPTY_STMT (imm_stmt) && (!calc_for || calc_for (use)))
- 	    add_immediate_use (imm_stmt, stmt);
- 	}
-     }
- 
-   if (flags & TDFA_USE_VOPS)
-     {
-       FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_VIRTUAL_USES)
- 	{
- 	  tree imm_rdef_stmt = SSA_NAME_DEF_STMT (use);
- 	  if (!IS_EMPTY_STMT (imm_rdef_stmt) && (!calc_for || calc_for (use)))
- 	    add_immediate_use (imm_rdef_stmt, stmt);
- 	}
-     }
- }
- 
- 
- /* Add statement USE_STMT to the list of statements that use definitions
-     made by STMT.  */
- 
- static void
- add_immediate_use (tree stmt, tree use_stmt)
- {
-   struct dataflow_d **df;
- 
-   if (TREE_CODE (stmt) == PHI_NODE)
-     df = &PHI_DF (stmt);
-   else
-     {
-       stmt_ann_t ann = get_stmt_ann (stmt);
-       df = &ann->df;
-     }
- 
-   if (*df == NULL)
-     {
-       *df = ggc_alloc (sizeof (struct dataflow_d));
-       memset ((void *) *df, 0, sizeof (struct dataflow_d));
-       (*df)->uses[0] = use_stmt;
-       return;
-     }
- 
-   if (!(*df)->uses[1])
-     {
-       (*df)->uses[1] = use_stmt;
-       return;
-     }
- 
-   if ((*df)->immediate_uses == NULL)
-     VARRAY_TREE_INIT ((*df)->immediate_uses, 4, "immediate_uses");
- 
-   VARRAY_PUSH_TREE ((*df)->immediate_uses, use_stmt);
- }
- 
- 
- /* If the immediate use of USE points to OLD, then redirect it to NEW.  */
- 
- static void
- redirect_immediate_use (tree use, tree old, tree new)
- {
-   tree imm_stmt = SSA_NAME_DEF_STMT (use);
-   struct dataflow_d *df = get_immediate_uses (imm_stmt);
-   unsigned int num_uses = num_immediate_uses (df);
-   unsigned int i;
- 
-   for (i = 0; i < num_uses; i++)
-     {
-       if (immediate_use (df, i) == old)
- 	{
- 	  if (i == 0 || i == 1)
- 	    df->uses[i] = new;
- 	  else
- 	    VARRAY_TREE (df->immediate_uses, i - 2) = new;
- 	}
-     }
- }
- 
- 
- /* Redirect all immediate uses for operands in OLD so that they point
-    to NEW.  This routine should have no knowledge of how immediate
-    uses are stored.  */
- 
- void
- redirect_immediate_uses (tree old, tree new)
- {
-   ssa_op_iter iter;
-   tree val;
- 
-   FOR_EACH_SSA_TREE_OPERAND (val, old, iter, SSA_OP_ALL_USES)
-     redirect_immediate_use (val, old, new);
- }
- 
  
  /*---------------------------------------------------------------------------
  			    Manage annotations
--- 138,143 ----
*************** debug_variable (tree var)
*** 583,661 ****
  }
  
  
- /* Dump def-use edges on FILE.  */
- 
- void
- dump_immediate_uses (FILE *file)
- {
-   basic_block bb;
-   block_stmt_iterator si;
-   const char *funcname
-     = lang_hooks.decl_printable_name (current_function_decl, 2);
- 
-   fprintf (file, "\nDef-use edges for function %s\n", funcname);
- 
-   FOR_EACH_BB (bb)
-     {
-       tree phi;
- 
-       for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
- 	dump_immediate_uses_for (file, phi);
- 
-       for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si))
- 	dump_immediate_uses_for (file, bsi_stmt (si));
-     }
- 
-   fprintf (file, "\n");
- }
- 
- 
- /* Dump def-use edges on stderr.  */
- 
- void
- debug_immediate_uses (void)
- {
-   dump_immediate_uses (stderr);
- }
- 
- 
- /* Dump all immediate uses for STMT on FILE.  */
- 
- void
- dump_immediate_uses_for (FILE *file, tree stmt)
- {
-   dataflow_t df = get_immediate_uses (stmt);
-   int num_imm_uses = num_immediate_uses (df);
- 
-   if (num_imm_uses > 0)
-     {
-       int i;
- 
-       fprintf (file, "-> ");
-       print_generic_stmt (file, stmt, TDF_SLIM);
-       fprintf (file, "\n");
- 
-       for (i = 0; i < num_imm_uses; i++)
- 	{
- 	  fprintf (file, "\t");
- 	  print_generic_stmt (file, immediate_use (df, i), TDF_SLIM);
- 	  fprintf (file, "\n");
- 	}
- 
-       fprintf (file, "\n");
-     }
- }
- 
- 
- /* Dump immediate uses for STMT on stderr.  */
- 
- void
- debug_immediate_uses_for (tree stmt)
- {
-   dump_immediate_uses_for (stderr, stmt);
- }
- 
- 
  /* Dump various DFA statistics to FILE.  */
  
  void
--- 331,336 ----
*************** mark_new_vars_to_rename (tree stmt, bitm
*** 974,981 ****
  
    /* Now force an operand re-scan on the statement and mark any newly
       exposed variables.  */
!   modify_stmt (stmt);
!   get_stmt_operands (stmt);
  
    v_may_defs_after = NUM_V_MAY_DEFS (STMT_V_MAY_DEF_OPS (stmt));
    v_must_defs_after = NUM_V_MUST_DEFS (STMT_V_MUST_DEF_OPS (stmt));
--- 649,655 ----
  
    /* Now force an operand re-scan on the statement and mark any newly
       exposed variables.  */
!   update_stmt (stmt);
  
    v_may_defs_after = NUM_V_MAY_DEFS (STMT_V_MAY_DEF_OPS (stmt));
    v_must_defs_after = NUM_V_MUST_DEFS (STMT_V_MUST_DEF_OPS (stmt));
Index: tree-dump.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-dump.c,v
retrieving revision 1.35
diff -c -p -r1.35 tree-dump.c
*** tree-dump.c	23 Sep 2004 14:34:19 -0000	1.35
--- tree-dump.c	14 Oct 2004 19:24:36 -0000
*************** static const struct dump_option_value_in
*** 744,750 ****
    {"vops", TDF_VOPS},
    {"lineno", TDF_LINENO},
    {"uid", TDF_UID},
!   {"all", ~(TDF_RAW | TDF_SLIM | TDF_LINENO)},
    {NULL, 0}
  };
  
--- 744,751 ----
    {"vops", TDF_VOPS},
    {"lineno", TDF_LINENO},
    {"uid", TDF_UID},
!   {"stmtaddr", TDF_STMT_ADDR},
!   {"all", ~(TDF_RAW | TDF_SLIM | TDF_LINENO | TDF_STMT_ADDR)},
    {NULL, 0}
  };
  
Index: tree-flow-inline.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-flow-inline.h,v
retrieving revision 2.23.8.1
diff -c -p -r2.23.8.1 tree-flow-inline.h
*** tree-flow-inline.h	8 Oct 2004 20:20:19 -0000	2.23.8.1
--- tree-flow-inline.h	14 Oct 2004 19:24:36 -0000
*************** get_filename (tree expr)
*** 133,154 ****
  
  /* Mark statement T as modified.  */
  static inline void
! modify_stmt (tree t)
  {
!   stmt_ann_t ann = stmt_ann (t);
    if (ann == NULL)
      ann = create_stmt_ann (t);
    ann->modified = 1;
  }
  
- /* Mark statement T as unmodified.  */
  static inline void
! unmodify_stmt (tree t)
  {
!   stmt_ann_t ann = stmt_ann (t);
!   if (ann == NULL)
!     ann = create_stmt_ann (t);
!   ann->modified = 0;
  }
  
  /* Return true if T is marked as modified, false otherwise.  */
--- 133,163 ----
  
  /* Mark statement T as modified.  */
  static inline void
! mark_stmt_modified (tree t)
  {
!   stmt_ann_t ann;
!   if (TREE_CODE (t) == PHI_NODE)
!     return;
! 
!   ann = stmt_ann (t);
    if (ann == NULL)
      ann = create_stmt_ann (t);
    ann->modified = 1;
  }
  
  static inline void
! modify_stmt (tree t)
  {
!   mark_stmt_modified (t);
! }
! /* Mark statement T as modified, and update it.  */
! static inline void
! update_stmt (tree t)
! {
!   if (TREE_CODE (t) == PHI_NODE)
!     return;
!   mark_stmt_modified (t);
!   get_stmt_operands (t);
  }
  
  /* Return true if T is marked as modified, false otherwise.  */
*************** stmt_modified_p (tree t)
*** 163,168 ****
--- 172,481 ----
    return ann ? ann->modified : true;
  }
  
+ /* Delink an immediate_uses node from its chain.  */
+ static inline void
+ delink_imm_use (ssa_imm_use_t *linknode)
+ {
+   /* Return if this node is not in a list.  */
+   if (linknode->prev == NULL)
+     return;
+ 
+   linknode->prev->next = linknode->next;
+   linknode->next->prev = linknode->prev;
+   linknode->prev = NULL;
+   linknode->next = NULL;
+ }
+ 
+ /* Link ssa_imm_use node LINKNODE into the chain for LIST.  */
+ static inline void
+ link_imm_use_to_list (ssa_imm_use_t *linknode, ssa_imm_use_t *list)
+ {
+ #ifdef ENABLE_CHECKING
+   /* list must be a structure in the correct SSA_NAME.  */
+   if ((TREE_CODE (list->stmt) != SSA_NAME) ||
+       (&(SSA_NAME_IMM_USE_NODE (list->stmt)) != list))
+     abort ();
+   /* In order to link linknode in, it must have a use.  */
+   if (!linknode->use || (*linknode->use) == NULL_TREE)
+     abort ();
+   /* Assert that this is the correct list for linknode.  */
+   if (*(linknode->use) != list->stmt)
+     abort ();
+ #endif
+ 
+   /* Link the new node at the head of the list.  If we are in the process of 
+      traversing the list, we wont visit any new nodes added to it.  */
+   linknode->prev = list;
+   linknode->next = list->next;
+   list->next->prev = linknode;
+   list->next = linknode;
+ }
+ 
+ /* Link ssa_imm_use node LINKNODE into the chain for DEF.  */
+ static inline void
+ link_imm_use (ssa_imm_use_t *linknode, tree def)
+ {
+   ssa_imm_use_t *root;
+ 
+   if (!def || TREE_CODE (def) != SSA_NAME)
+     linknode->prev = NULL;
+   else
+     {
+       root = &(SSA_NAME_IMM_USE_NODE (def));
+       link_imm_use_to_list (linknode, root);
+     }
+ }
+ 
+ /* Set the value of a use pointed by USE to VAL.  */
+ static inline void
+ set_ssa_use_from_ptr (use_operand_p use, tree val)
+ {
+   delink_imm_use (use);
+   *(use->use) = val;
+   link_imm_use (use, val);
+ }
+ 
+ 
+ /* Delink all immediate_use information for STMT.  */
+ static inline void
+ delink_stmt_imm_use (tree stmt)
+ {
+    unsigned int x;
+    use_optype uses = STMT_USE_OPS (stmt);
+    vuse_optype vuses = STMT_VUSE_OPS (stmt);
+    v_may_def_optype v_may_defs = STMT_V_MAY_DEF_OPS (stmt);
+ 
+    for (x = 0; x < NUM_USES (uses); x++)
+      delink_imm_use (&(uses->uses[x]));
+ 
+    for (x = 0; x < NUM_VUSES (vuses); x++)
+      delink_imm_use (&(vuses->vuses[x].imm_use));
+ 
+    for (x = 0; x < NUM_V_MAY_DEFS (v_may_defs); x++)
+      delink_imm_use (&(v_may_defs->v_may_defs[x].imm_use));
+ }
+ 
+ /* Link ssa_imm_use node LINKNODE into the chain for DEF, with use occuring 
+    in STMT.  */
+ static inline void
+ link_imm_use_stmt (ssa_imm_use_t *linknode, tree def, tree stmt)
+ {
+   if (stmt)
+     link_imm_use (linknode, def);
+   else
+     link_imm_use (linknode, NULL);
+   linknode->stmt = stmt;
+ }
+ 
+ /* Relink a new node in place of an old node in the list.  */
+ static inline void
+ relink_imm_use (ssa_imm_use_t *node, ssa_imm_use_t *old)
+ {
+ #ifdef ENABLE_CHECKING
+   /* The node one had better be in the same list.  */
+   if (*(old->use) != *(node->use))
+     abort ();
+ #endif
+   node->prev = old->prev;
+   node->next = old->next;
+   if (old->prev)
+     {
+       old->prev->next = node;
+       old->next->prev = node;
+       /* Remove the old node from the list.  */
+       old->prev = NULL;
+     }
+ 
+ }
+ 
+ /* Relink ssa_imm_use node LINKNODE into the chain for OLD, with use occuring 
+    in STMT.  */
+ static inline void
+ relink_imm_use_stmt (ssa_imm_use_t *linknode, ssa_imm_use_t *old, tree stmt)
+ {
+   if (stmt)
+     relink_imm_use (linknode, old);
+   else
+     link_imm_use (linknode, NULL);
+   linknode->stmt = stmt;
+ }
+ 
+ /* Finished the traverse of an immediate use list IMM by removing it from 
+    the list.  */
+ static inline void
+ end_safe_imm_use_traverse (imm_use_iterator *imm)
+ {
+  delink_imm_use (&(imm->iter_node));
+ }
+ 
+ /* Return true if IMM is at the end of the list.  */
+ static inline bool
+ end_safe_imm_use_p (imm_use_iterator *imm)
+ {
+   return (imm->imm_use == imm->end_p);
+ }
+ 
+ /* Initialize iterator IMM to process the list for VAR.  */
+ static inline use_operand_p
+ first_safe_imm_use (imm_use_iterator *imm, tree var)
+ {
+   /* Set up and link the iterator node into the linked list for VAR.  */
+   imm->var = var;
+   imm->iter_node.use = &(imm->var);
+   imm->iter_node.stmt = NULL_TREE;
+   imm->end_p = &(SSA_NAME_IMM_USE_NODE (var));
+   /* Check if there are 0 elements.  */
+   if (imm->end_p->next == imm->end_p)
+     {
+       imm->imm_use = imm->end_p;
+       return NULL_USE_OPERAND_P;
+     }
+ 
+   link_imm_use (&(imm->iter_node), var);
+   imm->imm_use = imm->iter_node.next;
+   return imm->imm_use;
+ }
+ 
+ /* Bump IMM to then next use in the list.  */
+ static inline use_operand_p
+ next_safe_imm_use (imm_use_iterator *imm)
+ {
+   ssa_imm_use_t *ptr;
+   use_operand_p old;
+ 
+   old = imm->imm_use;
+   /* If the next node following the iter_node is still the one refered to by
+      imm_use, then the list hasnt changed, go to the next node.  */
+   if (imm->iter_node.next == imm->imm_use)
+     {
+       ptr = &(imm->iter_node);
+       /* Remove iternode fromn the list.  */
+       delink_imm_use (ptr);
+       imm->imm_use = imm->imm_use->next;
+       if (! end_safe_imm_use_p (imm))
+ 	{
+ 	  /* This isnt the end, link iternode before the next use.  */
+ 	  ptr->prev = imm->imm_use->prev;
+ 	  ptr->next = imm->imm_use;
+ 	  imm->imm_use->prev->next = ptr;
+ 	  imm->imm_use->prev = ptr;
+ 	}
+       else
+ 	return old;
+     }
+     /* If the 'next' value after the iterator isn't the same as it was, then
+        a node has been deleted, so we sinply proceed to the node following where the iterator is in the list.  */
+   else
+     {
+       imm->imm_use = imm->iter_node.next;
+       if (end_safe_imm_use_p (imm))
+         {
+ 	  end_safe_imm_use_traverse (imm);
+ 	  return old;
+ 	}
+     }
+ 
+   return imm->imm_use;
+ }
+ 
+ /* Return true is IMM has reached the end of the immeidate use list.  */
+ static inline bool
+ end_readonly_imm_use_p (imm_use_iterator *imm)
+ {
+   return (imm->imm_use == imm->end_p);
+ }
+ 
+ /* Initialize iterator IMM to process the list for VAR.  */
+ static inline use_operand_p
+ first_readonly_imm_use (imm_use_iterator *imm, tree var)
+ {
+   gcc_assert (TREE_CODE (var) == SSA_NAME);
+ 
+   imm->end_p = &(SSA_NAME_IMM_USE_NODE (var));
+   imm->imm_use = imm->end_p->next;
+   if (end_readonly_imm_use_p (imm))
+     return NULL_USE_OPERAND_P;
+ #ifdef ENABLE_CHECKING
+   imm->iter_node.next = imm->imm_use->next;
+ #endif
+   return imm->imm_use;
+ }
+ 
+ /* Bump IMM to then next use in the list.  */
+ static inline use_operand_p
+ next_readonly_imm_use (imm_use_iterator *imm)
+ {
+   use_operand_p old = imm->imm_use;
+ 
+ #ifdef ENABLE_CHECKING
+   /* If this assertion fails, it indicates the 'next' pointer has changed 
+      since we the last bump.  This indicates that the list is being modified
+      via stmt changes, or SET_USE, or somesuch thing, and you need to be
+      using the SAFE version of the iterator.  */
+   gcc_assert (imm->iter_node.next == old->next);
+   imm->iter_node.next = old->next->next;
+ #endif
+ 
+   imm->imm_use = old->next;
+   if (end_readonly_imm_use_p (imm))
+     return old;
+   return imm->imm_use;
+ }
+ 
+ /* Return true if VAR has no uses.  */
+ static inline bool
+ has_zero_uses (tree var)
+ {
+   ssa_imm_use_t *ptr;
+   ptr = &(SSA_NAME_IMM_USE_NODE (var));
+   /* A single use means there is no items in the list.  */
+   return (ptr == ptr->next);
+ }
+ 
+ /* Return true if VAR has a single use.  */
+ static inline bool
+ has_single_use (tree var)
+ {
+   ssa_imm_use_t *ptr;
+   ptr = &(SSA_NAME_IMM_USE_NODE (var));
+   /* A single use means there is one item in the list.  */
+   return (ptr != ptr->next && ptr == ptr->next->next);
+ }
+ 
+ /* If VAR has only a single immediate use, return true, and set USE_P and STMT
+    to the use pointer and stmt of occurence.  */
+ static inline bool
+ single_imm_use (tree var, use_operand_p *use_p, tree *stmt)
+ {
+   ssa_imm_use_t *ptr;
+ 
+   ptr = &(SSA_NAME_IMM_USE_NODE (var));
+   if (ptr != ptr->next && ptr == ptr->next->next)
+     {
+       *use_p = ptr->next;
+       *stmt = ptr->next->stmt;
+       return true;
+     }
+   *use_p = NULL_USE_OPERAND_P;
+   *stmt = NULL_TREE;
+   return false;
+ }
+ 
+ /* Return the number of immediate uses of VAR.  */
+ static inline unsigned int
+ num_imm_uses (tree var)
+ {
+   ssa_imm_use_t *ptr, *start;
+   unsigned int num;
+ 
+   start = &(SSA_NAME_IMM_USE_NODE (var));
+   num = 0;
+   for (ptr = start->next; ptr != start; ptr = ptr->next)
+      num++;
+ 
+   return num;
+ }
+ 
  /* Return the definitions present in ANN, a statement annotation.
     Return NULL if this annotation contains no definitions.  */
  static inline def_optype
*************** get_v_must_def_ops (stmt_ann_t ann)
*** 208,214 ****
  static inline tree
  get_use_from_ptr (use_operand_p use)
  { 
!   return *(use.use);
  } 
  
  /* Return the tree pointer to by DEF.  */
--- 521,527 ----
  static inline tree
  get_use_from_ptr (use_operand_p use)
  { 
!   return *(use->use);
  } 
  
  /* Return the tree pointer to by DEF.  */
*************** static inline use_operand_p
*** 223,229 ****
  get_use_op_ptr (use_optype uses, unsigned int index)
  {
    gcc_assert (index < uses->num_uses);
!   return uses->uses[index];
  }
  
  /* Return a def_operand_p pointer for element INDEX of DEFS.  */
--- 536,542 ----
  get_use_op_ptr (use_optype uses, unsigned int index)
  {
    gcc_assert (index < uses->num_uses);
!   return &(uses->uses[index]);
  }
  
  /* Return a def_operand_p pointer for element INDEX of DEFS.  */
*************** get_def_op_ptr (def_optype defs, unsigne
*** 234,240 ****
    return defs->defs[index];
  }
  
- 
  /* Return the def_operand_p that is the V_MAY_DEF_RESULT for the V_MAY_DEF
     at INDEX in the V_MAY_DEFS array.  */
  static inline def_operand_p
--- 547,552 ----
*************** get_v_may_def_result_ptr(v_may_def_optyp
*** 251,270 ****
  static inline use_operand_p
  get_v_may_def_op_ptr(v_may_def_optype v_may_defs, unsigned int index)
  {
-   use_operand_p op;
    gcc_assert (index < v_may_defs->num_v_may_defs);
!   op.use = &(v_may_defs->v_may_defs[index].use);
!   return op;
  }
  
  /* Return a use_operand_p that is at INDEX in the VUSES array.  */
  static inline use_operand_p
  get_vuse_op_ptr(vuse_optype vuses, unsigned int index)
  {
-   use_operand_p op;
    gcc_assert (index < vuses->num_vuses);
!   op.use = &(vuses->vuses[index]);
!   return op;
  }
  
  /* Return a def_operand_p that is the V_MUST_DEF_OP for the
--- 563,578 ----
  static inline use_operand_p
  get_v_may_def_op_ptr(v_may_def_optype v_may_defs, unsigned int index)
  {
    gcc_assert (index < v_may_defs->num_v_may_defs);
!   return &(v_may_defs->v_may_defs[index].imm_use);
  }
  
  /* Return a use_operand_p that is at INDEX in the VUSES array.  */
  static inline use_operand_p
  get_vuse_op_ptr(vuse_optype vuses, unsigned int index)
  {
    gcc_assert (index < vuses->num_vuses);
!   return &(vuses->vuses[index].imm_use);
  }
  
  /* Return a def_operand_p that is the V_MUST_DEF_OP for the
*************** get_phi_result_ptr (tree phi)
*** 291,299 ****
  static inline use_operand_p
  get_phi_arg_def_ptr (tree phi, int i)
  {
!   use_operand_p op;
!   op.use = &(PHI_ARG_DEF_TREE (phi, i));
!   return op;
  }
   
  /* Return the bitmap of addresses taken by STMT, or NULL if it takes
--- 599,614 ----
  static inline use_operand_p
  get_phi_arg_def_ptr (tree phi, int i)
  {
!   return &(PHI_ARG_IMM_USE_NODE (phi,i));
! }
! 
! /* Set the value of a use pointed by USE to VAL.  */
! static inline void
! set_ssa_use_from_ptr2 (use_operand_p use, tree val)
! {
!   delink_imm_use (use);
!   *(use->use) = val;
!   link_imm_use (use, val);
  }
   
  /* Return the bitmap of addresses taken by STMT, or NULL if it takes
*************** addresses_taken (tree stmt)
*** 305,356 ****
    return ann ? ann->addresses_taken : NULL;
  }
  
- /* Return the immediate uses of STMT, or NULL if this information is
-    not computed.  */
- static dataflow_t
- get_immediate_uses (tree stmt)
- {
-   stmt_ann_t ann;
- 
-   if (TREE_CODE (stmt) == PHI_NODE)
-     return PHI_DF (stmt);
- 
-   ann = stmt_ann (stmt);
-   return ann ? ann->df : NULL;
- }
- 
- /* Return the number of immediate uses present in the dataflow
-    information at DF.  */
- static inline int
- num_immediate_uses (dataflow_t df)
- {
-   varray_type imm;
- 
-   if (!df)
-     return 0;
- 
-   imm = df->immediate_uses;
-   if (!imm)
-     return df->uses[1] ? 2 : 1;
- 
-   return VARRAY_ACTIVE_SIZE (imm) + 2;
- }
- 
- /* Return the tree that is at NUM in the immediate use DF array.  */
- static inline tree
- immediate_use (dataflow_t df, int num)
- {
-   if (!df)
-     return NULL_TREE;
- 
- #ifdef ENABLE_CHECKING
-   gcc_assert (num < num_immediate_uses (df));
- #endif
-   if (num < 2)
-     return df->uses[num];
-   return VARRAY_TREE (df->immediate_uses, num - 2);
- }
- 
  /* Return the basic_block annotation for BB.  */
  static inline bb_ann_t
  bb_ann (basic_block bb)
--- 620,625 ----
*************** phi_arg_from_edge (tree phi, edge e)
*** 393,398 ****
--- 662,695 ----
    return -1;
  }
  
+ /* Return the phi argument which contains the specified use.  */
+ 
+ static inline int
+ phi_arg_index_from_use (use_operand_p use)
+ {
+   struct phi_arg_d *element, *root;
+   int index;
+   tree phi;
+ 
+   /* Since the use is the first thing in a PHI arguemnt element, we can
+      calculate its index based on casting it to an argument, and performing
+      pointer arithmetic.  */
+ 
+   phi = USE_STMT (use);
+   gcc_assert (TREE_CODE (phi) == PHI_NODE);
+ 
+   element = (struct phi_arg_d *)use;
+   root = &(PHI_ARG_ELT (phi, 0));
+   index = element - root;
+ 
+   /* Make sure the calculation doesn't have any leftover bytes.  If it does, 
+      then imm_use is liekly not the first element in phi_arg_d.  */
+   gcc_assert (
+ 	  (((char *)element - (char *)root) % sizeof (struct phi_arg_d)) == 0);
+  
+  return index;
+ }
+ 
  /* Mark VAR as used, so that it'll be preserved during rtl expansion.  */
  
  static inline void
Index: tree-flow.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-flow.h,v
retrieving revision 2.50.6.1
diff -c -p -r2.50.6.1 tree-flow.h
*** tree-flow.h	8 Oct 2004 20:20:19 -0000	2.50.6.1
--- tree-flow.h	14 Oct 2004 19:24:36 -0000
*************** struct var_ann_d GTY(())
*** 208,250 ****
  };
  
  
! struct dataflow_d GTY(())
  {
!   /* Immediate uses.  This is a list of all the statements and PHI nodes
!      that are immediately reached by the definitions made in this
!      statement.  */
!   varray_type immediate_uses;
! 
!   /* Use this array for very small numbers of uses instead of the varray.  */
!   tree uses[2];
! 
!   /* Reached uses.  This is a list of all the possible program statements
!      that may be reached directly or indirectly by definitions made in this
!      statement.  Notice that this is a superset of IMMEDIATE_USES.
!      For instance, given the following piece of code:
! 
! 	    1	a1 = 10;
! 	    2	if (a1 > 3)
! 	    3	  a2 = a1 + 5;
! 	    4	a3 = PHI (a1, a2)
! 	    5	b1 = a3 - 2;
! 
!      IMMEDIATE_USES for statement #1 are all those statements that use a1
!      directly (i.e., #2, #3 and #4).  REACHED_USES for statement #1 also
!      includes statement #5 because 'a1' could reach 'a3' via the PHI node
!      at statement #4.  The set of REACHED_USES is then the transitive
!      closure over all the PHI nodes in the IMMEDIATE_USES set.  */
! 
!   /* Reaching definitions.  Similarly to REACHED_USES, the set
!      REACHING_DEFS is the set of all the statements that make definitions
!      that may reach this statement.  Notice that we don't need to have a
!      similar entry for immediate definitions, as these are represented by
!      the SSA_NAME nodes themselves (each SSA_NAME node contains a pointer
!      to the statement that makes that definition).  */
! };
! 
! typedef struct dataflow_d *dataflow_t;
! 
  
  struct stmt_ann_d GTY(())
  {
--- 208,241 ----
  };
  
  
! typedef struct immediate_use_iterator_d
  {
!   tree var;
!   ssa_imm_use_t *imm_use;
!   ssa_imm_use_t *end_p;
!   ssa_imm_use_t iter_node;
! } imm_use_iterator;
! 
! 
! /* Use this iterator when simply looking at stmts. Adding, deleteing or
!    modifying stmts will cause this iterator to malfunction.  */
! 
! #define FOR_EACH_IMM_USE_FAST(DEST, ITER, SSAVAR)			\
!   for ((DEST) = first_readonly_imm_use (&(ITER), (SSAVAR));	\
!        !end_readonly_imm_use_p (&(ITER));			\
!        (DEST) = next_readonly_imm_use (&(ITER)))
!   
! 
! #define FOR_EACH_IMM_USE_SAFE(DEST, ITER, SSAVAR)		\
!   for ((DEST) = first_safe_imm_use (&(ITER), (SSAVAR));		\
!        !end_safe_imm_use_p (&(ITER));				\
!        (DEST) = next_safe_imm_use (&(ITER)))
! 
! #define BREAK_FROM_SAFE_IMM_USE(ITER)				\
!    {								\
!      end_safe_imm_use_traverse (&(ITER));			\
!      break;							\
!    }
  
  struct stmt_ann_d GTY(())
  {
*************** struct stmt_ann_d GTY(())
*** 270,280 ****
    /* Basic block that contains this statement.  */
    basic_block GTY ((skip (""))) bb;
  
    struct stmt_operands_d operands;
  
-   /* Dataflow information.  */
-   dataflow_t df;
- 
    /* Set of variables that have had their address taken in the statement.  */
    bitmap addresses_taken;
  
--- 261,269 ----
    /* Basic block that contains this statement.  */
    basic_block GTY ((skip (""))) bb;
  
+   /* Operand cache for stmt.  */
    struct stmt_operands_d operands;
  
    /* Set of variables that have had their address taken in the statement.  */
    bitmap addresses_taken;
  
*************** static inline enum tree_ann_type ann_typ
*** 305,311 ****
  static inline basic_block bb_for_stmt (tree);
  extern void set_bb_for_stmt (tree, basic_block);
  static inline void modify_stmt (tree);
! static inline void unmodify_stmt (tree);
  static inline bool stmt_modified_p (tree);
  static inline varray_type may_aliases (tree);
  static inline int get_lineno (tree);
--- 294,300 ----
  static inline basic_block bb_for_stmt (tree);
  extern void set_bb_for_stmt (tree, basic_block);
  static inline void modify_stmt (tree);
! static inline void update_stmt (tree);
  static inline bool stmt_modified_p (tree);
  static inline varray_type may_aliases (tree);
  static inline int get_lineno (tree);
*************** static inline vuse_optype get_vuse_ops (
*** 317,325 ****
  static inline use_optype get_use_ops (stmt_ann_t);
  static inline def_optype get_def_ops (stmt_ann_t);
  static inline bitmap addresses_taken (tree);
- static inline int num_immediate_uses (dataflow_t);
- static inline tree immediate_use (dataflow_t, int);
- static inline dataflow_t get_immediate_uses (tree);
  static inline void set_default_def (tree, tree);
  static inline tree default_def (tree);
  
--- 306,311 ----
*************** extern bool aliases_computed_p;
*** 403,409 ****
  
  #define PERCENT(x,y) ((float)(x) * 100.0 / (float)(y))
  
- 
  /*---------------------------------------------------------------------------
  			      Block iterators
  ---------------------------------------------------------------------------*/
--- 389,394 ----
*************** extern void debug_referenced_vars (void)
*** 526,538 ****
  extern void dump_referenced_vars (FILE *);
  extern void dump_variable (FILE *, tree);
  extern void debug_variable (tree);
- extern void dump_immediate_uses (FILE *);
- extern void debug_immediate_uses (void);
- extern void dump_immediate_uses_for (FILE *, tree);
- extern void debug_immediate_uses_for (tree);
- extern void compute_immediate_uses (int, bool (*)(tree));
- extern void free_df (void);
- extern void free_df_for_stmt (tree);
  extern tree get_virtual_var (tree);
  extern void add_referenced_tmp_var (tree var);
  extern void mark_new_vars_to_rename (tree, bitmap);
--- 511,516 ----
*************** extern void ssa_remove_edge (edge);
*** 579,585 ****
  extern edge ssa_redirect_edge (edge, basic_block);
  extern bool tree_ssa_useless_type_conversion (tree);
  extern bool tree_ssa_useless_type_conversion_1 (tree, tree);
! extern void verify_ssa (void);
  extern void delete_tree_ssa (void);
  extern void register_new_def (tree, varray_type *);
  extern void walk_use_def_chains (tree, walk_use_def_chains_fn, void *, bool);
--- 557,563 ----
  extern edge ssa_redirect_edge (edge, basic_block);
  extern bool tree_ssa_useless_type_conversion (tree);
  extern bool tree_ssa_useless_type_conversion_1 (tree, tree);
! extern void verify_ssa (bool);
  extern void delete_tree_ssa (void);
  extern void register_new_def (tree, varray_type *);
  extern void walk_use_def_chains (tree, walk_use_def_chains_fn, void *, bool);
Index: tree-if-conv.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-if-conv.c,v
retrieving revision 2.10
diff -c -p -r2.10 tree-if-conv.c
*** tree-if-conv.c	28 Sep 2004 07:59:51 -0000	2.10
--- tree-if-conv.c	14 Oct 2004 19:24:37 -0000
*************** tree_if_conversion (struct loop *loop, b
*** 160,166 ****
  	  ifc_bbs = NULL;
  	}
        free_dominance_info (CDI_POST_DOMINATORS);
-       free_df ();
        return false;
      }
  
--- 160,165 ----
*************** tree_if_conversion (struct loop *loop, b
*** 205,211 ****
    clean_predicate_lists (loop);
    free (ifc_bbs);
    ifc_bbs = NULL;
-   free_df ();
  
    return true;
  }
--- 204,209 ----
*************** if_convertable_phi_p (struct loop *loop,
*** 346,358 ****
  
    if (!is_gimple_reg (SSA_NAME_VAR (PHI_RESULT (phi))))
      {
!       int j;
!       dataflow_t df = get_immediate_uses (phi);
!       int num_uses = num_immediate_uses (df);
!       for (j = 0; j < num_uses; j++)
  	{
! 	  tree use = immediate_use (df, j);
! 	  if (TREE_CODE (use) == PHI_NODE)
  	    {
  	      if (dump_file && (dump_flags & TDF_DETAILS))
  		fprintf (dump_file, "Difficult to handle this virtual phi.\n");
--- 344,354 ----
  
    if (!is_gimple_reg (SSA_NAME_VAR (PHI_RESULT (phi))))
      {
!       imm_use_iterator imm_iter;
!       use_operand_p use_p;
!       FOR_EACH_IMM_USE_FAST (use_p, imm_iter, PHI_RESULT (phi))
  	{
! 	  if (TREE_CODE (USE_STMT (use_p)) == PHI_NODE)
  	    {
  	      if (dump_file && (dump_flags & TDF_DETAILS))
  		fprintf (dump_file, "Difficult to handle this virtual phi.\n");
*************** if_convertable_loop_p (struct loop *loop
*** 562,569 ****
      if ( e->flags & EDGE_LOOP_EXIT)
        return false;
  
-   compute_immediate_uses (TDFA_USE_OPS|TDFA_USE_VOPS, NULL);
- 
    calculate_dominance_info (CDI_DOMINATORS);
    calculate_dominance_info (CDI_POST_DOMINATORS);
  
--- 558,563 ----
*************** replace_phi_with_cond_modify_expr (tree 
*** 788,794 ****
    bsi_insert_after (bsi, new_stmt, BSI_SAME_STMT);
    bsi_next (bsi);
  
!   modify_stmt (new_stmt);
  
    if (dump_file && (dump_flags & TDF_DETAILS))
      {
--- 782,788 ----
    bsi_insert_after (bsi, new_stmt, BSI_SAME_STMT);
    bsi_next (bsi);
  
!   update_stmt (new_stmt);
  
    if (dump_file && (dump_flags & TDF_DETAILS))
      {
Index: tree-loop-linear.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-loop-linear.c,v
retrieving revision 2.2
diff -c -p -r2.2 tree-loop-linear.c
*** tree-loop-linear.c	16 Sep 2004 16:16:14 -0000	2.2
--- tree-loop-linear.c	14 Oct 2004 19:24:37 -0000
*************** linear_transform_loops (struct loops *lo
*** 365,369 ****
        free_data_refs (datarefs);
      }
    rewrite_into_loop_closed_ssa ();
-   free_df ();
  }
--- 365,368 ----
Index: tree-optimize.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-optimize.c,v
retrieving revision 2.55
diff -c -p -r2.55 tree-optimize.c
*** tree-optimize.c	1 Oct 2004 15:11:10 -0000	2.55
--- tree-optimize.c	14 Oct 2004 19:24:37 -0000
*************** next_pass_1 (struct tree_opt_pass **list
*** 316,322 ****
            
  }
  
- /* Construct the pass tree.  */
  
  void
  init_tree_optimization_passes (void)
--- 316,321 ----
*************** static void execute_pass_list (struct tr
*** 413,420 ****
  static unsigned int last_verified;
  
  static void
! execute_todo (int properties, unsigned int flags)
  {
    if (flags & TODO_rename_vars)
      {
        rewrite_into_ssa (false);
--- 412,421 ----
  static unsigned int last_verified;
  
  static void
! execute_todo (struct tree_opt_pass *pass, unsigned int flags)
  {
+   int properties = pass->properties_required;
+ 
    if (flags & TODO_rename_vars)
      {
        rewrite_into_ssa (false);
*************** execute_todo (int properties, unsigned i
*** 437,447 ****
      }
  
    if (flags & TODO_ggc_collect)
!     ggc_collect ();
  
  #ifdef ENABLE_CHECKING
    if (flags & TODO_verify_ssa)
!     verify_ssa ();
    if (flags & TODO_verify_flow)
      verify_flow_info ();
    if (flags & TODO_verify_stmts)
--- 438,458 ----
      }
  
    if (flags & TODO_ggc_collect)
!     {
!       ggc_collect ();
!     }
! 
! #ifdef ENABLE_CHECKING
!       if ((pass->properties_required & PROP_ssa)
!           && !(pass->properties_destroyed & PROP_ssa))
!       {
! 	test_imm_links (dump_file);
!       }
! #endif
  
  #ifdef ENABLE_CHECKING
    if (flags & TODO_verify_ssa)
!     verify_ssa  (true);
    if (flags & TODO_verify_flow)
      verify_flow_info ();
    if (flags & TODO_verify_stmts)
*************** execute_one_pass (struct tree_opt_pass *
*** 465,471 ****
    /* Run pre-pass verification.  */
    todo = pass->todo_flags_start & ~last_verified;
    if (todo)
!     execute_todo (pass->properties_required, todo);
  
    /* If a dump file name is present, open it if enabled.  */
    if (pass->static_pass_number != -1)
--- 476,482 ----
    /* Run pre-pass verification.  */
    todo = pass->todo_flags_start & ~last_verified;
    if (todo)
!     execute_todo (pass, todo);
  
    /* If a dump file name is present, open it if enabled.  */
    if (pass->static_pass_number != -1)
*************** execute_one_pass (struct tree_opt_pass *
*** 511,517 ****
    todo = pass->todo_flags_finish;
    last_verified = todo & TODO_verify_all;
    if (todo)
!     execute_todo (pass->properties_provided, todo);
  
    /* Close down timevar and dump file.  */
    if (pass->tv_id)
--- 522,528 ----
    todo = pass->todo_flags_finish;
    last_verified = todo & TODO_verify_all;
    if (todo)
!     execute_todo (pass, todo);
  
    /* Close down timevar and dump file.  */
    if (pass->tv_id)
Index: tree-outof-ssa.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-outof-ssa.c,v
retrieving revision 2.25
diff -c -p -r2.25 tree-outof-ssa.c
*** tree-outof-ssa.c	30 Sep 2004 01:22:05 -0000	2.25
--- tree-outof-ssa.c	14 Oct 2004 19:24:37 -0000
*************** find_replaceable_in_bb (temp_expr_table_
*** 1634,1645 ****
--- 1634,1653 ----
    var_map map = tab->map;
    value_expr_p p;
    ssa_op_iter iter;
+   bitmap_iterator bi;
  
    for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
      {
        stmt = bsi_stmt (bsi);
        ann = stmt_ann (stmt);
  
+       if (TREE_CODE (stmt) == ASM_EXPR && ASM_VOLATILE_P (stmt))
+ 	{
+ 	  /* Volatile ASM_EXPRs kill all current expressions.  */
+ 	  EXECUTE_IF_SET_IN_BITMAP ((tab->partition_in_use), 0, partition, bi)
+ 	    kill_expr (tab, partition, false);
+ 	  continue;
+ 	}
        /* Determine if this stmt finishes an existing expression.  */
        FOR_EACH_SSA_TREE_OPERAND (def, stmt, iter, SSA_OP_USE)
  	{
*************** rewrite_trees (var_map map, tree *values
*** 1912,1919 ****
  		      && (DEF_FROM_PTR (def_p) == USE_OP (uses, 0)))
  		    remove = 1;
  		}
- 	      if (changed & !remove)
- 		modify_stmt (stmt);
  	    }
  
  	  /* Remove any stmts marked for removal.  */
--- 1920,1925 ----
Index: tree-phinodes.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-phinodes.c,v
retrieving revision 2.9
diff -c -p -r2.9 tree-phinodes.c
*** tree-phinodes.c	29 Sep 2004 21:23:35 -0000	2.9
--- tree-phinodes.c	14 Oct 2004 19:24:37 -0000
*************** tree
*** 165,171 ****
  make_phi_node (tree var, int len)
  {
    tree phi;
!   int size;
    int bucket = NUM_BUCKETS - 2;
  
    len = ideal_phi_node_len (len);
--- 165,171 ----
  make_phi_node (tree var, int len)
  {
    tree phi;
!   int size, i;
    int bucket = NUM_BUCKETS - 2;
  
    len = ideal_phi_node_len (len);
*************** make_phi_node (tree var, int len)
*** 208,213 ****
--- 208,221 ----
    else
      SET_PHI_RESULT (phi, make_ssa_name (var, phi));
  
+   for (i = 0; i < len; i++)
+     {
+       ssa_imm_use_t * imm;
+       imm = &(PHI_ARG_IMM_USE_NODE (phi, i));
+       imm->use = &(PHI_ARG_DEF_TREE (phi, i));
+       imm->prev = NULL;
+       imm->stmt = phi;
+     }
    return phi;
  }
  
*************** release_phi_node (tree phi)
*** 218,223 ****
--- 226,239 ----
  {
    int bucket;
    int len = PHI_ARG_CAPACITY (phi);
+   int x;
+ 
+   for (x = 0; x < PHI_NUM_ARGS (phi); x++)
+     {
+       ssa_imm_use_t * imm;
+       imm = &(PHI_ARG_IMM_USE_NODE (phi, x));
+       delink_imm_use (imm);
+     }
  
    bucket = len > NUM_BUCKETS - 1 ? NUM_BUCKETS - 1 : len;
    bucket -= 2;
*************** resize_phi_node (tree *phi, int len)
*** 270,281 ****
      }
  
    memcpy (new_phi, *phi, old_size);
- 
    old_len = PHI_ARG_CAPACITY (new_phi);
    PHI_ARG_CAPACITY (new_phi) = len;
                                                                                  
    for (i = old_len; i < len; i++)
      {
        SET_PHI_ARG_DEF (new_phi, i, NULL_TREE);
        PHI_ARG_EDGE (new_phi, i) = NULL;
        PHI_ARG_NONZERO (new_phi, i) = false;
--- 286,310 ----
      }
  
    memcpy (new_phi, *phi, old_size);
    old_len = PHI_ARG_CAPACITY (new_phi);
+   for (i = 0 ; i < old_len; i++)
+     {
+       ssa_imm_use_t *imm, *old_imm;
+       imm = &(PHI_ARG_IMM_USE_NODE (new_phi, i));
+       old_imm = &(PHI_ARG_IMM_USE_NODE (*phi, i));
+       imm->use = &(PHI_ARG_DEF_TREE (new_phi, i));
+       relink_imm_use_stmt (imm, old_imm, new_phi);
+     }
+ 
    PHI_ARG_CAPACITY (new_phi) = len;
                                                                                  
    for (i = old_len; i < len; i++)
      {
+       ssa_imm_use_t * imm;
+       imm = &(PHI_ARG_IMM_USE_NODE (new_phi, i));
+       imm->use = &(PHI_ARG_DEF_TREE (new_phi, i));
+       imm->prev = NULL;
+       imm->stmt = new_phi;
        SET_PHI_ARG_DEF (new_phi, i, NULL_TREE);
        PHI_ARG_EDGE (new_phi, i) = NULL;
        PHI_ARG_NONZERO (new_phi, i) = false;
*************** remove_phi_node (tree phi, tree prev, ba
*** 441,448 ****
  
        /* If we are deleting the PHI node, then we should release the
  	 SSA_NAME node so that it can be reused.  */
-       release_ssa_name (PHI_RESULT (phi));
        release_phi_node (phi);
      }
    else if (phi == phi_nodes (bb))
      {
--- 470,477 ----
  
        /* If we are deleting the PHI node, then we should release the
  	 SSA_NAME node so that it can be reused.  */
        release_phi_node (phi);
+       release_ssa_name (PHI_RESULT (phi));
      }
    else if (phi == phi_nodes (bb))
      {
*************** remove_phi_node (tree phi, tree prev, ba
*** 451,458 ****
  
        /* If we are deleting the PHI node, then we should release the
  	 SSA_NAME node so that it can be reused.  */
-       release_ssa_name (PHI_RESULT (phi));
        release_phi_node (phi);
      }
    else
      {
--- 480,487 ----
  
        /* If we are deleting the PHI node, then we should release the
  	 SSA_NAME node so that it can be reused.  */
        release_phi_node (phi);
+       release_ssa_name (PHI_RESULT (phi));
      }
    else
      {
Index: tree-pretty-print.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-pretty-print.c,v
retrieving revision 2.44.6.1
diff -c -p -r2.44.6.1 tree-pretty-print.c
*** tree-pretty-print.c	8 Oct 2004 20:20:20 -0000	2.44.6.1
--- tree-pretty-print.c	14 Oct 2004 19:24:37 -0000
*************** dump_generic_node (pretty_printer *buffe
*** 242,247 ****
--- 242,250 ----
        && stmt_ann (node))
      dump_vops (buffer, node, spc, flags);
  
+   if (is_stmt && (flags & TDF_STMT_ADDR))
+     pp_printf (buffer, "<&0x%x> ", (unsigned int)node);
+ 
    if (dumping_stmts
        && (flags & TDF_LINENO)
        && EXPR_HAS_LOCATION (node))
Index: tree-sra.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-sra.c,v
retrieving revision 2.37
diff -c -p -r2.37 tree-sra.c
*** tree-sra.c	28 Sep 2004 07:59:52 -0000	2.37
--- tree-sra.c	14 Oct 2004 19:24:38 -0000
*************** scalarize_use (struct sra_elt *elt, tree
*** 1719,1725 ****
        if (is_output)
  	mark_all_v_defs (stmt);
        *expr_p = elt->replacement;
!       modify_stmt (stmt);
      }
    else
      {
--- 1719,1725 ----
        if (is_output)
  	mark_all_v_defs (stmt);
        *expr_p = elt->replacement;
!       update_stmt (stmt);
      }
    else
      {
*************** scalarize_copy (struct sra_elt *lhs_elt,
*** 1767,1773 ****
  
        TREE_OPERAND (stmt, 0) = lhs_elt->replacement;
        TREE_OPERAND (stmt, 1) = rhs_elt->replacement;
!       modify_stmt (stmt);
      }
    else if (lhs_elt->use_block_copy || rhs_elt->use_block_copy)
      {
--- 1767,1773 ----
  
        TREE_OPERAND (stmt, 0) = lhs_elt->replacement;
        TREE_OPERAND (stmt, 1) = rhs_elt->replacement;
!       update_stmt (stmt);
      }
    else if (lhs_elt->use_block_copy || rhs_elt->use_block_copy)
      {
Index: tree-ssa-ccp.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-ccp.c,v
retrieving revision 2.47
diff -c -p -r2.47 tree-ssa-ccp.c
*** tree-ssa-ccp.c	29 Sep 2004 09:04:17 -0000	2.47
--- tree-ssa-ccp.c	14 Oct 2004 19:24:38 -0000
*************** likely_value (tree stmt)
*** 330,345 ****
  }
  
  
- /* Function indicating whether we ought to include information for VAR
-    when calculating immediate uses.  */
- 
- static bool
- need_imm_uses_for (tree var)
- {
-   return get_value (var)->lattice_val != VARYING;
- }
- 
- 
  /* Initialize local data structures for CCP.  */
  
  static void
--- 330,335 ----
*************** ccp_initialize (void)
*** 429,437 ****
      }
  
    sbitmap_free (is_may_def);
- 
-   /* Compute immediate uses for variables we care about.  */
-   compute_immediate_uses (TDFA_USE_OPS | TDFA_USE_VOPS, need_imm_uses_for);
  }
  
  
--- 419,424 ----
*************** substitute_and_fold (void)
*** 588,594 ****
  		    tree_purge_dead_eh_edges (bb);
  		}
  	      else
! 		modify_stmt (stmt);
  	    }
  
  	  if (dump_file && (dump_flags & TDF_DETAILS))
--- 575,581 ----
  		    tree_purge_dead_eh_edges (bb);
  		}
  	      else
! 		update_stmt (stmt);
  	    }
  
  	  if (dump_file && (dump_flags & TDF_DETAILS))
*************** execute_fold_all_builtins (void)
*** 2187,2193 ****
  	      if (result && !set_rhs (stmtp, result))
  		abort ();
  	    }
! 	  modify_stmt (*stmtp);
  	  if (maybe_clean_eh_stmt (*stmtp)
  	      && tree_purge_dead_eh_edges (bb))
  	    cfg_changed = true;
--- 2174,2180 ----
  	      if (result && !set_rhs (stmtp, result))
  		abort ();
  	    }
! 	  update_stmt (*stmtp);
  	  if (maybe_clean_eh_stmt (*stmtp)
  	      && tree_purge_dead_eh_edges (bb))
  	    cfg_changed = true;
Index: tree-ssa-dce.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-dce.c,v
retrieving revision 2.22
diff -c -p -r2.22 tree-ssa-dce.c
*** tree-ssa-dce.c	29 Sep 2004 23:08:31 -0000	2.22
--- tree-ssa-dce.c	14 Oct 2004 19:24:39 -0000
*************** mark_stmt_if_obviously_necessary (tree s
*** 336,342 ****
  	     statement from being marked necessary, we replace the condition
  	     with a constant.  The stmt is killed later on in cfg_cleanup.  */
  	  COND_EXPR_COND (stmt) = integer_zero_node;
! 	  modify_stmt (stmt);
  	  return;
  	}
        /* Fall through.  */
--- 336,342 ----
  	     statement from being marked necessary, we replace the condition
  	     with a constant.  The stmt is killed later on in cfg_cleanup.  */
  	  COND_EXPR_COND (stmt) = integer_zero_node;
! 	  update_stmt (stmt);
  	  return;
  	}
        /* Fall through.  */
Index: tree-ssa-dom.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-dom.c,v
retrieving revision 2.58
diff -c -p -r2.58 tree-ssa-dom.c
*** tree-ssa-dom.c	4 Oct 2004 13:19:20 -0000	2.58
--- tree-ssa-dom.c	14 Oct 2004 19:24:39 -0000
*************** tree_ssa_dominator_optimize (void)
*** 424,429 ****
--- 424,443 ----
        if (value && !is_gimple_min_invariant (value))
  	SSA_NAME_VALUE (name) = NULL;
      }
+ 
+ 
+   {
+     block_stmt_iterator bsi;
+     basic_block bb;
+     FOR_EACH_BB (bb)
+       {
+ 	for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
+ 	  {
+ 	    get_stmt_operands (bsi_stmt (bsi));
+ 	  }
+       }
+   }
+ 
  }
  
  static bool
Index: tree-ssa-dse.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-dse.c,v
retrieving revision 2.12
diff -c -p -r2.12 tree-ssa-dse.c
*** tree-ssa-dse.c	26 Sep 2004 19:53:13 -0000	2.12
--- tree-ssa-dse.c	14 Oct 2004 19:24:39 -0000
*************** static void dse_optimize_stmt (struct do
*** 94,101 ****
  			       block_stmt_iterator);
  static void dse_record_phis (struct dom_walk_data *, basic_block);
  static void dse_finalize_block (struct dom_walk_data *, basic_block);
- static void fix_phi_uses (tree, tree);
- static void fix_stmt_v_may_defs (tree, tree);
  static void record_voperand_set (bitmap, bitmap *, unsigned int);
  
  static unsigned max_stmt_uid;	/* Maximal uid of a statement.  Uids to phi
--- 94,99 ----
*************** need_imm_uses_for (tree var)
*** 124,196 ****
  }
  
  
- /* Replace uses in PHI which match V_MAY_DEF_RESULTs in STMT with the 
-    corresponding V_MAY_DEF_OP in STMT.  */
- 
- static void
- fix_phi_uses (tree phi, tree stmt)
- {
-   stmt_ann_t ann = stmt_ann (stmt);
-   v_may_def_optype v_may_defs;
-   unsigned int i;
-   int j;
- 
-   get_stmt_operands (stmt);
-   v_may_defs = V_MAY_DEF_OPS (ann);
- 
-   /* Walk each V_MAY_DEF in STMT.  */
-   for (i = 0; i < NUM_V_MAY_DEFS (v_may_defs); i++)
-     {
-       tree v_may_def = V_MAY_DEF_RESULT (v_may_defs, i);
- 
-       /* Find any uses in the PHI which match V_MAY_DEF and replace
- 	 them with the appropriate V_MAY_DEF_OP.  */
-       for (j = 0; j < PHI_NUM_ARGS (phi); j++)
- 	if (v_may_def == PHI_ARG_DEF (phi, j))
- 	  SET_PHI_ARG_DEF (phi, j, V_MAY_DEF_OP (v_may_defs, i));
-     }
- }
- 
- /* Replace the V_MAY_DEF_OPs in STMT1 which match V_MAY_DEF_RESULTs 
-    in STMT2 with the appropriate V_MAY_DEF_OPs from STMT2.  */
- 
- static void
- fix_stmt_v_may_defs (tree stmt1, tree stmt2)
- {
-   stmt_ann_t ann1 = stmt_ann (stmt1);
-   stmt_ann_t ann2 = stmt_ann (stmt2);
-   v_may_def_optype v_may_defs1;
-   v_may_def_optype v_may_defs2;
-   unsigned int i, j;
- 
-   get_stmt_operands (stmt1);
-   get_stmt_operands (stmt2);
-   v_may_defs1 = V_MAY_DEF_OPS (ann1);
-   v_may_defs2 = V_MAY_DEF_OPS (ann2);
- 
-   /* Walk each V_MAY_DEF_OP in stmt1.  */
-   for (i = 0; i < NUM_V_MAY_DEFS (v_may_defs1); i++)
-     {
-       tree v_may_def1 = V_MAY_DEF_OP (v_may_defs1, i);
- 
-       /* Find the appropriate V_MAY_DEF_RESULT in STMT2.  */
-       for (j = 0; j < NUM_V_MAY_DEFS (v_may_defs2); j++)
- 	{
- 	  if (v_may_def1 == V_MAY_DEF_RESULT (v_may_defs2, j))
- 	    {
- 	      /* Update.  */
- 	      SET_V_MAY_DEF_OP (v_may_defs1, i, V_MAY_DEF_OP (v_may_defs2, j));
- 	      break;
- 	    }
- 	}
- 
-       /* If we did not find a corresponding V_MAY_DEF_RESULT, then something
- 	 has gone terribly wrong.  */
-       gcc_assert (j != NUM_V_MAY_DEFS (v_may_defs2));
-     }
- }
- 
- 
  /* Set bit UID in bitmaps GLOBAL and *LOCAL, creating *LOCAL as needed.  */
  static void
  record_voperand_set (bitmap global, bitmap *local, unsigned int uid)
--- 122,127 ----
*************** dse_optimize_stmt (struct dom_walk_data 
*** 261,318 ****
      return;
    if (TREE_CODE (stmt) == MODIFY_EXPR)
      {
!       dataflow_t df = get_immediate_uses (stmt);
!       unsigned int num_uses = num_immediate_uses (df);
!       tree use;
!       tree skipped_phi;
! 
  
!       /* If there are no uses then there is nothing left to do.  */
!       if (num_uses == 0)
  	{
  	  record_voperand_set (dse_gd->stores, &bd->stores, ann->uid);
  	  return;
  	}
  
-       use = immediate_use (df, 0);
-       skipped_phi = NULL;
- 
        /* Skip through any PHI nodes we have already seen if the PHI
  	 represents the only use of this store.
  
  	 Note this does not handle the case where the store has
  	 multiple V_MAY_DEFs which all reach a set of PHI nodes in the
  	 same block.  */
!       while (num_uses == 1
! 	     && TREE_CODE (use) == PHI_NODE
! 	     && bitmap_bit_p (dse_gd->stores, get_stmt_uid (use)))
  	{
- 	  /* Record the first PHI we skip so that we can fix its
- 	     uses if we find that STMT is a dead store.  */
- 	  if (!skipped_phi)
- 	    skipped_phi = use;
- 
  	  /* Skip past this PHI and loop again in case we had a PHI
  	     chain.  */
! 	  df = get_immediate_uses (use);
! 	  num_uses = num_immediate_uses (df);
! 	  use = immediate_use (df, 0);
  	}
  
        /* If we have precisely one immediate use at this point, then we may
  	 have found redundant store.  */
!       if (num_uses == 1
! 	  && bitmap_bit_p (dse_gd->stores, get_stmt_uid (use))
  	  && operand_equal_p (TREE_OPERAND (stmt, 0),
! 			      TREE_OPERAND (use, 0), 0))
  	{
! 	  /* We need to fix the operands if either the first PHI we
! 	     skipped, or the store which we are not deleting if we did
! 	     not skip any PHIs.  */
! 	  if (skipped_phi)
! 	    fix_phi_uses (skipped_phi, stmt);
! 	  else
! 	    fix_stmt_v_may_defs (use, stmt);
  
  	  if (dump_file && (dump_flags & TDF_DETAILS))
              {
--- 192,254 ----
      return;
    if (TREE_CODE (stmt) == MODIFY_EXPR)
      {
!       unsigned int num_uses = 0, count = 0;
!       use_operand_p first_use_p = NULL_USE_OPERAND_P;
!       use_operand_p use_p;
!       tree use, use_stmt;
!       tree defvar = NULL_TREE, usevar = NULL_TREE;
!       use_operand_p var2;
!       def_operand_p var1;
!       ssa_op_iter op_iter;
! 
!       FOR_EACH_SSA_MAYDEF_OPERAND (var1, var2, stmt, op_iter)
!         {
! 	  defvar = DEF_FROM_PTR (var1);
! 	  usevar = USE_FROM_PTR (var2);
! 	  num_uses += num_imm_uses (defvar);
! 	  count++;
! 	  if (num_uses > 1 || count > 1)
! 	    break;
! 	}
  
!       if (count == 1 && num_uses == 1)
!         {
! 	  single_imm_use (defvar, &use_p, &use_stmt);
! 	  gcc_assert (use_p != NULL_USE_OPERAND_P);
! 	  first_use_p = use_p;
! 	  use = USE_FROM_PTR (use_p);
! 	}
!       else
  	{
  	  record_voperand_set (dse_gd->stores, &bd->stores, ann->uid);
  	  return;
  	}
  
        /* Skip through any PHI nodes we have already seen if the PHI
  	 represents the only use of this store.
  
  	 Note this does not handle the case where the store has
  	 multiple V_MAY_DEFs which all reach a set of PHI nodes in the
  	 same block.  */
!       while (use_p != NULL_USE_OPERAND_P
! 	     && TREE_CODE (use_stmt) == PHI_NODE
! 	     && bitmap_bit_p (dse_gd->stores, get_stmt_uid (use_stmt)))
  	{
  	  /* Skip past this PHI and loop again in case we had a PHI
  	     chain.  */
! 	  if (single_imm_use (PHI_RESULT (use_stmt), &use_p, &use_stmt))
! 	    use = USE_FROM_PTR (use_p);
  	}
  
        /* If we have precisely one immediate use at this point, then we may
  	 have found redundant store.  */
!       if (use_p != NULL_USE_OPERAND_P
! 	  && bitmap_bit_p (dse_gd->stores, get_stmt_uid (use_stmt))
  	  && operand_equal_p (TREE_OPERAND (stmt, 0),
! 			      TREE_OPERAND (use_stmt, 0), 0))
  	{
! 	  /* We need to fix the operand of the consuming stmt.  */
! 	  SET_USE (first_use_p, usevar);
  
  	  if (dump_file && (dump_flags & TDF_DETAILS))
              {
*************** dse_optimize_stmt (struct dom_walk_data 
*** 321,341 ****
                fprintf (dump_file, "'\n");
              }
  
! 	  /* Any immediate uses which reference STMT need to instead
! 	     reference the new consumer, either SKIPPED_PHI or USE.  
! 	     This allows us to cascade dead stores.  */
! 	  redirect_immediate_uses (stmt, skipped_phi ? skipped_phi : use);
! 
! 	  /* Be sure to remove any dataflow information attached to
! 	     this statement.  */
! 	  free_df_for_stmt (stmt);
  
  	  /* And release any SSA_NAMEs set in this statement back to the
  	     SSA_NAME manager.  */
  	  release_defs (stmt);
- 
- 	  /* Finally remove the dead store.  */
- 	  bsi_remove (&bsi);
  	}
  
        record_voperand_set (dse_gd->stores, &bd->stores, ann->uid);
--- 257,268 ----
                fprintf (dump_file, "'\n");
              }
  
! 	  /* Remove the dead store.  */
! 	  bsi_remove (&bsi);
  
  	  /* And release any SSA_NAMEs set in this statement back to the
  	     SSA_NAME manager.  */
  	  release_defs (stmt);
  	}
  
        record_voperand_set (dse_gd->stores, &bd->stores, ann->uid);
*************** tree_ssa_dse (void)
*** 402,410 ****
       dominators.  */
    calculate_dominance_info (CDI_POST_DOMINATORS);
  
-   /* We also need immediate use information for virtual operands.  */
-   compute_immediate_uses (TDFA_USE_VOPS, need_imm_uses_for);
- 
    /* Dead store elimination is fundamentally a walk of the post-dominator
       tree and a backwards walk of statements within each block.  */
    walk_data.walk_stmts_backward = true;
--- 329,334 ----
*************** tree_ssa_dse (void)
*** 435,443 ****
    /* Release the main bitmap.  */
    BITMAP_XFREE (dse_gd.stores);
  
-   /* Free dataflow information.  It's probably out of date now anyway.  */
-   free_df ();
- 
    /* For now, just wipe the post-dominator information.  */
    free_dominance_info (CDI_POST_DOMINATORS);
  }
--- 359,364 ----
Index: tree-ssa-forwprop.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-forwprop.c,v
retrieving revision 2.8
diff -c -p -r2.8 tree-ssa-forwprop.c
*** tree-ssa-forwprop.c	24 Sep 2004 13:26:29 -0000	2.8
--- tree-ssa-forwprop.c	14 Oct 2004 19:24:39 -0000
*************** Boston, MA 02111-1307, USA.  */
*** 113,134 ****
     by record_single_argument_cond_exprs and tested in need_imm_uses_for.  */
  static bitmap vars;
  
- static bool need_imm_uses_for (tree);
  static void tree_ssa_forward_propagate_single_use_vars (void);
  static void record_single_argument_cond_exprs (varray_type,
  					       varray_type *,
  					       bitmap);
  static void substitute_single_use_vars (varray_type *, varray_type);
  
- /* Function indicating whether we ought to include information for 'var'
-    when calculating immediate uses.  */
- 
- static bool
- need_imm_uses_for (tree var)
- {
-   return bitmap_bit_p (vars, SSA_NAME_VERSION (var));
- }
- 
  /* Find all COND_EXPRs with a condition that is a naked SSA_NAME or
     an equality comparison against a constant.
  
--- 113,124 ----
*************** static void
*** 323,350 ****
  substitute_single_use_vars (varray_type *cond_worklist,
  			    varray_type vars_worklist)
  {
    while (VARRAY_ACTIVE_SIZE (vars_worklist) > 0)
      {
        tree test_var = VARRAY_TOP_TREE (vars_worklist);
!       tree def = SSA_NAME_DEF_STMT (test_var);
!       dataflow_t df;
!       int j, num_uses, propagated_uses;
        block_stmt_iterator bsi;
  
        VARRAY_POP (vars_worklist);
  
-       /* Now compute the immediate uses of TEST_VAR.  */
-       df = get_immediate_uses (def);
-       num_uses = num_immediate_uses (df);
        propagated_uses = 0;
  
        /* If TEST_VAR is used more than once and is not a boolean set
  	 via TRUTH_NOT_EXPR with another SSA_NAME as its argument, then
  	 we can not optimize.  */
!       if (num_uses == 1
  	  || (TREE_CODE (TREE_TYPE (test_var)) == BOOLEAN_TYPE
! 	      && TREE_CODE (TREE_OPERAND (def, 1)) == TRUTH_NOT_EXPR
! 	      && (TREE_CODE (TREE_OPERAND (TREE_OPERAND (def, 1), 0))
  		  == SSA_NAME)))
  	;
        else
--- 313,345 ----
  substitute_single_use_vars (varray_type *cond_worklist,
  			    varray_type vars_worklist)
  {
+   use_operand_p use_p;
    while (VARRAY_ACTIVE_SIZE (vars_worklist) > 0)
      {
        tree test_var = VARRAY_TOP_TREE (vars_worklist);
!       tree def_stmt = SSA_NAME_DEF_STMT (test_var);
!       tree def;
!       int num_uses, propagated_uses;
        block_stmt_iterator bsi;
+       imm_use_iterator imm_iter;
  
        VARRAY_POP (vars_worklist);
  
        propagated_uses = 0;
+       num_uses = 0;
  
+       if (NUM_DEFS (STMT_DEF_OPS (def_stmt)) != 1)
+         continue;
+ 
+       def = DEF_OP (STMT_DEF_OPS (def_stmt), 0);
        /* If TEST_VAR is used more than once and is not a boolean set
  	 via TRUTH_NOT_EXPR with another SSA_NAME as its argument, then
  	 we can not optimize.  */
! 
!       if (has_single_use (def)
  	  || (TREE_CODE (TREE_TYPE (test_var)) == BOOLEAN_TYPE
! 	      && TREE_CODE (TREE_OPERAND (def_stmt, 1)) == TRUTH_NOT_EXPR
! 	      && (TREE_CODE (TREE_OPERAND (TREE_OPERAND (def_stmt, 1), 0))
  		  == SSA_NAME)))
  	;
        else
*************** substitute_single_use_vars (varray_type 
*** 352,358 ****
  
        /* Walk over each use and try to forward propagate the RHS of
  	 DEF into the use.  */
!       for (j = 0; j < num_uses; j++)
  	{
  	  tree cond_stmt;
  	  tree cond;
--- 347,353 ----
  
        /* Walk over each use and try to forward propagate the RHS of
  	 DEF into the use.  */
!       FOR_EACH_IMM_USE_SAFE (use_p, imm_iter, def)
  	{
  	  tree cond_stmt;
  	  tree cond;
*************** substitute_single_use_vars (varray_type 
*** 361,367 ****
  	  enum tree_code def_rhs_code;
  	  tree new_cond;
  
! 	  cond_stmt = immediate_use (df, j);
  
  	  /* For now we can only propagate into COND_EXPRs.  */
  	  if (TREE_CODE (cond_stmt) != COND_EXPR) 
--- 356,363 ----
  	  enum tree_code def_rhs_code;
  	  tree new_cond;
  
! 	  cond_stmt = USE_STMT (use_p);
! 	  num_uses++;
  
  	  /* For now we can only propagate into COND_EXPRs.  */
  	  if (TREE_CODE (cond_stmt) != COND_EXPR) 
*************** substitute_single_use_vars (varray_type 
*** 369,375 ****
  
  	  cond = COND_EXPR_COND (cond_stmt);
  	  cond_code = TREE_CODE (cond);
! 	  def_rhs = TREE_OPERAND (def, 1);
  	  def_rhs_code = TREE_CODE (def_rhs);
  
  	  /* If the definition of the single use variable was from an
--- 365,371 ----
  
  	  cond = COND_EXPR_COND (cond_stmt);
  	  cond_code = TREE_CODE (cond);
! 	  def_rhs = TREE_OPERAND (def_stmt, 1);
  	  def_rhs_code = TREE_CODE (def_rhs);
  
  	  /* If the definition of the single use variable was from an
*************** substitute_single_use_vars (varray_type 
*** 457,463 ****
  
  	  /* Replace the condition.  */
  	  COND_EXPR_COND (cond_stmt) = new_cond;
! 	  modify_stmt (cond_stmt);
  	  propagated_uses++;
  	  VARRAY_PUSH_TREE (*cond_worklist, cond_stmt);
  	}
--- 453,459 ----
  
  	  /* Replace the condition.  */
  	  COND_EXPR_COND (cond_stmt) = new_cond;
! 	  update_stmt (cond_stmt);
  	  propagated_uses++;
  	  VARRAY_PUSH_TREE (*cond_worklist, cond_stmt);
  	}
*************** substitute_single_use_vars (varray_type 
*** 466,476 ****
  	 Unfortunately, we have to find the defining statement in
  	 whatever block it might be in.  */
        if (num_uses && num_uses == propagated_uses)
! 	for (bsi = bsi_start (bb_for_stmt (def));
  	     !bsi_end_p (bsi);
  	     bsi_next (&bsi))
  	  {
! 	    if (def == bsi_stmt (bsi))
  	      {
  		bsi_remove (&bsi);
  		break;
--- 462,472 ----
  	 Unfortunately, we have to find the defining statement in
  	 whatever block it might be in.  */
        if (num_uses && num_uses == propagated_uses)
! 	for (bsi = bsi_start (bb_for_stmt (def_stmt));
  	     !bsi_end_p (bsi);
  	     bsi_next (&bsi))
  	  {
! 	    if (def_stmt == bsi_stmt (bsi))
  	      {
  		bsi_remove (&bsi);
  		break;
*************** tree_ssa_forward_propagate_single_use_va
*** 509,517 ****
  
        if (VARRAY_ACTIVE_SIZE (vars_worklist) > 0)
  	{
- 	  /* Now compute immediate uses for all the variables we care about.  */
- 	  compute_immediate_uses (TDFA_USE_OPS, need_imm_uses_for);
- 
  	  /* We've computed immediate uses, so we can/must clear the VARS
  	     bitmap for the next iteration.  */
  	  bitmap_clear (vars);
--- 505,510 ----
*************** tree_ssa_forward_propagate_single_use_va
*** 519,530 ****
  	  /* And optimize.  This will drain VARS_WORKLIST and initialize
  	     COND_WORKLIST for the next iteration.  */
  	  substitute_single_use_vars (&cond_worklist, vars_worklist);
- 
- 	  /* We do not incrementally update the dataflow information
- 	     so we must free it here and recompute the necessary bits
- 	     on the next iteration.  If this turns out to be expensive,
- 	     methods for incrementally updating the dataflow are known.  */
- 	  free_df ();
  	}
      }
  
--- 512,517 ----
Index: tree-ssa-loop-im.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-loop-im.c,v
retrieving revision 2.18
diff -c -p -r2.18 tree-ssa-loop-im.c
*** tree-ssa-loop-im.c	29 Sep 2004 23:08:32 -0000	2.18
--- tree-ssa-loop-im.c	14 Oct 2004 19:24:40 -0000
*************** single_reachable_address (struct loop *l
*** 929,940 ****
    tree *queue = xmalloc (sizeof (tree) * max_uid);
    sbitmap seen = sbitmap_alloc (max_uid);
    unsigned in_queue = 1;
!   dataflow_t df;
!   unsigned i, n;
    struct sra_data sra_data;
    tree call;
    tree val;
    ssa_op_iter iter;
  
    sbitmap_zero (seen);
  
--- 929,941 ----
    tree *queue = xmalloc (sizeof (tree) * max_uid);
    sbitmap seen = sbitmap_alloc (max_uid);
    unsigned in_queue = 1;
!   unsigned i;
    struct sra_data sra_data;
    tree call;
    tree val;
    ssa_op_iter iter;
+   imm_use_iterator imm_iter;
+   use_operand_p use_p;
  
    sbitmap_zero (seen);
  
*************** single_reachable_address (struct loop *l
*** 992,1013 ****
  	}
  
        /* Find uses of virtual names.  */
!       df = get_immediate_uses (stmt);
!       n = num_immediate_uses (df);
  
!       for (i = 0; i < n; i++)
! 	{
! 	  stmt = immediate_use (df, i);
  
! 	  if (!flow_bb_inside_loop_p (loop, bb_for_stmt (stmt)))
! 	    continue;
  
! 	  if (TEST_BIT (seen, get_stmt_uid (stmt)))
! 	    continue;
! 	  SET_BIT (seen, get_stmt_uid (stmt));
! 
! 	  queue[in_queue++] = stmt;
! 	}
      }
  
    free (queue);
--- 993,1027 ----
  	}
  
        /* Find uses of virtual names.  */
!       if (TREE_CODE (stmt) == PHI_NODE)
! 	FOR_EACH_IMM_USE_FAST (use_p, imm_iter, PHI_RESULT (stmt))
! 	  {	      
! 	    tree imm_stmt = USE_STMT (use_p);
! 
! 	    if (!flow_bb_inside_loop_p (loop, bb_for_stmt (imm_stmt)))
! 	      continue;
! 
! 	    if (TEST_BIT (seen, get_stmt_uid (imm_stmt)))
! 	      continue;
! 	    SET_BIT (seen, get_stmt_uid (imm_stmt));
! 
! 	    queue[in_queue++] = imm_stmt;
! 	  }
!       else
! 	FOR_EACH_SSA_TREE_OPERAND (val, stmt, iter, SSA_OP_VIRTUAL_DEFS)
! 	  FOR_EACH_IMM_USE_FAST (use_p, imm_iter, val)
! 	    {
! 	      tree imm_stmt = USE_STMT (use_p);
  
! 	      if (!flow_bb_inside_loop_p (loop, bb_for_stmt (imm_stmt)))
! 		continue;
  
! 	      if (TEST_BIT (seen, get_stmt_uid (imm_stmt)))
! 		continue;
! 	      SET_BIT (seen, get_stmt_uid (imm_stmt));
  
! 	      queue[in_queue++] = imm_stmt;
! 	    }
      }
  
    free (queue);
*************** rewrite_mem_refs (tree tmp_var, struct m
*** 1042,1048 ****
  	}
  
        *mem_refs->ref = tmp_var;
!       modify_stmt (mem_refs->stmt);
      }
  }
  
--- 1056,1062 ----
  	}
  
        *mem_refs->ref = tmp_var;
!       update_stmt (mem_refs->stmt);
      }
  }
  
*************** determine_lsm (struct loops *loops)
*** 1266,1273 ****
  	stmt_ann (bsi_stmt (bsi))->uid = max_stmt_uid++;
      }
  
-   compute_immediate_uses (TDFA_USE_VOPS, NULL);
- 
    /* Pass the loops from the outermost.  For each virtual operand loop phi node
       check whether all the references inside the loop correspond to a single
       address, and if so, move them.  */
--- 1280,1285 ----
*************** determine_lsm (struct loops *loops)
*** 1287,1293 ****
  	  loop = loop->outer;
  	  if (loop == loops->tree_root)
  	    {
- 	      free_df ();
  	      loop_commit_inserts ();
  	      return;
  	    }
--- 1299,1304 ----
Index: tree-ssa-loop-ivcanon.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-loop-ivcanon.c,v
retrieving revision 2.5
diff -c -p -r2.5 tree-ssa-loop-ivcanon.c
*** tree-ssa-loop-ivcanon.c	1 Oct 2004 18:26:31 -0000	2.5
--- tree-ssa-loop-ivcanon.c	14 Oct 2004 19:24:40 -0000
*************** create_canonical_iv (struct loop *loop, 
*** 97,103 ****
    COND_EXPR_COND (cond) = build2 (cmp, boolean_type_node,
  				  var,
  				  build_int_cst (type, 0));
!   modify_stmt (cond);
  }
  
  /* Computes an estimated number of insns in LOOP.  */
--- 97,103 ----
    COND_EXPR_COND (cond) = build2 (cmp, boolean_type_node,
  				  var,
  				  build_int_cst (type, 0));
!   update_stmt (cond);
  }
  
  /* Computes an estimated number of insns in LOOP.  */
*************** try_unroll_loop_completely (struct loops
*** 173,191 ****
  
        old_cond = COND_EXPR_COND (cond);
        COND_EXPR_COND (cond) = dont_exit;
!       modify_stmt (cond);
  
        if (!tree_duplicate_loop_to_header_edge (loop, loop_preheader_edge (loop),
  					       loops, n_unroll, NULL,
  					       NULL, NULL, NULL, 0))
  	{
  	  COND_EXPR_COND (cond) = old_cond;
  	  return false;
  	}
      }
    
    COND_EXPR_COND (cond) = do_exit;
!   modify_stmt (cond);
  
    if (dump_file && (dump_flags & TDF_DETAILS))
      fprintf (dump_file, "Unrolled loop %d completely.\n", loop->num);
--- 173,192 ----
  
        old_cond = COND_EXPR_COND (cond);
        COND_EXPR_COND (cond) = dont_exit;
!       update_stmt (cond);
  
        if (!tree_duplicate_loop_to_header_edge (loop, loop_preheader_edge (loop),
  					       loops, n_unroll, NULL,
  					       NULL, NULL, NULL, 0))
  	{
  	  COND_EXPR_COND (cond) = old_cond;
+ 	  update_stmt (cond);
  	  return false;
  	}
      }
    
    COND_EXPR_COND (cond) = do_exit;
!   update_stmt (cond);
  
    if (dump_file && (dump_flags & TDF_DETAILS))
      fprintf (dump_file, "Unrolled loop %d completely.\n", loop->num);
Index: tree-ssa-loop-ivopts.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-loop-ivopts.c,v
retrieving revision 2.16.4.1
diff -c -p -r2.16.4.1 tree-ssa-loop-ivopts.c
*** tree-ssa-loop-ivopts.c	8 Oct 2004 20:20:20 -0000	2.16.4.1
--- tree-ssa-loop-ivopts.c	14 Oct 2004 19:24:40 -0000
*************** rewrite_address_base (block_stmt_iterato
*** 4012,4017 ****
--- 4012,4018 ----
        new_name = make_ssa_name (new_var, copy);
      }
    TREE_OPERAND (copy, 0) = new_name;
+   update_stmt (copy);
    bsi_insert_before (bsi, copy, BSI_SAME_STMT);
    with = new_name;
  
*************** rewrite_use_compare (struct ivopts_data 
*** 4074,4080 ****
        *use->op_p = build2 (compare, boolean_type_node,
  			  var_at_stmt (data->current_loop,
  				       cand, use->stmt), op);
!       modify_stmt (use->stmt);
        return;
      }
  
--- 4075,4081 ----
        *use->op_p = build2 (compare, boolean_type_node,
  			  var_at_stmt (data->current_loop,
  				       cand, use->stmt), op);
!       update_stmt (use->stmt);
        return;
      }
  
*************** rewrite_use (struct ivopts_data *data,
*** 4306,4312 ****
        default:
  	gcc_unreachable ();
      }
!   modify_stmt (use->stmt);
  }
  
  /* Rewrite the uses using the selected induction variables.  */
--- 4307,4313 ----
        default:
  	gcc_unreachable ();
      }
!   update_stmt (use->stmt);
  }
  
  /* Rewrite the uses using the selected induction variables.  */
Index: tree-ssa-loop-manip.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-loop-manip.c,v
retrieving revision 2.9
diff -c -p -r2.9 tree-ssa-loop-manip.c
*** tree-ssa-loop-manip.c	28 Sep 2004 07:59:52 -0000	2.9
--- tree-ssa-loop-manip.c	14 Oct 2004 19:24:40 -0000
*************** verify_loop_closed_ssa (void)
*** 379,385 ****
    tree phi;
    unsigned i;
  
!   verify_ssa ();
  
    FOR_EACH_BB (bb)
      {
--- 379,385 ----
    tree phi;
    unsigned i;
  
!   verify_ssa (false);
  
    FOR_EACH_BB (bb)
      {
Index: tree-ssa-loop-unswitch.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-loop-unswitch.c,v
retrieving revision 2.3
diff -c -p -r2.3 tree-ssa-loop-unswitch.c
*** tree-ssa-loop-unswitch.c	28 Sep 2004 07:59:52 -0000	2.3
--- tree-ssa-loop-unswitch.c	14 Oct 2004 19:24:40 -0000
*************** tree_unswitch_single_loop (struct loops 
*** 252,258 ****
        else
  	break;
  
!       modify_stmt (stmt);
        i++;
      }
  
--- 252,258 ----
        else
  	break;
  
!       update_stmt (stmt);
        i++;
      }
  
Index: tree-ssa-operands.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-operands.c,v
retrieving revision 2.49
diff -c -p -r2.49 tree-ssa-operands.c
*** tree-ssa-operands.c	5 Oct 2004 22:42:34 -0000	2.49
--- tree-ssa-operands.c	14 Oct 2004 19:24:41 -0000
*************** tree check_build_stmt;
*** 124,133 ****
  #endif
  
  def_operand_p NULL_DEF_OPERAND_P = { NULL };
- use_operand_p NULL_USE_OPERAND_P = { NULL };
  
  static void note_addressable (tree, stmt_ann_t);
! static void get_expr_operands (tree, tree *, int);
  static void get_asm_expr_operands (tree);
  static void get_indirect_ref_operands (tree, tree, int);
  static void get_call_expr_operands (tree, tree);
--- 124,132 ----
  #endif
  
  def_operand_p NULL_DEF_OPERAND_P = { NULL };
  
  static void note_addressable (tree, stmt_ann_t);
! static void get_expr_operands (tree, tree *, int, stmt_operands_t *);
  static void get_asm_expr_operands (tree);
  static void get_indirect_ref_operands (tree, tree, int);
  static void get_call_expr_operands (tree, tree);
*************** allocate_use_optype (unsigned num)
*** 160,166 ****
  {
    use_optype use_ops;
    unsigned size;
!   size = sizeof (struct use_optype_d) + sizeof (tree *) * (num - 1);
    use_ops =  ggc_alloc (size);
    use_ops->num_uses = num;
    return use_ops;
--- 159,165 ----
  {
    use_optype use_ops;
    unsigned size;
!   size = sizeof (struct use_optype_d) + sizeof (use_operand_type_t) * (num - 1);
    use_ops =  ggc_alloc (size);
    use_ops->num_uses = num;
    return use_ops;
*************** allocate_vuse_optype (unsigned num)
*** 189,195 ****
  {
    vuse_optype vuse_ops;
    unsigned size;
!   size = sizeof (struct vuse_optype_d) + sizeof (tree) * (num - 1);
    vuse_ops =  ggc_alloc (size);
    vuse_ops->num_vuses = num;
    return vuse_ops;
--- 188,195 ----
  {
    vuse_optype vuse_ops;
    unsigned size;
!   size = sizeof (struct vuse_optype_d) 
!        + sizeof (vuse_operand_type_t) * (num - 1);
    vuse_ops =  ggc_alloc (size);
    vuse_ops->num_vuses = num;
    return vuse_ops;
*************** free_uses (use_optype *uses)
*** 217,222 ****
--- 217,226 ----
  {
    if (*uses)
      {
+       unsigned int x;
+       use_optype use = *uses;
+       for (x = 0; x < use->num_uses; x++)
+         delink_imm_use (&(use->uses[x]));
        ggc_free (*uses);
        *uses = NULL;
      }
*************** free_vuses (vuse_optype *vuses)
*** 243,248 ****
--- 247,256 ----
  {
    if (*vuses)
      {
+       unsigned int x;
+       vuse_optype vuse = *vuses;
+       for (x = 0; x < vuse->num_vuses; x++)
+         delink_imm_use (&(vuse->vuses[x].imm_use));
        ggc_free (*vuses);
        *vuses = NULL;
      }
*************** free_v_may_defs (v_may_def_optype *v_may
*** 256,261 ****
--- 264,273 ----
  {
    if (*v_may_defs)
      {
+       unsigned int x;
+       v_may_def_optype v_may_def = *v_may_defs;
+       for (x = 0; x < v_may_def->num_v_may_defs; x++)
+         delink_imm_use (&(v_may_def->v_may_defs[x].imm_use));
        ggc_free (*v_may_defs);
        *v_may_defs = NULL;
      }
*************** fini_ssa_operands (void)
*** 305,310 ****
--- 317,359 ----
    build_v_must_defs = NULL;
  }
  
+ /* Initialize V_USES index INDEX to VAL for STMT.  If OLD is present, preserve
+    the position of the may-def in the immediate_use list.  */
+ 
+ static inline void
+ initialize_vuse_operand (vuse_optype vuses, unsigned int index, tree val, 
+ 			 tree stmt, ssa_imm_use_t *old)
+ {
+   vuse_operand_type_t *ptr;
+   ptr = &(vuses->vuses[index]);
+   ptr->use = val;
+   ptr->imm_use.use = &(ptr->use);
+   if (old)
+     relink_imm_use_stmt (&(ptr->imm_use), old, stmt);
+   else
+     link_imm_use_stmt (&(ptr->imm_use), ptr->use, stmt);
+ }
+ 
+ 
+ /* Initialize V_MAY_DEF_OPS index X to be DEF = MAY_DEF <USE> for STMT.  If
+    OLD is present, preserve the position of the may-def in the immediate_use
+    list.  */
+ 
+ static inline void
+ initialize_v_may_def_operand (v_may_def_optype v_may_def_ops, unsigned int x, 
+ 			      tree def, tree use, tree stmt, ssa_imm_use_t *old)
+ {
+   v_may_def_operand_type_t *ptr;
+   ptr = &(v_may_def_ops->v_may_defs[x]);
+   ptr->def = def;
+   ptr->use = use;
+   ptr->imm_use.use = &(ptr->use);
+   if (old)
+     relink_imm_use_stmt (&(ptr->imm_use), old, stmt);
+   else
+     link_imm_use_stmt (&(ptr->imm_use), ptr->use, stmt);
+ }
+ 
  
  /* All the finalize_ssa_* routines do the work required to turn the build_
     VARRAY into an operand_vector of the appropriate type.  The original vector,
*************** fini_ssa_operands (void)
*** 315,321 ****
  /* Return a new def operand vector for STMT, comparing to OLD_OPS_P.  */
  
  static def_optype
! finalize_ssa_defs (def_optype *old_ops_p, tree stmt ATTRIBUTE_UNUSED)
  {
    unsigned num, x;
    def_optype def_ops, old_ops;
--- 364,370 ----
  /* Return a new def operand vector for STMT, comparing to OLD_OPS_P.  */
  
  static def_optype
! finalize_ssa_defs (def_optype *old_ops_p, tree stmt)
  {
    unsigned num, x;
    def_optype def_ops, old_ops;
*************** finalize_ssa_defs (def_optype *old_ops_p
*** 326,338 ****
      return NULL;
  
    /* There should only be a single real definition per assignment.  */
!   gcc_assert (TREE_CODE (stmt) != MODIFY_EXPR || num <= 1);
  
    old_ops = *old_ops_p;
  
    /* Compare old vector and new array.  */
    build_diff = true;
!   if (old_ops && old_ops->num_defs == num)
      {
        build_diff = false;
        for (x = 0; x < num; x++)
--- 375,387 ----
      return NULL;
  
    /* There should only be a single real definition per assignment.  */
!   gcc_assert ((stmt && TREE_CODE (stmt) != MODIFY_EXPR) || num <= 1);
  
    old_ops = *old_ops_p;
  
    /* Compare old vector and new array.  */
    build_diff = true;
!   if (stmt && old_ops && old_ops->num_defs == num)
      {
        build_diff = false;
        for (x = 0; x < num; x++)
*************** finalize_ssa_defs (def_optype *old_ops_p
*** 361,372 ****
  }
  
  
  /* Return a new use operand vector for STMT, comparing to OLD_OPS_P.  */
  
  static use_optype
! finalize_ssa_uses (use_optype *old_ops_p, tree stmt ATTRIBUTE_UNUSED)
  {
!   unsigned num, x;
    use_optype use_ops, old_ops;
    bool build_diff;
  
--- 410,449 ----
  }
  
  
+ /* Make sure PTR is inn the correct immediate use list.  Since uses are simply
+    pointers into the stmt TREE, there is no way of telling if anyone has
+    changed what this pointer points to via TREE_OPERANDS (exp, 0) = <...>.
+    THe contents are different, but the the pointer is still the same.  This
+    routine will check to make sure PTR is in the correct list, and if it isn't
+    put it in the correct list.  */
+ 
+ static inline void
+ correct_use_link (ssa_imm_use_t *ptr)
+ {
+   ssa_imm_use_t *prev;
+   tree root;
+ 
+   prev = ptr->prev;
+   if (prev)
+     {
+       while (prev->use)
+         prev = prev->prev;
+       root = prev->stmt;
+       if (root == *(ptr->use))
+ 	return;
+     }
+   /* Its in the wrong list if we reach here.  */
+   delink_imm_use (ptr);
+   link_imm_use (ptr, *(ptr->use));
+ }
+ 
+ 
  /* Return a new use operand vector for STMT, comparing to OLD_OPS_P.  */
  
  static use_optype
! finalize_ssa_uses (use_optype *old_ops_p, tree stmt)
  {
!   unsigned num, x, num_old, i;
    use_optype use_ops, old_ops;
    bool build_diff;
  
*************** finalize_ssa_uses (use_optype *old_ops_p
*** 386,415 ****
    }
  #endif
    old_ops = *old_ops_p;
  
    /* Check if the old vector and the new array are the same.  */
    build_diff = true;
!   if (old_ops && old_ops->num_uses == num)
      {
        build_diff = false;
        for (x = 0; x < num; x++)
!         if (old_ops->uses[x].use != VARRAY_TREE_PTR (build_uses, x))
! 	  {
! 	    build_diff = true;
! 	    break;
! 	  }
      }
  
    if (!build_diff)
      {
        use_ops = old_ops;
        *old_ops_p = NULL;
      }
    else
      {
        use_ops = allocate_use_optype (num);
        for (x = 0; x < num ; x++)
! 	use_ops->uses[x].use = VARRAY_TREE_PTR (build_uses, x);
      }
    VARRAY_POP_ALL (build_uses);
  
--- 463,515 ----
    }
  #endif
    old_ops = *old_ops_p;
+   num_old = ((stmt && old_ops) ? old_ops->num_uses : 0);
  
    /* Check if the old vector and the new array are the same.  */
    build_diff = true;
!   if (stmt && old_ops && num_old == num)
      {
        build_diff = false;
        for (x = 0; x < num; x++)
!         {
! 	  tree *var_p = VARRAY_TREE_PTR (build_uses, x);
! 	  tree *node = old_ops->uses[x].use;
! 	  /* Check the pointer values to see if they are the same. */
! 	  if (node != var_p)
! 	    {
! 	      build_diff = true;
! 	      break;
! 	    }
! 	}
      }
  
    if (!build_diff)
      {
        use_ops = old_ops;
        *old_ops_p = NULL;
+       for (i = 0; i < num_old; i++)
+         correct_use_link (&(use_ops->uses[i]));
      }
    else
      {
        use_ops = allocate_use_optype (num);
        for (x = 0; x < num ; x++)
!         {
! 	  tree *var = VARRAY_TREE_PTR (build_uses, x);
! 	  use_ops->uses[x].use = var;
! 	  for (i = 0; i < num_old; i++)
! 	    {
! 	      ssa_imm_use_t *ptr = &(old_ops->uses[i]);
! 	      if (ptr->use == var)
! 		{
! 		  relink_imm_use_stmt (&(use_ops->uses[x]), ptr, stmt);
! 		  correct_use_link (&(use_ops->uses[x]));
! 		  break;
! 		}
! 	    }
! 	  if (i == num_old)
! 	    link_imm_use_stmt (&(use_ops->uses[x]), *var, stmt);
! 	}
      }
    VARRAY_POP_ALL (build_uses);
  
*************** finalize_ssa_uses (use_optype *old_ops_p
*** 420,426 ****
  /* Return a new v_may_def operand vector for STMT, comparing to OLD_OPS_P.  */
  
  static v_may_def_optype
! finalize_ssa_v_may_defs (v_may_def_optype *old_ops_p)
  {
    unsigned num, x, i, old_num;
    v_may_def_optype v_may_def_ops, old_ops;
--- 520,526 ----
  /* Return a new v_may_def operand vector for STMT, comparing to OLD_OPS_P.  */
  
  static v_may_def_optype
! finalize_ssa_v_may_defs (v_may_def_optype *old_ops_p, tree stmt)
  {
    unsigned num, x, i, old_num;
    v_may_def_optype v_may_def_ops, old_ops;
*************** finalize_ssa_v_may_defs (v_may_def_optyp
*** 435,441 ****
  
    /* Check if the old vector and the new array are the same.  */
    build_diff = true;
!   if (old_ops && old_ops->num_v_may_defs == num)
      {
        old_num = num;
        build_diff = false;
--- 535,541 ----
  
    /* Check if the old vector and the new array are the same.  */
    build_diff = true;
!   if (stmt && old_ops && old_ops->num_v_may_defs == num)
      {
        old_num = num;
        build_diff = false;
*************** finalize_ssa_v_may_defs (v_may_def_optyp
*** 458,463 ****
--- 558,565 ----
      {
        v_may_def_ops = old_ops;
        *old_ops_p = NULL;
+       for (x = 0; x < num; x++)
+         correct_use_link (&(v_may_def_ops->v_may_defs[x].imm_use));
      }
    else
      {
*************** finalize_ssa_v_may_defs (v_may_def_optyp
*** 473,486 ****
  		result = SSA_NAME_VAR (result);
  	      if (result == var)
  	        {
! 		  v_may_def_ops->v_may_defs[x] = old_ops->v_may_defs[i];
  		  break;
  		}
  	    }
  	  if (i == old_num)
  	    {
! 	      v_may_def_ops->v_may_defs[x].def = var;
! 	      v_may_def_ops->v_may_defs[x].use = var;
  	    }
  	}
      }
--- 575,592 ----
  		result = SSA_NAME_VAR (result);
  	      if (result == var)
  	        {
! 		  initialize_v_may_def_operand (v_may_def_ops, x, 
! 						old_ops->v_may_defs[i].def,
! 						old_ops->v_may_defs[i].use,
! 						stmt, 
! 						&(old_ops->v_may_defs[i].imm_use));
  		  break;
  		}
  	    }
  	  if (i == old_num)
  	    {
! 	      initialize_v_may_def_operand (v_may_def_ops, x, var, var, stmt, 
! 					    NULL);
  	    }
  	}
      }
*************** finalize_ssa_v_may_defs (v_may_def_optyp
*** 494,500 ****
  /* Return a new vuse operand vector, comparing to OLD_OPS_P.  */
  
  static vuse_optype
! finalize_ssa_vuses (vuse_optype *old_ops_p)
  {
    unsigned num, x, i, num_v_may_defs, old_num;
    vuse_optype vuse_ops, old_ops;
--- 600,606 ----
  /* Return a new vuse operand vector, comparing to OLD_OPS_P.  */
  
  static vuse_optype
! finalize_ssa_vuses (vuse_optype *old_ops_p, tree stmt)
  {
    unsigned num, x, i, num_v_may_defs, old_num;
    vuse_optype vuse_ops, old_ops;
*************** finalize_ssa_vuses (vuse_optype *old_ops
*** 568,581 ****
  
    /* Determine whether vuses is the same as the old vector.  */
    build_diff = true;
!   if (old_ops && old_ops->num_vuses == num)
      {
        old_num = num;
        build_diff = false;
        for (x = 0; x < num ; x++)
          {
  	  tree v;
! 	  v = old_ops->vuses[x];
  	  if (TREE_CODE (v) == SSA_NAME)
  	    v = SSA_NAME_VAR (v);
  	  if (v != VARRAY_TREE (build_vuses, x))
--- 674,687 ----
  
    /* Determine whether vuses is the same as the old vector.  */
    build_diff = true;
!   if (stmt && old_ops && old_ops->num_vuses == num)
      {
        old_num = num;
        build_diff = false;
        for (x = 0; x < num ; x++)
          {
  	  tree v;
! 	  v = old_ops->vuses[x].use;
  	  if (TREE_CODE (v) == SSA_NAME)
  	    v = SSA_NAME_VAR (v);
  	  if (v != VARRAY_TREE (build_vuses, x))
*************** finalize_ssa_vuses (vuse_optype *old_ops
*** 592,597 ****
--- 698,705 ----
      {
        vuse_ops = old_ops;
        *old_ops_p = NULL;
+       for (x = 0; x < num; x++)
+         correct_use_link (&(vuse_ops->vuses[x].imm_use));
      }
    else
      {
*************** finalize_ssa_vuses (vuse_optype *old_ops
*** 602,618 ****
  	  /* Look for VAR in the old vector, and use that SSA_NAME.  */
  	  for (i = 0; i < old_num; i++)
  	    {
! 	      result = old_ops->vuses[i];
  	      if (TREE_CODE (result) == SSA_NAME)
  		result = SSA_NAME_VAR (result);
  	      if (result == var)
  	        {
! 		  vuse_ops->vuses[x] = old_ops->vuses[i];
  		  break;
  		}
  	    }
  	  if (i == old_num)
! 	    vuse_ops->vuses[x] = var;
  	}
      }
  
--- 710,727 ----
  	  /* Look for VAR in the old vector, and use that SSA_NAME.  */
  	  for (i = 0; i < old_num; i++)
  	    {
! 	      result = old_ops->vuses[i].use;
  	      if (TREE_CODE (result) == SSA_NAME)
  		result = SSA_NAME_VAR (result);
  	      if (result == var)
  	        {
! 		  initialize_vuse_operand (vuse_ops, x, old_ops->vuses[i].use, 
! 					   stmt, &(old_ops->vuses[i].imm_use));
  		  break;
  		}
  	    }
  	  if (i == old_num)
! 	    initialize_vuse_operand (vuse_ops, x, var, stmt, NULL);
  	}
      }
  
*************** finalize_ssa_vuses (vuse_optype *old_ops
*** 627,634 ****
  /* Return a new v_must_def operand vector for STMT, comparing to OLD_OPS_P.  */
  
  static v_must_def_optype
! finalize_ssa_v_must_defs (v_must_def_optype *old_ops_p, 
! 			  tree stmt ATTRIBUTE_UNUSED)
  {
    unsigned num, x, i, old_num = 0;
    v_must_def_optype v_must_def_ops, old_ops;
--- 736,742 ----
  /* Return a new v_must_def operand vector for STMT, comparing to OLD_OPS_P.  */
  
  static v_must_def_optype
! finalize_ssa_v_must_defs (v_must_def_optype *old_ops_p, tree stmt)
  {
    unsigned num, x, i, old_num = 0;
    v_must_def_optype v_must_def_ops, old_ops;
*************** finalize_ssa_v_must_defs (v_must_def_opt
*** 639,651 ****
      return NULL;
  
    /* There should only be a single V_MUST_DEF per assignment.  */
!   gcc_assert (TREE_CODE (stmt) != MODIFY_EXPR || num <= 1);
  
    old_ops = *old_ops_p;
  
    /* Check if the old vector and the new array are the same.  */
    build_diff = true;
!   if (old_ops && old_ops->num_v_must_defs == num)
      {
        old_num = num;
        build_diff = false;
--- 747,759 ----
      return NULL;
  
    /* There should only be a single V_MUST_DEF per assignment.  */
!   gcc_assert ((stmt && TREE_CODE (stmt) != MODIFY_EXPR) || num <= 1);
  
    old_ops = *old_ops_p;
  
    /* Check if the old vector and the new array are the same.  */
    build_diff = true;
!   if (stmt && old_ops && old_ops->num_v_must_defs == num)
      {
        old_num = num;
        build_diff = false;
*************** finalize_ssa_stmt_operands (tree stmt, s
*** 707,714 ****
    new_ops->use_ops = finalize_ssa_uses (&(old_ops->use_ops), stmt);
    new_ops->v_must_def_ops 
      = finalize_ssa_v_must_defs (&(old_ops->v_must_def_ops), stmt);
!   new_ops->v_may_def_ops = finalize_ssa_v_may_defs (&(old_ops->v_may_def_ops));
!   new_ops->vuse_ops = finalize_ssa_vuses (&(old_ops->vuse_ops));
  }
  
  
--- 815,823 ----
    new_ops->use_ops = finalize_ssa_uses (&(old_ops->use_ops), stmt);
    new_ops->v_must_def_ops 
      = finalize_ssa_v_must_defs (&(old_ops->v_must_def_ops), stmt);
!   new_ops->v_may_def_ops 
!     = finalize_ssa_v_may_defs (&(old_ops->v_may_def_ops), stmt);
!   new_ops->vuse_ops = finalize_ssa_vuses (&(old_ops->vuse_ops), stmt);
  }
  
  
*************** append_v_must_def (tree var)
*** 792,801 ****
  
  /* Create an operands cache for STMT, returning it in NEW_OPS. OLD_OPS are the
     original operands, and if ANN is non-null, appropriate stmt flags are set
!    in the stmt's annotation.  Note that some fields in old_ops may 
!    change to NULL, although none of the memory they originally pointed to 
!    will be destroyed.  It is appropriate to call free_stmt_operands() on 
!    the value returned in old_ops.
  
     The rationale for this: Certain optimizations wish to examine the difference
     between new_ops and old_ops after processing.  If a set of operands don't
--- 901,914 ----
  
  /* Create an operands cache for STMT, returning it in NEW_OPS. OLD_OPS are the
     original operands, and if ANN is non-null, appropriate stmt flags are set
!    in the stmt's annotation.  If ANN is NULL, this is not considered a "real"
!    stmt, and none of the operands will be entered into their respective
!    immediate uses tables.  This is to allow stmts to be processed when they
!    are not actually in the CFG.
! 
!    Note that some fields in old_ops may change to NULL, although none of the
!    memory they originally pointed to will be destroyed.  It is appropriate
!    to call free_stmt_operands() on the value returned in old_ops.
  
     The rationale for this: Certain optimizations wish to examine the difference
     between new_ops and old_ops after processing.  If a set of operands don't
*************** build_ssa_operands (tree stmt, stmt_ann_
*** 835,841 ****
    switch (code)
      {
      case MODIFY_EXPR:
!       get_expr_operands (stmt, &TREE_OPERAND (stmt, 1), opf_none);
        if (TREE_CODE (TREE_OPERAND (stmt, 0)) == ARRAY_REF 
  	  || TREE_CODE (TREE_OPERAND (stmt, 0)) == ARRAY_RANGE_REF
  	  || TREE_CODE (TREE_OPERAND (stmt, 0)) == COMPONENT_REF
--- 948,954 ----
    switch (code)
      {
      case MODIFY_EXPR:
!       get_expr_operands (stmt, &TREE_OPERAND (stmt, 1), opf_none, old_ops);
        if (TREE_CODE (TREE_OPERAND (stmt, 0)) == ARRAY_REF 
  	  || TREE_CODE (TREE_OPERAND (stmt, 0)) == ARRAY_RANGE_REF
  	  || TREE_CODE (TREE_OPERAND (stmt, 0)) == COMPONENT_REF
*************** build_ssa_operands (tree stmt, stmt_ann_
*** 845,862 ****
  	     modified in that case.  FIXME we should represent somehow
  	     that it is killed on the fallthrough path.  */
  	  || tree_could_throw_p (TREE_OPERAND (stmt, 1)))
!         get_expr_operands (stmt, &TREE_OPERAND (stmt, 0), opf_is_def);
        else
          get_expr_operands (stmt, &TREE_OPERAND (stmt, 0), 
! 	                   opf_is_def | opf_kill_def);
        break;
  
      case COND_EXPR:
!       get_expr_operands (stmt, &COND_EXPR_COND (stmt), opf_none);
        break;
  
      case SWITCH_EXPR:
!       get_expr_operands (stmt, &SWITCH_COND (stmt), opf_none);
        break;
  
      case ASM_EXPR:
--- 958,975 ----
  	     modified in that case.  FIXME we should represent somehow
  	     that it is killed on the fallthrough path.  */
  	  || tree_could_throw_p (TREE_OPERAND (stmt, 1)))
!         get_expr_operands (stmt, &TREE_OPERAND (stmt, 0), opf_is_def, old_ops);
        else
          get_expr_operands (stmt, &TREE_OPERAND (stmt, 0), 
! 	                   opf_is_def | opf_kill_def, old_ops);
        break;
  
      case COND_EXPR:
!       get_expr_operands (stmt, &COND_EXPR_COND (stmt), opf_none, old_ops);
        break;
  
      case SWITCH_EXPR:
!       get_expr_operands (stmt, &SWITCH_COND (stmt), opf_none, old_ops);
        break;
  
      case ASM_EXPR:
*************** build_ssa_operands (tree stmt, stmt_ann_
*** 864,878 ****
        break;
  
      case RETURN_EXPR:
!       get_expr_operands (stmt, &TREE_OPERAND (stmt, 0), opf_none);
        break;
  
      case GOTO_EXPR:
!       get_expr_operands (stmt, &GOTO_DESTINATION (stmt), opf_none);
        break;
  
      case LABEL_EXPR:
!       get_expr_operands (stmt, &LABEL_EXPR_LABEL (stmt), opf_none);
        break;
  
        /* These nodes contain no variable references.  */
--- 977,991 ----
        break;
  
      case RETURN_EXPR:
!       get_expr_operands (stmt, &TREE_OPERAND (stmt, 0), opf_none, old_ops);
        break;
  
      case GOTO_EXPR:
!       get_expr_operands (stmt, &GOTO_DESTINATION (stmt), opf_none, old_ops);
        break;
  
      case LABEL_EXPR:
!       get_expr_operands (stmt, &LABEL_EXPR_LABEL (stmt), opf_none, old_ops);
        break;
  
        /* These nodes contain no variable references.  */
*************** build_ssa_operands (tree stmt, stmt_ann_
*** 891,901 ****
  	 append_use.  This default will handle statements like empty
  	 statements, or CALL_EXPRs that may appear on the RHS of a statement
  	 or as statements themselves.  */
!       get_expr_operands (stmt, &stmt, opf_none);
        break;
      }
  
!   finalize_ssa_stmt_operands (stmt, old_ops, new_ops);
    stmt->common.ann = saved_ann;
  }
  
--- 1004,1017 ----
  	 append_use.  This default will handle statements like empty
  	 statements, or CALL_EXPRs that may appear on the RHS of a statement
  	 or as statements themselves.  */
!       get_expr_operands (stmt, &stmt, opf_none, old_ops);
        break;
      }
  
!   if (ann)
!     finalize_ssa_stmt_operands (stmt, old_ops, new_ops);
!   else
!     finalize_ssa_stmt_operands (NULL, old_ops, new_ops);
    stmt->common.ann = saved_ann;
  }
  
*************** free_ssa_operands (stmt_operands_p ops)
*** 920,926 ****
  
  /* Get the operands of statement STMT.  Note that repeated calls to
     get_stmt_operands for the same statement will do nothing until the
!    statement is marked modified by a call to modify_stmt().  */
  
  void
  get_stmt_operands (tree stmt)
--- 1036,1042 ----
  
  /* Get the operands of statement STMT.  Note that repeated calls to
     get_stmt_operands for the same statement will do nothing until the
!    statement is marked modified by a call to mark_stmt_modified().  */
  
  void
  get_stmt_operands (tree stmt)
*************** get_stmt_operands (tree stmt)
*** 928,933 ****
--- 1044,1053 ----
    stmt_ann_t ann;
    stmt_operands_t old_operands;
  
+   /* If get_stmt_operands is called before SSA is initialized, dont
+   do anything.  */
+   if (build_defs == NULL)
+     return;
    /* The optimizers cannot handle statements that are nothing but a
       _DECL.  This indicates a bug in the gimplifier.  */
    gcc_assert (!SSA_VAR_P (stmt));
*************** get_stmt_operands (tree stmt)
*** 952,958 ****
  
    /* Clear the modified bit for STMT.  Subsequent calls to
       get_stmt_operands for this statement will do nothing until the
!      statement is marked modified by a call to modify_stmt().  */
    ann->modified = 0;
  
    timevar_pop (TV_TREE_OPS);
--- 1072,1078 ----
  
    /* Clear the modified bit for STMT.  Subsequent calls to
       get_stmt_operands for this statement will do nothing until the
!      statement is marked modified by a call to mark_stmt_modified().  */
    ann->modified = 0;
  
    timevar_pop (TV_TREE_OPS);
*************** get_stmt_operands (tree stmt)
*** 964,970 ****
     operands found.  */
  
  static void
! get_expr_operands (tree stmt, tree *expr_p, int flags)
  {
    enum tree_code code;
    enum tree_code_class class;
--- 1084,1090 ----
     operands found.  */
  
  static void
! get_expr_operands (tree stmt, tree *expr_p, int flags, stmt_operands_t *old_ops)
  {
    enum tree_code code;
    enum tree_code_class class;
*************** get_expr_operands (tree stmt, tree *expr
*** 997,1003 ****
  	 does not allow non-registers as array indices).  */
        flags |= opf_no_vops;
  
!       get_expr_operands (stmt, &TREE_OPERAND (expr, 0), flags);
        return;
  
      case SSA_NAME:
--- 1117,1123 ----
  	 does not allow non-registers as array indices).  */
        flags |= opf_no_vops;
  
!       get_expr_operands (stmt, &TREE_OPERAND (expr, 0), flags, old_ops);
        return;
  
      case SSA_NAME:
*************** get_expr_operands (tree stmt, tree *expr
*** 1011,1017 ****
        return;
  
      case MISALIGNED_INDIRECT_REF:
!       get_expr_operands (stmt, &TREE_OPERAND (expr, 1), flags);
        /* fall through */
  
      case ALIGN_INDIRECT_REF:
--- 1131,1137 ----
        return;
  
      case MISALIGNED_INDIRECT_REF:
!       get_expr_operands (stmt, &TREE_OPERAND (expr, 1), flags, old_ops);
        /* fall through */
  
      case ALIGN_INDIRECT_REF:
*************** get_expr_operands (tree stmt, tree *expr
*** 1031,1041 ****
        if (SSA_VAR_P (TREE_OPERAND (expr, 0)))
  	add_stmt_operand (expr_p, stmt, flags);
        else
! 	get_expr_operands (stmt, &TREE_OPERAND (expr, 0), flags);
  
!       get_expr_operands (stmt, &TREE_OPERAND (expr, 1), opf_none);
!       get_expr_operands (stmt, &TREE_OPERAND (expr, 2), opf_none);
!       get_expr_operands (stmt, &TREE_OPERAND (expr, 3), opf_none);
        return;
  
      case COMPONENT_REF:
--- 1151,1161 ----
        if (SSA_VAR_P (TREE_OPERAND (expr, 0)))
  	add_stmt_operand (expr_p, stmt, flags);
        else
! 	get_expr_operands (stmt, &TREE_OPERAND (expr, 0), flags, old_ops);
  
!       get_expr_operands (stmt, &TREE_OPERAND (expr, 1), opf_none, old_ops);
!       get_expr_operands (stmt, &TREE_OPERAND (expr, 2), opf_none, old_ops);
!       get_expr_operands (stmt, &TREE_OPERAND (expr, 3), opf_none, old_ops);
        return;
  
      case COMPONENT_REF:
*************** get_expr_operands (tree stmt, tree *expr
*** 1059,1075 ****
        if (SSA_VAR_P (TREE_OPERAND (expr, 0)))
  	add_stmt_operand (expr_p, stmt, flags);
        else
! 	get_expr_operands (stmt, &TREE_OPERAND (expr, 0), flags);
  
        if (code == COMPONENT_REF)
! 	get_expr_operands (stmt, &TREE_OPERAND (expr, 2), opf_none);
        return;
  
      case WITH_SIZE_EXPR:
        /* WITH_SIZE_EXPR is a pass-through reference to its first argument,
  	 and an rvalue reference to its second argument.  */
!       get_expr_operands (stmt, &TREE_OPERAND (expr, 1), opf_none);
!       get_expr_operands (stmt, &TREE_OPERAND (expr, 0), flags);
        return;
  
      case CALL_EXPR:
--- 1179,1195 ----
        if (SSA_VAR_P (TREE_OPERAND (expr, 0)))
  	add_stmt_operand (expr_p, stmt, flags);
        else
! 	get_expr_operands (stmt, &TREE_OPERAND (expr, 0), flags, old_ops);
  
        if (code == COMPONENT_REF)
! 	get_expr_operands (stmt, &TREE_OPERAND (expr, 2), opf_none, old_ops);
        return;
  
      case WITH_SIZE_EXPR:
        /* WITH_SIZE_EXPR is a pass-through reference to its first argument,
  	 and an rvalue reference to its second argument.  */
!       get_expr_operands (stmt, &TREE_OPERAND (expr, 1), opf_none, old_ops);
!       get_expr_operands (stmt, &TREE_OPERAND (expr, 0), flags, old_ops);
        return;
  
      case CALL_EXPR:
*************** get_expr_operands (tree stmt, tree *expr
*** 1078,1086 ****
  
      case COND_EXPR:
      case VEC_COND_EXPR:
!       get_expr_operands (stmt, &TREE_OPERAND (expr, 0), opf_none);
!       get_expr_operands (stmt, &TREE_OPERAND (expr, 1), opf_none);
!       get_expr_operands (stmt, &TREE_OPERAND (expr, 2), opf_none);
        return;
  
      case MODIFY_EXPR:
--- 1198,1206 ----
  
      case COND_EXPR:
      case VEC_COND_EXPR:
!       get_expr_operands (stmt, &TREE_OPERAND (expr, 0), opf_none, old_ops);
!       get_expr_operands (stmt, &TREE_OPERAND (expr, 1), opf_none, old_ops);
!       get_expr_operands (stmt, &TREE_OPERAND (expr, 2), opf_none, old_ops);
        return;
  
      case MODIFY_EXPR:
*************** get_expr_operands (tree stmt, tree *expr
*** 1088,1094 ****
  	int subflags;
  	tree op;
  
! 	get_expr_operands (stmt, &TREE_OPERAND (expr, 1), opf_none);
  
  	op = TREE_OPERAND (expr, 0);
  	if (TREE_CODE (op) == WITH_SIZE_EXPR)
--- 1208,1214 ----
  	int subflags;
  	tree op;
  
! 	get_expr_operands (stmt, &TREE_OPERAND (expr, 1), opf_none, old_ops);
  
  	op = TREE_OPERAND (expr, 0);
  	if (TREE_CODE (op) == WITH_SIZE_EXPR)
*************** get_expr_operands (tree stmt, tree *expr
*** 1102,1108 ****
  	else
  	  subflags = opf_is_def | opf_kill_def;
  
! 	get_expr_operands (stmt, &TREE_OPERAND (expr, 0), subflags);
  	return;
        }
  
--- 1222,1228 ----
  	else
  	  subflags = opf_is_def | opf_kill_def;
  
! 	get_expr_operands (stmt, &TREE_OPERAND (expr, 0), subflags, old_ops);
  	return;
        }
  
*************** get_expr_operands (tree stmt, tree *expr
*** 1113,1119 ****
  
  	tree t;
  	for (t = TREE_OPERAND (expr, 0); t ; t = TREE_CHAIN (t))
! 	  get_expr_operands (stmt, &TREE_VALUE (t), opf_none);
  
  	return;
        }
--- 1233,1239 ----
  
  	tree t;
  	for (t = TREE_OPERAND (expr, 0); t ; t = TREE_CHAIN (t))
! 	  get_expr_operands (stmt, &TREE_VALUE (t), opf_none, old_ops);
  
  	return;
        }
*************** get_expr_operands (tree stmt, tree *expr
*** 1122,1128 ****
      case BIT_FIELD_REF:
      case VIEW_CONVERT_EXPR:
      do_unary:
!       get_expr_operands (stmt, &TREE_OPERAND (expr, 0), flags);
        return;
  
      case TRUTH_AND_EXPR:
--- 1242,1248 ----
      case BIT_FIELD_REF:
      case VIEW_CONVERT_EXPR:
      do_unary:
!       get_expr_operands (stmt, &TREE_OPERAND (expr, 0), flags, old_ops);
        return;
  
      case TRUTH_AND_EXPR:
*************** get_expr_operands (tree stmt, tree *expr
*** 1143,1148 ****
--- 1263,1278 ----
  	   when the statement is modified.  */
  	if (tree_swap_operands_p (op0, op1, false))
  	  {
+ 	    use_operand_p use1 = NULL_USE_OPERAND_P;
+ 	    use_operand_p use2 = NULL_USE_OPERAND_P;
+ #if 0
+ 	    if (old_ops && NUM_USES (old_ops->use_ops) == 2)
+ 	      {
+ 	        use1 = USE_OP_PTR (old_ops->use_ops, 0);
+ 	        use2 = USE_OP_PTR (old_ops->use_ops, 1);
+ 	      }
+ #endif
+ 
  	    /* For relationals we need to swap the operands
  	       and change the code.  */
  	    if (code == LT_EXPR
*************** get_expr_operands (tree stmt, tree *expr
*** 1151,1178 ****
  		|| code == GE_EXPR)
  	      {
  		TREE_SET_CODE (expr, swap_tree_comparison (code));
! 		TREE_OPERAND (expr, 0) = op1;
! 		TREE_OPERAND (expr, 1) = op0;
  	      }
  	  
  	    /* For a commutative operator we can just swap the operands.  */
  	    else if (commutative_tree_code (code))
  	      {
! 		TREE_OPERAND (expr, 0) = op1;
! 		TREE_OPERAND (expr, 1) = op0;
  	      }
  	  }
  
! 	get_expr_operands (stmt, &TREE_OPERAND (expr, 0), flags);
! 	get_expr_operands (stmt, &TREE_OPERAND (expr, 1), flags);
  	return;
        }
  
      case REALIGN_LOAD_EXPR:
        {
! 	get_expr_operands (stmt, &TREE_OPERAND (expr, 0), flags);
!         get_expr_operands (stmt, &TREE_OPERAND (expr, 1), flags);
!         get_expr_operands (stmt, &TREE_OPERAND (expr, 2), flags);
          return;
        }
  
--- 1281,1328 ----
  		|| code == GE_EXPR)
  	      {
  		TREE_SET_CODE (expr, swap_tree_comparison (code));
! 		if (use1 != NULL_USE_OPERAND_P)
! 		  {
! 		    SET_USE (use1, op1);
! 		    SET_USE (use2, op0);
! 		    gcc_assert (TREE_OPERAND (expr, 0) == op1);
! 		    gcc_assert (TREE_OPERAND (expr, 1) == op0);
! 		  }
! 		else
! 		  {
! 		    TREE_OPERAND (expr, 0) = op1;
! 		    TREE_OPERAND (expr, 1) = op0;
! 		  }
  	      }
  	  
  	    /* For a commutative operator we can just swap the operands.  */
  	    else if (commutative_tree_code (code))
  	      {
! 		if (use1 != NULL_USE_OPERAND_P)
! 		  {
! 		    SET_USE (use1, op1);
! 		    SET_USE (use2, op0);
! 		    gcc_assert (TREE_OPERAND (expr, 0) == op1);
! 		    gcc_assert (TREE_OPERAND (expr, 1) == op0);
! 		  }
! 		else
! 		  {
! 		    TREE_OPERAND (expr, 0) = op1;
! 		    TREE_OPERAND (expr, 1) = op0;
! 		  }
  	      }
  	  }
  
! 	get_expr_operands (stmt, &TREE_OPERAND (expr, 0), flags, old_ops);
! 	get_expr_operands (stmt, &TREE_OPERAND (expr, 1), flags, old_ops);
  	return;
        }
  
      case REALIGN_LOAD_EXPR:
        {
! 	get_expr_operands (stmt, &TREE_OPERAND (expr, 0), flags, old_ops);
!         get_expr_operands (stmt, &TREE_OPERAND (expr, 1), flags, old_ops);
!         get_expr_operands (stmt, &TREE_OPERAND (expr, 2), flags, old_ops);
          return;
        }
  
*************** get_asm_expr_operands (tree stmt)
*** 1237,1243 ****
  	    note_addressable (t, s_ann);
  	}
  
!       get_expr_operands (stmt, &TREE_VALUE (link), opf_is_def);
      }
  
    for (link = ASM_INPUTS (stmt); link; link = TREE_CHAIN (link))
--- 1387,1393 ----
  	    note_addressable (t, s_ann);
  	}
  
!       get_expr_operands (stmt, &TREE_VALUE (link), opf_is_def, NULL);
      }
  
    for (link = ASM_INPUTS (stmt); link; link = TREE_CHAIN (link))
*************** get_asm_expr_operands (tree stmt)
*** 1256,1262 ****
  	    note_addressable (t, s_ann);
  	}
  
!       get_expr_operands (stmt, &TREE_VALUE (link), 0);
      }
  
  
--- 1406,1412 ----
  	    note_addressable (t, s_ann);
  	}
  
!       get_expr_operands (stmt, &TREE_VALUE (link), 0,  NULL);
      }
  
  
*************** get_indirect_ref_operands (tree stmt, tr
*** 1380,1386 ****
  
        /* Mark the object itself with a VUSE.  */
        pptr = &TREE_OPERAND (*pptr, 0);
!       get_expr_operands (stmt, pptr, flags);
        return;
      }
  
--- 1530,1536 ----
  
        /* Mark the object itself with a VUSE.  */
        pptr = &TREE_OPERAND (*pptr, 0);
!       get_expr_operands (stmt, pptr, flags, NULL);
        return;
      }
  
*************** get_indirect_ref_operands (tree stmt, tr
*** 1389,1395 ****
      gcc_unreachable ();
  
    /* Add a USE operand for the base pointer.  */
!   get_expr_operands (stmt, pptr, opf_none);
  }
  
  /* A subroutine of get_expr_operands to handle CALL_EXPR.  */
--- 1539,1545 ----
      gcc_unreachable ();
  
    /* Add a USE operand for the base pointer.  */
!   get_expr_operands (stmt, pptr, opf_none, NULL);
  }
  
  /* A subroutine of get_expr_operands to handle CALL_EXPR.  */
*************** get_call_expr_operands (tree stmt, tree 
*** 1402,1413 ****
    tree callee = get_callee_fndecl (expr);
  
    /* Find uses in the called function.  */
!   get_expr_operands (stmt, &TREE_OPERAND (expr, 0), opf_none);
  
    for (op = TREE_OPERAND (expr, 1); op; op = TREE_CHAIN (op))
!     get_expr_operands (stmt, &TREE_VALUE (op), opf_none);
  
!   get_expr_operands (stmt, &TREE_OPERAND (expr, 2), opf_none);
  
    if (bitmap_first_set_bit (call_clobbered_vars) >= 0)
      {
--- 1552,1563 ----
    tree callee = get_callee_fndecl (expr);
  
    /* Find uses in the called function.  */
!   get_expr_operands (stmt, &TREE_OPERAND (expr, 0), opf_none, NULL);
  
    for (op = TREE_OPERAND (expr, 1); op; op = TREE_CHAIN (op))
!     get_expr_operands (stmt, &TREE_VALUE (op), opf_none, NULL);
  
!   get_expr_operands (stmt, &TREE_OPERAND (expr, 2), opf_none, NULL);
  
    if (bitmap_first_set_bit (call_clobbered_vars) >= 0)
      {
*************** copy_virtual_operands (tree dst, tree sr
*** 1704,1710 ****
      {
        *vuses_new = allocate_vuse_optype (NUM_VUSES (vuses));
        for (i = 0; i < NUM_VUSES (vuses); i++)
! 	SET_VUSE_OP (*vuses_new, i, VUSE_OP (vuses, i));
      }
  
    if (v_may_defs)
--- 1854,1860 ----
      {
        *vuses_new = allocate_vuse_optype (NUM_VUSES (vuses));
        for (i = 0; i < NUM_VUSES (vuses); i++)
! 	initialize_vuse_operand (*vuses_new, i, VUSE_OP (vuses, i), dst, NULL);
      }
  
    if (v_may_defs)
*************** copy_virtual_operands (tree dst, tree sr
*** 1712,1726 ****
        *v_may_defs_new = allocate_v_may_def_optype (NUM_V_MAY_DEFS (v_may_defs));
        for (i = 0; i < NUM_V_MAY_DEFS (v_may_defs); i++)
  	{
! 	  SET_V_MAY_DEF_OP (*v_may_defs_new, i, V_MAY_DEF_OP (v_may_defs, i));
! 	  SET_V_MAY_DEF_RESULT (*v_may_defs_new, i, 
! 				V_MAY_DEF_RESULT (v_may_defs, i));
  	}
      }
  
    if (v_must_defs)
      {
!       *v_must_defs_new = allocate_v_must_def_optype (NUM_V_MUST_DEFS (v_must_defs));
        for (i = 0; i < NUM_V_MUST_DEFS (v_must_defs); i++)
  	SET_V_MUST_DEF_OP (*v_must_defs_new, i, V_MUST_DEF_OP (v_must_defs, i));
      }
--- 1862,1878 ----
        *v_may_defs_new = allocate_v_may_def_optype (NUM_V_MAY_DEFS (v_may_defs));
        for (i = 0; i < NUM_V_MAY_DEFS (v_may_defs); i++)
  	{
! 	  initialize_v_may_def_operand (*v_may_defs_new, i, 
! 					V_MAY_DEF_RESULT (v_may_defs, i),
! 					V_MAY_DEF_OP (v_may_defs, i), dst,
! 					NULL);
  	}
      }
  
    if (v_must_defs)
      {
!       *v_must_defs_new 
! 	 = allocate_v_must_def_optype (NUM_V_MUST_DEFS (v_must_defs));
        for (i = 0; i < NUM_V_MUST_DEFS (v_must_defs); i++)
  	SET_V_MUST_DEF_OP (*v_must_defs_new, i, V_MUST_DEF_OP (v_must_defs, i));
      }
*************** create_ssa_artficial_load_stmt (stmt_ope
*** 1768,1774 ****
      }
  
    /* Now set the vuses for this new stmt.  */
!   ann->operands.vuse_ops = finalize_ssa_vuses (&(tmp.vuse_ops));
  }
  
  #include "gt-tree-ssa-operands.h"
--- 1920,2137 ----
      }
  
    /* Now set the vuses for this new stmt.  */
!   ann->operands.vuse_ops = finalize_ssa_vuses (&(tmp.vuse_ops), NULL);
! }
! 
! 
! #ifdef ENABLE_CHECKING
! static void
! test_imm_print (FILE *file, use_operand_p var, tree stmt)
! {
!   if (TREE_CODE (USE_FROM_PTR (var)) == SSA_NAME)
!     {
!       if (stmt_modified_p (stmt) && TREE_CODE (stmt) != PHI_NODE)
!         {
! 	  fprintf (file, " STMT MODIFIED. - <0x%x> ", (unsigned int)stmt);
! 	  print_generic_stmt (file, stmt, TDF_SLIM);
! 	}
!       if (var->prev == NULL)
! 	{
! 	  fprintf (file, " IMM ERROR : (use_p : tree: 0x%X:0x%x)", (unsigned int)var, (unsigned int)var->use);
! 	  print_generic_expr (file, USE_FROM_PTR (var), TDF_SLIM);
! 	  fprintf (file, " is not in a list\n");
! 	  fprintf (file, "<0x%x> ", (unsigned int)stmt);
! 	  print_generic_stmt (file, stmt, TDF_VOPS);
! 	}
!     }
! 
! }
! #endif
! 
! void
! test_imm_links(FILE *file ATTRIBUTE_UNUSED)
! {
! #ifdef  ENABLE_CHECKING
!   unsigned int x;
!   basic_block bb;
!   use_operand_p var;
! 
!   if (file == NULL)
!     file = stderr;
! 
!   for (x = 1; x < num_ssa_names; x++)
!     if (ssa_name(x))
!       verify_imm_links (&(SSA_NAME_IMM_USE_NODE (ssa_name(x))));
! 
!   FOR_EACH_BB (bb)
!     {
!       block_stmt_iterator i;
!       tree phi;
!       int x;
!       for (phi = phi_nodes (bb); phi; phi = TREE_CHAIN (phi))
!         {
! 	  for (x = 0; x < PHI_NUM_ARGS (phi); x++)
! 	    {
! 	      var = &(PHI_ARG_IMM_USE_NODE(phi, x));
! 	      test_imm_print (file, var, phi);
! 	    }
! 	}
! 
!       for (i = bsi_start (bb); !bsi_end_p (i); bsi_next (&i))
!         {
! 	  tree stmt = bsi_stmt (i);
! 	  ssa_op_iter iter;
! 	  get_stmt_operands (stmt);
! 	  FOR_EACH_SSA_USE_OPERAND (var, stmt, iter, SSA_OP_ALL_USES)
! 	    {
! 	      test_imm_print (file, var, stmt);
! 	    }
! 	    
! 	}
!     }
! 
! #endif
! }
! 
! #ifdef ENABLE_CHECKING
! static void 
! verify_abort(ssa_imm_use_t *var)
! {
!   tree stmt;
!   if ((stmt = var->stmt))
!     {
!       if (stmt_modified_p(stmt))
! 	{
! 	  fprintf (stderr, " STMT MODIFIED. - <0x%x> ", (unsigned int)stmt);
! 	  print_generic_stmt (stderr, stmt, TDF_SLIM);
! 	}
!     }
!   fprintf (stderr, " IMM ERROR : (use_p : tree: 0x%X:0x%x)", (unsigned int)var, (unsigned int)var->use);
!   print_generic_expr (stderr, USE_FROM_PTR (var), TDF_SLIM);
!   abort ();
! }
! #endif
! 
! void
! verify_imm_links (ssa_imm_use_t *list ATTRIBUTE_UNUSED)
! {
! #ifdef ENABLE_CHECKING
!   ssa_imm_use_t *ptr, *prev, *root = NULL;
!   int count;
! 
!   if (list->prev == NULL)
!     return;
! 
!   prev = list;
!   if (list->use == NULL)
!     root = list;
!   count = 0;
!   for (ptr = list->next; ptr != list; )
!     {
!       if (prev != ptr->prev)
! 	verify_abort (ptr);
! 
!       if (ptr->use == NULL)
!         {
! 	  if (root)
! 	    verify_abort(ptr);  	/* 2 roots.  */
! 	  else
! 	    {
! 	      root = ptr;
! 	      if (*(prev->use) != root->stmt)
! 		verify_abort(ptr);
! 	    }
! 	}
!       else
! 	if (root)
! 	  {
! 	    if (*(ptr->use) != root->stmt)
! 	      verify_abort (ptr);
! 	  }
! 	else
! 	  if (*(prev->use) != *(ptr->use))
! 	    verify_abort(ptr);
!       prev = ptr;
!       ptr = ptr->next;
!       if (count++ > 30000)
!         verify_abort (ptr);
!     }
! 
!   prev = list;
!   count = 0;
!   for (ptr = list->prev; ptr != list; )
!     {
!       if (prev != ptr->next)
!         verify_abort (ptr);
!       prev = ptr;
!       ptr = ptr->prev;
!       if (count++ > 30000)
!         verify_abort (ptr);
!     }
! #endif
! }
! 
! 
! /* Dump all the immediate uses to FILE.  */
! 
! void
! dump_immediate_uses_for (FILE *file, tree var)
! {
!   imm_use_iterator iter;
!   use_operand_p use_p;
! 
!   gcc_assert (var && TREE_CODE (var) == SSA_NAME);
! 
!   print_generic_expr (file, var, TDF_SLIM);
!   fprintf (file, " : -->");
!   if (has_zero_uses (var))
!     fprintf (file, " no uses.\n");
!   else
!     if (has_single_use (var))
!       fprintf (file, " single use.\n");
!     else
!       fprintf (file, "%d uses.\n", num_imm_uses (var));
! 
!   FOR_EACH_IMM_USE_FAST (use_p, iter, var)
!     {
!       print_generic_stmt (file, USE_STMT (use_p), TDF_SLIM);
!     }
!   fprintf(file, "\n");
! }
! 
! /* Dump all the immediate uses to FILE.  */
! 
! void
! dump_immediate_uses (FILE *file)
! {
!   tree var;
!   unsigned int x;
! 
!   fprintf (file, "Immediate_uses: \n\n");
!   for (x = 1; x < num_ssa_names; x++)
!     {
!       var = ssa_name(x);
!       if (!var)
!         continue;
!       dump_immediate_uses_for (file, var);
!     }
! }
! 
! 
! /* Dump def-use edges on stderr.  */
! 
! void
! debug_immediate_uses (void)
! {
!   dump_immediate_uses (stderr);
! }
! 
! /* Dump def-use edges on stderr.  */
! 
! void
! debug_immediate_uses_for (tree var)
! {
!   dump_immediate_uses_for (stderr, var);
  }
  
  #include "gt-tree-ssa-operands.h"
Index: tree-ssa-operands.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-operands.h,v
retrieving revision 2.7
diff -c -p -r2.7 tree-ssa-operands.h
*** tree-ssa-operands.h	5 Sep 2004 15:24:15 -0000	2.7
--- tree-ssa-operands.h	14 Oct 2004 19:24:41 -0000
*************** typedef struct def_operand_ptr GTY(())
*** 31,43 ****
  } def_operand_p;
  
  /* This represents a pointer to a USE operand.  */
! typedef struct use_operand_ptr GTY(())
! {
!   tree * GTY((skip(""))) use;
! } use_operand_p;
  
  extern def_operand_p NULL_DEF_OPERAND_P;
- extern use_operand_p NULL_USE_OPERAND_P;
  
  /* This represents the DEF operands of a stmt.  */
  typedef struct def_optype_d GTY(())
--- 31,40 ----
  } def_operand_p;
  
  /* This represents a pointer to a USE operand.  */
! typedef ssa_imm_use_t *use_operand_p;
  
+ #define NULL_USE_OPERAND_P 		NULL
  extern def_operand_p NULL_DEF_OPERAND_P;
  
  /* This represents the DEF operands of a stmt.  */
  typedef struct def_optype_d GTY(())
*************** typedef struct def_optype_d GTY(())
*** 48,67 ****
  
  typedef def_optype_t *def_optype;
  
  /* This represents the USE operands of a stmt.  */
  typedef struct use_optype_d GTY(())
  {
    unsigned num_uses; 
!   struct use_operand_ptr GTY((length("%h.num_uses"))) uses[1];
  } use_optype_t;
  
  typedef use_optype_t *use_optype;
  
! /* Operand type which stores a def and a use tree.  */
  typedef struct v_may_def_operand_type GTY(())
  {
    tree def;
    tree use;
  } v_may_def_operand_type_t;
  
  /* This represents the MAY_DEFS for a stmt.  */
--- 45,68 ----
  
  typedef def_optype_t *def_optype;
  
+ /* Operand type which uses a pointer to a tree ihn an immediate use.  */
+ typedef ssa_imm_use_t use_operand_type_t;
+ 
  /* This represents the USE operands of a stmt.  */
  typedef struct use_optype_d GTY(())
  {
    unsigned num_uses; 
!   struct ssa_imm_use_d GTY((length("%h.num_uses"))) uses[1];
  } use_optype_t;
  
  typedef use_optype_t *use_optype;
  
! /* Operand type which stores a def, a use, and an immediate use.  */
  typedef struct v_may_def_operand_type GTY(())
  {
    tree def;
    tree use;
+   ssa_imm_use_t imm_use;
  } v_may_def_operand_type_t;
  
  /* This represents the MAY_DEFS for a stmt.  */
*************** typedef struct v_may_def_optype_d GTY(()
*** 74,84 ****
  
  typedef v_may_def_optype_t *v_may_def_optype;
  
  /* This represents the VUSEs for a stmt.  */
  typedef struct vuse_optype_d GTY(()) 
  {
    unsigned num_vuses; 
!   tree GTY((length ("%h.num_vuses"))) vuses[1];
  } vuse_optype_t;
  
  typedef vuse_optype_t *vuse_optype;
--- 75,92 ----
  
  typedef v_may_def_optype_t *v_may_def_optype;
  
+ /* Operand type which stores a tree and an immeidate_use.  */
+ typedef struct vuse_operand_type GTY(())
+ {
+   tree use;
+   ssa_imm_use_t imm_use;
+ } vuse_operand_type_t;
+ 
  /* This represents the VUSEs for a stmt.  */
  typedef struct vuse_optype_d GTY(()) 
  {
    unsigned num_vuses; 
!   struct vuse_operand_type GTY((length ("%h.num_vuses"))) vuses[1];
  } vuse_optype_t;
  
  typedef vuse_optype_t *vuse_optype;
*************** typedef stmt_operands_t *stmt_operands_p
*** 109,117 ****
  
  #define USE_FROM_PTR(OP)	get_use_from_ptr (OP)
  #define DEF_FROM_PTR(OP)	get_def_from_ptr (OP)
! #define SET_USE(OP, V)		((*((OP).use)) = (V))
  #define SET_DEF(OP, V)		((*((OP).def)) = (V))
  
  
  #define USE_OPS(ANN)		get_use_ops (ANN)
  #define STMT_USE_OPS(STMT)	get_use_ops (stmt_ann (STMT))
--- 117,126 ----
  
  #define USE_FROM_PTR(OP)	get_use_from_ptr (OP)
  #define DEF_FROM_PTR(OP)	get_def_from_ptr (OP)
! #define SET_USE(OP, V)		set_ssa_use_from_ptr (OP, V)
  #define SET_DEF(OP, V)		((*((OP).def)) = (V))
  
+ #define USE_STMT(OP)		(OP)->stmt
  
  #define USE_OPS(ANN)		get_use_ops (ANN)
  #define STMT_USE_OPS(STMT)	get_use_ops (stmt_ann (STMT))
*************** typedef stmt_operands_t *stmt_operands_p
*** 179,191 ****
--- 188,208 ----
  				PHI_ARG_DEF_PTR ((PHI), 		\
  					     phi_arg_from_edge ((PHI),(E)))
  
+ #define PHI_ARG_INDEX_FROM_USE(USE)	phi_arg_index_from_use (USE)
  
  extern void init_ssa_operands (void);
  extern void fini_ssa_operands (void);
  extern void get_stmt_operands (tree);
+ extern void test_imm_links(FILE *);
+ extern void verify_imm_links (ssa_imm_use_t *list);
+ 
  extern void copy_virtual_operands (tree, tree);
  extern void create_ssa_artficial_load_stmt (stmt_operands_p, tree);
  
+ extern void dump_immediate_uses (FILE *file);
+ extern void dump_immediate_uses_for (FILE *file, tree var);
+ extern void debug_immediate_uses (void);
+ extern void debug_immediate_uses_for (tree var);
  
  /* This structure is used in the operand iterator loops.  It contains the 
     items required to determine which operand is retrieved next.  During
Index: tree-ssa-pre.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-pre.c,v
retrieving revision 2.46.6.1
diff -c -p -r2.46.6.1 tree-ssa-pre.c
*** tree-ssa-pre.c	8 Oct 2004 20:20:20 -0000	2.46.6.1
--- tree-ssa-pre.c	14 Oct 2004 19:24:41 -0000
*************** eliminate (void)
*** 1882,1888 ****
  		    }
  		  pre_stats.eliminations++;
  		  propagate_tree_value (rhs_p, sprime);
! 		  modify_stmt (stmt);
  
  		  /* If we removed EH side effects from the statement, clean
  		     its EH information.  */
--- 1882,1888 ----
  		    }
  		  pre_stats.eliminations++;
  		  propagate_tree_value (rhs_p, sprime);
! 		  update_stmt (stmt);
  
  		  /* If we removed EH side effects from the statement, clean
  		     its EH information.  */
Index: tree-ssa-propagate.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-propagate.c,v
retrieving revision 2.8
diff -c -p -r2.8 tree-ssa-propagate.c
*** tree-ssa-propagate.c	28 Sep 2004 20:31:16 -0000	2.8
--- tree-ssa-propagate.c	14 Oct 2004 19:24:41 -0000
*************** cfg_blocks_get (void)
*** 234,247 ****
  static void
  add_ssa_edge (tree var, bool is_varying)
  {
!   tree stmt = SSA_NAME_DEF_STMT (var);
!   dataflow_t df = get_immediate_uses (stmt);
!   int num_uses = num_immediate_uses (df);
!   int i;
  
!   for (i = 0; i < num_uses; i++)
      {
!       tree use_stmt = immediate_use (df, i);
  
        if (!DONT_SIMULATE_AGAIN (use_stmt)
  	  && !STMT_IN_SSA_EDGE_WORKLIST (use_stmt))
--- 234,245 ----
  static void
  add_ssa_edge (tree var, bool is_varying)
  {
!   imm_use_iterator iter;
!   use_operand_p use_p;
  
!   FOR_EACH_IMM_USE_FAST (use_p, iter, var)
      {
!       tree use_stmt = USE_STMT (use_p);
  
        if (!DONT_SIMULATE_AGAIN (use_stmt)
  	  && !STMT_IN_SSA_EDGE_WORKLIST (use_stmt))
*************** ssa_prop_fini (void)
*** 514,520 ****
    cfg_blocks = NULL;
    sbitmap_free (bb_in_list);
    sbitmap_free (executable_blocks);
-   free_df ();
  }
  
  
--- 512,517 ----
Index: tree-ssa.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa.c,v
retrieving revision 2.45
diff -c -p -r2.45 tree-ssa.c
*** tree-ssa.c	5 Oct 2004 13:57:06 -0000	2.45
--- tree-ssa.c	14 Oct 2004 19:24:41 -0000
*************** verify_alias_info (void)
*** 514,520 ****
     TODO: verify the variable annotations.  */
  
  void
! verify_ssa (void)
  {
    size_t i;
    basic_block bb;
--- 514,520 ----
     TODO: verify the variable annotations.  */
  
  void
! verify_ssa (bool check_modified)
  {
    size_t i;
    basic_block bb;
*************** verify_ssa (void)
*** 563,569 ****
  	  tree stmt;
  
  	  stmt = bsi_stmt (bsi);
! 	  get_stmt_operands (stmt);
  
  	  if (stmt_ann (stmt)->makes_aliased_stores 
  	      && NUM_V_MAY_DEFS (STMT_V_MAY_DEF_OPS (stmt)) == 0)
--- 563,574 ----
  	  tree stmt;
  
  	  stmt = bsi_stmt (bsi);
! 	  if (check_modified && stmt_modified_p (stmt))
! 	    {
! 	      error ("Stmt (0x%x) is marked modified at end of optimization pass: ", (unsigned long)stmt);
! 	      print_generic_stmt (stderr, stmt, TDF_VOPS);
! 	      goto err;
! 	    }
  
  	  if (stmt_ann (stmt)->makes_aliased_stores 
  	      && NUM_V_MAY_DEFS (STMT_V_MAY_DEF_OPS (stmt)) == 0)
*************** walk_use_def_chains (tree var, walk_use_
*** 936,943 ****
  /* Replaces VAR with REPL in memory reference expression *X in
     statement STMT.  */
  
! static void
! propagate_into_addr (tree stmt, tree var, tree *x, tree repl)
  {
    tree new_var, ass_stmt, addr_var;
    basic_block bb;
--- 941,948 ----
  /* Replaces VAR with REPL in memory reference expression *X in
     statement STMT.  */
  
! static bool
! propagate_into_addr (tree stmt, use_operand_p use_p, tree *x, tree repl)
  {
    tree new_var, ass_stmt, addr_var;
    basic_block bb;
*************** propagate_into_addr (tree stmt, tree var
*** 945,951 ****
  
    /* There is nothing special to handle in the other cases.  */
    if (TREE_CODE (repl) != ADDR_EXPR)
!     return;
    addr_var = TREE_OPERAND (repl, 0);
  
    while (handled_component_p (*x)
--- 950,956 ----
  
    /* There is nothing special to handle in the other cases.  */
    if (TREE_CODE (repl) != ADDR_EXPR)
!     return false;
    addr_var = TREE_OPERAND (repl, 0);
  
    while (handled_component_p (*x)
*************** propagate_into_addr (tree stmt, tree var
*** 953,974 ****
  	 || TREE_CODE (*x) == IMAGPART_EXPR)
      x = &TREE_OPERAND (*x, 0);
  
    if (TREE_CODE (*x) != INDIRECT_REF
!       || TREE_OPERAND (*x, 0) != var)
!     return;
  
    if (TREE_TYPE (*x) == TREE_TYPE (addr_var))
      {
        *x = addr_var;
        mark_new_vars_to_rename (stmt, vars_to_rename);
!       return;
      }
  
  
    /* Frontends sometimes produce expressions like *&a instead of a[0].
       Create a temporary variable to handle this case.  */
    ass_stmt = build2 (MODIFY_EXPR, void_type_node, NULL_TREE, repl);
!   new_var = duplicate_ssa_name (var, ass_stmt);
    TREE_OPERAND (*x, 0) = new_var;
    TREE_OPERAND (ass_stmt, 0) = new_var;
  
--- 958,981 ----
  	 || TREE_CODE (*x) == IMAGPART_EXPR)
      x = &TREE_OPERAND (*x, 0);
  
+   /* Heres a hack but since KRPhinodes is going away soon, Im not going to 
+      sweat it.  */
    if (TREE_CODE (*x) != INDIRECT_REF
!       || &(TREE_OPERAND (*x, 0)) != use_p->use)  /* HACK ALERT. */
!     return false;
  
    if (TREE_TYPE (*x) == TREE_TYPE (addr_var))
      {
        *x = addr_var;
        mark_new_vars_to_rename (stmt, vars_to_rename);
!       return true;
      }
  
  
    /* Frontends sometimes produce expressions like *&a instead of a[0].
       Create a temporary variable to handle this case.  */
    ass_stmt = build2 (MODIFY_EXPR, void_type_node, NULL_TREE, repl);
!   new_var = duplicate_ssa_name (USE_FROM_PTR (use_p), ass_stmt);
    TREE_OPERAND (*x, 0) = new_var;
    TREE_OPERAND (ass_stmt, 0) = new_var;
  
*************** propagate_into_addr (tree stmt, tree var
*** 978,983 ****
--- 985,991 ----
    bsi_insert_after (&bsi, ass_stmt, BSI_NEW_STMT);
  
    mark_new_vars_to_rename (stmt, vars_to_rename);
+   return true;
  }
  
  /* Replaces immediate uses of VAR by REPL.  */
*************** propagate_into_addr (tree stmt, tree var
*** 985,1041 ****
  static void
  replace_immediate_uses (tree var, tree repl)
  {
-   int i, j, n;
-   dataflow_t df;
    tree stmt;
    bool mark_new_vars;
!   ssa_op_iter iter;
!   use_operand_p use_p;
! 
!   df = get_immediate_uses (SSA_NAME_DEF_STMT (var));
!   n = num_immediate_uses (df);
  
!   for (i = 0; i < n; i++)
      {
!       stmt = immediate_use (df, i);
  
        if (TREE_CODE (stmt) == PHI_NODE)
  	{
! 	  for (j = 0; j < PHI_NUM_ARGS (stmt); j++)
! 	    if (PHI_ARG_DEF (stmt, j) == var)
! 	      {
! 		SET_PHI_ARG_DEF (stmt, j, repl);
! 		if (TREE_CODE (repl) == SSA_NAME
! 		    && PHI_ARG_EDGE (stmt, j)->flags & EDGE_ABNORMAL)
! 		  SSA_NAME_OCCURS_IN_ABNORMAL_PHI (repl) = 1;
! 	      }
  
  	  continue;
  	}
  
!       get_stmt_operands (stmt);
        mark_new_vars = false;
        if (is_gimple_reg (SSA_NAME_VAR (var)))
  	{
  	  if (TREE_CODE (stmt) == MODIFY_EXPR)
  	    {
! 	      propagate_into_addr (stmt, var, &TREE_OPERAND (stmt, 0), repl);
! 	      propagate_into_addr (stmt, var, &TREE_OPERAND (stmt, 1), repl);
  	    }
  
! 	  FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_USE)
! 	    if (USE_FROM_PTR (use_p) == var)
! 	      {
! 		propagate_value (use_p, repl);
! 		mark_new_vars = POINTER_TYPE_P (TREE_TYPE (repl));
! 	      }
  	}
        else
! 	{
! 	  FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_VIRTUAL_USES)
! 	    if (USE_FROM_PTR (use_p) == var)
! 	      propagate_value (use_p, repl);
! 	}
  
        /* FIXME.  If REPL is a constant, we need to fold STMT.
  	 However, fold_stmt wants a pointer to the statement, because
--- 993,1047 ----
  static void
  replace_immediate_uses (tree var, tree repl)
  {
    tree stmt;
    bool mark_new_vars;
!   use_operand_p imm_use;
!   imm_use_iterator imm_iter;
  
!   FOR_EACH_IMM_USE_SAFE (imm_use, imm_iter, var)
      {
!       stmt = USE_STMT (imm_use);
  
        if (TREE_CODE (stmt) == PHI_NODE)
  	{
! 	  int index = PHI_ARG_INDEX_FROM_USE (imm_use);
! #ifdef ENABLE_CHECKING
! 	  gcc_assert (&(PHI_ARG_IMM_USE_NODE (stmt, index)) == imm_use);
! #endif
!           SET_USE (imm_use, repl);
! 	  if (TREE_CODE (repl) == SSA_NAME
! 	      && PHI_ARG_EDGE (stmt, index)->flags & EDGE_ABNORMAL)
! 	    SSA_NAME_OCCURS_IN_ABNORMAL_PHI (repl) = 1;
  
  	  continue;
  	}
  
!       gcc_assert (!stmt_modified_p (stmt));
! 
        mark_new_vars = false;
        if (is_gimple_reg (SSA_NAME_VAR (var)))
  	{
+ 	  bool propagated = false;
  	  if (TREE_CODE (stmt) == MODIFY_EXPR)
  	    {
! 	      if (TREE_CODE (repl) == ADDR_EXPR)
! 	        {
! 		  propagated =
! 		    propagate_into_addr (stmt, imm_use, &TREE_OPERAND (stmt, 0),
! 					 repl);
! 		  if (!propagated)
! 		    propagated = 
! 		      propagate_into_addr (stmt, imm_use, 
! 					   &TREE_OPERAND (stmt, 1), repl);
! 		}
  	    }
  
! 	  if (!propagated)
! 	    propagate_value (imm_use, repl);
! 	  mark_new_vars = POINTER_TYPE_P (TREE_TYPE (repl));
  	}
        else
! 	propagate_value (imm_use, repl);
  
        /* FIXME.  If REPL is a constant, we need to fold STMT.
  	 However, fold_stmt wants a pointer to the statement, because
*************** replace_immediate_uses (tree var, tree r
*** 1064,1070 ****
        if (mark_new_vars)
  	mark_new_vars_to_rename (stmt, vars_to_rename);
        else
! 	modify_stmt (stmt);
      }
  }
  
--- 1070,1076 ----
        if (mark_new_vars)
  	mark_new_vars_to_rename (stmt, vars_to_rename);
        else
! 	update_stmt (stmt);
      }
  }
  
*************** static void
*** 1105,1112 ****
  check_phi_redundancy (tree phi, tree *eq_to)
  {
    tree val = NULL_TREE, def, res = PHI_RESULT (phi), stmt;
!   unsigned i, ver = SSA_NAME_VERSION (res), n;
!   dataflow_t df;
  
    /* It is unlikely that such large phi node would be redundant.  */
    if (PHI_NUM_ARGS (phi) > 16)
--- 1111,1119 ----
  check_phi_redundancy (tree phi, tree *eq_to)
  {
    tree val = NULL_TREE, def, res = PHI_RESULT (phi), stmt;
!   unsigned i, ver = SSA_NAME_VERSION (res);
!   imm_use_iterator imm_iter;
!   use_operand_p use_p;
  
    /* It is unlikely that such large phi node would be redundant.  */
    if (PHI_NUM_ARGS (phi) > 16)
*************** check_phi_redundancy (tree phi, tree *eq
*** 1142,1154 ****
  
    eq_to[ver] = val;
  
!   df = get_immediate_uses (SSA_NAME_DEF_STMT (res));
!   n = num_immediate_uses (df);
! 
!   for (i = 0; i < n; i++)
      {
!       stmt = immediate_use (df, i);
! 
        if (TREE_CODE (stmt) == PHI_NODE)
  	check_phi_redundancy (stmt, eq_to);
      }
--- 1149,1157 ----
  
    eq_to[ver] = val;
  
!   FOR_EACH_IMM_USE_FAST (use_p, imm_iter, res)
      {
!       stmt = USE_STMT (use_p);
        if (TREE_CODE (stmt) == PHI_NODE)
  	check_phi_redundancy (stmt, eq_to);
      }
*************** kill_redundant_phi_nodes (void)
*** 1188,1199 ****
       it safe).  */
    eq_to = xcalloc (num_ssa_names, sizeof (tree));
  
-   /* We have had cases where computing immediate uses takes a
-      significant amount of compile time.  If we run into such
-      problems here, we may want to only compute immediate uses for
-      a subset of all the SSA_NAMEs instead of computing it for
-      all of the SSA_NAMEs.  */
-   compute_immediate_uses (TDFA_USE_OPS | TDFA_USE_VOPS, NULL);
    old_num_ssa_names = num_ssa_names;
  
    FOR_EACH_BB (bb)
--- 1191,1196 ----
*************** kill_redundant_phi_nodes (void)
*** 1230,1236 ****
  	}
      }
  
-   free_df ();
    free (eq_to);
  }
  
--- 1227,1232 ----
Index: tree-ssanames.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssanames.c,v
retrieving revision 2.15
diff -c -p -r2.15 tree-ssanames.c
*** tree-ssanames.c	21 Sep 2004 03:19:00 -0000	2.15
--- tree-ssanames.c	14 Oct 2004 19:24:42 -0000
*************** tree
*** 180,185 ****
--- 180,186 ----
  make_ssa_name (tree var, tree stmt)
  {
    tree t;
+   ssa_imm_use_t *imm;
  
    gcc_assert (DECL_P (var)
  	      || TREE_CODE (var) == INDIRECT_REF);
*************** make_ssa_name (tree var, tree stmt)
*** 215,220 ****
--- 216,226 ----
    SSA_NAME_DEF_STMT (t) = stmt;
    SSA_NAME_PTR_INFO (t) = NULL;
    SSA_NAME_IN_FREE_LIST (t) = 0;
+   imm = &(SSA_NAME_IMM_USE_NODE (t));
+   imm->use = NULL;
+   imm->prev = imm;
+   imm->next = imm;
+   imm->stmt = t;
  
    return t;
  }
*************** release_ssa_name (tree var)
*** 256,265 ****
--- 262,291 ----
      {
        tree saved_ssa_name_var = SSA_NAME_VAR (var);
        int saved_ssa_name_version = SSA_NAME_VERSION (var);
+       ssa_imm_use_t *imm = &(SSA_NAME_IMM_USE_NODE (var));
+ 
+ #ifdef ENABLE_CHECKING
+       verify_imm_links (imm);
+ #endif
+       while (imm->next != imm)
+         {
+ #ifdef ENABLE_CHECKING
+ 	  if (*(imm->next->use) != var)
+ 	    abort ();
+ #endif
+ 	  delink_imm_use (imm->next);
+ 	}
+ #ifdef ENABLE_CHECKING
+       if (imm->next != imm)
+         abort();
+ #endif
  
        VARRAY_TREE (ssa_names, SSA_NAME_VERSION (var)) = NULL;
        memset (var, 0, tree_size (var));
  
+       imm->prev = imm;
+       imm->next = imm;
+       imm->stmt = var;
        /* First put back the right tree node so that the tree checking
  	 macros do not complain.  */
        TREE_SET_CODE (var, SSA_NAME);
Index: tree-tailcall.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-tailcall.c,v
retrieving revision 2.30.6.1
diff -c -p -r2.30.6.1 tree-tailcall.c
*** tree-tailcall.c	8 Oct 2004 20:20:20 -0000	2.30.6.1
--- tree-tailcall.c	14 Oct 2004 19:24:42 -0000
*************** adjust_return_value (basic_block bb, tre
*** 657,663 ****
      }
  
    TREE_OPERAND (ret_stmt, 0) = var;
!   modify_stmt (ret_stmt);
  }
  
  /* Eliminates tail call described by T.  TMP_VARS is a list of
--- 657,663 ----
      }
  
    TREE_OPERAND (ret_stmt, 0) = var;
!   update_stmt (ret_stmt);
  }
  
  /* Eliminates tail call described by T.  TMP_VARS is a list of
Index: tree-vectorizer.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-vectorizer.c,v
retrieving revision 2.14
diff -c -p -r2.14 tree-vectorizer.c
*** tree-vectorizer.c	1 Oct 2004 09:59:00 -0000	2.14
--- tree-vectorizer.c	14 Oct 2004 19:24:42 -0000
*************** vect_stmt_relevant_p (tree stmt, loop_ve
*** 3652,3660 ****
    v_may_def_optype v_may_defs;
    v_must_def_optype v_must_defs;
    struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
!   int i;
!   dataflow_t df;
!   int num_uses;
  
    /* cond stmt other than loop exit cond.  */
    if (is_ctrl_stmt (stmt) && (stmt != LOOP_VINFO_EXIT_COND (loop_vinfo)))
--- 3652,3661 ----
    v_may_def_optype v_may_defs;
    v_must_def_optype v_must_defs;
    struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
!   ssa_op_iter op_iter;
!   imm_use_iterator imm_iter;
!   use_operand_p use_p;
!   tree var;
  
    /* cond stmt other than loop exit cond.  */
    if (is_ctrl_stmt (stmt) && (stmt != LOOP_VINFO_EXIT_COND (loop_vinfo)))
*************** vect_stmt_relevant_p (tree stmt, loop_ve
*** 3671,3687 ****
      }
  
    /* uses outside the loop.  */
!   df = get_immediate_uses (stmt);
!   num_uses = num_immediate_uses (df);
!   for (i = 0; i < num_uses; i++)
!     {
!       tree use = immediate_use (df, i);
!       basic_block bb = bb_for_stmt (use);
!       if (!flow_bb_inside_loop_p (loop, bb))
  	{
! 	  if (vect_debug_details (NULL))
! 	    fprintf (dump_file, "vec_stmt_relevant_p: used out of loop.");
! 	  return true;
  	}
      }
  
--- 3672,3688 ----
      }
  
    /* uses outside the loop.  */
!   FOR_EACH_SSA_TREE_OPERAND (var, stmt, op_iter, SSA_OP_DEF)
!     {
!       FOR_EACH_IMM_USE_FAST (use_p, imm_iter, var)
  	{
! 	  basic_block bb = bb_for_stmt (USE_STMT (use_p));
! 	  if (!flow_bb_inside_loop_p (loop, bb))
! 	    {
! 	      if (vect_debug_details (NULL))
! 		fprintf (dump_file, "vec_stmt_relevant_p: used out of loop.");
! 	      return true;
! 	    }
  	}
      }
  
*************** vect_analyze_loop (struct loop *loop)
*** 4073,4091 ****
  }
  
  
- /* Function need_imm_uses_for.
- 
-    Return whether we ought to include information for 'var'
-    when calculating immediate uses.  For this pass we only want use
-    information for non-virtual variables.  */
- 
- static bool
- need_imm_uses_for (tree var)
- {
-   return is_gimple_reg (var);
- }
- 
- 
  /* Function vectorize_loops.
     
     Entry Point to loop vectorization phase.  */
--- 4074,4079 ----
*************** vectorize_loops (struct loops *loops)
*** 4105,4112 ****
        return;
      }
  
-   compute_immediate_uses (TDFA_USE_OPS, need_imm_uses_for);
- 
    /*  ----------- Analyze loops. -----------  */
  
    /* If some loop was duplicated, it gets bigger number 
--- 4093,4098 ----
*************** vectorize_loops (struct loops *loops)
*** 4137,4143 ****
  
    /*  ----------- Finalize. -----------  */
  
-   free_df ();
    for (i = 1; i < loops_num; i++)
      {
        struct loop *loop = loops->parray[i];
--- 4123,4128 ----
Index: tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.h,v
retrieving revision 1.635
diff -c -p -r1.635 tree.h
*** tree.h	1 Oct 2004 07:42:49 -0000	1.635
--- tree.h	14 Oct 2004 19:24:43 -0000
*************** struct tree_exp GTY(())
*** 1334,1339 ****
--- 1334,1354 ----
  struct ptr_info_def;
  #endif
  
+ 
+ 
+ /* Immediate use linking structure. THis structure is used for maintaining
+    a doubly linked list of uses of an SSA_NAME.  */
+ typedef struct ssa_imm_use_d GTY(())
+ {
+   struct ssa_imm_use_d* GTY((skip(""))) prev;
+   struct ssa_imm_use_d* GTY((skip(""))) next;
+   tree GTY((skip(""))) stmt;
+   tree *GTY((skip(""))) use;
+ } ssa_imm_use_t;
+ 
+ /* Return the immediate_use information for an SSA_NAME. */
+ #define SSA_NAME_IMM_USE_NODE(NODE) SSA_NAME_CHECK (NODE)->ssa_name.imm_uses
+ 
  struct tree_ssa_name GTY(())
  {
    struct tree_common common;
*************** struct tree_ssa_name GTY(())
*** 1358,1363 ****
--- 1373,1381 ----
  
    /* Auxiliary information stored with the ssa name.  */
    PTR GTY((skip)) aux;
+ 
+   /* Immediate uses list for this SSA_NAME.  */
+   struct ssa_imm_use_d imm_uses;
  };
  \f
  /* In a PHI_NODE node.  */
*************** struct tree_ssa_name GTY(())
*** 1378,1389 ****
  #define PHI_ARG_EDGE(NODE, I)		PHI_NODE_ELT_CHECK (NODE, I).e
  #define PHI_ARG_NONZERO(NODE, I) 	PHI_NODE_ELT_CHECK (NODE, I).nonzero
  #define PHI_BB(NODE)			PHI_NODE_CHECK (NODE)->phi.bb
! #define PHI_DF(NODE)			PHI_NODE_CHECK (NODE)->phi.df
  
  struct edge_def;
  
  struct phi_arg_d GTY(())
  {
    tree def;
    struct edge_def * GTY((skip (""))) e;
    bool nonzero;
--- 1396,1408 ----
  #define PHI_ARG_EDGE(NODE, I)		PHI_NODE_ELT_CHECK (NODE, I).e
  #define PHI_ARG_NONZERO(NODE, I) 	PHI_NODE_ELT_CHECK (NODE, I).nonzero
  #define PHI_BB(NODE)			PHI_NODE_CHECK (NODE)->phi.bb
! #define PHI_ARG_IMM_USE_NODE(NODE, I)	PHI_NODE_ELT_CHECK (NODE, I).imm_use
  
  struct edge_def;
  
  struct phi_arg_d GTY(())
  {
+   struct ssa_imm_use_d imm_use;	/* imm_use MUST be first element in struct.  */
    tree def;
    struct edge_def * GTY((skip (""))) e;
    bool nonzero;
*************** struct tree_phi_node GTY(())
*** 1403,1411 ****
    /* Basic block to that the phi node belongs.  */
    struct basic_block_def *bb;
  
-   /* Dataflow information.  */
-   struct dataflow_d *df;
- 
    struct phi_arg_d GTY ((length ("((tree)&%h)->phi.capacity"))) a[1];
  };
  \f
--- 1422,1427 ----
*************** enum tree_dump_index
*** 3876,3881 ****
--- 3892,3898 ----
  #define TDF_TREE	(1 << 9)	/* is a tree dump */
  #define TDF_RTL		(1 << 10)	/* is a RTL dump */
  #define TDF_IPA		(1 << 11)	/* is an IPA dump */
+ #define TDF_STMT_ADDR	(1 << 12)	/* Address of stmt.  */
  
  typedef struct dump_info *dump_info_p;
  

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: integrated immediate uses - alpha patch
  2004-10-14 20:40 integrated immediate uses - alpha patch Andrew MacLeod
@ 2004-10-15  3:07 ` Giovanni Bajo
  2004-10-15 12:31   ` Andrew MacLeod
  0 siblings, 1 reply; 6+ messages in thread
From: Giovanni Bajo @ 2004-10-15  3:07 UTC (permalink / raw)
  To: Andrew MacLeod; +Cc: gcc-patches

Andrew MacLeod wrote:

> The only difference is that the SAFE loop allows you to delete and
> modify stmts, its just a bit slower because it links a guard into the
> list and moves the guard along as you iterate thorugh the list.  The
> presence of the guard requires you to use
>
>     BREAK_FROM_SAFE_IMM_USE(iter);
>
> instead of
>
>     break;

Did you think about ways to catch about mistakes in this regard in checking
builds?

Giovanni Bajo


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: integrated immediate uses - alpha patch
  2004-10-15  3:07 ` Giovanni Bajo
@ 2004-10-15 12:31   ` Andrew MacLeod
  2004-10-15 12:32     ` Richard Guenther
  2004-10-15 12:44     ` Giovanni Bajo
  0 siblings, 2 replies; 6+ messages in thread
From: Andrew MacLeod @ 2004-10-15 12:31 UTC (permalink / raw)
  To: Giovanni Bajo; +Cc: gcc-patches

On Thu, 2004-10-14 at 23:04, Giovanni Bajo wrote:
> Andrew MacLeod wrote:
> 
> > The only difference is that the SAFE loop allows you to delete and
> > modify stmts, its just a bit slower because it links a guard into the
> > list and moves the guard along as you iterate thorugh the list.  The
> > presence of the guard requires you to use
> >
> >     BREAK_FROM_SAFE_IMM_USE(iter);
> >
> > instead of
> >
> >     break;
> 
> Did you think about ways to catch about mistakes in this regard in checking
> builds?

Yes, but it hasn't been implemented yet. In the verify_ssa or
verify_imm_links (which will be changed an integrated into verify_ssa)
phase a guard can be identified in the list.  

I havent figure out how to avoid the BREAK macro tho. unless we find
another way to implement the safety aspect.  Perhaps something will
occur to me to someone else eventually.  

Andrew

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: integrated immediate uses - alpha patch
  2004-10-15 12:31   ` Andrew MacLeod
@ 2004-10-15 12:32     ` Richard Guenther
  2004-10-15 12:44     ` Giovanni Bajo
  1 sibling, 0 replies; 6+ messages in thread
From: Richard Guenther @ 2004-10-15 12:32 UTC (permalink / raw)
  To: Andrew MacLeod; +Cc: Giovanni Bajo, gcc-patches

On Fri, 15 Oct 2004 08:20:18 -0400, Andrew MacLeod <amacleod@redhat.com> wrote:
> On Thu, 2004-10-14 at 23:04, Giovanni Bajo wrote:
> 
> 
> > Andrew MacLeod wrote:
> >
> > > The only difference is that the SAFE loop allows you to delete and
> > > modify stmts, its just a bit slower because it links a guard into the
> > > list and moves the guard along as you iterate thorugh the list.  The
> > > presence of the guard requires you to use
> > >
> > >     BREAK_FROM_SAFE_IMM_USE(iter);
> > >
> > > instead of
> > >
> > >     break;
> >
> > Did you think about ways to catch about mistakes in this regard in checking
> > builds?
> 
> Yes, but it hasn't been implemented yet. In the verify_ssa or
> verify_imm_links (which will be changed an integrated into verify_ssa)
> phase a guard can be identified in the list.
> 
> I havent figure out how to avoid the BREAK macro tho. unless we find
> another way to implement the safety aspect.  Perhaps something will
> occur to me to someone else eventually.

The only way would be to use iterators and removal of the guard at
iterator destruction.  Though this can't be automatic either in C.  So use
C++ :)

Richard.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: integrated immediate uses - alpha patch
  2004-10-15 12:31   ` Andrew MacLeod
  2004-10-15 12:32     ` Richard Guenther
@ 2004-10-15 12:44     ` Giovanni Bajo
  2004-10-15 13:37       ` Andrew MacLeod
  1 sibling, 1 reply; 6+ messages in thread
From: Giovanni Bajo @ 2004-10-15 12:44 UTC (permalink / raw)
  To: Andrew MacLeod; +Cc: gcc-patches

Andrew MacLeod wrote:

> I havent figure out how to avoid the BREAK macro tho. unless we find
> another way to implement the safety aspect.  Perhaps something will
> occur to me to someone else eventually.

I looked into your patch but there are things still unclear to me (eg. how do
you plan to find out in verify_* if there is a guard a linked?), but maybe you
can use attribute((cleanup))?

Giovanni Bajo


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: integrated immediate uses - alpha patch
  2004-10-15 12:44     ` Giovanni Bajo
@ 2004-10-15 13:37       ` Andrew MacLeod
  0 siblings, 0 replies; 6+ messages in thread
From: Andrew MacLeod @ 2004-10-15 13:37 UTC (permalink / raw)
  To: Giovanni Bajo; +Cc: gcc-patches

On Fri, 2004-10-15 at 08:32, Giovanni Bajo wrote:
> Andrew MacLeod wrote:
> 
> > I havent figure out how to avoid the BREAK macro tho. unless we find
> > another way to implement the safety aspect.  Perhaps something will
> > occur to me to someone else eventually.
> 
> I looked into your patch but there are things still unclear to me (eg. how do
> you plan to find out in verify_* if there is a guard a linked?), but maybe you
> can use attribute((cleanup))?
> 

The guard doesn't need either the 'stmt' or 'use' field set, so setting
them both to NULL in the guard node would mark it as a guard.

I haven't done that as yet because of the overly aggressive verify
checking I was doing to get this implementation up and running (I was
running verify links after every single linking at one point to make
sure everything was kosher). I didnt want it crapping out whenever it
saw a guard when an iterator was in use.


Andrew

oh, one other side effect I forgot is that now, given an arbitrary
use_operand_p, you can get the stmt it belongs to via USE_STMT (use_p).
The stmt is an attribute of the use, not the iterator.

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2004-10-15 12:44 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-10-14 20:40 integrated immediate uses - alpha patch Andrew MacLeod
2004-10-15  3:07 ` Giovanni Bajo
2004-10-15 12:31   ` Andrew MacLeod
2004-10-15 12:32     ` Richard Guenther
2004-10-15 12:44     ` Giovanni Bajo
2004-10-15 13:37       ` Andrew MacLeod

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).