public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [tree-ssa]: SSAPRE Update
@ 2002-11-06  8:25 Daniel Berlin
  2002-11-06  8:41 ` Diego Novillo
  0 siblings, 1 reply; 3+ messages in thread
From: Daniel Berlin @ 2002-11-06  8:25 UTC (permalink / raw)
  To: gcc-patches

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

Starting to cleanup and remove unnecessary redundancy, structures, 
ugliness, and speeding up pieces of code that are slow.
Large portions of insertion code may look very ugly right now due to 
being in flux (It's waiting for DFA updates. I can't write code to 
update the SSA until we know the interface, which is still being 
decided).

I'll clean up and commonize the strength reduction bits next.

This update includes basic load PRE (aka register promotion) for 
indirect loads.
I'll do component refs, direct loads, and array loads after more clean 
up.
But
int main(int argc)
{
         static int a;
         static int *b;
         static int *d;
         static int c;
         a = 5;
         b = &a;
         d = &a;
         c = *b;
         c = *b;
         if (argc)
         {
                 *b = 5;
         }
         c = *b;

Will be optimized to:

main()
{
   int pretmp.1;
   static int a;
   static int * b;
   static int * d;
   static int c;

   a = 5;
   b = &a;
   d = &a;
   pretmp.1 = *b;
   c = pretmp.1;
   c = pretmp.1;
   if (argc != 0)
     {
       {
         pretmp.1 = 5;
         *b = pretmp.1
       }
     };
   c = pretmp.1
}
I'll wait a few hours before committing, on the off chance Diego is 
really against making set_bb_for_stmt external.

Diego, I externalized set_bb_for_stmt because it's one of the only 
functions we don't have a "get" but not a "set" accessible for (ie 
bb_for_stmt was around, but not set_bb_for_stmt) and it was necessary 
for proper operation.
Alternatively, you could make both bb_for_stmt and set_bb_for_stmt 
private, and have replace_ref_* call set_bb_for_stmt for us.
I only did it this way because I didn't want to interfere with any ref 
updating work you've done.

2002-11-04  Daniel Berlin  <dberlin@dberlin.org>

	* tree-flow.h: Prototype set_bb_for_stmt, last_stmt_ptr,
	add_ephi_arg, num_ephi_args, set_ephi_arg, ephi_arg.
	(enum tree_ref_type): Add E_LEFT, E_KILL, E_EXIT.

	* tree-cfg.c (set_bb_for_stmt): Move to tree-flow-inline.h.
	(last_stmt_ptr): New function, gives pointer to last statement in
	bb.

	* tree-flow-inline.h: Add exprref_processed, exprref_processed2,
	expruse_phi, num_ephi_args, set_ephi_arg, ephi_arg, add_ephi_arg.
	
	* tree-dfa.c (tree_ref_structure): Handle E_{LEFT,KILL,EXIT}.
	(ref_type_name): Ditto.
	(tree_ref_size): Ditto.
	(dump_ref): E_PHI's phi_args is now a varray of phi_arg structs.
	(add_ephi_arg): New function.
	(remove_ref_list): Fix crash when node not found.
	(compute_may_aliases): Add timing for points-to analysis.

	* timevar.def: Add TV_TREE_PTA.

	* tree-ssa-pre.c: Start of massive cleanup and rewriting (in
	preparation for load/store PRE). No more uses of ref_expr, proper
	call handling. Started removing unnecessary structures and lists,
	started removing redundant and inefficient operations (IE O(n^2)
	loops to process all phi operands, etc).  Basic load PRE implemented.
	Code may look ugly due to large pieces commented out waiting for DFA
	updating of refs to redo.
	

[-- Attachment #2: prediff --]
[-- Type: application/octet-stream, Size: 134710 bytes --]

Index: tree-dfa.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-dfa.c,v
retrieving revision 1.1.4.40
diff -c -3 -p -r1.1.4.40 tree-dfa.c
*** tree-dfa.c	5 Nov 2002 23:50:38 -0000	1.1.4.40
--- tree-dfa.c	6 Nov 2002 16:02:51 -0000
*************** Boston, MA 02111-1307, USA.  */
*** 29,34 ****
--- 29,35 ----
  #include "basic-block.h"
  #include "output.h"
  #include "errors.h"
+ #include "timevar.h"
  #include "expr.h"
  #include "ggc.h"
  #include "flags.h"
*************** static tree clobber_vars_r		PARAMS ((tre
*** 93,99 ****
  static void compute_may_aliases		PARAMS ((void));
  static void find_may_aliases_for	PARAMS ((tree));
  static void add_may_alias		PARAMS ((tree, tree));
! static bool may_alias_p			PARAMS ((tree, tree));
  static bool is_visible_to		PARAMS ((tree, tree));
  static size_t tree_ref_size		PARAMS ((enum tree_ref_type));
  static inline tree create_indirect_ref	PARAMS ((tree));
--- 94,100 ----
  static void compute_may_aliases		PARAMS ((void));
  static void find_may_aliases_for	PARAMS ((tree));
  static void add_may_alias		PARAMS ((tree, tree));
! static inline bool may_alias_p			PARAMS ((tree, tree));
  static bool is_visible_to		PARAMS ((tree, tree));
  static size_t tree_ref_size		PARAMS ((enum tree_ref_type));
  static inline tree create_indirect_ref	PARAMS ((tree));
*************** remove_ref_from_list (list, ref)
*** 532,537 ****
--- 533,540 ----
      return;
  
    tmp = find_list_node (list, ref);
+   if (!tmp)
+     return;
  
    if (tmp == list->first)
      list->first = tmp->next;
*************** tree_ref_size (ref_type)
*** 775,780 ****
--- 778,787 ----
        return sizeof (struct expr_use_d);
      case E_KILL:
        return sizeof (struct expr_ref_common);
+     case E_EXIT:
+       return sizeof (struct expr_ref_common);
+     case E_LEFT:
+       return sizeof (struct expr_ref_common);
      }
  
    abort ();
*************** create_ref (var, ref_type, ref_mod, bb, 
*** 900,912 ****
      {
        varray_type temp;
        VARRAY_GENERIC_PTR_INIT (temp, 
! 			       last_basic_block, "ephi_chain");
        set_exprphi_phi_args (ref, temp);
!       set_exprphi_processed (ref, BITMAP_GGC_ALLOC ());
!       set_exprphi_downsafe (ref, 1);
!       set_exprphi_canbeavail (ref, 1);
!       set_exprphi_later (ref, 1);
!       set_exprphi_extraneous (ref, 1);
      }
  
    if (var)
--- 907,918 ----
      {
        varray_type temp;
        VARRAY_GENERIC_PTR_INIT (temp, 
! 			       1, "ephi_chain");
        set_exprphi_phi_args (ref, temp);
!       set_exprphi_downsafe (ref, true);
!       set_exprphi_canbeavail (ref, true);
!       set_exprphi_later (ref, true);
!       set_exprphi_extraneous (ref, true);
      }
  
    if (var)
*************** add_phi_arg (phi, def, e)
*** 975,980 ****
--- 981,1005 ----
  }
  
  
+ /* Add a new argument to EPHI for definition DEF reaching in via edge E.  */
+ 
+ void
+ add_ephi_arg (phi, def, e)
+      tree_ref phi;
+      tree_ref def;
+      edge e;
+ {
+   phi_node_arg arg;
+ 
+   arg = (phi_node_arg) ggc_alloc (sizeof (*arg));
+   memset ((void *) arg, 0, sizeof (*arg));
+ 
+   arg->def = def;
+   arg->e = e;
+ 
+   VARRAY_PUSH_GENERIC_PTR (phi->ephi.phi_args, (PTR)arg);
+ }
+ 
  /* Add a unique copy of variable VAR to the list of referenced variables.  */
  
  static void
*************** dump_ref (outf, prefix, ref, indent, det
*** 1171,1177 ****
  		     exprref_class (ref), exprphi_downsafe (ref), 
  		     exprphi_canbeavail (ref), exprphi_later (ref));
  	  fputs (" expr-phi-args:\n", outf);
! 	  dump_ref_array (outf, prefix, exprphi_phi_args (ref), indent + 4, 1);
  	}	
  
        if (ref_type (ref) == V_DEF && imm_uses (ref))
--- 1196,1202 ----
  		     exprref_class (ref), exprphi_downsafe (ref), 
  		     exprphi_canbeavail (ref), exprphi_later (ref));
  	  fputs (" expr-phi-args:\n", outf);
! 	  dump_phi_args (outf, prefix, exprphi_phi_args (ref), indent + 4, 1);
  	}	
  
        if (ref_type (ref) == V_DEF && imm_uses (ref))
*************** ref_type_name (ref)
*** 1693,1703 ****
--- 1718,1732 ----
  	        : type == E_PHI ? "E_PHI"
  	        : type == E_USE ? "E_USE"
  	        : type == E_KILL ? "E_KILL"
+ 	        : type == E_EXIT ? "E_EXIT"
+ 	        : type == E_LEFT ? "E_LEFT"
  	        : "???",
  	   max);
    
    if (ref_type (ref) == E_USE 
        || ref_type (ref) == E_KILL
+       || ref_type (ref) == E_EXIT
+       || ref_type (ref) == E_LEFT
        || ref_type (ref) == E_PHI)
      return str;
    
*************** clobber_vars_r (tp, walk_subtrees, data)
*** 1746,1758 ****
        create_ref (*tp, V_USE, TRM_MAY, clobber->bb, clobber->parent_stmt_p,
  		  clobber->parent_expr_p, NULL, 1);
        create_ref (*tp, V_DEF, TRM_CLOBBER, clobber->bb, clobber->parent_stmt_p,
! 		  clobber->parent_expr_p, NULL, 1);
      }
  
    return NULL;
  }
  
- 
  /* Compute may-alias information for every variable referenced in the
     program.  FIXME this computes a bigger set than necessary.
  
--- 1775,1786 ----
        create_ref (*tp, V_USE, TRM_MAY, clobber->bb, clobber->parent_stmt_p,
  		  clobber->parent_expr_p, NULL, 1);
        create_ref (*tp, V_DEF, TRM_CLOBBER, clobber->bb, clobber->parent_stmt_p,
! 		  clobber->parent_expr_p, NULL, 1); 
      }
  
    return NULL;
  }
  
  /* Compute may-alias information for every variable referenced in the
     program.  FIXME this computes a bigger set than necessary.
  
*************** static void
*** 1766,1774 ****
  compute_may_aliases ()
  {
    unsigned long i;
! 
!   if (flag_tree_points_to)
!     create_alias_vars ();
  
    for (i = 0; i < num_referenced_vars; i++)
      {
--- 1794,1806 ----
  compute_may_aliases ()
  {
    unsigned long i;
!   
!   if (flag_tree_points_to != PTA_NONE  && num_referenced_vars)
!     {
!       timevar_push (TV_TREE_PTA);
!       create_alias_vars ();
!       timevar_pop (TV_TREE_PTA);
!     }
  
    for (i = 0; i < num_referenced_vars; i++)
      {
*************** compute_may_aliases ()
*** 1780,1810 ****
  	find_may_aliases_for (var);
      }
  
!   if (flag_tree_points_to)
!     delete_alias_vars ();
! }
! 
! 
! /* Find variables that PTR may be aliasing.  */
! 
! static void
! find_may_aliases_for (ptr)
!      tree ptr;
! {
!   unsigned long i;
! 
!   for (i = 0; i < num_referenced_vars; i++)
      {
!       tree var = referenced_var (i);
!       tree var_sym = get_base_symbol (var);
! 
!       if (may_alias_p (ptr, var_sym)
! 	  /* Avoid adding duplicate aliases.  */
! 	  && get_alias_index (ptr, var_sym) == -1)
! 	{
! 	  add_may_alias (ptr, var_sym);
! 	  add_may_alias (var_sym, ptr);
! 	}
      }
  }
  
--- 1812,1822 ----
  	find_may_aliases_for (var);
      }
  
!   if (flag_tree_points_to != PTA_NONE && num_referenced_vars)
      {
!       timevar_push (TV_TREE_PTA);
!       delete_alias_vars ();
!       timevar_pop (TV_TREE_PTA);
      }
  }
  
*************** find_may_aliases_for (ptr)
*** 1812,1825 ****
  /* Return true if PTR (an INDIRECT_REF tree) may alias VAR_SYM (a _DECL tree).
     FIXME  This returns true more often than it should.  */
  
! static bool
  may_alias_p (ptr, var_sym)
       tree ptr;
       tree var_sym;
  {
    HOST_WIDE_INT ptr_alias_set, var_alias_set;
    tree ptr_sym = get_base_symbol (ptr);
! 
    /* GLOBAL_VAR aliases every global variable and locals that have had
       their address taken, unless points-to analysis is done. This is because
       points-to is supposed to handle this case, and thus, can give a more
--- 1824,1837 ----
  /* Return true if PTR (an INDIRECT_REF tree) may alias VAR_SYM (a _DECL tree).
     FIXME  This returns true more often than it should.  */
  
! static inline bool
  may_alias_p (ptr, var_sym)
       tree ptr;
       tree var_sym;
  {
    HOST_WIDE_INT ptr_alias_set, var_alias_set;
    tree ptr_sym = get_base_symbol (ptr);
!   
    /* GLOBAL_VAR aliases every global variable and locals that have had
       their address taken, unless points-to analysis is done. This is because
       points-to is supposed to handle this case, and thus, can give a more
*************** may_alias_p (ptr, var_sym)
*** 1831,1837 ****
        && (TREE_ADDRESSABLE (var_sym)
  	  || decl_function_context (var_sym) == NULL))
      return true;
! 
    /* Obvious reasons why PTR_SYM and VAR_SYM can't possibly alias
       each other.  */
    if (var_sym == ptr_sym
--- 1843,1849 ----
        && (TREE_ADDRESSABLE (var_sym)
  	  || decl_function_context (var_sym) == NULL))
      return true;
!   
    /* Obvious reasons why PTR_SYM and VAR_SYM can't possibly alias
       each other.  */
    if (var_sym == ptr_sym
*************** may_alias_p (ptr, var_sym)
*** 1843,1859 ****
  
    ptr_alias_set = get_alias_set (TREE_TYPE (ptr));
    var_alias_set = get_alias_set (TREE_TYPE (var_sym));
! 
    if (!alias_sets_conflict_p (ptr_alias_set, var_alias_set))
      return false;
  
!   if (!flag_tree_points_to)
!     return true;
  
!   return ptr_may_alias_var (ptr_sym, var_sym);
  }
  
  
  /* Return true if SYM1 and SYM2 are visible to each other.  Visibility is
     determined based on the scopes where each variable is declared.  Both
     scopes must be the same or one must be enclosed in the other.  */
--- 1855,1896 ----
  
    ptr_alias_set = get_alias_set (TREE_TYPE (ptr));
    var_alias_set = get_alias_set (TREE_TYPE (var_sym));
!   
    if (!alias_sets_conflict_p (ptr_alias_set, var_alias_set))
      return false;
  
!   if (flag_tree_points_to)
!     if (!ptr_may_alias_var (ptr_sym, var_sym))
!        return false;
!   
!   return true;
! }
! /* Find variables that PTR may be aliasing.  */
  
! static void
! find_may_aliases_for (ptr)
!      tree ptr;
! {
!   unsigned long i;
! 
!   for (i = 0; i < num_referenced_vars; i++)
!     {
!       tree var = referenced_var (i);
!       tree var_sym = get_base_symbol (var);
! 
!       if (may_alias_p (ptr, var_sym)
! 	  /* Avoid adding duplicate aliases.  */
! 	  && get_alias_index (ptr, var_sym) == -1)
! 	{
! 	  add_may_alias (ptr, var_sym);
! 	  add_may_alias (var_sym, ptr);
! 	}
!     }
  }
  
  
+ 
+ 
  /* Return true if SYM1 and SYM2 are visible to each other.  Visibility is
     determined based on the scopes where each variable is declared.  Both
     scopes must be the same or one must be enclosed in the other.  */
*************** tree_ref_structure (ref)
*** 2011,2016 ****
--- 2048,2057 ----
    else if (type == E_USE)
      return TR_EXPR_USE;
    else if (type == E_KILL)
+     return TR_EXPR_REF_COMMON;
+   else if (type == E_EXIT)
+     return TR_EXPR_REF_COMMON;
+   else if (type == E_LEFT)
      return TR_EXPR_REF_COMMON;
  
    abort ();
Index: timevar.def
===================================================================
RCS file: /cvs/gcc/gcc/gcc/timevar.def,v
retrieving revision 1.14.2.1
diff -c -3 -p -r1.14.2.1 timevar.def
*** timevar.def	22 Oct 2002 16:07:09 -0000	1.14.2.1
--- timevar.def	6 Nov 2002 16:02:51 -0000
*************** DEFTIMEVAR (TV_LEX		     , "lexical anal
*** 53,58 ****
--- 53,59 ----
  DEFTIMEVAR (TV_PARSE                 , "parser")
  DEFTIMEVAR (TV_EXPAND		     , "expand")
  DEFTIMEVAR (TV_TREE_CFG		     , "tree CFG construction")
+ DEFTIMEVAR (TV_TREE_PTA		     , "tree PTA")
  DEFTIMEVAR (TV_TREE_SSA		     , "tree SSA building")	 
  DEFTIMEVAR (TV_TREE_CCP		     , "tree CCP")
  DEFTIMEVAR (TV_TREE_PRE		     , "tree PRE")
Index: tree-ssa-pre.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa-pre.c,v
retrieving revision 1.1.4.31
diff -c -3 -p -r1.1.4.31 tree-ssa-pre.c
*** tree-ssa-pre.c	5 Nov 2002 23:50:39 -0000	1.1.4.31
--- tree-ssa-pre.c	6 Nov 2002 16:02:51 -0000
*************** Boston, MA 02111-1307, USA.  */
*** 49,55 ****
  
  #define EXTRANEOUS_EPHI_REMOVAL 0
  #define DEBUGGING_STRRED 1
! #define DEBUGGING_SSA_UPDATE 1
  
  /* See http://citeseer.nj.nec.com/chow97new.html, and
     http://citeseer.nj.nec.com/kennedy99partial.html for details of the
--- 49,56 ----
  
  #define EXTRANEOUS_EPHI_REMOVAL 0
  #define DEBUGGING_STRRED 1
! #define DEBUGGING_SSA_UPDATE 0
! #define DEBUGGING_EPHI_REMOVAL 0
  
  /* See http://citeseer.nj.nec.com/chow97new.html, and
     http://citeseer.nj.nec.com/kennedy99partial.html for details of the
*************** Boston, MA 02111-1307, USA.  */
*** 65,70 ****
--- 66,77 ----
  
  */
  /* TODO:
+    
+    Commonize injuring def stuff into a seperate function (get_injuring_def or
+    something). 
+ 
+    Load PRE bug testing and fixing.
+ 
     Get rid of hunting through statements for refs, now that
     expressions have the refs we want as well -- This should substantially
     clean up the code, which was written when only statements had refs,
*************** Boston, MA 02111-1307, USA.  */
*** 73,84 ****
     Remapping expression occurrences to the entire expression is a pain, and is
     only done to avoid having to grab the first operand all the time (the code
     was started before the change to include the *entire* expression in the
!    ref_expr was made).  It would clean up the code a lot and remove a lot of
     duplicated functions, whose only difference is one remaps and one doesn't.
  
     Strength reduction improvements.
  
!    Register promotion.
  */
  struct expr_info;
  static int expr_lexically_eq PARAMS ((tree, tree));
--- 80,91 ----
     Remapping expression occurrences to the entire expression is a pain, and is
     only done to avoid having to grab the first operand all the time (the code
     was started before the change to include the *entire* expression in the
!    ref_stmt was made).  It would clean up the code a lot and remove a lot of
     duplicated functions, whose only difference is one remaps and one doesn't.
  
     Strength reduction improvements.
  
! 
  */
  struct expr_info;
  static int expr_lexically_eq PARAMS ((tree, tree));
*************** static void code_motion PARAMS ((struct 
*** 104,126 ****
  static bool can_insert PARAMS ((tree_ref));
  static inline bool defs_match_p PARAMS ((struct expr_info *, tree, tree));
  static inline bool defs_y_dom_x PARAMS ((struct expr_info *, tree_ref, tree_ref));
! static void assign_new_class PARAMS ((tree_ref, varray_type *));
  static void insert_occ_in_preorder_dt_order_1 PARAMS ((struct expr_info *, 
  						       fibheap_t, basic_block));
  static void insert_occ_in_preorder_dt_order PARAMS ((struct expr_info *, 
  						     fibheap_t));
  static void insert_euse_in_preorder_dt_order_1 PARAMS ((struct expr_info *, 
! 							fibheap_t, basic_block));
! static void insert_euse_in_preorder_dt_order PARAMS ((struct expr_info *, 
! 						      fibheap_t));
  static inline int opnum_of_phi PARAMS ((tree_ref, int));
  static varray_type phi_opnd_from_res PARAMS ((struct expr_info *, tree_ref, 
  					      int, basic_block));
  static splay_tree rename_2 PARAMS ((struct expr_info *, varray_type *));
  static void rename_1 PARAMS ((struct expr_info *));
  static void finalize_2 PARAMS ((struct expr_info *));
! static void finalize_1 PARAMS ((struct expr_info *, tree));
! static tree_ref phi_for_operand PARAMS ((struct expr_info *, tree_ref));
  static void set_save PARAMS ((struct expr_info *, tree_ref));
  static void set_replacement PARAMS ((struct expr_info *, tree_ref, tree_ref));
  #if 0
--- 111,133 ----
  static bool can_insert PARAMS ((tree_ref));
  static inline bool defs_match_p PARAMS ((struct expr_info *, tree, tree));
  static inline bool defs_y_dom_x PARAMS ((struct expr_info *, tree_ref, tree_ref));
! static void assign_new_class PARAMS ((tree_ref, varray_type *, varray_type *));
  static void insert_occ_in_preorder_dt_order_1 PARAMS ((struct expr_info *, 
  						       fibheap_t, basic_block));
  static void insert_occ_in_preorder_dt_order PARAMS ((struct expr_info *, 
  						     fibheap_t));
  static void insert_euse_in_preorder_dt_order_1 PARAMS ((struct expr_info *, 
! 							basic_block));
! static void insert_euse_in_preorder_dt_order PARAMS ((struct expr_info *));
  static inline int opnum_of_phi PARAMS ((tree_ref, int));
  static varray_type phi_opnd_from_res PARAMS ((struct expr_info *, tree_ref, 
  					      int, basic_block));
  static splay_tree rename_2 PARAMS ((struct expr_info *, varray_type *));
  static void rename_1 PARAMS ((struct expr_info *));
  static void finalize_2 PARAMS ((struct expr_info *));
! static bool finalize_1 PARAMS ((struct expr_info *, tree));
! 
! static tree_ref phi_operand_for_pred PARAMS ((tree_ref, edge));
  static void set_save PARAMS ((struct expr_info *, tree_ref));
  static void set_replacement PARAMS ((struct expr_info *, tree_ref, tree_ref));
  #if 0
*************** static void calculate_preorder PARAMS ((
*** 137,143 ****
  static void update_phis_in_list PARAMS ((ref_list, tree_ref, tree_ref));
  static void update_ssa_for_new_use PARAMS ((tree, tree, tree_ref, basic_block));
  static int find_reaching_def_of_var PARAMS ((tree_ref, basic_block, tree_ref));
! 
  static int *pre_preorder;
  static dominance_info pre_idom;
  static sbitmap *pre_dfs;
--- 144,156 ----
  static void update_phis_in_list PARAMS ((ref_list, tree_ref, tree_ref));
  static void update_ssa_for_new_use PARAMS ((tree, tree, tree_ref, basic_block));
  static int find_reaching_def_of_var PARAMS ((tree_ref, basic_block, tree_ref));
! static void temp_fix_refs PARAMS ((tree, tree, tree *));
! static void update_old_new PARAMS ((struct expr_info *, tree *, tree *));
! static inline bool is_a_call PARAMS ((tree));
! static inline bool okay_injuring_def PARAMS ((tree_ref, tree));
! static void process_left_occs_and_kills PARAMS ((varray_type, struct expr_info *,
! 						 tree_ref, tree));
! static tree get_operand PARAMS ((tree, unsigned int));
  static int *pre_preorder;
  static dominance_info pre_idom;
  static sbitmap *pre_dfs;
*************** static int preorder_count;
*** 149,157 ****
  static tree_ref *avdefs;
  
  static splay_tree new_stmt_map;
- 
  static splay_tree need_repair_map;
  
  
  /* sbitmap vector mapping blocks to the child blocks they dominate. */
  static sbitmap *domchildren;
--- 162,177 ----
  static tree_ref *avdefs;
  
  static splay_tree new_stmt_map;
  static splay_tree need_repair_map;
  
+ /* Map from pointers to statements we've replaced to pointers to where they are
+ now.  This is used to update the occurs list. We only need to update the occurs
+ list right before we create E_USE's (if we don't update them  at all, we create
+ E_USE's that point to the wrong place), and it would be O(n^2) to do it as we
+ replace statements (since we don't have something that gives us the index into
+ the occurs array an e_use came from, we'd have to search the entire occurs
+ array every time).  */
+ static splay_tree old_new_map;
  
  /* sbitmap vector mapping blocks to the child blocks they dominate. */
  static sbitmap *domchildren;
*************** struct expr_info
*** 159,173 ****
  {
    /* The actual expression.  */
    tree expr;  
!   /* The occurrences, which can include calls. */
    varray_type occurs;
!   /* Statements for the occurrences. */
!   varray_type occurstmts;
    /* An array of real occurrences. */
    varray_type reals;
-   /* An array mapping reals to the containing statements (so we can
-      get defs/uses/etc about them. */
-   varray_type realstmts;
    /* The ephis we've added for this expr. */
    varray_type phis;
    /* All the erefs. */
--- 179,192 ----
  {
    /* The actual expression.  */
    tree expr;  
!   /* The occurrences. */
    varray_type occurs;
!   /* The kills. */
!   varray_type kills;
!   /* The left occurrences. */
!   varray_type lefts;
    /* An array of real occurrences. */
    varray_type reals;
    /* The ephis we've added for this expr. */
    varray_type phis;
    /* All the erefs. */
*************** struct expr_info
*** 181,186 ****
--- 200,207 ----
    /* List of injury defs we need to fix reaching defs on *after* other
       insertions. */ 
    ref_list injfixups;
+   /* The euses/ephis in preorder dt order. */
+   ref_list euses_dt_order;
  };
  
  /* Returns true if a dominates b */
*************** is_strred_cand (expr)
*** 263,272 ****
    ref_list_iterator i;
    
    STRIP_WFL (expr);
    /* Multiplications that def a variable they use can't be strength reduced.
       Removing the multiplications would require adding more multiplications.
       IE a = a * 5. */
!   if (TREE_CODE (TREE_OPERAND (expr, 1)) != MULT_EXPR)
      return false;
    
    def = use = NULL;
--- 284,294 ----
    ref_list_iterator i;
    
    STRIP_WFL (expr);
+ 
    /* Multiplications that def a variable they use can't be strength reduced.
       Removing the multiplications would require adding more multiplications.
       IE a = a * 5. */
!   if (TREE_CODE (TREE_OPERAND (expr, 1)) != MULT_EXPR )
      return false;
    
    def = use = NULL;
*************** is_strred_cand (expr)
*** 291,301 ****
    
    return true;
  }
  
  /* Return true is INJ is an injuring definition */
  static bool 
  is_injuring_def (ei, inj)
! 	struct expr_info *ei;
       tree inj;
  {
    if (!inj || !is_simple_modify_expr (inj))
--- 313,335 ----
    
    return true;
  }
+ static inline bool
+ okay_injuring_def (inj, var)
+      tree_ref inj;
+      tree var;
+ {
+   if (is_default_def (inj) 
+       || ref_type (inj) == V_PHI
+       || ref_defines (inj, var)
+       || !maybe_find_rhs_use_for_var (inj, var))
+     return false;
+   return true;
+ }
  
  /* Return true is INJ is an injuring definition */
  static bool 
  is_injuring_def (ei, inj)
!      struct expr_info *ei;
       tree inj;
  {
    if (!inj || !is_simple_modify_expr (inj))
*************** free_expr_info (v1)
*** 366,374 ****
  {
    struct expr_info *e1 = (struct expr_info *)v1;
    VARRAY_CLEAR (e1->occurs);
!   VARRAY_CLEAR (e1->occurstmts);
    VARRAY_CLEAR (e1->reals);
-   VARRAY_CLEAR (e1->realstmts);
    VARRAY_CLEAR (e1->phis);
    VARRAY_CLEAR (e1->erefs);
    VARRAY_CLEAR (e1->refs);
--- 400,408 ----
  {
    struct expr_info *e1 = (struct expr_info *)v1;
    VARRAY_CLEAR (e1->occurs);
!   VARRAY_CLEAR (e1->kills);
!   VARRAY_CLEAR (e1->lefts);
    VARRAY_CLEAR (e1->reals);
    VARRAY_CLEAR (e1->phis);
    VARRAY_CLEAR (e1->erefs);
    VARRAY_CLEAR (e1->refs);
*************** set_var_phis (ei, phi, i)
*** 409,425 ****
          {
            phi_operand = phi_arg_def (phi_arg (phi, curr_phi_operand));
  	  if (ei->strred_cand && ref_type (phi_operand) != V_PHI)
! 	    while (is_injuring_def (ei, ref_expr (phi_operand)))
  	      {
  		tree_ref ird;
  		phi_operand = find_rhs_use_for_var (phi_operand, 
  						    ref_var
  						    (phi_operand));
  		ird = imm_reaching_def (phi_operand);
! 		if (is_default_def (ird)
! 		    || ref_type (ird) == V_PHI
! 		    || !maybe_find_rhs_use_for_var (ird, 
! 						    ref_var (phi_operand)))
  		  {
  		    phi_operand = ird;
  		    break;
--- 443,456 ----
          {
            phi_operand = phi_arg_def (phi_arg (phi, curr_phi_operand));
  	  if (ei->strred_cand && ref_type (phi_operand) != V_PHI)
! 	    while (is_injuring_def (ei, ref_stmt (phi_operand)))
  	      {
  		tree_ref ird;
  		phi_operand = find_rhs_use_for_var (phi_operand, 
  						    ref_var
  						    (phi_operand));
  		ird = imm_reaching_def (phi_operand);
! 		if (!okay_injuring_def (ird, ref_var (phi_operand)))
  		  {
  		    phi_operand = ird;
  		    break;
*************** set_var_phis (ei, phi, i)
*** 438,455 ****
  /* Helper macro to simplify accessing the phi for a given block. */
  #define phi_at_block(expr, b) VARRAY_GENERIC_PTR ((expr)->phis, pre_preorder[(b)->index])
  
- /* Helper macro to simplify accessing a phi operand for a given block. */
- #define phi_operand(phi, b) VARRAY_GENERIC_PTR (exprphi_phi_args (phi), pre_preorder[(b)->index])
- 
  /* Given a statement, find the V_DEF in it. */
  static inline tree_ref
  find_def_for_stmt (stmt)
       tree stmt;
  {
    ref_list_iterator i;
- 
    for (i = rli_start (tree_refs (stmt)); !rli_after_end (i); rli_step (&i))
!     if (ref_type (rli_ref (i)) == V_DEF)
        return rli_ref (i);
  
    return NULL;
--- 469,482 ----
  /* Helper macro to simplify accessing the phi for a given block. */
  #define phi_at_block(expr, b) VARRAY_GENERIC_PTR ((expr)->phis, pre_preorder[(b)->index])
  
  /* Given a statement, find the V_DEF in it. */
  static inline tree_ref
  find_def_for_stmt (stmt)
       tree stmt;
  {
    ref_list_iterator i;
    for (i = rli_start (tree_refs (stmt)); !rli_after_end (i); rli_step (&i))
!     if (ref_type (rli_ref (i)) == V_DEF && ref_var (rli_ref (i)) != global_var)
        return rli_ref (i);
  
    return NULL;
*************** find_rhs_use_for_var (def, var)
*** 467,473 ****
      abort ();
    return ret;
  }
!   
  /* Given the the DEF, and a VAR, find the V_USE of the VAR contained
     in that occurrence, if there is one. */
  static inline tree_ref
--- 494,500 ----
      abort ();
    return ret;
  }
! 
  /* Given the the DEF, and a VAR, find the V_USE of the VAR contained
     in that occurrence, if there is one. */
  static inline tree_ref
*************** maybe_find_rhs_use_for_var (def, var)
*** 478,490 ****
    ref_list_iterator i;
  
    /* Now look for the use of var in that expression. */
!   i = rli_start (tree_refs (ref_expr (def)));
    for (; !rli_after_end (i); rli_step (&i))
      {
        tree_ref ref = rli_ref (i);
  
        if (ref_type (ref) != V_USE
! 	  || !is_simple_modify_expr (ref_expr (ref)))
          continue;
        if (ref_var (ref) != var)
          continue;
--- 505,517 ----
    ref_list_iterator i;
  
    /* Now look for the use of var in that expression. */
!   i = rli_start (tree_refs (ref_stmt (def)));
    for (; !rli_after_end (i); rli_step (&i))
      {
        tree_ref ref = rli_ref (i);
  
        if (ref_type (ref) != V_USE
! 	  || !is_simple_modify_expr (ref_stmt (ref)))
          continue;
        if (ref_var (ref) != var)
          continue;
*************** maybe_find_rhs_use_for_var (def, var)
*** 492,499 ****
--- 519,573 ----
      }
    return NULL;
  }
+ /* Used soley by defs_match_p to make sure we are comparing RHS uses, not LHS
+    ones. 
+    The GIMPLE grammar thankfully gives us a strict set of things that will
+    appear on the LHS.
+    Thus, we know we aren't being handed weird crap.
+ */
+ static bool
+ is_on_lhs (var_p, expr_p)
+      tree *var_p;
+      tree *expr_p;
+ {
+   tree expr = *expr_p;
+   STRIP_WFL (expr);
+   STRIP_NOPS (expr);
+   switch (TREE_CODE (expr))
+     {
+     case MODIFY_EXPR:
+     case INIT_EXPR:
+       return is_on_lhs (var_p, &TREE_OPERAND (expr, 0));
+     case COMPONENT_REF:
+     case INDIRECT_REF:
+     case ADDR_EXPR:
+     case REFERENCE_EXPR:
+       return is_on_lhs (var_p, &TREE_OPERAND (expr, 0));
+     case VAR_DECL:
+     case FIELD_DECL:
+     case PARM_DECL:
+     case FUNCTION_DECL:
+       return var_p == expr_p;
+     default:
+       abort();
+     }
+ }
  
+ static bool
+ names_match_p (x, y)
+      tree x;
+      tree y;
+ {
+   while (TREE_CODE (x) == INDIRECT_REF || TREE_CODE (x) == ADDR_EXPR)
+     x = TREE_OPERAND (x, 0);
+   while (TREE_CODE (y) == INDIRECT_REF || TREE_CODE (y) == ADDR_EXPR)
+     y = TREE_OPERAND (y, 0);
+   
+   return y == x;
+ }
  
+   
+      
  /* Determine if the definitions of variables in Y dominate the basic
     block of X. */
  static inline bool 
*************** defs_y_dom_x (ei, y, x)
*** 511,520 ****
        ref_list_iterator j;
        tree yexpr, refexpr;
        
!       yexpr = ref_expr (y);
        STRIP_WFL (yexpr);
        yexpr = TREE_OPERAND (yexpr, 1);
!       
        if (!TREE_OPERAND (yexpr, i))
          continue;
  
--- 585,594 ----
        ref_list_iterator j;
        tree yexpr, refexpr;
        
!       yexpr = ref_stmt (y);
        STRIP_WFL (yexpr);
        yexpr = TREE_OPERAND (yexpr, 1);
! 
        if (!TREE_OPERAND (yexpr, i))
          continue;
  
*************** defs_y_dom_x (ei, y, x)
*** 526,551 ****
            /* Find the ref for this operand. */
  	  if (ref_type (ref) != V_USE)
  	    continue;
! 	  refexpr = ref_expr (ref);
  	  STRIP_WFL (refexpr);
! 	  if (!is_simple_modify_expr (refexpr)
!               || TREE_OPERAND (refexpr, 1) != yexpr)
              continue;
!           if (ref_var (ref) != TREE_OPERAND (yexpr, i))
              continue;
            if (!imm_reaching_def (ref))
              return false;
  
  	  if (ei->strred_cand)
! 	    while (is_injuring_def (ei, ref_expr (imm_reaching_def (ref))))
  	      {
  		ref = find_rhs_use_for_var (imm_reaching_def (ref), 
! 					    TREE_OPERAND (yexpr, i));
! 		if (ref_type (imm_reaching_def (ref)) == V_PHI
! 		    || is_default_def (imm_reaching_def (ref)))
  		  break;
  		ref = find_rhs_use_for_var (imm_reaching_def (ref), 
! 					    TREE_OPERAND (yexpr, i));
  	      }
            if (!(a_dom_b (ref_bb (imm_reaching_def (ref)), ref_bb (x))))
              return false;
--- 600,624 ----
            /* Find the ref for this operand. */
  	  if (ref_type (ref) != V_USE)
  	    continue;
! 	  refexpr = ref_stmt (ref);
  	  STRIP_WFL (refexpr);
! 	  if (!is_simple_modify_expr (refexpr))
! 	    //              || TREE_OPERAND (refexpr, 1) != yexpr)
              continue;
!           if (!names_match_p (ref_var (ref), get_operand (yexpr, i)))
              continue;
            if (!imm_reaching_def (ref))
              return false;
  
  	  if (ei->strred_cand)
! 	    while (is_injuring_def (ei, ref_stmt (imm_reaching_def (ref))))
  	      {
  		ref = find_rhs_use_for_var (imm_reaching_def (ref), 
! 					    get_operand (yexpr, i));	       
! 		if (!okay_injuring_def (imm_reaching_def (ref), ref_var (ref)))
  		  break;
  		ref = find_rhs_use_for_var (imm_reaching_def (ref), 
! 					    get_operand (yexpr, i));
  	      }
            if (!(a_dom_b (ref_bb (imm_reaching_def (ref)), ref_bb (x))))
              return false;
*************** defs_y_dom_x (ei, y, x)
*** 556,564 ****
  }
  
  /* Return true if the variables in t1 have the same defs as the
!    variables in t2.  
!    NB: t1 is expected to be a statement or assignment (IE both left and right sides).
!    t2 is expected to be the right hand side only.*/
  static inline bool
  defs_match_p (ei, t1, t2)
       struct expr_info *ei;
--- 629,635 ----
  }
  
  /* Return true if the variables in t1 have the same defs as the
!    variables in t2.  */
  static inline bool
  defs_match_p (ei, t1, t2)
       struct expr_info *ei;
*************** defs_match_p (ei, t1, t2)
*** 577,601 ****
    for (i = rli_start (tree_refs (t1)); !rli_after_end (i); rli_step (&i))
      {
        tree_ref use1 = rli_ref (i);
!       tree use1expr = ref_expr (use1);
        if (ref_type (use1) != V_USE
! 	  || !is_simple_modify_expr (use1expr))
          continue;
  
        STRIP_WFL (use1expr);
        use1expr = TREE_OPERAND (use1expr, 1);
!       if (TREE_CODE (use1expr) != TREE_CODE (t2))
!         continue;
!       use2 = find_rhs_use_for_var (find_def_for_stmt (origt2), ref_var (use1));
!       if (!use2) 
  	return false;
        /* Find the injuring definition, if one exists. */
        if (ei->strred_cand)
! 	while (is_injuring_def (ei, ref_expr (imm_reaching_def (use1))))
  	  {
  	    /* First, we get the use in the *injuring definition*. */
  	    use1 = find_rhs_use_for_var (imm_reaching_def (use1), 
  					 ref_var (use1));
  	    /* Now, use the use we just got to get the use from before it was
  	       injured. */
  	    use1 = find_rhs_use_for_var (imm_reaching_def (use1), 
--- 648,676 ----
    for (i = rli_start (tree_refs (t1)); !rli_after_end (i); rli_step (&i))
      {
        tree_ref use1 = rli_ref (i);
!       tree use1expr = ref_stmt (use1);
        if (ref_type (use1) != V_USE
! 	  || !is_simple_modify_expr (use1expr)
! 	  || is_on_lhs (&TREE_OPERAND (use1expr, 0), use1->common.stmt_p))
          continue;
  
        STRIP_WFL (use1expr);
        use1expr = TREE_OPERAND (use1expr, 1);
!       use2 = maybe_find_rhs_use_for_var (find_def_for_stmt (origt2),
! 					 ref_var (use1));
!       if (!use2 && (TREE_CODE (use1expr) != TREE_CODE (t2)))
! 	continue;	
!       else if (!use2) 
  	return false;
        /* Find the injuring definition, if one exists. */
        if (ei->strred_cand)
! 	while (is_injuring_def (ei, ref_stmt (imm_reaching_def (use1))))
  	  {
  	    /* First, we get the use in the *injuring definition*. */
  	    use1 = find_rhs_use_for_var (imm_reaching_def (use1), 
  					 ref_var (use1));
+ 	    if (!okay_injuring_def (imm_reaching_def (use1), ref_var (use1)))
+ 	      break;
  	    /* Now, use the use we just got to get the use from before it was
  	       injured. */
  	    use1 = find_rhs_use_for_var (imm_reaching_def (use1), 
*************** defs_match_p (ei, t1, t2)
*** 610,618 ****
  /* Assign a new redundancy class to the occurrence, and push it on the
     stack.  */ 
  static void
! assign_new_class (occ, stack)
       tree_ref occ;
       varray_type *stack;
  {
    /* class(occ) <- count
       Push(occ, stack)
--- 685,694 ----
  /* Assign a new redundancy class to the occurrence, and push it on the
     stack.  */ 
  static void
! assign_new_class (occ, stack, stack2)
       tree_ref occ;
       varray_type *stack;
+      varray_type *stack2;
  {
    /* class(occ) <- count
       Push(occ, stack)
*************** assign_new_class (occ, stack)
*** 620,633 ****
    */
    set_exprref_class (occ, class_count);
    VARRAY_PUSH_GENERIC_PTR (*stack, occ);
    class_count++;
  }
  
! /* Insert the expressions in preorder DT order in the fibheap.  */
  static void
! insert_euse_in_preorder_dt_order_1 (ei, fh, block)
       struct expr_info *ei;
-      fibheap_t fh;
       basic_block block;
  {
    size_t i;
--- 696,709 ----
    */
    set_exprref_class (occ, class_count);
    VARRAY_PUSH_GENERIC_PTR (*stack, occ);
+   VARRAY_PUSH_GENERIC_PTR (*stack2, occ);
    class_count++;
  }
  
! /* Insert the expressions in preorder DT order in the ref_list.  */
  static void
! insert_euse_in_preorder_dt_order_1 (ei, block)
       struct expr_info *ei;
       basic_block block;
  {
    size_t i;
*************** insert_euse_in_preorder_dt_order_1 (ei, 
*** 637,660 ****
        tree_ref ref = VARRAY_GENERIC_PTR (bbrefs, i);
        if (ref_bb (ref) != block)
  	continue;
!       if (ref_type (ref) == E_USE || ref_type (ref) == E_PHI)
! 	fibheap_insert (fh, preorder_count++, ref);
      }
    EXECUTE_IF_SET_IN_SBITMAP (domchildren[block->index], 0, i, 
    {
!     insert_euse_in_preorder_dt_order_1 (ei, fh, BASIC_BLOCK (i));
    });
  }
  
  static void
! insert_euse_in_preorder_dt_order (ei, fh)
       struct expr_info *ei;
-      fibheap_t fh;
  {
!   preorder_count = 0;
!   insert_euse_in_preorder_dt_order_1 (ei, fh, ENTRY_BLOCK_PTR->next_bb);
  }
  
  /* Insert the occurrences in preorder DT order, in the fibheap.  */
  static void
  insert_occ_in_preorder_dt_order_1 (ei, fh, block)
--- 713,748 ----
        tree_ref ref = VARRAY_GENERIC_PTR (bbrefs, i);
        if (ref_bb (ref) != block)
  	continue;
!       if (ref_type (ref) == E_USE || ref_type (ref) == E_PHI 
! 	  || ref_type (ref) == E_LEFT)
! 	add_ref_to_list_end (ei->euses_dt_order, ref);
      }
    EXECUTE_IF_SET_IN_SBITMAP (domchildren[block->index], 0, i, 
    {
!     insert_euse_in_preorder_dt_order_1 (ei, BASIC_BLOCK (i));
    });
  }
  
  static void
! insert_euse_in_preorder_dt_order (ei)
       struct expr_info *ei;
  {
!   insert_euse_in_preorder_dt_order_1 (ei, ENTRY_BLOCK_PTR->next_bb);
  }
  
+ static inline bool
+ is_a_call (expr)
+      tree expr;
+ {
+   STRIP_WFL (expr);
+   STRIP_NOPS (expr);
+   if (TREE_CODE (expr) == CALL_EXPR)
+     return true;
+   if (is_simple_modify_expr (expr) 
+       && TREE_CODE (TREE_OPERAND (expr, 1)) == CALL_EXPR)
+     return true;
+   return false;
+ }
  /* Insert the occurrences in preorder DT order, in the fibheap.  */
  static void
  insert_occ_in_preorder_dt_order_1 (ei, fh, block)
*************** insert_occ_in_preorder_dt_order_1 (ei, f
*** 670,697 ****
    for (i = 0; i < VARRAY_ACTIVE_SIZE (ei->occurs); i++)
      {
        tree_ref newref;
!       tree *occurexpr = VARRAY_GENERIC_PTR (ei->occurs, i);
!       tree *occurstmt = VARRAY_GENERIC_PTR (ei->occurstmts, i);
!       tree_ref occurref = VARRAY_GENERIC_PTR (ei->refs, i);
!       if (ref_bb (occurref) != block)
          continue;
!       if (TREE_CODE (*occurexpr) == CALL_EXPR)
  	{
! 	  newref = create_ref (*occurexpr,
! 				  E_KILL, 0, block, occurstmt,
! 				  occurexpr, NULL, true);
  	  VARRAY_PUSH_GENERIC_PTR (ei->erefs, newref);
  	  fibheap_insert (fh, preorder_count++, newref);
  	}
        else
  	{
  	  newref = create_ref (*occurexpr,
! 				  E_USE, 0, block, occurstmt, 
  				  occurexpr, NULL, true);
  	  VARRAY_PUSH_GENERIC_PTR (ei->erefs, newref);
  	  set_expruse_def (newref, NULL);
  	  set_exprref_class (newref, 0);
  	  set_expruse_phiop (newref, false);
  	  set_expruse_has_real_use (newref, false);
  	  fibheap_insert (fh, preorder_count++, newref);
  	}     
--- 758,801 ----
    for (i = 0; i < VARRAY_ACTIVE_SIZE (ei->occurs); i++)
      {
        tree_ref newref;
!       tree *current;
!       current = VARRAY_GENERIC_PTR (ei->occurs, i);
!       current = current ? current : VARRAY_GENERIC_PTR (ei->kills, i);
!       current = current ? current : VARRAY_GENERIC_PTR (ei->lefts, i);
!       if (bb_for_stmt (*current) != block)
          continue;
! 
!       if (VARRAY_GENERIC_PTR (ei->kills, i) != NULL)
  	{
! 	  tree *killexpr  = VARRAY_GENERIC_PTR (ei->kills, i);
! 	  
! 	  newref = create_ref (*killexpr,
! 			       E_KILL, 0, block, killexpr,
! 			       killexpr, NULL, true);
! 	  VARRAY_PUSH_GENERIC_PTR (ei->erefs, newref);
! 	  fibheap_insert (fh, preorder_count++, newref);
! 	}
!       else if (VARRAY_GENERIC_PTR (ei->lefts, i) != NULL)
! 	{
! 	  tree *leftexpr = VARRAY_GENERIC_PTR (ei->lefts, i);
! 	  newref = create_ref (*leftexpr, 
! 			       E_LEFT, 0, block, leftexpr,
! 			       leftexpr, NULL, true);
  	  VARRAY_PUSH_GENERIC_PTR (ei->erefs, newref);
  	  fibheap_insert (fh, preorder_count++, newref);
  	}
        else
  	{
+ 	  tree *occurexpr = VARRAY_GENERIC_PTR (ei->occurs, i);
  	  newref = create_ref (*occurexpr,
! 				  E_USE, 0, block, occurexpr, 
  				  occurexpr, NULL, true);
  	  VARRAY_PUSH_GENERIC_PTR (ei->erefs, newref);
  	  set_expruse_def (newref, NULL);
  	  set_exprref_class (newref, 0);
  	  set_expruse_phiop (newref, false);
+ 	  set_exprref_processed (newref, false);
+ 	  set_exprref_processed2 (newref, false);
  	  set_expruse_has_real_use (newref, false);
  	  fibheap_insert (fh, preorder_count++, newref);
  	}     
*************** insert_occ_in_preorder_dt_order_1 (ei, f
*** 705,721 ****
          {
            if (phi_at_block (ei, succ->dest) != NULL)
              {
!               tree_ref newref = create_ref (NULL, E_USE, 0, block, 0, 0, 0, true);
                tree_ref phi = phi_at_block (ei, succ->dest);
  	      VARRAY_PUSH_GENERIC_PTR (ei->erefs, newref);
                set_expruse_def (newref, NULL);
                set_exprref_class (newref, 0);
                set_expruse_phiop (newref, true);
                set_expruse_has_real_use (newref, false);
  	      set_exprref_save (newref, false);
  	      set_exprref_reload (newref, false);
  	      set_exprref_inserted (newref, false);
!               phi_operand (phi, block) = newref;
                fibheap_insert (fh, preorder_count++, newref);
              }
          }      
--- 809,829 ----
          {
            if (phi_at_block (ei, succ->dest) != NULL)
              {
!               tree_ref newref = create_ref (NULL, E_USE, 0, block, 0, 
! 					    0, 0, true);
                tree_ref phi = phi_at_block (ei, succ->dest);
  	      VARRAY_PUSH_GENERIC_PTR (ei->erefs, newref);
                set_expruse_def (newref, NULL);
                set_exprref_class (newref, 0);
                set_expruse_phiop (newref, true);
+ 	      set_expruse_phi (newref, phi);
                set_expruse_has_real_use (newref, false);
  	      set_exprref_save (newref, false);
  	      set_exprref_reload (newref, false);
  	      set_exprref_inserted (newref, false);
! 	      set_exprref_processed (newref, false);
! 	      set_exprref_processed2 (newref, false);	 
! 	      add_ephi_arg (phi, newref, succ);
                fibheap_insert (fh, preorder_count++, newref);
              }
          }      
*************** insert_occ_in_preorder_dt_order_1 (ei, f
*** 724,730 ****
  	  /* No point in inserting exit blocks into heap first, since
  	     they'll never be anything on the stack. */
  	  if (preorder_count != 0)
! 	    fibheap_insert (fh, preorder_count++, (void *) EXIT_BLOCK_PTR);
          }
            
      }
--- 832,844 ----
  	  /* No point in inserting exit blocks into heap first, since
  	     they'll never be anything on the stack. */
  	  if (preorder_count != 0)
! 	    {
! 	      tree_ref newref;
! 	      newref = create_ref (NULL, E_EXIT, 0, block, 
! 				   NULL, NULL, NULL, true);
! 	      VARRAY_PUSH_GENERIC_PTR (ei->erefs, newref);
! 	      fibheap_insert (fh, preorder_count++, newref);
! 	    }
          }
            
      }
*************** phi_opnd_from_res (ei, Z, j, b)
*** 787,797 ****
        tree_ref v = rli_ref (k);
        if (ref_type (v) == V_USE)
  	if (ei->strred_cand)
! 	  while  (is_injuring_def (ei, ref_expr (imm_reaching_def (v))))
  	    {
  	      v = find_rhs_use_for_var (imm_reaching_def (v), ref_var (v));
! 	      if (is_default_def (imm_reaching_def (v))
! 		  || ref_type (imm_reaching_def (v)) == V_PHI)
  		break;
  	      v = find_rhs_use_for_var (imm_reaching_def (v), ref_var (v));
  	    }
--- 901,910 ----
        tree_ref v = rli_ref (k);
        if (ref_type (v) == V_USE)
  	if (ei->strred_cand)
! 	  while  (is_injuring_def (ei, ref_stmt (imm_reaching_def (v))))
  	    {
  	      v = find_rhs_use_for_var (imm_reaching_def (v), ref_var (v));
! 	      if (!okay_injuring_def (imm_reaching_def (v), ref_var (v)))
  		break;
  	      v = find_rhs_use_for_var (imm_reaching_def (v), ref_var (v));
  	    }
*************** phi_opnd_from_res (ei, Z, j, b)
*** 813,819 ****
                 || ref_type (v) == V_PHI
                 || ref_type (v) == E_USE)
  	VARRAY_GENERIC_PTR (Q, i) = NULL;
!     i++;
      }
    return Q;
  }
--- 926,932 ----
                 || ref_type (v) == V_PHI
                 || ref_type (v) == E_USE)
  	VARRAY_GENERIC_PTR (Q, i) = NULL;
!       i++;
      }
    return Q;
  }
*************** rename_2 (ei, rename2_set)
*** 826,851 ****
  {
    size_t i;
    splay_tree touched_set;
-   basic_block block;
  
    /* Keep track of which phi operands we touch.  */
    touched_set = splay_tree_new (splay_tree_compare_pointers, NULL, NULL);
  
    /* For each exprphi f in the program do
  	for each operand w of f do
! 	  processed (w) = false.  */
!   for (i = 0; i < VARRAY_SIZE (ei->phis); i++)
!     {
!       tree_ref phi = VARRAY_GENERIC_PTR (ei->phis, i);
!       if (phi != NULL)
!         bitmap_clear (exprphi_processed(phi));
!     }
!   
    /* while (set_for_rename2 not empty) do { */
    while (VARRAY_ACTIVE_SIZE (*rename2_set) > 0)
      {
        tree_ref Z; 
        tree_ref phiZ;
  
        /* Remove real occurrence Z from set_for_rename2.  */
        Z = VARRAY_TOP_GENERIC_PTR (*rename2_set);
--- 939,960 ----
  {
    size_t i;
    splay_tree touched_set;
  
    /* Keep track of which phi operands we touch.  */
    touched_set = splay_tree_new (splay_tree_compare_pointers, NULL, NULL);
  
    /* For each exprphi f in the program do
  	for each operand w of f do
! 	  processed (w) = false.  
! 
! 	  This was done earlier, i'm just including the comment for reference
! 	  purposes. */
    /* while (set_for_rename2 not empty) do { */
    while (VARRAY_ACTIVE_SIZE (*rename2_set) > 0)
      {
        tree_ref Z; 
        tree_ref phiZ;
+       size_t curr_phiop;
  
        /* Remove real occurrence Z from set_for_rename2.  */
        Z = VARRAY_TOP_GENERIC_PTR (*rename2_set);
*************** rename_2 (ei, rename2_set)
*** 856,873 ****
        /* f <- phi that defines Z. */
        phiZ = expruse_def (Z);
        
!       /* for each operand w of f do { */
!       FOR_EACH_BB (block)
  	{
            tree_ref w;
! 	  i = block->index;
! 	  
!           if (phi_operand (phiZ, block) == NULL)
!             continue;
!           w = phi_operand (phiZ, block);
  	  
  	  /* if (not processed(w)) { */
!           if (!bitmap_bit_p (exprphi_processed (phiZ), i))
              {
                /* j = i because we lookup the real index in the
                   function. */
--- 965,978 ----
        /* f <- phi that defines Z. */
        phiZ = expruse_def (Z);
        
!       for (curr_phiop = 0; curr_phiop < num_ephi_args (phiZ); curr_phiop++)
  	{
            tree_ref w;
! 	  i = phi_arg_edge (ephi_arg (phiZ, curr_phiop))->src->index;
! 	  w = phi_arg_def (ephi_arg (phiZ, curr_phiop));
  	  
  	  /* if (not processed(w)) { */
!           if (!exprref_processed (w))
              {
                /* j = i because we lookup the real index in the
                   function. */
*************** rename_2 (ei, rename2_set)
*** 889,895 ****
  	        }
  
  	      /* if (X is a real occurrence) */
! 	      if (ref_type (X) == E_USE)
                  {
                    bool match = true;
  		  ref_list_iterator l;
--- 994,1000 ----
  	        }
  
  	      /* if (X is a real occurrence) */
! 	      if (ref_type (X) == E_USE || ref_type (X) == E_LEFT)
                  {
                    bool match = true;
  		  ref_list_iterator l;
*************** rename_2 (ei, rename2_set)
*** 905,917 ****
  		    if ((ref_type (op1) != V_USE))
  		      continue;
  		    if (ei->strred_cand)
! 		      while (is_injuring_def (ei, ref_expr (imm_reaching_def (op1))))
  			{
  			  op1 = find_rhs_use_for_var (imm_reaching_def (op1),
  						      ref_var (op1));
  
! 			  if (is_default_def (imm_reaching_def (op1))
! 			      || ref_type (imm_reaching_def (op1)) == V_PHI)
  			    break;
  
  			  op1 = find_rhs_use_for_var (imm_reaching_def (op1),
--- 1010,1024 ----
  		    if ((ref_type (op1) != V_USE))
  		      continue;
  		    if (ei->strred_cand)
! 		      while (is_injuring_def (ei, ref_stmt (imm_reaching_def (op1))))
  			{
+ 			  if (!maybe_find_rhs_use_for_var (imm_reaching_def (op1),
+ 							  ref_var (op1)))
+ 			    break;
  			  op1 = find_rhs_use_for_var (imm_reaching_def (op1),
  						      ref_var (op1));
  
! 			  if (!okay_injuring_def (imm_reaching_def (op1), ref_var (op1)))
  			    break;
  
  			  op1 = find_rhs_use_for_var (imm_reaching_def (op1),
*************** rename_2 (ei, rename2_set)
*** 927,942 ****
  		      op2 = imm_reaching_def (op2);
  
  		    if (ei->strred_cand)
! 		      while (is_injuring_def (ei, ref_expr (op2)))
  			{
  			  tree_ref ird;
  			  op2 = find_rhs_use_for_var (op2, ref_var
  						      (op2));
  			  ird = imm_reaching_def (op2);
! 			  if (is_default_def (ird)
! 			      || ref_type (ird) == V_PHI
! 			      || !maybe_find_rhs_use_for_var (ird, 
! 							      ref_var (op2)))
  			    {
  			      op2 = ird;
  			      break;
--- 1034,1046 ----
  		      op2 = imm_reaching_def (op2);
  
  		    if (ei->strred_cand)
! 		      while (is_injuring_def (ei, ref_stmt (op2)))
  			{
  			  tree_ref ird;
  			  op2 = find_rhs_use_for_var (op2, ref_var
  						      (op2));
  			  ird = imm_reaching_def (op2);
! 			  if (!okay_injuring_def (ird, ref_var (op2)))
  			    {
  			      op2 = ird;
  			      break;
*************** rename_2 (ei, rename2_set)
*** 1001,1007 ****
                      }
                  }
  	      /* processed (w) <- true */
! 	      bitmap_set_bit (exprphi_processed (phiZ), i);
                VARRAY_CLEAR (Y); 
              }
          }
--- 1105,1111 ----
                      }
                  }
  	      /* processed (w) <- true */
! 	      set_exprref_processed (w, true);
                VARRAY_CLEAR (Y); 
              }
          }
*************** rename_1 (ei)
*** 1017,1022 ****
--- 1121,1127 ----
    fibheap_t fh = fibheap_new ();
    tree_ref y;
    varray_type stack;
+   varray_type stack2;
    varray_type rename2_set;
    varray_type recheck_set;
    splay_tree touched_set;
*************** rename_1 (ei)
*** 1025,1031 ****
    /* count <- 0
       stack <- empty
       set_for_rename2 <- {} */
!   VARRAY_GENERIC_PTR_INIT (stack, 1, "Stack");
    VARRAY_GENERIC_PTR_INIT (rename2_set, 1, "Rename2 set");
    VARRAY_GENERIC_PTR_INIT (recheck_set, 1, "Recheck set");
    class_count = 1;
--- 1130,1137 ----
    /* count <- 0
       stack <- empty
       set_for_rename2 <- {} */
!   VARRAY_GENERIC_PTR_INIT (stack, 1, "Stack for renaming");
!   VARRAY_GENERIC_PTR_INIT (stack2, 1, "Stack for downsafety");
    VARRAY_GENERIC_PTR_INIT (rename2_set, 1, "Rename2 set");
    VARRAY_GENERIC_PTR_INIT (recheck_set, 1, "Recheck set");
    class_count = 1;
*************** rename_1 (ei)
*** 1036,1066 ****
    while (!fibheap_empty (fh))
      {
        y = fibheap_extract_min (fh);
-       if ((basic_block) y == EXIT_BLOCK_PTR)
-         {
- 	  if (VARRAY_ACTIVE_SIZE (stack) > 0)
-             {
-               tree_ref stackref = VARRAY_TOP_GENERIC_PTR (stack);
-               if (ref_type (stackref) == E_PHI)
-                 set_exprphi_downsafe (stackref, false);
-             }
-           continue;
-         }
-       if (ref_type (y) == E_KILL 
- 	  && TREE_CODE (ref_expr (y)) == CALL_EXPR)
-         {
- 	  if (VARRAY_ACTIVE_SIZE (stack) > 0)
-             {
-               tree_ref stackref = VARRAY_TOP_GENERIC_PTR (stack);
-               if (ref_type (stackref) == E_PHI)
-                 set_exprphi_downsafe (stackref, false);
- 	      VARRAY_POP_ALL (stack);
-             }
-           continue;       
-         }
-       
        /* while (Top(stack) does not dominate Y) do 
! 	   Pop(stack)  */
        while (VARRAY_ACTIVE_SIZE (stack) > 0)
          {
            tree_ref stackref = VARRAY_TOP_GENERIC_PTR (stack);
--- 1142,1149 ----
    while (!fibheap_empty (fh))
      {
        y = fibheap_extract_min (fh);
        /* while (Top(stack) does not dominate Y) do 
! 	 Pop(stack)  */
        while (VARRAY_ACTIVE_SIZE (stack) > 0)
          {
            tree_ref stackref = VARRAY_TOP_GENERIC_PTR (stack);
*************** rename_1 (ei)
*** 1068,1079 ****
              break;           
            VARRAY_POP (stack);
          }
! 
        /* if (Y is an exprphi occurrence)
             assign_new_class (Y)  */
        if (ref_type (y) == E_PHI)
          {
! 	  assign_new_class (y, &stack);
          }
        /* else if (Y is a real occurrence) */
        else if (ref_type (y) == E_USE && expruse_phiop (y) == false)
--- 1151,1178 ----
              break;           
            VARRAY_POP (stack);
          }
!       while (VARRAY_ACTIVE_SIZE (stack2) > 0)
!         {
!           tree_ref stackref = VARRAY_TOP_GENERIC_PTR (stack2);
!           if (a_dom_b (ref_bb (stackref), ref_bb (y)))
!             break;           
!           VARRAY_POP (stack2);
!         }
!       if (ref_type (y) == E_EXIT)
!         {
! 	  if (VARRAY_ACTIVE_SIZE (stack2) > 0)
!             {
!               tree_ref stackref = VARRAY_TOP_GENERIC_PTR (stack2);
!               if (ref_type (stackref) == E_PHI)
!                 set_exprphi_downsafe (stackref, false);
!             }
!           continue;
!         }
        /* if (Y is an exprphi occurrence)
             assign_new_class (Y)  */
        if (ref_type (y) == E_PHI)
          {
! 	  assign_new_class (y, &stack, &stack2);
          }
        /* else if (Y is a real occurrence) */
        else if (ref_type (y) == E_USE && expruse_phiop (y) == false)
*************** rename_1 (ei)
*** 1082,1088 ****
  	       Assign_New_Class(Y) */
            if (VARRAY_ACTIVE_SIZE (stack) == 0)
              {
!               assign_new_class ( y, &stack);
              }
            /* else */
            else
--- 1181,1187 ----
  	       Assign_New_Class(Y) */
            if (VARRAY_ACTIVE_SIZE (stack) == 0)
              {
!               assign_new_class ( y, &stack, &stack2);
              }
            /* else */
            else
*************** rename_1 (ei)
*** 1090,1117 ****
  	      /* X <- Top(stack) */
                tree_ref x = VARRAY_TOP_GENERIC_PTR (stack);
  	      
!               /* If (X is a real occurrence) */
!               if (ref_type (x) == E_USE)
                  {
                    /* If (all corresponding variables in Y and X have
                       the same SSA version) */
!                   if (defs_match_p (ei, ref_stmt (y), ref_expr (x)))
                      {
                        /* class(Y) <- class(X)
                           def(Y) <- X */
                        set_exprref_class (y, exprref_class (x));
! #if 0
!                       EXPRUSE_DEF (y) = x;
  #else
  		      set_expruse_def (y, expruse_def (x) != NULL ? expruse_def (x) : x);
  #endif
                      }
  		  /* else Assign_New_Class (Y) */
                    else
                      {
!                       assign_new_class ( y, &stack);
                      }
                  }
                else /* X is a ExprPhi occurrence. */
                  {
                    if (ref_type (x) != E_PHI)
--- 1189,1221 ----
  	      /* X <- Top(stack) */
                tree_ref x = VARRAY_TOP_GENERIC_PTR (stack);
  	      
!               /* If (X is a real occurrence or a left occurrence) */
!               if (ref_type (x) == E_USE || ref_type (x) == E_LEFT)
                  {
                    /* If (all corresponding variables in Y and X have
                       the same SSA version) */
!                   if (defs_match_p (ei, ref_stmt (y), ref_stmt (x)))
                      {
                        /* class(Y) <- class(X)
                           def(Y) <- X */
                        set_exprref_class (y, exprref_class (x));
! #if 1
! 		      set_expruse_def (y, x);
  #else
  		      set_expruse_def (y, expruse_def (x) != NULL ? expruse_def (x) : x);
  #endif
+ 		      VARRAY_PUSH_GENERIC_PTR (stack2, y);
                      }
  		  /* else Assign_New_Class (Y) */
                    else
                      {
!                       assign_new_class ( y, &stack, &stack2);
                      }
                  }
+ 	      else if (ref_type (x) == E_KILL)
+ 		{
+ 		  assign_new_class (y, &stack, &stack2);
+ 		}
                else /* X is a ExprPhi occurrence. */
                  {
                    if (ref_type (x) != E_PHI)
*************** doesn't dominate whatever  occurrences w
*** 1160,1172 ****
  we'll pop it, and if the phi isn't really going to be downsafe, we'll
  catch it in rename_2 or during downsafety propagation. */
  
! 		      VARRAY_PUSH_GENERIC_PTR (stack, y);		      
  		      VARRAY_PUSH_GENERIC_PTR (rename2_set, y);
                      }
                    else
                      {
  		      set_exprphi_downsafe (x, false);
!                       assign_new_class ( y, &stack);
                      }
                  } 
              } 
--- 1264,1277 ----
  we'll pop it, and if the phi isn't really going to be downsafe, we'll
  catch it in rename_2 or during downsafety propagation. */
  
! //		      VARRAY_PUSH_GENERIC_PTR (stack, y);
! 		      VARRAY_PUSH_GENERIC_PTR (stack2, y);
  		      VARRAY_PUSH_GENERIC_PTR (rename2_set, y);
                      }
                    else
                      {
  		      set_exprphi_downsafe (x, false);
!                       assign_new_class ( y, &stack, &stack2);
                      }
                  } 
              } 
*************** catch it in rename_2 or during downsafet
*** 1179,1207 ****
                /* def(Y) <- tack */
  	      set_expruse_def (y, NULL);
  	      set_expruse_has_real_use (y, false);
              }
            else
              {
- 
                /* X = Top(stack)
                   class(Y) <- class(X)
                   def(Y) <- X */
                tree_ref x = VARRAY_TOP_GENERIC_PTR (stack);
!               set_exprref_class (y, exprref_class (x));
!               set_expruse_def (y, x);
! 	      if (ref_type (x) != E_PHI)
! 		{
! 		  set_expruse_has_real_use (y, true);
! 		  if (expruse_def (x) && ref_type (expruse_def (x)) == E_PHI)
! 			VARRAY_PUSH_GENERIC_PTR (rename2_set, x);
  		}
  	      else
  		{
! 		  set_expruse_has_real_use (y, false);
! 		  VARRAY_PUSH_GENERIC_PTR (recheck_set, y);
  		}
  	    }
          }
        else
          abort();
      }
--- 1284,1336 ----
                /* def(Y) <- tack */
  	      set_expruse_def (y, NULL);
  	      set_expruse_has_real_use (y, false);
+ 	      set_exprref_processed (y, true);
              }
            else
              {
                /* X = Top(stack)
                   class(Y) <- class(X)
                   def(Y) <- X */
                tree_ref x = VARRAY_TOP_GENERIC_PTR (stack);
! 	      tree_ref x2 = VARRAY_TOP_GENERIC_PTR (stack2);
! 	      if (ref_type (x) == E_KILL)
! 		{		  
! 		  set_expruse_def (y, NULL);
! 		  set_exprref_processed (y, true);
! 		  if (ref_type (x2) == E_PHI)
! 		    {
! 		      set_exprphi_downsafe (x2, false);
! 		    }
  		}
  	      else
  		{
! 		  
! 		  set_exprref_class (y, exprref_class (x));
! 		  set_expruse_def (y, x);
! 		  if ((ref_type (x2) == E_USE && !expruse_phiop (x2)) 
! 		      || ref_type (x2) == E_LEFT)
! 		    {
! 		      set_expruse_has_real_use (y, true);
! 		      		  
! 		/*	if (expruse_def (x) && ref_type (expruse_def (x)) == E_PHI)
! 			  VARRAY_PUSH_GENERIC_PTR (rename2_set, x);*/
! 		    }
! 		  else
! 		    {
! 		      set_expruse_has_real_use (y, false);
! 		      VARRAY_PUSH_GENERIC_PTR (recheck_set, y);
! 		    }
  		}
  	    }
          }
+       else if (ref_type (y) == E_KILL)
+ 	{
+ 	  VARRAY_PUSH_GENERIC_PTR (stack, y);
+ 	}
+       else if (ref_type (y) == E_LEFT)
+ 	{
+ 	  assign_new_class (y, &stack, &stack2);
+ 	}
        else
          abort();
      }
*************** catch it in rename_2 or during downsafet
*** 1223,1244 ****
      {
        tree_ref ref = VARRAY_GENERIC_PTR (recheck_set, i);
        tree_ref def;
!       bool needcheck = true;
!       edge succ;
        if (!ref)
  	continue;
        def = expruse_def (ref);
!       for (succ = ref_bb (ref)->succ; succ; succ = succ->succ_next)
! 	{
! 	  if (phi_at_block (ei, succ->dest) != NULL)
! 	    {
! 	      tree_ref phi = phi_at_block (ei, succ->dest);
! 	      if (bitmap_bit_p (exprphi_processed (phi), 
! 				ref_bb (ref)->index))
! 		needcheck = false;
! 	    }
! 	}
!       if (!needcheck)
  	continue;
  
        if (def && (ref_type (def) == E_PHI))
--- 1352,1363 ----
      {
        tree_ref ref = VARRAY_GENERIC_PTR (recheck_set, i);
        tree_ref def;
! 
        if (!ref)
  	continue;
+ 
        def = expruse_def (ref);
!       if (exprref_processed (ref))
  	continue;
  
        if (def && (ref_type (def) == E_PHI))
*************** catch it in rename_2 or during downsafet
*** 1248,1320 ****
      }
    fibheap_delete (fh);
    VARRAY_CLEAR (stack);
    VARRAY_CLEAR (rename2_set);
    VARRAY_CLEAR (recheck_set);
    splay_tree_delete (touched_set);
  }
  
- /* XXX: Do this smarter */
- /* Figure out which PHI contains the operand.  */
  static tree_ref
! phi_for_operand (ei, operand)
!      struct expr_info *ei;
!      tree_ref operand;
  {
!   int count = 0;
!   tree_ref retval = NULL;
!   basic_block bb;
! 
!   FOR_EACH_BB (bb)
!     {
!       tree_ref phi = phi_at_block (ei, bb);
!       if (phi != NULL)
!         {
! 	  basic_block bb2;
! 	  FOR_EACH_BB (bb2)
! 	    {
! 	      if (phi_operand (phi, bb2) ==  operand)
! 	      {
! 		count++;
! 		retval = phi;
! 	      }	  
! 	    }
! 	}
!     }
!   /* Theoretically, phi operand to phi is a 1 to many mapping.  But we
!      don't return more than one value right now, so if we found multiple
!      phis containing this operand, abort.  */
!   if (count > 1)
!     abort();
!   
!   return retval;
  }
! 
  /* Figure out which expressions need to be saved.  */
  static void
  set_save (ei, X)
       struct expr_info *ei;
       tree_ref X;
  {
!   basic_block bb;
!   if (ref_type (X) == E_USE && !expruse_phiop (X))
      set_exprref_save (X, true);
    else if (ref_type (X) == E_PHI)
      {
        int i;
!       FOR_EACH_BB (bb)
  	{
! 	  tree_ref w = phi_operand (X, bb);
! 	  i = bb->index;
  
! 	  if (w && !bitmap_bit_p (exprphi_processed (X), i))
  	    {
! 	      bitmap_set_bit (exprphi_processed (X), i);
  	      set_save (ei, expruse_def (w));
  	    }
  	}
      }
  #if EXTRANEOUS_EPHI_REMOVAL 
!   if (ref_type (X) == E_USE && !expruse_phiop (X))
      {
        sbitmap idfs = compute_idfs (pre_dfs, ref_stmt (X));
        int i;
--- 1367,1418 ----
      }
    fibheap_delete (fh);
    VARRAY_CLEAR (stack);
+   VARRAY_CLEAR (stack2);
    VARRAY_CLEAR (rename2_set);
    VARRAY_CLEAR (recheck_set);
    splay_tree_delete (touched_set);
  }
  
  static tree_ref
! phi_operand_for_pred (phi, e)
!      tree_ref phi;
!      edge e;
  {
!   size_t i;
!   for (i = 0; i < num_ephi_args (phi); i++)
!     if (phi_arg_edge (ephi_arg (phi, i)) == e)
!       return phi_arg_def (ephi_arg (phi, i));
!   abort ();
  }
!      
  /* Figure out which expressions need to be saved.  */
  static void
  set_save (ei, X)
       struct expr_info *ei;
       tree_ref X;
  {
!   if ((ref_type (X) == E_USE && !expruse_phiop (X))
!       || ref_type (X) == E_LEFT)
      set_exprref_save (X, true);
    else if (ref_type (X) == E_PHI)
      {
        int i;
!       size_t curr_phiop;
!       for (curr_phiop = 0; curr_phiop < num_ephi_args (X); curr_phiop++)
  	{
! 	  tree_ref w = phi_arg_def (ephi_arg (X, curr_phiop));
! 	  i = phi_arg_edge (ephi_arg (X, curr_phiop))->src->index;
  
! 	  if (!exprref_processed2 (w))
  	    {
! 	      set_exprref_processed2 (w, true);
  	      set_save (ei, expruse_def (w));
  	    }
  	}
      }
  #if EXTRANEOUS_EPHI_REMOVAL 
!   if ((ref_type (X) == E_USE && !expruse_phiop (X))
!       || ref_type (X) == E_LEFT)
      {
        sbitmap idfs = compute_idfs (pre_dfs, ref_stmt (X));
        int i;
*************** set_replacement (ei, g, replacing_def)
*** 1336,1374 ****
       tree_ref g;
       tree_ref replacing_def;
  {
!   basic_block bb1;
!   FOR_EACH_BB (bb1)
      {
!       size_t k;
!       basic_block bb2;
!       tree_ref f = phi_at_block (ei, bb1);
!       if (f == NULL || !exprphi_willbeavail (f) || f == g)
! 	continue;
!       FOR_EACH_BB (bb2)
  	{
! 	  tree_ref operand = phi_operand (f, bb2);
! 	  if (operand && expruse_def (operand) == g)
  	    {
! 	      if (exprphi_extraneous (f))
! 		set_replacement (ei, f, replacing_def);
! 	      else
! 		phi_operand (f, bb2) = replacing_def;
  	    }
! 	}
!       for (k = 0; k < VARRAY_ACTIVE_SIZE (ei->erefs); k++)
! 	{
! 	  tree_ref X = VARRAY_GENERIC_PTR (ei->erefs, k);
! 	  if (ref_type (X) == E_USE 
! 	      && expruse_phiop (X) == false
! 	      && exprref_reload (X)
! 	      && expruse_def (X) == g)
  	    {
! 	      set_expruse_def (X, replacing_def);
  	    }
  	}
      }
    phi_at_block (ei, ref_bb (g)) = NULL;
!   
  }
  
  /* Second part of finalize algorithm.  */
--- 1434,1483 ----
       tree_ref g;
       tree_ref replacing_def;
  {
!   ref_list_iterator rli;
!   
!   rli = rli_start (exprref_uses (g));
!   for (; !rli_after_end (rli); rli_step (&rli))
      {
!       tree_ref x = rli_ref (rli);
!       
!       if (ref_type (x) == E_USE && expruse_phiop (x))
  	{
! 	  tree_ref f = expruse_phi (x);
! 	  if (exprphi_extraneous (f) && !exprref_processed (f))
  	    {
! 	      set_exprref_processed (f, true);
! 	      set_replacement (ei, f, replacing_def);
  	    }
! 	  else if (!exprphi_extraneous (f))
  	    {
! #if DEBUGGING_EPHI_REMOVAL 
! 	      if (dump_file)
! 		fprintf (dump_file, "Replacing id %lu with id %lu\n", ref_id (x), ref_id (replacing_def));
! #endif
! 	      set_exprref_class (x, exprref_class (replacing_def));
! 	      set_expruse_def (x, replacing_def);
  	    }
  	}
      }
+   rli = rli_start (exprref_uses (g));
+   for (; !rli_after_end (rli); rli_step (&rli))
+     {
+       tree_ref x = rli_ref (rli);
+       if (ref_type (x) == E_USE && !expruse_phiop (x) 
+ 	  && exprref_reload (x))
+ 	{
+ 	  set_exprref_class (x, exprref_class (replacing_def));
+ 	  set_expruse_def (x, replacing_def);
+ 	}
+     }
+ 
+ #if DEBUGGING_EPHI_REMOVAL
+       if (dump_file)
+ 	fprintf (dump_file, "Removing E_PHI id %lu\n", ref_id (g));
+ #endif
    phi_at_block (ei, ref_bb (g)) = NULL;
!   remove_ref_from_list (ei->euses_dt_order, g);
  }
  
  /* Second part of finalize algorithm.  */
*************** finalize_2 (ei)
*** 1382,1388 ****
        tree_ref ref = VARRAY_GENERIC_PTR (ei->erefs, i);
        if (ref_type (ref) == E_PHI)
  	{
- 	  bitmap_clear (exprphi_processed (ref));
  	  if (exprphi_willbeavail (ref))
  	    set_exprphi_extraneous (ref, true);
  	}
--- 1491,1496 ----
*************** finalize_2 (ei)
*** 1413,1429 ****
        if (exprphi_willbeavail (ref))
  	{
  	  int k;
! 	  for (k = 0; k < n_basic_blocks; k++)
  	    {
! 	      tree_ref w = phi_operand (ref, BASIC_BLOCK (k));
  	      tree_ref defw;
  	      if (!w || !expruse_def (w) )
  		continue;
  	      defw = expruse_def (w);
! 	      if ((ref_type (defw) == E_PHI 
! 		   && !exprphi_extraneous (defw))
! 		  || (ref_type (defw) == E_USE 
! 		      && !expruse_phiop (defw)))
  		set_replacement (ei, ref, expruse_def (w));  
  	    }
  	}
--- 1521,1536 ----
        if (exprphi_willbeavail (ref))
  	{
  	  int k;
! 	  for (k = 0; k < num_ephi_args (ref); k++)
  	    {
! 	      tree_ref w = phi_arg_def (ephi_arg (ref, k));
  	      tree_ref defw;
  	      if (!w || !expruse_def (w) )
  		continue;
  	      defw = expruse_def (w);
! 	      if ((ref_type (defw) == E_PHI && !exprphi_extraneous (defw))
! 		  || (ref_type (defw) == E_USE && !expruse_phiop (defw)) 
! 		  || ref_type (defw) == E_LEFT)
  		set_replacement (ei, ref, expruse_def (w));  
  	    }
  	}
*************** finalize_2 (ei)
*** 1434,1461 ****
      }
  #endif
  }
  
  /* First part of finalize algorithm.  */
! static void
  finalize_1 (ei, temp)
       struct expr_info *ei;
       tree temp;
  {
    tree_ref X;
    int x;
!   fibheap_t fh;
!   avdefs = xcalloc (class_count + 1,sizeof (tree_ref));
!   fh = fibheap_new ();
!   insert_euse_in_preorder_dt_order (ei, fh);
!   while (!fibheap_empty (fh))
      {
!       X = fibheap_extract_min (fh);
        x = exprref_class (X);
        if (ref_type (X) == E_PHI)
          {
            if (exprphi_willbeavail (X))
              avdefs[x] = X;
          }
        else if (ref_type (X) == E_USE && expruse_phiop (X) == false)
          {
            if (avdefs[x] == NULL 
--- 1541,1621 ----
      }
  #endif
  }
+ static void
+ update_old_new (ei, old, new)
+      struct expr_info *ei;
+      tree *old;
+      tree *new;
+ {
+   splay_tree_node result;
+   
+   result = splay_tree_lookup (old_new_map, (splay_tree_key)old);
+   if (result)
+     {
+       size_t i;
+       for (i = 0; i < VARRAY_ACTIVE_SIZE (ei->occurs); i++)
+ 	{
+ 	  if (VARRAY_GENERIC_PTR (ei->occurs, i) == old)
+ 	    VARRAY_GENERIC_PTR (ei->occurs, i) = (PTR) result->value;
+ 	}
+     }
+   splay_tree_insert (old_new_map, (splay_tree_key) old, (splay_tree_value) new);
+ }
+ /* This routine is a temporary thing. It is meant to fix up refs that *MUST* be
+    fixed up in order for the algorithm to continue to work properly (as opposed
+    to  those we fix up in order to update the SSA representation).  Their will
+    be  routines that do this for us eventually. */
+ static void
+ temp_fix_refs (lookin, lookfor, replacewith)
+      tree lookin;
+      tree lookfor;
+      tree *replacewith;
+ {
+   ref_list_iterator rli;
+ 
+   rli = rli_start (tree_refs (lookin));
+   for (; !rli_after_end (rli); rli_step (&rli))
+     {
+       tree_ref ref = rli_ref (rli);
+       if (ref_stmt (ref) == lookfor)
+ 	{
+ 	  ref->common.stmt_p = replacewith;
+ 	  ref->common.expr_p = replacewith;
+ 	}
+     }
+ }
+ 
  
  /* First part of finalize algorithm.  */
! static bool
  finalize_1 (ei, temp)
       struct expr_info *ei;
       tree temp;
  {
    tree_ref X;
    int x;
!   ref_list_iterator euse_rli;
!   bool made_a_reload = false;
!   
!   avdefs = xcalloc (class_count + 1,sizeof (tree_ref));  
!   ei->euses_dt_order = create_ref_list ();
!   
!   insert_euse_in_preorder_dt_order (ei);
!   
!   euse_rli = rli_start (ei->euses_dt_order);
!   for (; !rli_after_end (euse_rli); rli_step (&euse_rli))
      {
!       X = rli_ref (euse_rli);
        x = exprref_class (X);
        if (ref_type (X) == E_PHI)
          {
            if (exprphi_willbeavail (X))
              avdefs[x] = X;
          }
+       else if (ref_type (X) == E_LEFT)
+ 	{
+ 	  avdefs[x] = X;
+ 	}
        else if (ref_type (X) == E_USE && expruse_phiop (X) == false)
          {
            if (avdefs[x] == NULL 
*************** finalize_1 (ei, temp)
*** 1467,1478 ****
            else
              {
  	      set_exprref_reload (X, true);
                set_expruse_def (X, avdefs[x]);
              }
          }
        else
          {
!           tree_ref phi = phi_for_operand (ei, X);
            if (!phi)
              abort ();
            if (exprphi_willbeavail (phi))           
--- 1627,1639 ----
            else
              {
  	      set_exprref_reload (X, true);
+ 	      made_a_reload = true;
                set_expruse_def (X, avdefs[x]);
              }
          }
        else
          {
!           tree_ref phi = expruse_phi (X);
            if (!phi)
              abort ();
            if (exprphi_willbeavail (phi))           
*************** finalize_1 (ei, temp)
*** 1481,1489 ****
                  {
  		  tree stmt;
  		  tree expr;
! 		  tree *place;
  		  basic_block bb;
  		  tree endtree;
  
                    /* Insert definition of expr at end of BB containing X. */
  		  if (dump_file)
--- 1642,1652 ----
                  {
  		  tree stmt;
  		  tree expr;
! 		  tree *newexprplace;
! 		  tree *otherexprplace;
  		  basic_block bb;
  		  tree endtree;
+ 		  tree *endtreep;
  
                    /* Insert definition of expr at end of BB containing X. */
  		  if (dump_file)
*************** finalize_1 (ei, temp)
*** 1505,1530 ****
  						  deep_copy_node (ei->expr)));
  		  bb = ref_bb (X);
  		  endtree = last_stmt (bb);
  		  /* FIXME: Need DFA inserting updating to do this the right
  		     way. */
  		  /* If it's a goto, we need to insert *before* it.
  		     This might not be necessary once goto elimination
! 		     is functional.  */
! 		  if (is_ctrl_altering_stmt (endtree))
  		    {
! 		      stmt = build (COMPOUND_EXPR, void_type_node, expr, endtree);
! 		      place = &TREE_OPERAND (stmt, 0);
  		    }
  		  else
  		    {
! 		      stmt = build (COMPOUND_EXPR, void_type_node, endtree, expr);
! 		      place = &TREE_OPERAND (stmt, 1);
  		    }
! 		  
! 		  *bb->end_tree_p = stmt;
  		  TREE_CHAIN (stmt) = TREE_CHAIN (endtree);
  		  TREE_CHAIN (endtree) = NULL;
! 		  TREE_TYPE (stmt) = TREE_TYPE (expr);
  
  #if WAITING_FOR_DFA_UPDATE
  		  /* Update the SSA for the newly inserted definition.
--- 1668,1805 ----
  						  deep_copy_node (ei->expr)));
  		  bb = ref_bb (X);
  		  endtree = last_stmt (bb);
+ 		  endtreep = last_stmt_ptr (bb);
  		  /* FIXME: Need DFA inserting updating to do this the right
  		     way. */
  		  /* If it's a goto, we need to insert *before* it.
  		     This might not be necessary once goto elimination
! 		     is functional.  
! 		     If it's an empty statement, always insert before. */
! 		  if (endtree == empty_stmt_node)
  		    {
! 		      stmt = build (COMPOUND_EXPR, void_type_node,
! 				    expr, empty_stmt_node);
! 		      newexprplace = &TREE_OPERAND (stmt, 0);
! 		      otherexprplace = &TREE_OPERAND (stmt, 1);
! 		    }
! 		  else if (is_ctrl_altering_stmt (endtree))
! 		    {
! 		      stmt = build (COMPOUND_EXPR, void_type_node, 
! 				    expr, endtree);
! 		      newexprplace = &TREE_OPERAND (stmt, 0);
! 		      otherexprplace = &TREE_OPERAND (stmt, 1);
  		    }
  		  else
  		    {
! 		      stmt = build (COMPOUND_EXPR, void_type_node, 
! 				    endtree, expr);
! 		      newexprplace = &TREE_OPERAND (stmt, 1);
! 		      otherexprplace = &TREE_OPERAND (stmt, 0);
  		    }
! 		  /* FIXME: This can't be fixed without the insertion machinery
! 		     knowing what to do about it. */
! 		  if (endtree == empty_stmt_node)
! 		    abort ();
! #if 0
! 		  if (endtree == empty_stmt_node)
! 		    {
! 		      gimple_stmt_iterator gsi;
! 		      edge e;
! 		      if (bb->parent_tree_p)
! 		        {
! 				*bb->parent_tree_p = stmt;
! 				bb->end_tree_p = bb->parent_tree_p;
! 				endtreep = bb->end_tree_p;
! 				goto done;
! 			}
! #if 1
! 		      for (e = bb->pred; e; e = e->pred_next)
! 			{
! 			  for (gsi = gsi_start_bb (e->src); 
! 			       !gsi_after_end (gsi); 
! 			       gsi_step (&gsi))
! 			    {
! 			      tree temp = gsi_stmt (gsi);
! 			      STRIP_WFL (temp);
! 			      STRIP_NOPS(temp);
! 			      if (TREE_CODE (temp) == COND_EXPR)
! 				{
! 				  if (COND_EXPR_COND (temp) == endtree)
! 				    {
! 				      COND_EXPR_COND (temp) = stmt;
! 				      bb->end_tree_p = &COND_EXPR_COND (temp);
! 				    }
! 				  else if (COND_EXPR_THEN (temp) == endtree)
! 				    {
! 				      COND_EXPR_THEN (temp) = stmt;
! 				      bb->end_tree_p = &COND_EXPR_THEN (temp);
! 				    }
! 				  else if (COND_EXPR_ELSE (temp) == endtree)
! 				    {
! 				      COND_EXPR_ELSE (temp) = stmt;
! 				      bb->end_tree_p = &COND_EXPR_ELSE (temp);
! 				    }
! 				  endtreep = bb->end_tree_p;
! 				  goto done;
! 				}
! 			    }
! 			} 
! #endif
! #if 1	      
! 		      for (gsi = gsi_start_bb (parent_block (bb)); 
! 			   !gsi_after_end (gsi); 
! 			   gsi_step (&gsi))
! 			{
! 			  tree temp = gsi_stmt (gsi);
! 			  STRIP_WFL (temp);
! 			  STRIP_NOPS (temp);
! 			  if (TREE_CODE (temp) == LOOP_EXPR)
! 			    {
! 			      gsi = gsi_start (&TREE_OPERAND (LOOP_EXPR_BODY (temp), 0));
! 			      temp = gsi_stmt (gsi);
! 			      STRIP_WFL (temp);
! 			      STRIP_NOPS (temp);
! 			      
! 			    }
! 			  
! 			  if (TREE_CODE (temp) == COND_EXPR)
! 			    {
! 			      if (COND_EXPR_COND (temp) == endtree)
! 				{
! 				  COND_EXPR_COND (temp) = stmt;
! 				  bb->end_tree_p = &COND_EXPR_COND (temp);
! 				}
! 			      else if (COND_EXPR_THEN (temp) == endtree)
! 				{
! 				  COND_EXPR_THEN (temp) = stmt;
! 				  bb->end_tree_p = &COND_EXPR_THEN (temp);
! 				}
! 			      else if (COND_EXPR_ELSE (temp) == endtree)
! 				{
! 				  COND_EXPR_ELSE (temp) = stmt;
! 				  bb->end_tree_p = &COND_EXPR_ELSE (temp);
! 				}
! 			      endtreep = bb->end_tree_p;
! 			      goto done;
! 			    }
! 			}
! #endif
! done:
! 		    }
! 		    /* END TEMPORARY HACK */
! 		  else
! #endif
! 		    {
! 		      *endtreep = stmt;
! 		      update_old_new (ei, endtreep, otherexprplace);
! 		      /* REMOVE AFTER DFA UPDATE */
! 		      temp_fix_refs (*otherexprplace, stmt, otherexprplace);
! 		      /* END REMOVE AFTER DFA UPDATE */
! 		    }
! 		  /*
  		  TREE_CHAIN (stmt) = TREE_CHAIN (endtree);
  		  TREE_CHAIN (endtree) = NULL;
! 		  TREE_TYPE (stmt) = TREE_TYPE (expr);*/
  
  #if WAITING_FOR_DFA_UPDATE
  		  /* Update the SSA for the newly inserted definition.
*************** finalize_1 (ei, temp)
*** 1554,1576 ****
  		  splay_tree_insert (new_stmt_map, 
  				     (splay_tree_key) expr,
  				     (splay_tree_value)  stmt);
- 		  
- 		 
- 
  #endif
                    /*
                      expruse_def (X) = new occurrence. 
  		  */		  
  
  		  set_expruse_def (X,create_ref (expr, E_USE, 0,
! 						 ref_bb (X), bb->end_tree_p,
! 						 place, place,  true));
  		  VARRAY_PUSH_GENERIC_PTR (ei->erefs, expruse_def (X));
  		  set_exprref_reload (expruse_def (X), false);
  		  set_exprref_save (expruse_def (X), true);
  		  set_exprref_inserted (expruse_def (X), true);
  		  set_expruse_phiop (expruse_def (X), false);
  		  set_expruse_has_real_use (expruse_def (X), true);
  		  set_exprref_save (X, false);
  		  set_exprref_reload (X, false);
                  }
--- 1829,1853 ----
  		  splay_tree_insert (new_stmt_map, 
  				     (splay_tree_key) expr,
  				     (splay_tree_value)  stmt);
  #endif
                    /*
                      expruse_def (X) = new occurrence. 
  		  */		  
  
  		  set_expruse_def (X,create_ref (expr, E_USE, 0,
! 						 ref_bb (X), newexprplace,
! 						 newexprplace, newexprplace, 
! 						 true));
! 		  set_bb_for_stmt (*newexprplace, ref_bb (X));
! 		  
  		  VARRAY_PUSH_GENERIC_PTR (ei->erefs, expruse_def (X));
  		  set_exprref_reload (expruse_def (X), false);
  		  set_exprref_save (expruse_def (X), true);
  		  set_exprref_inserted (expruse_def (X), true);
  		  set_expruse_phiop (expruse_def (X), false);
  		  set_expruse_has_real_use (expruse_def (X), true);
+ 		  set_exprref_processed (X, false);
+ 		  set_exprref_processed2 (X, false);
  		  set_exprref_save (X, false);
  		  set_exprref_reload (X, false);
                  }
*************** finalize_1 (ei, temp)
*** 1581,1587 ****
              }
          }
      }
!   fibheap_delete (fh);
  }
  
  /* ExprPhi insertion algorithm.  */
--- 1858,1864 ----
              }
          }
      }
!   return made_a_reload;
  }
  
  /* ExprPhi insertion algorithm.  */
*************** expr_phi_insertion (dfs, ei)
*** 1596,1628 ****
    varphis = sbitmap_vector_alloc (2, last_basic_block);
    sbitmap_vector_zero (varphis, 2);  
  
!   for (i = 0; i < VARRAY_ACTIVE_SIZE (ei->reals); i++)
      {
!       tree real = VARRAY_TREE (ei->reals, i);
!       sbitmap temp = compute_idfs (dfs, VARRAY_TREE (ei->realstmts, i));      
        sbitmap_a_or_b (dfphis, dfphis, temp);
        sbitmap_free (temp);
!       if (is_simple_id (TREE_OPERAND (real, 0)) 
! 	  || (TREE_OPERAND (real, 1) 
! 	      && is_simple_id (TREE_OPERAND (real, 1))))
          {
            int varcount = 0;
  	  ref_list_iterator j;
  
! 	  j = rli_start (tree_refs (VARRAY_TREE (ei->realstmts, i)));
  	  for (; !rli_after_end (j); rli_step (&j))
  	  {
  	    tree_ref ref = rli_ref (j);
  	    if (ei->strred_cand)
  	      while (ref_type (ref) == V_USE
! 		     && ref_var (ref) == TREE_OPERAND (real, 0)
  		     && imm_reaching_def (ref)
! 		     && is_injuring_def (ei, ref_expr (imm_reaching_def (ref))))
  		{
  		  ref = find_rhs_use_for_var (imm_reaching_def (ref), 
  					      ref_var (ref));
! 		  if (is_default_def (imm_reaching_def (ref))
! 		      || ref_type (imm_reaching_def (ref)) == V_PHI)
  		    break;
  		  
  		  ref = find_rhs_use_for_var (imm_reaching_def (ref), 
--- 1873,1921 ----
    varphis = sbitmap_vector_alloc (2, last_basic_block);
    sbitmap_vector_zero (varphis, 2);  
  
!   for (i = 0; i < VARRAY_ACTIVE_SIZE (ei->occurs); i++)
      {
!       tree *occurp = VARRAY_GENERIC_PTR (ei->occurs, i);
!       tree occur = occurp ? *occurp : NULL;
!       tree *killp = VARRAY_GENERIC_PTR (ei->kills, i);
!       tree kill = killp ? *killp : NULL;
!       tree *leftp = VARRAY_GENERIC_PTR (ei->lefts, i);
!       tree left = leftp ? *leftp : NULL;
!       sbitmap temp;
!       if ((kill && occur) || (left && occur) || (kill && left))
! 	abort();
!       occurp = occur ? occurp : kill ? killp : leftp;      
!       occur = occur ? occur : kill ? kill : left;
!       temp = compute_idfs (dfs, occur);
        sbitmap_a_or_b (dfphis, dfphis, temp);
        sbitmap_free (temp);
!       STRIP_WFL (occur);
!       if (kill != NULL)
! 	continue;
!       occur = TREE_OPERAND (occur, 1);
!       if (is_simple_id (get_operand (occur, 0))
! 	  || (get_operand (occur, 1) 
! 	      && is_simple_id (get_operand (occur, 1))))
          {
            int varcount = 0;
  	  ref_list_iterator j;
  
! 	  j = rli_start (tree_refs (*occurp));
  	  for (; !rli_after_end (j); rli_step (&j))
  	  {
  	    tree_ref ref = rli_ref (j);
  	    if (ei->strred_cand)
  	      while (ref_type (ref) == V_USE
! 		     && ref_var (ref) == get_operand (occur, 0)
  		     && imm_reaching_def (ref)
! 		     && is_injuring_def (ei, ref_stmt (imm_reaching_def (ref))))
  		{
+ 		  if (!maybe_find_rhs_use_for_var (imm_reaching_def (ref), 
+ 						   ref_var (ref)))
+ 		    break;
  		  ref = find_rhs_use_for_var (imm_reaching_def (ref), 
  					      ref_var (ref));
! 		  if (!okay_injuring_def (imm_reaching_def (ref), ref_var (ref)))
  		    break;
  		  
  		  ref = find_rhs_use_for_var (imm_reaching_def (ref), 
*************** expr_phi_insertion (dfs, ei)
*** 1631,1643 ****
  	      /* ??? If the trees aren't shared, will the last part of this ||
  		 work right? */ 
                if (ref_type (ref) != V_USE
!                   || !is_simple_modify_expr (ref_expr (ref))
!                   /*|| TREE_OPERAND (ref_expr (ref), 1) != real*/)
!                 continue;
!               if (ref_var (ref) != TREE_OPERAND (real, 0)
!                   && (TREE_OPERAND (real, 1) == NULL 
! 		      || ref_var (ref) != TREE_OPERAND (real, 1)))
                  continue;
                if (!imm_reaching_def (ref)
  		  || ref_type (imm_reaching_def (ref)) != V_PHI)
                  continue;
--- 1924,1936 ----
  	      /* ??? If the trees aren't shared, will the last part of this ||
  		 work right? */ 
                if (ref_type (ref) != V_USE
!                   || !is_simple_modify_expr (ref_stmt (ref))
!                   /*|| TREE_OPERAND (ref_stmt (ref), 1) != real*/)
                  continue;
+               if (ref_var (ref) != get_operand (occur, 0)
+                   && (get_operand (occur, 1) == NULL 
+ 		      || ref_var (ref) != get_operand (occur, 1)))
+                 continue; 
                if (!imm_reaching_def (ref)
  		  || ref_type (imm_reaching_def (ref)) != V_PHI)
                  continue;
*************** expr_phi_insertion (dfs, ei)
*** 1654,1659 ****
--- 1947,1954 ----
                                  BASIC_BLOCK (i), 
                                  NULL, NULL, NULL, true);
      VARRAY_PUSH_GENERIC_PTR (ei->erefs, ref);
+     set_exprref_processed (ref, false);
+     set_exprref_processed2 (ref, false);
      set_exprphi_downsafe (ref, true);
      set_exprphi_canbeavail (ref, true);
      set_exprphi_later (ref, true);
*************** reset_down_safe (phiop)
*** 1670,1676 ****
       tree_ref phiop;
  {
    tree_ref phi;
!   basic_block bb;
    
    if (expruse_has_real_use (phiop))
      return;
--- 1965,1971 ----
       tree_ref phiop;
  {
    tree_ref phi;
!   size_t i;
    
    if (expruse_has_real_use (phiop))
      return;
*************** reset_down_safe (phiop)
*** 1680,1688 ****
    if (!exprphi_downsafe (phi))
      return;  
    set_exprphi_downsafe (phi, false);
!   FOR_EACH_BB (bb)
!     if (phi_operand (phi, bb) != NULL)
!       reset_down_safe (phi_operand (phi, bb));
  }
  
  /* Compute down_safety.  */
--- 1975,1982 ----
    if (!exprphi_downsafe (phi))
      return;  
    set_exprphi_downsafe (phi, false);
!   for (i = 0; i < num_ephi_args (phi); i++)
!     reset_down_safe (phi_arg_def (ephi_arg (phi, i)));
  }
  
  /* Compute down_safety.  */
*************** down_safety (ei)
*** 1694,1705 ****
    FOR_EACH_BB (block)
      {
        tree_ref phi = phi_at_block (ei, block);
!       basic_block block2;
        if (phi == NULL || exprphi_downsafe (phi))
          continue;
!       FOR_EACH_BB (block2)
!         if (phi_operand (phi, block2) != NULL)
!           reset_down_safe (phi_operand (phi, block2));
      }      
  } 
  
--- 1988,1999 ----
    FOR_EACH_BB (block)
      {
        tree_ref phi = phi_at_block (ei, block);
!       size_t i;
!       
        if (phi == NULL || exprphi_downsafe (phi))
          continue;
!       for (i = 0; i < num_ephi_args (phi); i++)       
! 	reset_down_safe (phi_arg_def (ephi_arg (phi, i)));
      }      
  } 
  
*************** requires_edge_placement (phi)
*** 1715,1721 ****
      {
        if (pred->src != ENTRY_BLOCK_PTR)
  	{
! 	  tree_ref operand = phi_operand (phi, pred->src);
  	  if (expruse_def (operand) == NULL && EDGE_CRITICAL_P (pred))
  	    return true;
  	}
--- 2009,2015 ----
      {
        if (pred->src != ENTRY_BLOCK_PTR)
  	{
! 	  tree_ref operand = phi_operand_for_pred (phi, pred);
  	  if (expruse_def (operand) == NULL && EDGE_CRITICAL_P (pred))
  	    return true;
  	}
*************** compute_can_be_avail (ei)
*** 1765,1771 ****
          {
            if (pred->src != ENTRY_BLOCK_PTR)
              {
!               tree_ref operand = phi_operand (phi, pred->src);
                if (expruse_def (operand) == NULL)
                  {
                    reset_can_be_avail (ei, phi);
--- 2059,2065 ----
          {
            if (pred->src != ENTRY_BLOCK_PTR)
              {
!               tree_ref operand = phi_operand_for_pred (phi, pred);
                if (expruse_def (operand) == NULL)
                  {
                    reset_can_be_avail (ei, phi);
*************** reset_can_be_avail (ei, phi)
*** 1781,1786 ****
--- 2075,2081 ----
       struct expr_info *ei;   
       tree_ref phi;
  {
+ #if 0
    basic_block block;
  
    set_exprphi_canbeavail (phi, false);
*************** reset_can_be_avail (ei, phi)
*** 1796,1802 ****
          {
            if (pred->src != ENTRY_BLOCK_PTR)
              {
!               tree_ref operand = phi_operand (other, pred->src);
                if (expruse_def (operand) == phi)
                  {
                    if (!expruse_has_real_use(operand))
--- 2091,2097 ----
          {
            if (pred->src != ENTRY_BLOCK_PTR)
              {
!               tree_ref operand = phi_operand_for_pred (other, pred);
                if (expruse_def (operand) == phi)
                  {
                    if (!expruse_has_real_use(operand))
*************** reset_can_be_avail (ei, phi)
*** 1809,1814 ****
--- 2104,2127 ----
              }
          }
      }
+ #else
+   ref_list_iterator rli;
+   
+   set_exprphi_canbeavail (phi, false);
+   rli = rli_start (exprref_uses (phi));
+   for (; !rli_after_end (rli); rli_step (&rli))
+     {
+       tree_ref w = rli_ref (rli);
+       
+       if (ref_type (w) == E_USE && expruse_phiop (w)
+ 		      && !expruse_has_real_use (w))
+ 	{
+ 	  tree_ref f = expruse_phi (w);
+ 	  if (!exprphi_downsafe (f) && exprphi_canbeavail (f))
+ 	    reset_can_be_avail (ei, f);
+ 	}
+     }
+ #endif
  }
  
  /*  Reset later flags.  */
*************** reset_later (ei, phi)
*** 1817,1822 ****
--- 2130,2136 ----
       struct expr_info *ei;
       tree_ref phi;
  {
+ #if 0
    basic_block block;
  
    set_exprphi_later (phi, false);
*************** reset_later (ei, phi)
*** 1832,1838 ****
          {
            if (pred->src != ENTRY_BLOCK_PTR)
              {
!               tree_ref operand = phi_operand (other, pred->src);
                if (expruse_def (operand) == phi)
                  {
                    if (exprphi_later (other))                
--- 2146,2152 ----
          {
            if (pred->src != ENTRY_BLOCK_PTR)
              {
!               tree_ref operand = phi_operand_for_pred (other, pred);
                if (expruse_def (operand) == phi)
                  {
                    if (exprphi_later (other))                
*************** reset_later (ei, phi)
*** 1841,1846 ****
--- 2155,2180 ----
              }
          }
      }
+ #else
+   ref_list_iterator rli;
+ 
+   set_exprphi_later (phi, false);  
+   rli = rli_start (exprref_uses (phi));
+   for (; !rli_after_end (rli); rli_step (&rli))
+     {
+       tree_ref w = rli_ref (rli);
+       
+       if (expruse_def (w) != phi)
+ 	abort ();
+       
+       if (ref_type (w) == E_USE && expruse_phiop (w))
+ 	{
+ 	  tree_ref f = expruse_phi (w);
+ 	  if (exprphi_later (f))
+ 	    reset_later (ei, f);
+ 	}
+     }  
+ #endif
  }
  
  /*  Compute later flags.  */
*************** compute_later (ei)
*** 1854,1860 ****
        tree_ref phi = phi_at_block (ei, block);
        if (phi == NULL)
          continue;
!       set_exprphi_later (phi,exprphi_canbeavail (phi));
      }
        
    FOR_EACH_BB (block)
--- 2188,2194 ----
        tree_ref phi = phi_at_block (ei, block);
        if (phi == NULL)
          continue;
!       set_exprphi_later (phi ,exprphi_canbeavail (phi));
      }
        
    FOR_EACH_BB (block)
*************** compute_later (ei)
*** 1870,1876 ****
          {
            if (pred->src != ENTRY_BLOCK_PTR)
              {
!               tree_ref operand = phi_operand (phi, pred->src);
                if (expruse_def (operand) != NULL 
  		  && expruse_has_real_use (operand))
  	      {
--- 2204,2210 ----
          {
            if (pred->src != ENTRY_BLOCK_PTR)
              {
!               tree_ref operand = phi_operand_for_pred (phi, pred);
                if (expruse_def (operand) != NULL 
  		  && expruse_has_real_use (operand))
  	      {
*************** set_need_repair (ei, q)
*** 1919,1927 ****
  	  || !DECL_P (TREE_OPERAND (ei->expr, i)))
  	continue;
        v = TREE_OPERAND (ei->expr, i);
!       if (ref_expr (p))
! 	vp = find_use_for_var (ref_expr (p), v);
!       vq = find_use_for_var (ref_expr (q), v);
        if (vp != vq)
  	{
  	  splay_tree_insert (need_repair_map, 
--- 2253,2261 ----
  	  || !DECL_P (TREE_OPERAND (ei->expr, i)))
  	continue;
        v = TREE_OPERAND (ei->expr, i);
!       if (ref_stmt (p))
! 	vp = find_use_for_var (ref_stmt (p), v);
!       vq = find_use_for_var (ref_stmt (q), v);
        if (vp != vq)
  	{
  	  splay_tree_insert (need_repair_map, 
*************** repair_injury (ei, use, temp, orig_euse)
*** 1976,2010 ****
    tree expr, stmt;
    basic_block bb;
    ref_list toprocess = create_ref_list();
!      
    for (i = 0; i < 2; i++)
      {
        tree incr = integer_zero_node;
        tree_ref v;
!       if (!DECL_P (TREE_OPERAND (ei->expr, i)))
  	continue;
        if (ref_type (use) == E_USE)
  	v = find_rhs_use_for_var (use, TREE_OPERAND (ei->expr, i));
        else 
  	v = use;      
! 
        if (ref_type (v) == V_DEF)
  	{
  	  ref_list_iterator j;
  
  	  /* If this isn't a def of *this* variable, ignore it, since it can't
  	   *possibly* injure it. */
! 	  if (ref_var (find_def_for_stmt (ref_stmt (v))) 
! 	      != TREE_OPERAND  (ei->expr, i))
  	    continue;
! 	  while (is_injuring_def (ei, ref_expr (v)))
  	    {
  	      add_ref_to_list_begin (toprocess, v);
  	      v = find_rhs_use_for_var (v, TREE_OPERAND (ei->expr, i));
! 	      if (is_default_def (imm_reaching_def (v))
! 		  || ref_type (imm_reaching_def (v)) == V_PHI
! 		  || !maybe_find_rhs_use_for_var (imm_reaching_def (v),
! 						  TREE_OPERAND (ei->expr, i)))
  		break;
  	      v = find_rhs_use_for_var (imm_reaching_def (v), 
  					TREE_OPERAND (ei->expr, i));
--- 2310,2349 ----
    tree expr, stmt;
    basic_block bb;
    ref_list toprocess = create_ref_list();
! 
!   if (htab_find (ei->repaired, use) != NULL)
!       return;
! 
!   *(htab_find_slot (ei->repaired, use, INSERT)) = use;
!   
    for (i = 0; i < 2; i++)
      {
        tree incr = integer_zero_node;
        tree_ref v;
!       if (!DECL_P (get_operand (ei->expr, i)))
  	continue;
        if (ref_type (use) == E_USE)
  	v = find_rhs_use_for_var (use, TREE_OPERAND (ei->expr, i));
        else 
  	v = use;      
!       
        if (ref_type (v) == V_DEF)
  	{
  	  ref_list_iterator j;
  
  	  /* If this isn't a def of *this* variable, ignore it, since it can't
  	   *possibly* injure it. */
! 	  if (is_default_def (v) 
! 	      || htab_find (ei->repaired, ref_stmt (v))
! 	      || !ref_defines (find_def_for_stmt (ref_stmt (v)), 
! 			       TREE_OPERAND (ei->expr, i)))
! 
  	    continue;
! 	  while (is_injuring_def (ei, ref_stmt (v)))
  	    {
  	      add_ref_to_list_begin (toprocess, v);
  	      v = find_rhs_use_for_var (v, TREE_OPERAND (ei->expr, i));
! 	      if (!okay_injuring_def (imm_reaching_def (v), ref_var (v)))
  		break;
  	      v = find_rhs_use_for_var (imm_reaching_def (v), 
  					TREE_OPERAND (ei->expr, i));
*************** repair_injury (ei, use, temp, orig_euse)
*** 2015,2041 ****
  	     yet. */
  	  for (j = rli_start (toprocess); !rli_after_end (j); rli_step (&j))
  	    {
  	      v = rli_ref (j);
! 	      if (htab_find (ei->repaired, ref_expr (v)) == NULL)
  		{
  #if DEBUGGING_STRRED
  		  if (dump_file)
  		      {
  			fprintf (dump_file, "Injuring def to repair is: ");
! 			print_generic_expr (dump_file, ref_expr (v), 0);
  			fprintf (dump_file, "\n");
  		      }
  #endif
! 		    incr = calculate_increment (ei, ref_expr (v));
  		    expr = build_modify_expr (temp, NOP_EXPR, 
  					      fold (build (PLUS_EXPR, 
  							  TREE_TYPE (temp),
  							  temp, incr)));
! 		    stmt = build (COMPOUND_EXPR, void_type_node, ref_stmt (v), expr);
  		    TREE_TYPE (stmt) = TREE_TYPE (expr);
  		    bb = ref_bb (use);
  		    replace_ref_stmt_with (v, stmt);
! 		    *(htab_find_slot (ei->repaired, ref_expr (v), INSERT)) = ref_expr (v);
  #if WAITING_FOR_DFA_UPDATE		  
  		    /* Update SSA for the repair.  
  		      1. Find the refs in the statement.
--- 2354,2388 ----
  	     yet. */
  	  for (j = rli_start (toprocess); !rli_after_end (j); rli_step (&j))
  	    {
+ 	      tree oldstmt;
+ 
  	      v = rli_ref (j);
! 	      if (htab_find (ei->repaired, ref_stmt (v)) == NULL)
  		{
  #if DEBUGGING_STRRED
  		  if (dump_file)
  		      {
  			fprintf (dump_file, "Injuring def to repair is: ");
! 			print_generic_stmt (dump_file, ref_stmt (v), 0);
  			fprintf (dump_file, "\n");
  		      }
  #endif
! 		    incr = calculate_increment (ei, ref_stmt (v));
  		    expr = build_modify_expr (temp, NOP_EXPR, 
  					      fold (build (PLUS_EXPR, 
  							  TREE_TYPE (temp),
  							  temp, incr)));
! 		    oldstmt = ref_stmt (v);
! 		    stmt = build (COMPOUND_EXPR, void_type_node, oldstmt,
! 				  expr);
  		    TREE_TYPE (stmt) = TREE_TYPE (expr);
  		    bb = ref_bb (use);
  		    replace_ref_stmt_with (v, stmt);
! 		    update_old_new (ei, v->common.stmt_p, &TREE_OPERAND (stmt, 0));
! 		    /* REMOVE AFTER DFA UPDATE */
! 		    temp_fix_refs (oldstmt, stmt, &TREE_OPERAND (stmt, 0));
! 		    /* END REMOVE AFTER DFA UPDATE */
! 		    *(htab_find_slot (ei->repaired, ref_stmt (v), INSERT)) = ref_stmt (v);
  #if WAITING_FOR_DFA_UPDATE		  
  		    /* Update SSA for the repair.  
  		      1. Find the refs in the statement.
*************** repair_injury (ei, use, temp, orig_euse)
*** 2058,2067 ****
  		  }
  	    }
  	}
!       else if (ref_type (imm_reaching_def (v)) == V_PHI)
  	{
  	  size_t curr_phi_operand;
! 	  tree_ref phi = imm_reaching_def (v);
  	  for (curr_phi_operand = 0; 
  	       curr_phi_operand < num_phi_args (phi); 
  	       curr_phi_operand++)
--- 2405,2415 ----
  		  }
  	    }
  	}
!       else if (ref_type (v) == V_PHI 
! 	       || ref_type (imm_reaching_def (v)) == V_PHI)
  	{
  	  size_t curr_phi_operand;
! 	  tree_ref phi = ref_type (v) == V_PHI ? v :  imm_reaching_def (v);
  	  for (curr_phi_operand = 0; 
  	       curr_phi_operand < num_phi_args (phi); 
  	       curr_phi_operand++)
*************** repair_injury (ei, use, temp, orig_euse)
*** 2069,2081 ****
  	      phi_node_arg phi_oper = phi_arg (phi, curr_phi_operand);
  	      tree_ref phi_op = phi_arg_def (phi_oper);
  	      tree_ref ephi = phi_at_block (ei, ref_bb (phi));
! 	      tree_ref ephi_op = phi_operand (ephi, 
! 					      phi_arg_edge (phi_oper)->src);
  	      repair_injury (ei, phi_op, temp, ephi_op);
  	    }
  	}
        else
! 	abort ();
      }
  }
  
--- 2417,2432 ----
  	      phi_node_arg phi_oper = phi_arg (phi, curr_phi_operand);
  	      tree_ref phi_op = phi_arg_def (phi_oper);
  	      tree_ref ephi = phi_at_block (ei, ref_bb (phi));
! 	      tree_ref ephi_op;
! 	      if (!ephi)
! 		continue;
! 	      ephi_op = phi_operand_for_pred (ephi, 
! 					      phi_arg_edge (phi_oper));
  	      repair_injury (ei, phi_op, temp, ephi_op);
  	    }
  	}
        else
! 	repair_injury (ei, imm_reaching_def (v), temp, orig_euse);
      }
  }
  
*************** find_reaching_def_of_var (var, stmtbb, p
*** 2093,2099 ****
    struct ref_list_node *fromhere;
  
    if (!stmtbb)
!     return NULL;
    
    if (phi)
      for (i = rli_start (bb_refs (ref_bb (phi)));
--- 2444,2450 ----
    struct ref_list_node *fromhere;
  
    if (!stmtbb)
!     return 0;
    
    if (phi)
      for (i = rli_start (bb_refs (ref_bb (phi)));
*************** find_reaching_def_of_var (var, stmtbb, p
*** 2132,2138 ****
        tree_ref tempref = rli_ref (i);
        if ((ref_type (tempref) != V_DEF
  	    && ref_type (tempref) != V_USE)
! 	  || ref_expr (var) == ref_expr (tempref)) 
  	continue;
        if (ref_var (tempref) == ref_var (var))
  	{
--- 2483,2489 ----
        tree_ref tempref = rli_ref (i);
        if ((ref_type (tempref) != V_DEF
  	    && ref_type (tempref) != V_USE)
! 	  || ref_stmt (var) == ref_stmt (tempref)) 
  	continue;
        if (ref_var (tempref) == ref_var (var))
  	{
*************** update_ssa_for_new_use (temp, newuse, de
*** 2197,2214 ****
       This is a bit simplified, since when i update a reaching def, we update
       the reaching def's immediate uses, etc.
    */
! 
!   for (i = rli_start (tree_refs (newuse)); !rli_after_end (i); rli_step (&i))
!     {
!       if (ref_type (rli_ref (i)) == V_DEF)
! 	{
! 	  use_orig_ref = rli_ref (i);
! 	  break;
! 	}
!     }
  #if WAITING_FOR_DFA_UPDATE
    olddefref = find_def_for_stmt (ref_stmt (use_orig_ref));
!   i = rli_start (tree_refs (ref_expr (use_orig_def)));
    for (; !rli_after_end (i); rli_step (&i))
      {
        tree_ref tempref = rli_ref (i);
--- 2548,2557 ----
       This is a bit simplified, since when i update a reaching def, we update
       the reaching def's immediate uses, etc.
    */
!   use_orig_ref = find_def_for_stmt (newuse);
  #if WAITING_FOR_DFA_UPDATE
    olddefref = find_def_for_stmt (ref_stmt (use_orig_ref));
!   i = rli_start (tree_refs (ref_stmt (use_orig_def)));
    for (; !rli_after_end (i); rli_step (&i))
      {
        tree_ref tempref = rli_ref (i);
*************** update_ssa_for_new_use (temp, newuse, de
*** 2235,2258 ****
      }
    
    for (i = rli_start (todelete); !rli_after_end (i); rli_step (&i))
!     remove_tree_ref (ref_expr (use_orig_ref), rli_ref (i));
  
!   ref_expr (use_orig_ref)->common.ann = NULL;
  #endif
!   useexpr = ref_expr (use_orig_ref);
    STRIP_WFL (useexpr);
    newmodifyexpr = build_modify_expr (TREE_OPERAND (useexpr, 0), 
  				     NOP_EXPR, temp);
!   replace_ref_expr_with (use_orig_ref, newmodifyexpr);
  
  #if WAITING_FOR_DFA_UPDATE
  
    /* FIXME: Hack.  Passing the address of local trees to create_ref is not
       correct.  We should keep statement and expression pointers here.  */
!   newdefref = create_ref (TREE_OPERAND (ref_expr (use_orig_ref), 0),
  			  V_DEF, 0, bb, ref_stmt (use_orig_ref), 
! 			  ref_expr (use_orig_ref),
! 			  &TREE_OPERAND (ref_expr (use_orig_ref), 0),
  			  true);
    add_list_to_list_end (reached_uses (newdefref), reachedtoadd);
    add_list_to_list_end (imm_uses (newdefref), immtoadd);
--- 2578,2601 ----
      }
    
    for (i = rli_start (todelete); !rli_after_end (i); rli_step (&i))
!     remove_tree_ref (ref_stmt (use_orig_ref), rli_ref (i));
  
!   ref_stmt (use_orig_ref)->common.ann = NULL;
  #endif
!   useexpr = ref_stmt (use_orig_ref);
    STRIP_WFL (useexpr);
    newmodifyexpr = build_modify_expr (TREE_OPERAND (useexpr, 0), 
  				     NOP_EXPR, temp);
!   replace_ref_stmt_with (use_orig_ref, newmodifyexpr);
  
  #if WAITING_FOR_DFA_UPDATE
  
    /* FIXME: Hack.  Passing the address of local trees to create_ref is not
       correct.  We should keep statement and expression pointers here.  */
!   newdefref = create_ref (TREE_OPERAND (ref_stmt (use_orig_ref), 0),
  			  V_DEF, 0, bb, ref_stmt (use_orig_ref), 
! 			  ref_stmt (use_orig_ref),
! 			  &TREE_OPERAND (ref_stmt (use_orig_ref), 0),
  			  true);
    add_list_to_list_end (reached_uses (newdefref), reachedtoadd);
    add_list_to_list_end (imm_uses (newdefref), immtoadd);
*************** update_ssa_for_new_use (temp, newuse, de
*** 2263,2277 ****
    /* FIXME: Hack.  Passing the address of local trees to create_ref is not
       correct.  We should keep statement and expression pointers here.  */
    newuseref = create_ref (temp, V_USE, 0, bb, ref_stmt (use_orig_ref),
! 			  ref_expr (use_orig_ref), 
! 			  find_expr_in_tree (ref_expr (use_orig_ref), temp), 
  			  true);
    if ( (ref_type (defby) != E_PHI))
      {
        /* For non-PHI's we created, the  map is euse expression -> new pretmp
  	 save stmt. */ 
        reachingnode = splay_tree_lookup (new_stmt_map, 
! 					(splay_tree_key) ref_expr (defby));
        if (!reachingnode)
  	abort();
        reachingstmt = (tree) reachingnode->value;
--- 2606,2620 ----
    /* FIXME: Hack.  Passing the address of local trees to create_ref is not
       correct.  We should keep statement and expression pointers here.  */
    newuseref = create_ref (temp, V_USE, 0, bb, ref_stmt (use_orig_ref),
! 			  ref_stmt (use_orig_ref), 
! 			  find_expr_in_tree (ref_stmt (use_orig_ref), temp), 
  			  true);
    if ( (ref_type (defby) != E_PHI))
      {
        /* For non-PHI's we created, the  map is euse expression -> new pretmp
  	 save stmt. */ 
        reachingnode = splay_tree_lookup (new_stmt_map, 
! 					(splay_tree_key) ref_stmt (defby));
        if (!reachingnode)
  	abort();
        reachingstmt = (tree) reachingnode->value;
*************** code_motion (ei, temp)
*** 2333,2374 ****
       struct expr_info *ei;
       tree temp;
  {
!   fibheap_t exprs;
    tree_ref use;
!   
    ei->injfixups = create_ref_list ();
    need_repair_map = splay_tree_new (splay_tree_compare_pointers, NULL, NULL);
!   exprs = fibheap_new ();
    if (ei->strred_cand)
      {
!       insert_euse_in_preorder_dt_order (ei, exprs);
!       while (!fibheap_empty (exprs))
  	{
! 	  use = fibheap_extract_min (exprs);
  	  if ((ref_type (use) == E_USE)
  	      && exprref_reload (use) 
  	      && !exprref_inserted (use))
  	    {
  	      repair_injury (ei, use, temp, use);
- 	      /*	    set_need_repair (ei, use);*/
  	    }
  	}
      }
!   insert_euse_in_preorder_dt_order (ei, exprs);
!   while (!fibheap_empty (exprs))
      {
!       use = fibheap_extract_min (exprs);
!       if (ref_type (use) == E_USE /*&& !EXPRUSE_PHIOP (use) */
! 	  && !exprref_inserted (use))
  	{
! 	  if (expruse_phiop (use) 
  	      && (exprref_reload (use) || exprref_save (use)))
  	    abort();
  	  if (exprref_save (use))
  	    {
  	      basic_block use_bb = ref_bb (use);
  	      tree use_stmt = ref_stmt (use);
! 	      tree use_expr = ref_expr (use);
  	      tree_ref use_orig_ref = NULL;
  	      tree newexpr, newstmt;
  	      size_t j;	      
--- 2676,2716 ----
       struct expr_info *ei;
       tree temp;
  {
! 
    tree_ref use;
!   ref_list_iterator euse_rli;
    ei->injfixups = create_ref_list ();
    need_repair_map = splay_tree_new (splay_tree_compare_pointers, NULL, NULL);
! 
    if (ei->strred_cand)
      {
!       euse_rli = rli_start (ei->euses_dt_order);
!       for (; !rli_after_end (euse_rli); rli_step (&euse_rli))
  	{
! 	  use = rli_ref (euse_rli);
  	  if ((ref_type (use) == E_USE)
  	      && exprref_reload (use) 
  	      && !exprref_inserted (use))
  	    {
  	      repair_injury (ei, use, temp, use);
  	    }
  	}
      }
!   euse_rli = rli_start (ei->euses_dt_order);
!   for (; !rli_after_end (euse_rli); rli_step (&euse_rli))
      {
!       use = rli_ref (euse_rli);
!       if ((ref_type (use) == E_USE
! 	   && !exprref_inserted (use)) || ref_type (use) == E_LEFT)
  	{
! 	  if (ref_type (use) != E_LEFT && expruse_phiop (use) 
  	      && (exprref_reload (use) || exprref_save (use)))
  	    abort();
  	  if (exprref_save (use))
  	    {
  	      basic_block use_bb = ref_bb (use);
  	      tree use_stmt = ref_stmt (use);
! 	      tree use_expr = ref_stmt (use);
  	      tree_ref use_orig_ref = NULL;
  	      tree newexpr, newstmt;
  	      size_t j;	      
*************** code_motion (ei, temp)
*** 2398,2423 ****
  			   EXPR_WFL_LINENO (use_expr));
  		}
  	      STRIP_WFL (use_expr);
! 	      newexpr = fold (build_modify_expr (temp, NOP_EXPR, 
! 						 deep_copy_node (TREE_OPERAND (use_expr, 1))));
  	      newstmt = build (COMPOUND_EXPR, void_type_node, newexpr,
  			       use_stmt);
  	      replace_ref_stmt_with (use, newstmt);
  	      use->common.stmt_p = &TREE_OPERAND (newstmt, 1);
  	      use->common.expr_p = &TREE_OPERAND (newstmt, 1);
  	      /* REMOVE AFTER DFA UPDATE */
! 	      i = rli_start (tree_refs (use_stmt));
! 	      for (; !rli_after_end (i); rli_step (&i))
! 		{
! 		  tree_ref a = rli_ref (i);
! 		  if (ref_stmt (a) == newstmt)
! 		    {
! 		      a->common.stmt_p = &TREE_OPERAND (newstmt, 1);
! 		      a->common.expr_p = &TREE_OPERAND (newstmt, 1);
! 		    }
! 		}	      
  	      /* END REMOVE AFTER DFA UPDATE */
! 	      update_ssa_for_new_use (temp, ref_expr (use), use, use_bb);
  
  #if WAITING_FOR_DFA_UPDATE
  	      /* Update the SSA representation for the new def of the
--- 2740,2761 ----
  			   EXPR_WFL_LINENO (use_expr));
  		}
  	      STRIP_WFL (use_expr);
! 	      newexpr = build_modify_expr (temp, NOP_EXPR, 
! 					   deep_copy_node (TREE_OPERAND (use_expr, 1)));
! 	      newexpr = fold (newexpr);
  	      newstmt = build (COMPOUND_EXPR, void_type_node, newexpr,
  			       use_stmt);
  	      replace_ref_stmt_with (use, newstmt);
+ 	      update_old_new (ei, use->common.stmt_p, &TREE_OPERAND (newstmt, 1));
+ 
+ 	      
  	      use->common.stmt_p = &TREE_OPERAND (newstmt, 1);
  	      use->common.expr_p = &TREE_OPERAND (newstmt, 1);
+ 
  	      /* REMOVE AFTER DFA UPDATE */
! 	      temp_fix_refs (use_stmt, newstmt, &TREE_OPERAND (newstmt, 1));
  	      /* END REMOVE AFTER DFA UPDATE */
! 	      update_ssa_for_new_use (temp, ref_stmt (use), use, use_bb);
  
  #if WAITING_FOR_DFA_UPDATE
  	      /* Update the SSA representation for the new def of the
*************** code_motion (ei, temp)
*** 2446,2454 ****
  		}
  	      
  	      splay_tree_insert (new_stmt_map, 
! 				 (splay_tree_key) ref_expr (use), 
  				 (splay_tree_value) newstmt);
! 	      update_ssa_for_new_use (temp, ref_expr (use), use, use_bb);
  #if DEBUGGING_SSA_UPDATE 
  	      if (dump_file)
  		{
--- 2784,2792 ----
  		}
  	      
  	      splay_tree_insert (new_stmt_map, 
! 				 (splay_tree_key) ref_stmt (use), 
  				 (splay_tree_value) newstmt);
! 	      update_ssa_for_new_use (temp, ref_stmt (use), use, use_bb);
  #if DEBUGGING_SSA_UPDATE 
  	      if (dump_file)
  		{
*************** code_motion (ei, temp)
*** 2462,2468 ****
  	    {
  	      basic_block use_bb = ref_bb (use);
  	      tree use_stmt = ref_stmt (use);
! 	      tree use_expr = ref_expr (use);
  	      if (dump_file)
                  {
  		  fprintf (dump_file, "In BB %d, insert reload of ", 
--- 2800,2806 ----
  	    {
  	      basic_block use_bb = ref_bb (use);
  	      tree use_stmt = ref_stmt (use);
! 	      tree use_expr = ref_stmt (use);
  	      if (dump_file)
                  {
  		  fprintf (dump_file, "In BB %d, insert reload of ", 
*************** code_motion (ei, temp)
*** 2471,2484 ****
                    fprintf (dump_file, " from ");
                    print_generic_expr (dump_file, temp, 0);
                    fprintf (dump_file, " in statement ");
!                   print_generic_expr (dump_file, TREE_OPERAND (use_stmt, 0), 0);
                    fprintf (dump_file, " on line %d\n", 
  			   EXPR_WFL_LINENO (use_stmt));
                  }
  	      /* Update the SSA representation for a new use of the temporary.
  		 Do exactly what we do for the new use generated by the save. 
  	      */
! 	      update_ssa_for_new_use (temp, ref_expr (use), expruse_def (use),
  				      ref_bb (use));
  #if DEBUGGING_SSA_UPDATE
  	      if (dump_file)
--- 2809,2822 ----
                    fprintf (dump_file, " from ");
                    print_generic_expr (dump_file, temp, 0);
                    fprintf (dump_file, " in statement ");
!                   print_generic_stmt (dump_file, use_stmt, 0);
                    fprintf (dump_file, " on line %d\n", 
  			   EXPR_WFL_LINENO (use_stmt));
                  }
  	      /* Update the SSA representation for a new use of the temporary.
  		 Do exactly what we do for the new use generated by the save. 
  	      */
! 	      update_ssa_for_new_use (temp, ref_stmt (use), expruse_def (use),
  				      ref_bb (use));
  #if DEBUGGING_SSA_UPDATE
  	      if (dump_file)
*************** code_motion (ei, temp)
*** 2555,2561 ****
  						  (splay_tree_key) defby);
  		else
  		  phidefnode = splay_tree_lookup (new_stmt_map,
! 						  (splay_tree_key) ref_expr (defby));
  		if (!phidefnode)
  		  abort();
  		tempdef = find_def_for_stmt ((tree) phidefnode->value);
--- 2893,2899 ----
  						  (splay_tree_key) defby);
  		else
  		  phidefnode = splay_tree_lookup (new_stmt_map,
! 						  (splay_tree_key) ref_stmt (defby));
  		if (!phidefnode)
  		  abort();
  		tempdef = find_def_for_stmt ((tree) phidefnode->value);
*************** code_motion (ei, temp)
*** 2585,2591 ****
      ref_list_iterator j;
      tempref = rli_ref (i);
  
!     j = rli_start (tree_refs (ref_expr (tempref)));
      for (; !rli_after_end (j); rli_step (&j))
        {
  	tree_ref tempref2 = rli_ref (j);
--- 2923,2929 ----
      ref_list_iterator j;
      tempref = rli_ref (i);
  
!     j = rli_start (tree_refs (ref_stmt (tempref)));
      for (; !rli_after_end (j); rli_step (&j))
        {
  	tree_ref tempref2 = rli_ref (j);
*************** will_be_avail (ei)
*** 2616,2622 ****
--- 2954,2983 ----
    compute_can_be_avail (ei);
    compute_later (ei);
  }
+ static bool
+ call_modifies_slot (call, expr)
+      tree_ref call;
+      tree expr;
+ {
  
+   ref_list_iterator rli;
+   
+   for (rli = rli_start (tree_refs (ref_stmt (call))); 
+        !rli_after_end (rli);
+        rli_step (&rli))
+     {
+       size_t i;
+       
+       for (i = 0; i < 2; i++)
+ 	{
+ 	  if (!TREE_OPERAND (expr, i))
+ 	    continue;
+ 	  if (ref_defines (rli_ref (rli), TREE_OPERAND (expr, i)))
+ 	    return true;
+ 	}
+     }
+   return false;
+ }
  /* Add call expression to expr-infos.  */
  static int
  add_call_to_ei (slot, data)
*************** add_call_to_ei (slot, data)
*** 2625,2633 ****
  {
    tree_ref call = (tree_ref) data;
    struct expr_info *ei = (struct expr_info *) slot;
!   VARRAY_PUSH_GENERIC_PTR (ei->occurs, call->common.expr_p);
!   VARRAY_PUSH_GENERIC_PTR (ei->occurstmts, call->common.stmt_p);
!   VARRAY_PUSH_GENERIC_PTR (ei->refs, call);
    return 0;
  }
  
--- 2986,2998 ----
  {
    tree_ref call = (tree_ref) data;
    struct expr_info *ei = (struct expr_info *) slot;
!   if (call_modifies_slot (call, ei->expr))
!     {
!       VARRAY_PUSH_GENERIC_PTR (ei->occurs, NULL);
!       VARRAY_PUSH_GENERIC_PTR (ei->lefts, NULL);
!       VARRAY_PUSH_GENERIC_PTR (ei->kills, call->common.stmt_p);
!       VARRAY_PUSH_GENERIC_PTR (ei->refs, call);
!     }
    return 0;
  }
  
*************** pre_part_1_trav (slot, data)
*** 2638,2648 ****
       void *data;
  {
    tree temp;
!   tree fnbody;
    struct expr_info *ei = (struct expr_info *) slot;
    if (VARRAY_ACTIVE_SIZE (ei->reals) < 2)
      return 0;
  
    expr_phi_insertion ((sbitmap *)data, ei);
    rename_1 (ei);
    if (dump_file)
--- 3003,3033 ----
       void *data;
  {
    tree temp;
!   size_t i;
!   bool changed = true;
    struct expr_info *ei = (struct expr_info *) slot;
+ 
    if (VARRAY_ACTIVE_SIZE (ei->reals) < 2)
      return 0;
  
+   /* Have to iterate until we are done changing, since we might have replaced
+      what we replaced (IE processing a single expression may cause a to move to
+   b, then b to c. If we don't iterate, we'll only change a to b. */ 
+   while (changed)
+     {
+       changed = false;
+       for (i = 0; i < VARRAY_ACTIVE_SIZE (ei->occurs); i++)
+ 	{
+ 	  splay_tree_node result;
+ 	  tree *occ = (tree *) VARRAY_GENERIC_PTR (ei->occurs, i);
+ 	  result = splay_tree_lookup (old_new_map, (splay_tree_key) occ);
+ 	  if (result)
+ 	    {
+ 	      changed = true;
+ 	      VARRAY_GENERIC_PTR (ei->occurs, i) = (PTR) result->value;
+ 	    }
+ 	}
+     }
    expr_phi_insertion ((sbitmap *)data, ei);
    rename_1 (ei);
    if (dump_file)
*************** pre_part_1_trav (slot, data)
*** 2664,2684 ****
    {
      tree_ref def = NULL;
      tree type_of_expr;
!     size_t i;
!     for (i = 0; i < VARRAY_ACTIVE_SIZE (ei->realstmts) && !def; i++)
!       def = find_def_for_stmt (VARRAY_TREE (ei->realstmts, 0));
! 
!     if (def != NULL)
!       type_of_expr = TREE_TYPE (ref_var (def));
!     else
!       type_of_expr = TREE_TYPE (VARRAY_TREE (ei->reals, 0));
  
      temp = create_tmp_var (type_of_expr, "pretmp");
!     finalize_1 (ei, temp);
!     finalize_2 (ei);
!     code_motion (ei, temp);
    }
-   
    return 0;
  }
  
--- 3049,3063 ----
    {
      tree_ref def = NULL;
      tree type_of_expr;
!     type_of_expr = TREE_TYPE (VARRAY_TREE (ei->reals, 0));
  
      temp = create_tmp_var (type_of_expr, "pretmp");
!     if (finalize_1 (ei, temp))
!       {
! 	finalize_2 (ei);
! 	code_motion (ei, temp);
!       }
    }
    return 0;
  }
  
*************** calculate_preorder ()
*** 2744,2749 ****
--- 3123,3194 ----
    free (stack);
    sbitmap_free (visited);
  }
+ static tree
+ get_operand (expr, num)
+      tree expr;
+      unsigned int num;
+ {
+   if (is_simple_binary_expr (expr))
+     return TREE_OPERAND (expr, num);
+   else if (TREE_CODE (expr) == INDIRECT_REF)
+     if (num == 0)
+       return expr;
+   return NULL;
+ }
+ static void
+ process_left_occs_and_kills (bexprs, slot, ref, expr)
+      varray_type bexprs;
+      struct expr_info *slot;
+      tree_ref ref; 
+      tree expr;
+ {
+   size_t k;
+   STRIP_WFL (expr);
+   if (TREE_CODE (TREE_OPERAND (expr, 1)) == CALL_EXPR)
+     {
+       tree callee = get_callee_fndecl (expr);
+       if (!callee || !DECL_IS_PURE (callee))
+ 	{		
+ 	  for (k = 0; k < VARRAY_ACTIVE_SIZE (bexprs); k++)
+ 	    if (VARRAY_GENERIC_PTR (bexprs, k) != slot)
+ 	      add_call_to_ei (VARRAY_GENERIC_PTR (bexprs, k), ref);
+ 	}
+     }  
+   else if (DECL_P (TREE_OPERAND (expr, 0)))
+     {
+       for (k = 0; k < VARRAY_ACTIVE_SIZE (bexprs); k++)
+ 	{
+ 	  struct expr_info *ei = VARRAY_GENERIC_PTR (bexprs, k);
+ 	  if (ei == slot)
+ 	    continue;
+ 	  if (TREE_CODE (ei->expr) == INDIRECT_REF)
+ 	    if (get_alias_index (TREE_OPERAND (ei->expr, 0),
+ 				 TREE_OPERAND (expr, 0)) >= 0)
+ 	      {
+ 		VARRAY_PUSH_GENERIC_PTR (ei->lefts, ref->common.stmt_p);
+ 		VARRAY_PUSH_GENERIC_PTR (ei->kills, NULL);
+ 		VARRAY_PUSH_GENERIC_PTR (ei->occurs, NULL);
+ 	      }
+ 	}
+     }
+   else if (TREE_CODE (TREE_OPERAND (expr, 0)) == INDIRECT_REF
+ 	   && DECL_P (TREE_OPERAND (TREE_OPERAND (expr, 0), 0)))
+     {
+       for (k = 0; k < VARRAY_ACTIVE_SIZE (bexprs); k++)
+ 	{
+ 	  struct expr_info *ei = VARRAY_GENERIC_PTR (bexprs, k);
+ 	  if (ei == slot)
+ 	    continue;
+ 	  if (TREE_CODE (ei->expr) == INDIRECT_REF)
+ 	    if (TREE_OPERAND (ei->expr, 0) == TREE_OPERAND (TREE_OPERAND (expr, 0), 0))
+ 	      {
+ 		VARRAY_PUSH_GENERIC_PTR (ei->lefts, ref->common.stmt_p);
+ 		VARRAY_PUSH_GENERIC_PTR (ei->kills, NULL);
+ 		VARRAY_PUSH_GENERIC_PTR (ei->occurs, NULL);
+ 	      }
+ 	}
+     }
+ }
  
  void 
  tree_perform_ssapre ()
*************** tree_perform_ssapre ()
*** 2756,2762 ****
    size_t j, k;
  
    new_stmt_map = splay_tree_new (splay_tree_compare_pointers, NULL, NULL);
!   
    VARRAY_GENERIC_PTR_INIT (bexprs, 1, "bexprs");
    
    /* Compute immediate dominators.  */
--- 3201,3208 ----
    size_t j, k;
  
    new_stmt_map = splay_tree_new (splay_tree_compare_pointers, NULL, NULL);
!   old_new_map = splay_tree_new (splay_tree_compare_pointers, NULL, NULL);
! 
    VARRAY_GENERIC_PTR_INIT (bexprs, 1, "bexprs");
    
    /* Compute immediate dominators.  */
*************** tree_perform_ssapre ()
*** 2764,2769 ****
--- 3210,3216 ----
    domchildren = sbitmap_vector_alloc (last_basic_block, last_basic_block);
    sbitmap_vector_zero (domchildren, last_basic_block);
    compute_domchildren (pre_idom, domchildren);
+ 
    /* Compute dominance frontiers.  */
    pre_dfs = sbitmap_vector_alloc (last_basic_block, last_basic_block);
    sbitmap_vector_zero (pre_dfs, last_basic_block);
*************** tree_perform_ssapre ()
*** 2779,2804 ****
        for (i = rli_start (bb_refs (bb)); !rli_after_end (i); rli_step (&i))
  	{
  	  tree_ref ref = rli_ref (i);
! 	  tree expr = ref_expr (ref);
  	  tree orig_expr = expr;
  	  tree stmt = ref_stmt (ref);
! 	  if (ref_type (ref) != V_USE)
  	    continue;
  	  STRIP_WFL (expr);
  	  if (htab_find (seen, orig_expr) != NULL)
  	    continue;
  	  if (is_simple_modify_expr (expr))
  	    {
- 	      expr = TREE_OPERAND (expr, 1);
- 	    }
- 	  if ((is_simple_binary_expr (expr)
- /*	       || is_simple_cast (expr)
- 	       || is_simple_unary_expr (expr)*/)
- 	     && TREE_CODE (expr) != INDIRECT_REF
- 	     && !is_simple_condexpr (expr))
- 	    {
- 	      struct expr_info *slot = NULL;
- 	      size_t k;
  	      for (k = 0; k < VARRAY_ACTIVE_SIZE (bexprs); k++)
  	        {
  		  slot = VARRAY_GENERIC_PTR (bexprs, k);
--- 3226,3251 ----
        for (i = rli_start (bb_refs (bb)); !rli_after_end (i); rli_step (&i))
  	{
  	  tree_ref ref = rli_ref (i);
! 	  tree expr = ref_stmt (ref);
  	  tree orig_expr = expr;
  	  tree stmt = ref_stmt (ref);
! 	  struct expr_info *slot = NULL;
! 	  
! 	  if (ref_type (ref) != V_USE
! 	      || ref_stmt (ref) == NULL_TREE)
  	    continue;
+ 
  	  STRIP_WFL (expr);
  	  if (htab_find (seen, orig_expr) != NULL)
  	    continue;
+ 
  	  if (is_simple_modify_expr (expr))
+ 	    expr = TREE_OPERAND (expr, 1);
+ 
+ 	  if (is_simple_binary_expr (expr)
+ 	      || (TREE_CODE (expr) == INDIRECT_REF 
+ 		  && DECL_P (TREE_OPERAND (expr, 0))))
  	    {
  	      for (k = 0; k < VARRAY_ACTIVE_SIZE (bexprs); k++)
  	        {
  		  slot = VARRAY_GENERIC_PTR (bexprs, k);
*************** tree_perform_ssapre ()
*** 2809,2818 ****
  	        slot = NULL;
  	      if (slot)
  		{
! 		  VARRAY_PUSH_GENERIC_PTR (slot->occurs, ref->common.expr_p);
! 		  VARRAY_PUSH_GENERIC_PTR (slot->occurstmts, ref->common.stmt_p);
! 		  VARRAY_PUSH_TREE (slot->reals, expr);
! 		  VARRAY_PUSH_TREE (slot->realstmts, stmt);
  		  VARRAY_PUSH_GENERIC_PTR (slot->refs, ref);
  		  slot->strred_cand &= is_strred_cand (orig_expr);
  		}
--- 3256,3266 ----
  	        slot = NULL;
  	      if (slot)
  		{
! 		  VARRAY_PUSH_GENERIC_PTR (slot->occurs, 
! 					   ref->common.stmt_p);
! 		  VARRAY_PUSH_GENERIC_PTR (slot->kills, NULL);
! 		  VARRAY_PUSH_GENERIC_PTR (slot->lefts, NULL);
! 		  VARRAY_PUSH_TREE (slot->reals, stmt);
  		  VARRAY_PUSH_GENERIC_PTR (slot->refs, ref);
  		  slot->strred_cand &= is_strred_cand (orig_expr);
  		}
*************** tree_perform_ssapre ()
*** 2820,2839 ****
  		{
  		  slot = ggc_alloc (sizeof (struct expr_info));
  		  slot->expr = expr;
! 		  VARRAY_GENERIC_PTR_INIT (slot->occurs, 1, "Kills and occurrence");
! 		  VARRAY_GENERIC_PTR_INIT (slot->occurstmts, 1, 
! 				    "Kills and occurrence statements");
  		  VARRAY_TREE_INIT (slot->reals, 1, "Real occurrences");
- 		  VARRAY_TREE_INIT (slot->realstmts, 1, 
- 				    "Real occurrence statements");
  		  VARRAY_GENERIC_PTR_INIT (slot->phis, last_basic_block, 
  					   "EPHIs");
  		  VARRAY_GENERIC_PTR_INIT (slot->erefs, 1, "EREFs");
  		  VARRAY_GENERIC_PTR_INIT (slot->refs, 1, "REFs");
! 		  VARRAY_PUSH_GENERIC_PTR (slot->occurs, ref->common.expr_p);
! 		  VARRAY_PUSH_GENERIC_PTR (slot->occurstmts, ref->common.stmt_p);
! 		  VARRAY_PUSH_TREE (slot->reals, expr);
! 		  VARRAY_PUSH_TREE (slot->realstmts, stmt);
  		  VARRAY_PUSH_GENERIC_PTR (slot->refs, ref);
  
  		  VARRAY_PUSH_GENERIC_PTR (bexprs, slot);
--- 3268,3288 ----
  		{
  		  slot = ggc_alloc (sizeof (struct expr_info));
  		  slot->expr = expr;
! 		  VARRAY_GENERIC_PTR_INIT (slot->occurs, 1, 
! 					   "Occurrence");
! 		  VARRAY_GENERIC_PTR_INIT (slot->kills, 1,
! 					   "Kills");
! 		  VARRAY_GENERIC_PTR_INIT (slot->lefts, 1,
! 					   "Left occurrences");
  		  VARRAY_TREE_INIT (slot->reals, 1, "Real occurrences");
  		  VARRAY_GENERIC_PTR_INIT (slot->phis, last_basic_block, 
  					   "EPHIs");
  		  VARRAY_GENERIC_PTR_INIT (slot->erefs, 1, "EREFs");
  		  VARRAY_GENERIC_PTR_INIT (slot->refs, 1, "REFs");
! 		  VARRAY_PUSH_GENERIC_PTR (slot->occurs, ref->common.stmt_p);
! 		  VARRAY_PUSH_GENERIC_PTR (slot->kills, NULL);
! 		  VARRAY_PUSH_GENERIC_PTR (slot->lefts, NULL);
! 		  VARRAY_PUSH_TREE (slot->reals, stmt);
  		  VARRAY_PUSH_GENERIC_PTR (slot->refs, ref);
  
  		  VARRAY_PUSH_GENERIC_PTR (bexprs, slot);
*************** tree_perform_ssapre ()
*** 2842,2862 ****
  						htab_eq_pointer, NULL);
  		}
  	    }
! 	  else if (TREE_CODE (expr) == CALL_EXPR 
! 		   && TREE_CODE (ref_var (ref)) == FUNCTION_DECL)
! 	    {
! 	      if (!DECL_IS_PURE (ref_var (ref)))
! 	      {
! 		for (k = 0; k < VARRAY_ACTIVE_SIZE (bexprs); k++)
! 	  	  add_call_to_ei (VARRAY_GENERIC_PTR (bexprs, k), ref);
! 	      }
! 	    }  
  	  *(htab_find_slot  (seen, orig_expr, INSERT)) = orig_expr;
  	}
      }
    for (j = 0; j < VARRAY_ACTIVE_SIZE (bexprs); j++)
       pre_part_1_trav (VARRAY_GENERIC_PTR (bexprs, j), pre_dfs);
-   /*  simplify_stmt (fn, NULL_TREE); */
    /* Debugging dump after SSA PRE */
    if (dump_file)
      {
--- 3291,3304 ----
  						htab_eq_pointer, NULL);
  		}
  	    }
! 	  process_left_occs_and_kills (bexprs, slot, ref, orig_expr);
! 	  
! 
  	  *(htab_find_slot  (seen, orig_expr, INSERT)) = orig_expr;
  	}
      }
    for (j = 0; j < VARRAY_ACTIVE_SIZE (bexprs); j++)
       pre_part_1_trav (VARRAY_GENERIC_PTR (bexprs, j), pre_dfs);
    /* Debugging dump after SSA PRE */
    if (dump_file)
      {
*************** tree_perform_ssapre ()
*** 2880,2884 ****
    sbitmap_vector_free (domchildren);
  
    splay_tree_delete (new_stmt_map);
!   
  }
--- 3322,3326 ----
    sbitmap_vector_free (domchildren);
  
    splay_tree_delete (new_stmt_map);
!   splay_tree_delete (old_new_map);  
  }
Index: tree-flow-inline.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-flow-inline.h,v
retrieving revision 1.1.2.10
diff -c -3 -p -r1.1.2.10 tree-flow-inline.h
*** tree-flow-inline.h	5 Nov 2002 23:50:38 -0000	1.1.2.10
--- tree-flow-inline.h	6 Nov 2002 16:02:52 -0000
*************** bb_for_stmt (t)
*** 200,205 ****
--- 200,230 ----
    return tree_annotation (t) ? tree_annotation (t)->bb : NULL;
  }
  
+ 
+ static inline void
+ set_bb_for_stmt (t, bb)
+      tree t;
+      basic_block bb;
+ {
+   tree_ann ann;
+ 
+   if (t == empty_stmt_node)
+     return;
+ 
+   do
+     {
+       ann = tree_annotation (t) ? tree_annotation (t) : create_tree_ann (t);
+       ann->bb = bb;
+       if (TREE_CODE (t) == COMPOUND_EXPR)
+ 	t = TREE_OPERAND (t, 0);
+       else if (TREE_CODE (t) == EXPR_WITH_FILE_LOCATION)
+ 	t = EXPR_WFL_NODE (t);
+       else
+ 	t = NULL;
+     }
+   while (t);
+ }
+ 
  static inline tree_ref
  currdef_for (decl)
       tree decl;
*************** exprref_reload (ref)
*** 488,498 ****
--- 513,577 ----
    return ref->ecommon.reload;
  }
  
+ static inline void 
+ set_exprref_processed (ref, flag)
+      tree_ref ref;
+      unsigned int flag;
+ {
+   ref->ecommon.processed = flag;
+ }
+ 
+ static inline bool
+ exprref_processed (ref)
+      tree_ref ref;
+ {
+   return ref->ecommon.processed;
+ }
+ 
+ static inline void 
+ set_exprref_processed2 (ref, flag)
+      tree_ref ref;
+      unsigned int flag;
+ {
+   ref->ecommon.processed2  = flag;
+ }
+ 
+ static inline bool
+ exprref_processed2 (ref)
+      tree_ref ref;
+ {
+   return ref->ecommon.processed2;
+ }
+ 
+ static inline ref_list
+ exprref_uses (ref)
+      tree_ref ref;
+ {
+   return ref->ecommon.uses;
+ }
+ static inline void
+ set_exprref_uses (ref, list)
+      tree_ref ref;
+      ref_list list;
+ {
+   ref->ecommon.uses = list;
+ }
+ 
  static inline void
  set_expruse_def (ref, def)
       tree_ref ref;
       tree_ref def;
  {
+   if (def)
+     {
+       if (!exprref_uses (def))
+ 	set_exprref_uses (def, create_ref_list ());
+       
+       if (expruse_def (ref))
+ 	remove_ref_from_list (exprref_uses (expruse_def (ref)), ref);
+             
+       add_ref_to_list_end (exprref_uses (def), ref);
+     }
    ref->euse.def = def;
  }
  
*************** expruse_phiop (ref)
*** 518,523 ****
--- 597,617 ----
    return ref->euse.op_occurrence;
  }
  
+ static inline void
+ set_expruse_phi (ref, phi)
+      tree_ref ref;
+      tree_ref phi;
+ {
+   ref->euse.phi = phi;
+ }
+ 
+ static inline tree_ref
+ expruse_phi (ref)
+      tree_ref ref;
+ {
+   return ref->euse.phi;
+ }
+ 
  static inline void 
  set_expruse_has_real_use (ref, flag)
       tree_ref ref;
*************** exprphi_phi_args (ref)
*** 548,553 ****
--- 642,671 ----
    return ref->ephi.phi_args;
  }
  
+ static inline unsigned int
+ num_ephi_args (phi)
+      tree_ref phi;
+ {
+   return VARRAY_ACTIVE_SIZE (phi->ephi.phi_args);
+ }
+ 
+ static inline phi_node_arg
+ ephi_arg (phi, i)
+      tree_ref phi;
+      unsigned int i;
+ {
+   return (phi_node_arg)(VARRAY_GENERIC_PTR (phi->ephi.phi_args, i));
+ }
+ 
+ static inline void
+ set_ephi_arg (phi, i, arg)
+      tree_ref phi;
+      unsigned int i;
+      phi_node_arg arg;
+ {
+   VARRAY_GENERIC_PTR (phi->ephi.phi_args, i) = (PTR)arg;
+ }
+ 
  static inline void
  set_exprphi_downsafe (ref, flag)
       tree_ref ref;
*************** exprphi_extraneous (ref)
*** 606,626 ****
       tree_ref ref;
  {
    return ref->ephi.extraneous;
- }
- 
- static inline void
- set_exprphi_processed (ref, map)
-      tree_ref ref;
-      bitmap map;
- {
-   ref->ephi.processed = map;
- }
- 
- static inline bitmap
- exprphi_processed (ref)
-      tree_ref ref;
- {
-   return ref->ephi.processed;
  }
  
  static inline bool
--- 724,729 ----
Index: tree-cfg.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-cfg.c,v
retrieving revision 1.1.4.25
diff -c -3 -p -r1.1.4.25 tree-cfg.c
*** tree-cfg.c	5 Nov 2002 23:50:38 -0000	1.1.4.25
--- tree-cfg.c	6 Nov 2002 16:02:52 -0000
*************** static void make_cond_expr_blocks	PARAMS
*** 54,60 ****
  static void make_loop_expr_blocks	PARAMS ((tree *, basic_block));
  static void make_switch_expr_blocks	PARAMS ((tree *, basic_block));
  static basic_block create_bb		PARAMS ((tree *, basic_block));
- static void set_bb_for_stmt		PARAMS ((tree, basic_block));
  static void remove_unreachable_blocks	PARAMS ((void));
  
  /* Edges.  */
--- 54,59 ----
*************** create_bb (head_p, parent_block)
*** 377,409 ****
  }
  
  
- /* Add statement T to basic block BB.  If T is a COMPOUND_EXPR or WFL
-    container, also process the nodes inside it.  */
- 
- static void
- set_bb_for_stmt (t, bb)
-      tree t;
-      basic_block bb;
- {
-   tree_ann ann;
- 
-   if (t == empty_stmt_node)
-     return;
- 
-   do
-     {
-       ann = tree_annotation (t) ? tree_annotation (t) : create_tree_ann (t);
-       ann->bb = bb;
-       if (TREE_CODE (t) == COMPOUND_EXPR)
- 	t = TREE_OPERAND (t, 0);
-       else if (TREE_CODE (t) == EXPR_WITH_FILE_LOCATION)
- 	t = EXPR_WFL_NODE (t);
-       else
- 	t = NULL;
-     }
-   while (t);
- }
- 
  
  /* Create annotations for all the blocks in the flowgraph.  */
  
--- 376,381 ----
*************** last_stmt (bb)
*** 1781,1784 ****
--- 1753,1768 ----
    STRIP_WFL (t);
    STRIP_NOPS (t);
    return t;
+ }
+ tree *
+ last_stmt_ptr (bb)
+      basic_block bb;
+ {
+   gimple_stmt_iterator i;
+   
+   if (bb == NULL || bb->index == INVALID_BLOCK)
+     return NULL;
+ 
+   i = gsi_start (bb->end_tree_p);
+   return gsi_stmt_ptr (i);
  }
Index: tree-flow.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-flow.h,v
retrieving revision 1.1.4.32
diff -c -3 -p -r1.1.4.32 tree-flow.h
*** tree-flow.h	5 Nov 2002 23:50:38 -0000	1.1.4.32
--- tree-flow.h	6 Nov 2002 16:02:52 -0000
*************** enum tree_ref_type {
*** 67,73 ****
       (see tree-ssa-pre.c)  */
    E_PHI,
    E_USE,
!   E_KILL
  };
  
  /* Tree reference modifier bitmasks.  Used when calling create_ref.  */
--- 67,75 ----
       (see tree-ssa-pre.c)  */
    E_PHI,
    E_USE,
!   E_KILL,
!   E_EXIT,
!   E_LEFT
  };
  
  /* Tree reference modifier bitmasks.  Used when calling create_ref.  */
*************** struct expr_ref_common GTY(())
*** 302,310 ****
  
    /* SSAPRE: True if expression was inserted as a PHI operand occurrence.  */
    unsigned int inserted:1;
!   
    /* SSAPRE: Redundancy class of expression.  */
    unsigned int class;
  };
  
  
--- 304,321 ----
  
    /* SSAPRE: True if expression was inserted as a PHI operand occurrence.  */
    unsigned int inserted:1;
! 
    /* SSAPRE: Redundancy class of expression.  */
    unsigned int class;
+   
+   /* SSAPRE: Processed flag 1. */
+   unsigned int processed:1;
+ 
+   /* SSAPRE: Processed flag 2. */
+   unsigned int processed2:1;
+   
+   /* SSAPRE: List of uses for this ref. */
+   ref_list uses;
  };
  
  
*************** struct expr_phi_d GTY(())
*** 313,321 ****
  {
    struct expr_ref_common common;
    
!   /* Expression PHI operands.  This is an array of size
!      last_basic_block, with operands ordered by pre-order index of the
!      BB it's from.  */
    varray_type phi_args;
  
    /* SSAPRE: True if PHI is downsafe.  */
--- 324,330 ----
  {
    struct expr_ref_common common;
    
!   /* Expression PHI operands.*/
    varray_type phi_args;
  
    /* SSAPRE: True if PHI is downsafe.  */
*************** struct expr_phi_d GTY(())
*** 330,338 ****
    /* SSAPRE: True if PHI is expression.  */
    unsigned int extraneous:1;
  
-   /* SSAPRE: Bitmap to track which operands we've processed during
-      various algorithms.  */
-   bitmap processed;
  };
  
  
--- 339,344 ----
*************** struct expr_use_d GTY(())
*** 344,354 ****
    /* Definition chain.  */
    union tree_ref_d *def;
    
!   /* True if this use is a phi operand occurrence. */
!   int op_occurrence;
  
    /* SSAPRE: True if this is an operand, and it has a real use. */
!   int has_real_use;
  };
  
  enum tree_ref_structure_enum {
--- 350,363 ----
    /* Definition chain.  */
    union tree_ref_d *def;
    
!   /* SSAPRE: True if this use is a phi operand occurrence. */
!   unsigned int op_occurrence:1;
  
    /* SSAPRE: True if this is an operand, and it has a real use. */
!   unsigned int has_real_use:1;  
! 
!   /* For phi-operands, which phi it belongs to. */
!   union tree_ref_d *phi;
  };
  
  enum tree_ref_structure_enum {
*************** static inline void set_exprref_save PARA
*** 441,446 ****
--- 450,461 ----
  static inline bool exprref_save PARAMS ((tree_ref));
  static inline void set_exprref_reload PARAMS ((tree_ref, unsigned int));
  static inline bool exprref_reload PARAMS ((tree_ref));
+ static inline void set_exprref_processed PARAMS ((tree_ref, unsigned int));
+ static inline bool exprref_processed PARAMS ((tree_ref));
+ static inline void set_exprref_processed2 PARAMS ((tree_ref, unsigned int));
+ static inline bool exprref_processed2 PARAMS ((tree_ref));
+ static inline ref_list exprref_uses PARAMS ((tree_ref));
+ static inline void set_exprref_uses PARAMS ((tree_ref, ref_list));
  
  /* For expruse. */
  static inline void set_expruse_def PARAMS ((tree_ref, tree_ref));
*************** static inline void set_expruse_phiop PAR
*** 449,455 ****
  static inline bool expruse_phiop PARAMS ((tree_ref));
  static inline void set_expruse_has_real_use PARAMS ((tree_ref, unsigned int));
  static inline bool expruse_has_real_use PARAMS ((tree_ref));
! 
  /* For exprphi. */
  static inline void set_exprphi_phi_args PARAMS ((tree_ref, varray_type));
  static inline varray_type exprphi_phi_args PARAMS ((tree_ref));
--- 464,471 ----
  static inline bool expruse_phiop PARAMS ((tree_ref));
  static inline void set_expruse_has_real_use PARAMS ((tree_ref, unsigned int));
  static inline bool expruse_has_real_use PARAMS ((tree_ref));
! static inline void set_expruse_phi PARAMS ((tree_ref, tree_ref));
! static inline tree_ref expruse_phi PARAMS ((tree_ref));
  /* For exprphi. */
  static inline void set_exprphi_phi_args PARAMS ((tree_ref, varray_type));
  static inline varray_type exprphi_phi_args PARAMS ((tree_ref));
*************** static inline void set_exprphi_later PAR
*** 461,469 ****
  static inline bool exprphi_later PARAMS ((tree_ref));
  static inline void set_exprphi_extraneous PARAMS ((tree_ref, unsigned int));
  static inline bool exprphi_extraneous PARAMS ((tree_ref));
- static inline void set_exprphi_processed PARAMS ((tree_ref, bitmap));
- static inline bitmap exprphi_processed PARAMS ((tree_ref));
  static inline bool exprphi_willbeavail PARAMS ((tree_ref));
  
  
  /*---------------------------------------------------------------------------
--- 477,487 ----
  static inline bool exprphi_later PARAMS ((tree_ref));
  static inline void set_exprphi_extraneous PARAMS ((tree_ref, unsigned int));
  static inline bool exprphi_extraneous PARAMS ((tree_ref));
  static inline bool exprphi_willbeavail PARAMS ((tree_ref));
+ static inline phi_node_arg ephi_arg PARAMS ((tree_ref, unsigned));
+ extern void add_ephi_arg  PARAMS ((tree_ref, tree_ref, edge));
+ static inline void set_ephi_arg  PARAMS ((tree_ref, unsigned, phi_node_arg));
+ static inline unsigned int num_ephi_args PARAMS ((tree_ref));
  
  
  /*---------------------------------------------------------------------------
*************** enum tree_flags
*** 518,523 ****
--- 536,542 ----
  
  static inline tree_ann tree_annotation	PARAMS ((tree));
  static inline basic_block bb_for_stmt	PARAMS ((tree));
+ static inline void set_bb_for_stmt      PARAMS ((tree, basic_block));
  static inline tree_ref currdef_for	PARAMS ((tree));
  static inline void set_currdef_for	PARAMS ((tree, tree_ref));
  static inline ref_list tree_refs	PARAMS ((tree));
*************** extern void insert_bb_before		PARAMS ((b
*** 657,662 ****
--- 676,682 ----
  extern void cleanup_tree_cfg		PARAMS ((void));
  extern tree first_stmt			PARAMS ((basic_block));
  extern tree last_stmt			PARAMS ((basic_block));
+ extern tree *last_stmt_ptr			PARAMS ((basic_block));
  extern basic_block latch_block		PARAMS ((basic_block));
  extern bool is_latch_block		PARAMS ((basic_block));
  

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

* Re: [tree-ssa]: SSAPRE Update
  2002-11-06  8:25 [tree-ssa]: SSAPRE Update Daniel Berlin
@ 2002-11-06  8:41 ` Diego Novillo
  0 siblings, 0 replies; 3+ messages in thread
From: Diego Novillo @ 2002-11-06  8:41 UTC (permalink / raw)
  To: Daniel Berlin; +Cc: gcc-patches

On Wed, 06 Nov 2002, Daniel Berlin wrote:

> Diego, I externalized set_bb_for_stmt because it's one of the only 
> functions we don't have a "get" but not a "set" accessible for (ie 
> bb_for_stmt was around, but not set_bb_for_stmt) and it was necessary 
> for proper operation.
> Alternatively, you could make both bb_for_stmt and set_bb_for_stmt 
> private, and have replace_ref_* call set_bb_for_stmt for us.
>
Yes, replace_ref_stmt_with() will need to do that.  Leave the
external call for now.  It will be easy enough to replace once
replace_ref_* is working properly.


Diego.

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

* [tree-ssa]: SSAPRE Update
@ 2002-11-06  8:25 Daniel Berlin
  0 siblings, 0 replies; 3+ messages in thread
From: Daniel Berlin @ 2002-11-06  8:25 UTC (permalink / raw)
  To: gcc-patches

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

Starting to cleanup and remove unnecessary redundancy, structures, 
ugliness, and speeding up pieces of code that are slow.
Large portions of insertion code may look very ugly right now due to 
being in flux (It's waiting for DFA updates. I can't write code to 
update the SSA until we know the interface, which is still being 
decided).

I'll clean up and commonize the strength reduction bits next.

This update includes basic load PRE (aka register promotion) for 
indirect loads.
I'll do component refs, direct loads, and array loads after more clean 
up.
But
int main(int argc)
{
         static int a;
         static int *b;
         static int *d;
         static int c;
         a = 5;
         b = &a;
         d = &a;
         c = *b;
         c = *b;
         if (argc)
         {
                 *b = 5;
         }
         c = *b;

Will be optimized to:

main()
{
   int pretmp.1;
   static int a;
   static int * b;
   static int * d;
   static int c;

   a = 5;
   b = &a;
   d = &a;
   pretmp.1 = *b;
   c = pretmp.1;
   c = pretmp.1;
   if (argc != 0)
     {
       {
         pretmp.1 = 5;
         *b = pretmp.1
       }
     };
   c = pretmp.1
}
I'll wait a few hours before committing, on the off chance Diego is 
really against making set_bb_for_stmt external.

Diego, I externalized set_bb_for_stmt because it's one of the only 
functions we don't have a "get" but not a "set" accessible for (ie 
bb_for_stmt was around, but not set_bb_for_stmt) and it was necessary 
for proper operation.
Alternatively, you could make both bb_for_stmt and set_bb_for_stmt 
private, and have replace_ref_* call set_bb_for_stmt for us.
I only did it this way because I didn't want to interfere with any ref 
updating work you've done.

2002-11-04  Daniel Berlin  <dberlin@dberlin.org>

	* tree-flow.h: Prototype set_bb_for_stmt, last_stmt_ptr,
	add_ephi_arg, num_ephi_args, set_ephi_arg, ephi_arg.
	(enum tree_ref_type): Add E_LEFT, E_KILL, E_EXIT.

	* tree-cfg.c (set_bb_for_stmt): Move to tree-flow-inline.h.
	(last_stmt_ptr): New function, gives pointer to last statement in
	bb.

	* tree-flow-inline.h: Add exprref_processed, exprref_processed2,
	expruse_phi, num_ephi_args, set_ephi_arg, ephi_arg, add_ephi_arg.
	
	* tree-dfa.c (tree_ref_structure): Handle E_{LEFT,KILL,EXIT}.
	(ref_type_name): Ditto.
	(tree_ref_size): Ditto.
	(dump_ref): E_PHI's phi_args is now a varray of phi_arg structs.
	(add_ephi_arg): New function.
	(remove_ref_list): Fix crash when node not found.
	(compute_may_aliases): Add timing for points-to analysis.

	* timevar.def: Add TV_TREE_PTA.

	* tree-ssa-pre.c: Start of massive cleanup and rewriting (in
	preparation for load/store PRE). No more uses of ref_expr, proper
	call handling. Started removing unnecessary structures and lists,
	started removing redundant and inefficient operations (IE O(n^2)
	loops to process all phi operands, etc).  Basic load PRE implemented.
	Code may look ugly due to large pieces commented out waiting for DFA
	updating of refs to redo.
	

[-- Attachment #2: prediff --]
[-- Type: application/octet-stream, Size: 134710 bytes --]

Index: tree-dfa.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-dfa.c,v
retrieving revision 1.1.4.40
diff -c -3 -p -r1.1.4.40 tree-dfa.c
*** tree-dfa.c	5 Nov 2002 23:50:38 -0000	1.1.4.40
--- tree-dfa.c	6 Nov 2002 16:02:51 -0000
*************** Boston, MA 02111-1307, USA.  */
*** 29,34 ****
--- 29,35 ----
  #include "basic-block.h"
  #include "output.h"
  #include "errors.h"
+ #include "timevar.h"
  #include "expr.h"
  #include "ggc.h"
  #include "flags.h"
*************** static tree clobber_vars_r		PARAMS ((tre
*** 93,99 ****
  static void compute_may_aliases		PARAMS ((void));
  static void find_may_aliases_for	PARAMS ((tree));
  static void add_may_alias		PARAMS ((tree, tree));
! static bool may_alias_p			PARAMS ((tree, tree));
  static bool is_visible_to		PARAMS ((tree, tree));
  static size_t tree_ref_size		PARAMS ((enum tree_ref_type));
  static inline tree create_indirect_ref	PARAMS ((tree));
--- 94,100 ----
  static void compute_may_aliases		PARAMS ((void));
  static void find_may_aliases_for	PARAMS ((tree));
  static void add_may_alias		PARAMS ((tree, tree));
! static inline bool may_alias_p			PARAMS ((tree, tree));
  static bool is_visible_to		PARAMS ((tree, tree));
  static size_t tree_ref_size		PARAMS ((enum tree_ref_type));
  static inline tree create_indirect_ref	PARAMS ((tree));
*************** remove_ref_from_list (list, ref)
*** 532,537 ****
--- 533,540 ----
      return;
  
    tmp = find_list_node (list, ref);
+   if (!tmp)
+     return;
  
    if (tmp == list->first)
      list->first = tmp->next;
*************** tree_ref_size (ref_type)
*** 775,780 ****
--- 778,787 ----
        return sizeof (struct expr_use_d);
      case E_KILL:
        return sizeof (struct expr_ref_common);
+     case E_EXIT:
+       return sizeof (struct expr_ref_common);
+     case E_LEFT:
+       return sizeof (struct expr_ref_common);
      }
  
    abort ();
*************** create_ref (var, ref_type, ref_mod, bb, 
*** 900,912 ****
      {
        varray_type temp;
        VARRAY_GENERIC_PTR_INIT (temp, 
! 			       last_basic_block, "ephi_chain");
        set_exprphi_phi_args (ref, temp);
!       set_exprphi_processed (ref, BITMAP_GGC_ALLOC ());
!       set_exprphi_downsafe (ref, 1);
!       set_exprphi_canbeavail (ref, 1);
!       set_exprphi_later (ref, 1);
!       set_exprphi_extraneous (ref, 1);
      }
  
    if (var)
--- 907,918 ----
      {
        varray_type temp;
        VARRAY_GENERIC_PTR_INIT (temp, 
! 			       1, "ephi_chain");
        set_exprphi_phi_args (ref, temp);
!       set_exprphi_downsafe (ref, true);
!       set_exprphi_canbeavail (ref, true);
!       set_exprphi_later (ref, true);
!       set_exprphi_extraneous (ref, true);
      }
  
    if (var)
*************** add_phi_arg (phi, def, e)
*** 975,980 ****
--- 981,1005 ----
  }
  
  
+ /* Add a new argument to EPHI for definition DEF reaching in via edge E.  */
+ 
+ void
+ add_ephi_arg (phi, def, e)
+      tree_ref phi;
+      tree_ref def;
+      edge e;
+ {
+   phi_node_arg arg;
+ 
+   arg = (phi_node_arg) ggc_alloc (sizeof (*arg));
+   memset ((void *) arg, 0, sizeof (*arg));
+ 
+   arg->def = def;
+   arg->e = e;
+ 
+   VARRAY_PUSH_GENERIC_PTR (phi->ephi.phi_args, (PTR)arg);
+ }
+ 
  /* Add a unique copy of variable VAR to the list of referenced variables.  */
  
  static void
*************** dump_ref (outf, prefix, ref, indent, det
*** 1171,1177 ****
  		     exprref_class (ref), exprphi_downsafe (ref), 
  		     exprphi_canbeavail (ref), exprphi_later (ref));
  	  fputs (" expr-phi-args:\n", outf);
! 	  dump_ref_array (outf, prefix, exprphi_phi_args (ref), indent + 4, 1);
  	}	
  
        if (ref_type (ref) == V_DEF && imm_uses (ref))
--- 1196,1202 ----
  		     exprref_class (ref), exprphi_downsafe (ref), 
  		     exprphi_canbeavail (ref), exprphi_later (ref));
  	  fputs (" expr-phi-args:\n", outf);
! 	  dump_phi_args (outf, prefix, exprphi_phi_args (ref), indent + 4, 1);
  	}	
  
        if (ref_type (ref) == V_DEF && imm_uses (ref))
*************** ref_type_name (ref)
*** 1693,1703 ****
--- 1718,1732 ----
  	        : type == E_PHI ? "E_PHI"
  	        : type == E_USE ? "E_USE"
  	        : type == E_KILL ? "E_KILL"
+ 	        : type == E_EXIT ? "E_EXIT"
+ 	        : type == E_LEFT ? "E_LEFT"
  	        : "???",
  	   max);
    
    if (ref_type (ref) == E_USE 
        || ref_type (ref) == E_KILL
+       || ref_type (ref) == E_EXIT
+       || ref_type (ref) == E_LEFT
        || ref_type (ref) == E_PHI)
      return str;
    
*************** clobber_vars_r (tp, walk_subtrees, data)
*** 1746,1758 ****
        create_ref (*tp, V_USE, TRM_MAY, clobber->bb, clobber->parent_stmt_p,
  		  clobber->parent_expr_p, NULL, 1);
        create_ref (*tp, V_DEF, TRM_CLOBBER, clobber->bb, clobber->parent_stmt_p,
! 		  clobber->parent_expr_p, NULL, 1);
      }
  
    return NULL;
  }
  
- 
  /* Compute may-alias information for every variable referenced in the
     program.  FIXME this computes a bigger set than necessary.
  
--- 1775,1786 ----
        create_ref (*tp, V_USE, TRM_MAY, clobber->bb, clobber->parent_stmt_p,
  		  clobber->parent_expr_p, NULL, 1);
        create_ref (*tp, V_DEF, TRM_CLOBBER, clobber->bb, clobber->parent_stmt_p,
! 		  clobber->parent_expr_p, NULL, 1); 
      }
  
    return NULL;
  }
  
  /* Compute may-alias information for every variable referenced in the
     program.  FIXME this computes a bigger set than necessary.
  
*************** static void
*** 1766,1774 ****
  compute_may_aliases ()
  {
    unsigned long i;
! 
!   if (flag_tree_points_to)
!     create_alias_vars ();
  
    for (i = 0; i < num_referenced_vars; i++)
      {
--- 1794,1806 ----
  compute_may_aliases ()
  {
    unsigned long i;
!   
!   if (flag_tree_points_to != PTA_NONE  && num_referenced_vars)
!     {
!       timevar_push (TV_TREE_PTA);
!       create_alias_vars ();
!       timevar_pop (TV_TREE_PTA);
!     }
  
    for (i = 0; i < num_referenced_vars; i++)
      {
*************** compute_may_aliases ()
*** 1780,1810 ****
  	find_may_aliases_for (var);
      }
  
!   if (flag_tree_points_to)
!     delete_alias_vars ();
! }
! 
! 
! /* Find variables that PTR may be aliasing.  */
! 
! static void
! find_may_aliases_for (ptr)
!      tree ptr;
! {
!   unsigned long i;
! 
!   for (i = 0; i < num_referenced_vars; i++)
      {
!       tree var = referenced_var (i);
!       tree var_sym = get_base_symbol (var);
! 
!       if (may_alias_p (ptr, var_sym)
! 	  /* Avoid adding duplicate aliases.  */
! 	  && get_alias_index (ptr, var_sym) == -1)
! 	{
! 	  add_may_alias (ptr, var_sym);
! 	  add_may_alias (var_sym, ptr);
! 	}
      }
  }
  
--- 1812,1822 ----
  	find_may_aliases_for (var);
      }
  
!   if (flag_tree_points_to != PTA_NONE && num_referenced_vars)
      {
!       timevar_push (TV_TREE_PTA);
!       delete_alias_vars ();
!       timevar_pop (TV_TREE_PTA);
      }
  }
  
*************** find_may_aliases_for (ptr)
*** 1812,1825 ****
  /* Return true if PTR (an INDIRECT_REF tree) may alias VAR_SYM (a _DECL tree).
     FIXME  This returns true more often than it should.  */
  
! static bool
  may_alias_p (ptr, var_sym)
       tree ptr;
       tree var_sym;
  {
    HOST_WIDE_INT ptr_alias_set, var_alias_set;
    tree ptr_sym = get_base_symbol (ptr);
! 
    /* GLOBAL_VAR aliases every global variable and locals that have had
       their address taken, unless points-to analysis is done. This is because
       points-to is supposed to handle this case, and thus, can give a more
--- 1824,1837 ----
  /* Return true if PTR (an INDIRECT_REF tree) may alias VAR_SYM (a _DECL tree).
     FIXME  This returns true more often than it should.  */
  
! static inline bool
  may_alias_p (ptr, var_sym)
       tree ptr;
       tree var_sym;
  {
    HOST_WIDE_INT ptr_alias_set, var_alias_set;
    tree ptr_sym = get_base_symbol (ptr);
!   
    /* GLOBAL_VAR aliases every global variable and locals that have had
       their address taken, unless points-to analysis is done. This is because
       points-to is supposed to handle this case, and thus, can give a more
*************** may_alias_p (ptr, var_sym)
*** 1831,1837 ****
        && (TREE_ADDRESSABLE (var_sym)
  	  || decl_function_context (var_sym) == NULL))
      return true;
! 
    /* Obvious reasons why PTR_SYM and VAR_SYM can't possibly alias
       each other.  */
    if (var_sym == ptr_sym
--- 1843,1849 ----
        && (TREE_ADDRESSABLE (var_sym)
  	  || decl_function_context (var_sym) == NULL))
      return true;
!   
    /* Obvious reasons why PTR_SYM and VAR_SYM can't possibly alias
       each other.  */
    if (var_sym == ptr_sym
*************** may_alias_p (ptr, var_sym)
*** 1843,1859 ****
  
    ptr_alias_set = get_alias_set (TREE_TYPE (ptr));
    var_alias_set = get_alias_set (TREE_TYPE (var_sym));
! 
    if (!alias_sets_conflict_p (ptr_alias_set, var_alias_set))
      return false;
  
!   if (!flag_tree_points_to)
!     return true;
  
!   return ptr_may_alias_var (ptr_sym, var_sym);
  }
  
  
  /* Return true if SYM1 and SYM2 are visible to each other.  Visibility is
     determined based on the scopes where each variable is declared.  Both
     scopes must be the same or one must be enclosed in the other.  */
--- 1855,1896 ----
  
    ptr_alias_set = get_alias_set (TREE_TYPE (ptr));
    var_alias_set = get_alias_set (TREE_TYPE (var_sym));
!   
    if (!alias_sets_conflict_p (ptr_alias_set, var_alias_set))
      return false;
  
!   if (flag_tree_points_to)
!     if (!ptr_may_alias_var (ptr_sym, var_sym))
!        return false;
!   
!   return true;
! }
! /* Find variables that PTR may be aliasing.  */
  
! static void
! find_may_aliases_for (ptr)
!      tree ptr;
! {
!   unsigned long i;
! 
!   for (i = 0; i < num_referenced_vars; i++)
!     {
!       tree var = referenced_var (i);
!       tree var_sym = get_base_symbol (var);
! 
!       if (may_alias_p (ptr, var_sym)
! 	  /* Avoid adding duplicate aliases.  */
! 	  && get_alias_index (ptr, var_sym) == -1)
! 	{
! 	  add_may_alias (ptr, var_sym);
! 	  add_may_alias (var_sym, ptr);
! 	}
!     }
  }
  
  
+ 
+ 
  /* Return true if SYM1 and SYM2 are visible to each other.  Visibility is
     determined based on the scopes where each variable is declared.  Both
     scopes must be the same or one must be enclosed in the other.  */
*************** tree_ref_structure (ref)
*** 2011,2016 ****
--- 2048,2057 ----
    else if (type == E_USE)
      return TR_EXPR_USE;
    else if (type == E_KILL)
+     return TR_EXPR_REF_COMMON;
+   else if (type == E_EXIT)
+     return TR_EXPR_REF_COMMON;
+   else if (type == E_LEFT)
      return TR_EXPR_REF_COMMON;
  
    abort ();
Index: timevar.def
===================================================================
RCS file: /cvs/gcc/gcc/gcc/timevar.def,v
retrieving revision 1.14.2.1
diff -c -3 -p -r1.14.2.1 timevar.def
*** timevar.def	22 Oct 2002 16:07:09 -0000	1.14.2.1
--- timevar.def	6 Nov 2002 16:02:51 -0000
*************** DEFTIMEVAR (TV_LEX		     , "lexical anal
*** 53,58 ****
--- 53,59 ----
  DEFTIMEVAR (TV_PARSE                 , "parser")
  DEFTIMEVAR (TV_EXPAND		     , "expand")
  DEFTIMEVAR (TV_TREE_CFG		     , "tree CFG construction")
+ DEFTIMEVAR (TV_TREE_PTA		     , "tree PTA")
  DEFTIMEVAR (TV_TREE_SSA		     , "tree SSA building")	 
  DEFTIMEVAR (TV_TREE_CCP		     , "tree CCP")
  DEFTIMEVAR (TV_TREE_PRE		     , "tree PRE")
Index: tree-ssa-pre.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa-pre.c,v
retrieving revision 1.1.4.31
diff -c -3 -p -r1.1.4.31 tree-ssa-pre.c
*** tree-ssa-pre.c	5 Nov 2002 23:50:39 -0000	1.1.4.31
--- tree-ssa-pre.c	6 Nov 2002 16:02:51 -0000
*************** Boston, MA 02111-1307, USA.  */
*** 49,55 ****
  
  #define EXTRANEOUS_EPHI_REMOVAL 0
  #define DEBUGGING_STRRED 1
! #define DEBUGGING_SSA_UPDATE 1
  
  /* See http://citeseer.nj.nec.com/chow97new.html, and
     http://citeseer.nj.nec.com/kennedy99partial.html for details of the
--- 49,56 ----
  
  #define EXTRANEOUS_EPHI_REMOVAL 0
  #define DEBUGGING_STRRED 1
! #define DEBUGGING_SSA_UPDATE 0
! #define DEBUGGING_EPHI_REMOVAL 0
  
  /* See http://citeseer.nj.nec.com/chow97new.html, and
     http://citeseer.nj.nec.com/kennedy99partial.html for details of the
*************** Boston, MA 02111-1307, USA.  */
*** 65,70 ****
--- 66,77 ----
  
  */
  /* TODO:
+    
+    Commonize injuring def stuff into a seperate function (get_injuring_def or
+    something). 
+ 
+    Load PRE bug testing and fixing.
+ 
     Get rid of hunting through statements for refs, now that
     expressions have the refs we want as well -- This should substantially
     clean up the code, which was written when only statements had refs,
*************** Boston, MA 02111-1307, USA.  */
*** 73,84 ****
     Remapping expression occurrences to the entire expression is a pain, and is
     only done to avoid having to grab the first operand all the time (the code
     was started before the change to include the *entire* expression in the
!    ref_expr was made).  It would clean up the code a lot and remove a lot of
     duplicated functions, whose only difference is one remaps and one doesn't.
  
     Strength reduction improvements.
  
!    Register promotion.
  */
  struct expr_info;
  static int expr_lexically_eq PARAMS ((tree, tree));
--- 80,91 ----
     Remapping expression occurrences to the entire expression is a pain, and is
     only done to avoid having to grab the first operand all the time (the code
     was started before the change to include the *entire* expression in the
!    ref_stmt was made).  It would clean up the code a lot and remove a lot of
     duplicated functions, whose only difference is one remaps and one doesn't.
  
     Strength reduction improvements.
  
! 
  */
  struct expr_info;
  static int expr_lexically_eq PARAMS ((tree, tree));
*************** static void code_motion PARAMS ((struct 
*** 104,126 ****
  static bool can_insert PARAMS ((tree_ref));
  static inline bool defs_match_p PARAMS ((struct expr_info *, tree, tree));
  static inline bool defs_y_dom_x PARAMS ((struct expr_info *, tree_ref, tree_ref));
! static void assign_new_class PARAMS ((tree_ref, varray_type *));
  static void insert_occ_in_preorder_dt_order_1 PARAMS ((struct expr_info *, 
  						       fibheap_t, basic_block));
  static void insert_occ_in_preorder_dt_order PARAMS ((struct expr_info *, 
  						     fibheap_t));
  static void insert_euse_in_preorder_dt_order_1 PARAMS ((struct expr_info *, 
! 							fibheap_t, basic_block));
! static void insert_euse_in_preorder_dt_order PARAMS ((struct expr_info *, 
! 						      fibheap_t));
  static inline int opnum_of_phi PARAMS ((tree_ref, int));
  static varray_type phi_opnd_from_res PARAMS ((struct expr_info *, tree_ref, 
  					      int, basic_block));
  static splay_tree rename_2 PARAMS ((struct expr_info *, varray_type *));
  static void rename_1 PARAMS ((struct expr_info *));
  static void finalize_2 PARAMS ((struct expr_info *));
! static void finalize_1 PARAMS ((struct expr_info *, tree));
! static tree_ref phi_for_operand PARAMS ((struct expr_info *, tree_ref));
  static void set_save PARAMS ((struct expr_info *, tree_ref));
  static void set_replacement PARAMS ((struct expr_info *, tree_ref, tree_ref));
  #if 0
--- 111,133 ----
  static bool can_insert PARAMS ((tree_ref));
  static inline bool defs_match_p PARAMS ((struct expr_info *, tree, tree));
  static inline bool defs_y_dom_x PARAMS ((struct expr_info *, tree_ref, tree_ref));
! static void assign_new_class PARAMS ((tree_ref, varray_type *, varray_type *));
  static void insert_occ_in_preorder_dt_order_1 PARAMS ((struct expr_info *, 
  						       fibheap_t, basic_block));
  static void insert_occ_in_preorder_dt_order PARAMS ((struct expr_info *, 
  						     fibheap_t));
  static void insert_euse_in_preorder_dt_order_1 PARAMS ((struct expr_info *, 
! 							basic_block));
! static void insert_euse_in_preorder_dt_order PARAMS ((struct expr_info *));
  static inline int opnum_of_phi PARAMS ((tree_ref, int));
  static varray_type phi_opnd_from_res PARAMS ((struct expr_info *, tree_ref, 
  					      int, basic_block));
  static splay_tree rename_2 PARAMS ((struct expr_info *, varray_type *));
  static void rename_1 PARAMS ((struct expr_info *));
  static void finalize_2 PARAMS ((struct expr_info *));
! static bool finalize_1 PARAMS ((struct expr_info *, tree));
! 
! static tree_ref phi_operand_for_pred PARAMS ((tree_ref, edge));
  static void set_save PARAMS ((struct expr_info *, tree_ref));
  static void set_replacement PARAMS ((struct expr_info *, tree_ref, tree_ref));
  #if 0
*************** static void calculate_preorder PARAMS ((
*** 137,143 ****
  static void update_phis_in_list PARAMS ((ref_list, tree_ref, tree_ref));
  static void update_ssa_for_new_use PARAMS ((tree, tree, tree_ref, basic_block));
  static int find_reaching_def_of_var PARAMS ((tree_ref, basic_block, tree_ref));
! 
  static int *pre_preorder;
  static dominance_info pre_idom;
  static sbitmap *pre_dfs;
--- 144,156 ----
  static void update_phis_in_list PARAMS ((ref_list, tree_ref, tree_ref));
  static void update_ssa_for_new_use PARAMS ((tree, tree, tree_ref, basic_block));
  static int find_reaching_def_of_var PARAMS ((tree_ref, basic_block, tree_ref));
! static void temp_fix_refs PARAMS ((tree, tree, tree *));
! static void update_old_new PARAMS ((struct expr_info *, tree *, tree *));
! static inline bool is_a_call PARAMS ((tree));
! static inline bool okay_injuring_def PARAMS ((tree_ref, tree));
! static void process_left_occs_and_kills PARAMS ((varray_type, struct expr_info *,
! 						 tree_ref, tree));
! static tree get_operand PARAMS ((tree, unsigned int));
  static int *pre_preorder;
  static dominance_info pre_idom;
  static sbitmap *pre_dfs;
*************** static int preorder_count;
*** 149,157 ****
  static tree_ref *avdefs;
  
  static splay_tree new_stmt_map;
- 
  static splay_tree need_repair_map;
  
  
  /* sbitmap vector mapping blocks to the child blocks they dominate. */
  static sbitmap *domchildren;
--- 162,177 ----
  static tree_ref *avdefs;
  
  static splay_tree new_stmt_map;
  static splay_tree need_repair_map;
  
+ /* Map from pointers to statements we've replaced to pointers to where they are
+ now.  This is used to update the occurs list. We only need to update the occurs
+ list right before we create E_USE's (if we don't update them  at all, we create
+ E_USE's that point to the wrong place), and it would be O(n^2) to do it as we
+ replace statements (since we don't have something that gives us the index into
+ the occurs array an e_use came from, we'd have to search the entire occurs
+ array every time).  */
+ static splay_tree old_new_map;
  
  /* sbitmap vector mapping blocks to the child blocks they dominate. */
  static sbitmap *domchildren;
*************** struct expr_info
*** 159,173 ****
  {
    /* The actual expression.  */
    tree expr;  
!   /* The occurrences, which can include calls. */
    varray_type occurs;
!   /* Statements for the occurrences. */
!   varray_type occurstmts;
    /* An array of real occurrences. */
    varray_type reals;
-   /* An array mapping reals to the containing statements (so we can
-      get defs/uses/etc about them. */
-   varray_type realstmts;
    /* The ephis we've added for this expr. */
    varray_type phis;
    /* All the erefs. */
--- 179,192 ----
  {
    /* The actual expression.  */
    tree expr;  
!   /* The occurrences. */
    varray_type occurs;
!   /* The kills. */
!   varray_type kills;
!   /* The left occurrences. */
!   varray_type lefts;
    /* An array of real occurrences. */
    varray_type reals;
    /* The ephis we've added for this expr. */
    varray_type phis;
    /* All the erefs. */
*************** struct expr_info
*** 181,186 ****
--- 200,207 ----
    /* List of injury defs we need to fix reaching defs on *after* other
       insertions. */ 
    ref_list injfixups;
+   /* The euses/ephis in preorder dt order. */
+   ref_list euses_dt_order;
  };
  
  /* Returns true if a dominates b */
*************** is_strred_cand (expr)
*** 263,272 ****
    ref_list_iterator i;
    
    STRIP_WFL (expr);
    /* Multiplications that def a variable they use can't be strength reduced.
       Removing the multiplications would require adding more multiplications.
       IE a = a * 5. */
!   if (TREE_CODE (TREE_OPERAND (expr, 1)) != MULT_EXPR)
      return false;
    
    def = use = NULL;
--- 284,294 ----
    ref_list_iterator i;
    
    STRIP_WFL (expr);
+ 
    /* Multiplications that def a variable they use can't be strength reduced.
       Removing the multiplications would require adding more multiplications.
       IE a = a * 5. */
!   if (TREE_CODE (TREE_OPERAND (expr, 1)) != MULT_EXPR )
      return false;
    
    def = use = NULL;
*************** is_strred_cand (expr)
*** 291,301 ****
    
    return true;
  }
  
  /* Return true is INJ is an injuring definition */
  static bool 
  is_injuring_def (ei, inj)
! 	struct expr_info *ei;
       tree inj;
  {
    if (!inj || !is_simple_modify_expr (inj))
--- 313,335 ----
    
    return true;
  }
+ static inline bool
+ okay_injuring_def (inj, var)
+      tree_ref inj;
+      tree var;
+ {
+   if (is_default_def (inj) 
+       || ref_type (inj) == V_PHI
+       || ref_defines (inj, var)
+       || !maybe_find_rhs_use_for_var (inj, var))
+     return false;
+   return true;
+ }
  
  /* Return true is INJ is an injuring definition */
  static bool 
  is_injuring_def (ei, inj)
!      struct expr_info *ei;
       tree inj;
  {
    if (!inj || !is_simple_modify_expr (inj))
*************** free_expr_info (v1)
*** 366,374 ****
  {
    struct expr_info *e1 = (struct expr_info *)v1;
    VARRAY_CLEAR (e1->occurs);
!   VARRAY_CLEAR (e1->occurstmts);
    VARRAY_CLEAR (e1->reals);
-   VARRAY_CLEAR (e1->realstmts);
    VARRAY_CLEAR (e1->phis);
    VARRAY_CLEAR (e1->erefs);
    VARRAY_CLEAR (e1->refs);
--- 400,408 ----
  {
    struct expr_info *e1 = (struct expr_info *)v1;
    VARRAY_CLEAR (e1->occurs);
!   VARRAY_CLEAR (e1->kills);
!   VARRAY_CLEAR (e1->lefts);
    VARRAY_CLEAR (e1->reals);
    VARRAY_CLEAR (e1->phis);
    VARRAY_CLEAR (e1->erefs);
    VARRAY_CLEAR (e1->refs);
*************** set_var_phis (ei, phi, i)
*** 409,425 ****
          {
            phi_operand = phi_arg_def (phi_arg (phi, curr_phi_operand));
  	  if (ei->strred_cand && ref_type (phi_operand) != V_PHI)
! 	    while (is_injuring_def (ei, ref_expr (phi_operand)))
  	      {
  		tree_ref ird;
  		phi_operand = find_rhs_use_for_var (phi_operand, 
  						    ref_var
  						    (phi_operand));
  		ird = imm_reaching_def (phi_operand);
! 		if (is_default_def (ird)
! 		    || ref_type (ird) == V_PHI
! 		    || !maybe_find_rhs_use_for_var (ird, 
! 						    ref_var (phi_operand)))
  		  {
  		    phi_operand = ird;
  		    break;
--- 443,456 ----
          {
            phi_operand = phi_arg_def (phi_arg (phi, curr_phi_operand));
  	  if (ei->strred_cand && ref_type (phi_operand) != V_PHI)
! 	    while (is_injuring_def (ei, ref_stmt (phi_operand)))
  	      {
  		tree_ref ird;
  		phi_operand = find_rhs_use_for_var (phi_operand, 
  						    ref_var
  						    (phi_operand));
  		ird = imm_reaching_def (phi_operand);
! 		if (!okay_injuring_def (ird, ref_var (phi_operand)))
  		  {
  		    phi_operand = ird;
  		    break;
*************** set_var_phis (ei, phi, i)
*** 438,455 ****
  /* Helper macro to simplify accessing the phi for a given block. */
  #define phi_at_block(expr, b) VARRAY_GENERIC_PTR ((expr)->phis, pre_preorder[(b)->index])
  
- /* Helper macro to simplify accessing a phi operand for a given block. */
- #define phi_operand(phi, b) VARRAY_GENERIC_PTR (exprphi_phi_args (phi), pre_preorder[(b)->index])
- 
  /* Given a statement, find the V_DEF in it. */
  static inline tree_ref
  find_def_for_stmt (stmt)
       tree stmt;
  {
    ref_list_iterator i;
- 
    for (i = rli_start (tree_refs (stmt)); !rli_after_end (i); rli_step (&i))
!     if (ref_type (rli_ref (i)) == V_DEF)
        return rli_ref (i);
  
    return NULL;
--- 469,482 ----
  /* Helper macro to simplify accessing the phi for a given block. */
  #define phi_at_block(expr, b) VARRAY_GENERIC_PTR ((expr)->phis, pre_preorder[(b)->index])
  
  /* Given a statement, find the V_DEF in it. */
  static inline tree_ref
  find_def_for_stmt (stmt)
       tree stmt;
  {
    ref_list_iterator i;
    for (i = rli_start (tree_refs (stmt)); !rli_after_end (i); rli_step (&i))
!     if (ref_type (rli_ref (i)) == V_DEF && ref_var (rli_ref (i)) != global_var)
        return rli_ref (i);
  
    return NULL;
*************** find_rhs_use_for_var (def, var)
*** 467,473 ****
      abort ();
    return ret;
  }
!   
  /* Given the the DEF, and a VAR, find the V_USE of the VAR contained
     in that occurrence, if there is one. */
  static inline tree_ref
--- 494,500 ----
      abort ();
    return ret;
  }
! 
  /* Given the the DEF, and a VAR, find the V_USE of the VAR contained
     in that occurrence, if there is one. */
  static inline tree_ref
*************** maybe_find_rhs_use_for_var (def, var)
*** 478,490 ****
    ref_list_iterator i;
  
    /* Now look for the use of var in that expression. */
!   i = rli_start (tree_refs (ref_expr (def)));
    for (; !rli_after_end (i); rli_step (&i))
      {
        tree_ref ref = rli_ref (i);
  
        if (ref_type (ref) != V_USE
! 	  || !is_simple_modify_expr (ref_expr (ref)))
          continue;
        if (ref_var (ref) != var)
          continue;
--- 505,517 ----
    ref_list_iterator i;
  
    /* Now look for the use of var in that expression. */
!   i = rli_start (tree_refs (ref_stmt (def)));
    for (; !rli_after_end (i); rli_step (&i))
      {
        tree_ref ref = rli_ref (i);
  
        if (ref_type (ref) != V_USE
! 	  || !is_simple_modify_expr (ref_stmt (ref)))
          continue;
        if (ref_var (ref) != var)
          continue;
*************** maybe_find_rhs_use_for_var (def, var)
*** 492,499 ****
--- 519,573 ----
      }
    return NULL;
  }
+ /* Used soley by defs_match_p to make sure we are comparing RHS uses, not LHS
+    ones. 
+    The GIMPLE grammar thankfully gives us a strict set of things that will
+    appear on the LHS.
+    Thus, we know we aren't being handed weird crap.
+ */
+ static bool
+ is_on_lhs (var_p, expr_p)
+      tree *var_p;
+      tree *expr_p;
+ {
+   tree expr = *expr_p;
+   STRIP_WFL (expr);
+   STRIP_NOPS (expr);
+   switch (TREE_CODE (expr))
+     {
+     case MODIFY_EXPR:
+     case INIT_EXPR:
+       return is_on_lhs (var_p, &TREE_OPERAND (expr, 0));
+     case COMPONENT_REF:
+     case INDIRECT_REF:
+     case ADDR_EXPR:
+     case REFERENCE_EXPR:
+       return is_on_lhs (var_p, &TREE_OPERAND (expr, 0));
+     case VAR_DECL:
+     case FIELD_DECL:
+     case PARM_DECL:
+     case FUNCTION_DECL:
+       return var_p == expr_p;
+     default:
+       abort();
+     }
+ }
  
+ static bool
+ names_match_p (x, y)
+      tree x;
+      tree y;
+ {
+   while (TREE_CODE (x) == INDIRECT_REF || TREE_CODE (x) == ADDR_EXPR)
+     x = TREE_OPERAND (x, 0);
+   while (TREE_CODE (y) == INDIRECT_REF || TREE_CODE (y) == ADDR_EXPR)
+     y = TREE_OPERAND (y, 0);
+   
+   return y == x;
+ }
  
+   
+      
  /* Determine if the definitions of variables in Y dominate the basic
     block of X. */
  static inline bool 
*************** defs_y_dom_x (ei, y, x)
*** 511,520 ****
        ref_list_iterator j;
        tree yexpr, refexpr;
        
!       yexpr = ref_expr (y);
        STRIP_WFL (yexpr);
        yexpr = TREE_OPERAND (yexpr, 1);
!       
        if (!TREE_OPERAND (yexpr, i))
          continue;
  
--- 585,594 ----
        ref_list_iterator j;
        tree yexpr, refexpr;
        
!       yexpr = ref_stmt (y);
        STRIP_WFL (yexpr);
        yexpr = TREE_OPERAND (yexpr, 1);
! 
        if (!TREE_OPERAND (yexpr, i))
          continue;
  
*************** defs_y_dom_x (ei, y, x)
*** 526,551 ****
            /* Find the ref for this operand. */
  	  if (ref_type (ref) != V_USE)
  	    continue;
! 	  refexpr = ref_expr (ref);
  	  STRIP_WFL (refexpr);
! 	  if (!is_simple_modify_expr (refexpr)
!               || TREE_OPERAND (refexpr, 1) != yexpr)
              continue;
!           if (ref_var (ref) != TREE_OPERAND (yexpr, i))
              continue;
            if (!imm_reaching_def (ref))
              return false;
  
  	  if (ei->strred_cand)
! 	    while (is_injuring_def (ei, ref_expr (imm_reaching_def (ref))))
  	      {
  		ref = find_rhs_use_for_var (imm_reaching_def (ref), 
! 					    TREE_OPERAND (yexpr, i));
! 		if (ref_type (imm_reaching_def (ref)) == V_PHI
! 		    || is_default_def (imm_reaching_def (ref)))
  		  break;
  		ref = find_rhs_use_for_var (imm_reaching_def (ref), 
! 					    TREE_OPERAND (yexpr, i));
  	      }
            if (!(a_dom_b (ref_bb (imm_reaching_def (ref)), ref_bb (x))))
              return false;
--- 600,624 ----
            /* Find the ref for this operand. */
  	  if (ref_type (ref) != V_USE)
  	    continue;
! 	  refexpr = ref_stmt (ref);
  	  STRIP_WFL (refexpr);
! 	  if (!is_simple_modify_expr (refexpr))
! 	    //              || TREE_OPERAND (refexpr, 1) != yexpr)
              continue;
!           if (!names_match_p (ref_var (ref), get_operand (yexpr, i)))
              continue;
            if (!imm_reaching_def (ref))
              return false;
  
  	  if (ei->strred_cand)
! 	    while (is_injuring_def (ei, ref_stmt (imm_reaching_def (ref))))
  	      {
  		ref = find_rhs_use_for_var (imm_reaching_def (ref), 
! 					    get_operand (yexpr, i));	       
! 		if (!okay_injuring_def (imm_reaching_def (ref), ref_var (ref)))
  		  break;
  		ref = find_rhs_use_for_var (imm_reaching_def (ref), 
! 					    get_operand (yexpr, i));
  	      }
            if (!(a_dom_b (ref_bb (imm_reaching_def (ref)), ref_bb (x))))
              return false;
*************** defs_y_dom_x (ei, y, x)
*** 556,564 ****
  }
  
  /* Return true if the variables in t1 have the same defs as the
!    variables in t2.  
!    NB: t1 is expected to be a statement or assignment (IE both left and right sides).
!    t2 is expected to be the right hand side only.*/
  static inline bool
  defs_match_p (ei, t1, t2)
       struct expr_info *ei;
--- 629,635 ----
  }
  
  /* Return true if the variables in t1 have the same defs as the
!    variables in t2.  */
  static inline bool
  defs_match_p (ei, t1, t2)
       struct expr_info *ei;
*************** defs_match_p (ei, t1, t2)
*** 577,601 ****
    for (i = rli_start (tree_refs (t1)); !rli_after_end (i); rli_step (&i))
      {
        tree_ref use1 = rli_ref (i);
!       tree use1expr = ref_expr (use1);
        if (ref_type (use1) != V_USE
! 	  || !is_simple_modify_expr (use1expr))
          continue;
  
        STRIP_WFL (use1expr);
        use1expr = TREE_OPERAND (use1expr, 1);
!       if (TREE_CODE (use1expr) != TREE_CODE (t2))
!         continue;
!       use2 = find_rhs_use_for_var (find_def_for_stmt (origt2), ref_var (use1));
!       if (!use2) 
  	return false;
        /* Find the injuring definition, if one exists. */
        if (ei->strred_cand)
! 	while (is_injuring_def (ei, ref_expr (imm_reaching_def (use1))))
  	  {
  	    /* First, we get the use in the *injuring definition*. */
  	    use1 = find_rhs_use_for_var (imm_reaching_def (use1), 
  					 ref_var (use1));
  	    /* Now, use the use we just got to get the use from before it was
  	       injured. */
  	    use1 = find_rhs_use_for_var (imm_reaching_def (use1), 
--- 648,676 ----
    for (i = rli_start (tree_refs (t1)); !rli_after_end (i); rli_step (&i))
      {
        tree_ref use1 = rli_ref (i);
!       tree use1expr = ref_stmt (use1);
        if (ref_type (use1) != V_USE
! 	  || !is_simple_modify_expr (use1expr)
! 	  || is_on_lhs (&TREE_OPERAND (use1expr, 0), use1->common.stmt_p))
          continue;
  
        STRIP_WFL (use1expr);
        use1expr = TREE_OPERAND (use1expr, 1);
!       use2 = maybe_find_rhs_use_for_var (find_def_for_stmt (origt2),
! 					 ref_var (use1));
!       if (!use2 && (TREE_CODE (use1expr) != TREE_CODE (t2)))
! 	continue;	
!       else if (!use2) 
  	return false;
        /* Find the injuring definition, if one exists. */
        if (ei->strred_cand)
! 	while (is_injuring_def (ei, ref_stmt (imm_reaching_def (use1))))
  	  {
  	    /* First, we get the use in the *injuring definition*. */
  	    use1 = find_rhs_use_for_var (imm_reaching_def (use1), 
  					 ref_var (use1));
+ 	    if (!okay_injuring_def (imm_reaching_def (use1), ref_var (use1)))
+ 	      break;
  	    /* Now, use the use we just got to get the use from before it was
  	       injured. */
  	    use1 = find_rhs_use_for_var (imm_reaching_def (use1), 
*************** defs_match_p (ei, t1, t2)
*** 610,618 ****
  /* Assign a new redundancy class to the occurrence, and push it on the
     stack.  */ 
  static void
! assign_new_class (occ, stack)
       tree_ref occ;
       varray_type *stack;
  {
    /* class(occ) <- count
       Push(occ, stack)
--- 685,694 ----
  /* Assign a new redundancy class to the occurrence, and push it on the
     stack.  */ 
  static void
! assign_new_class (occ, stack, stack2)
       tree_ref occ;
       varray_type *stack;
+      varray_type *stack2;
  {
    /* class(occ) <- count
       Push(occ, stack)
*************** assign_new_class (occ, stack)
*** 620,633 ****
    */
    set_exprref_class (occ, class_count);
    VARRAY_PUSH_GENERIC_PTR (*stack, occ);
    class_count++;
  }
  
! /* Insert the expressions in preorder DT order in the fibheap.  */
  static void
! insert_euse_in_preorder_dt_order_1 (ei, fh, block)
       struct expr_info *ei;
-      fibheap_t fh;
       basic_block block;
  {
    size_t i;
--- 696,709 ----
    */
    set_exprref_class (occ, class_count);
    VARRAY_PUSH_GENERIC_PTR (*stack, occ);
+   VARRAY_PUSH_GENERIC_PTR (*stack2, occ);
    class_count++;
  }
  
! /* Insert the expressions in preorder DT order in the ref_list.  */
  static void
! insert_euse_in_preorder_dt_order_1 (ei, block)
       struct expr_info *ei;
       basic_block block;
  {
    size_t i;
*************** insert_euse_in_preorder_dt_order_1 (ei, 
*** 637,660 ****
        tree_ref ref = VARRAY_GENERIC_PTR (bbrefs, i);
        if (ref_bb (ref) != block)
  	continue;
!       if (ref_type (ref) == E_USE || ref_type (ref) == E_PHI)
! 	fibheap_insert (fh, preorder_count++, ref);
      }
    EXECUTE_IF_SET_IN_SBITMAP (domchildren[block->index], 0, i, 
    {
!     insert_euse_in_preorder_dt_order_1 (ei, fh, BASIC_BLOCK (i));
    });
  }
  
  static void
! insert_euse_in_preorder_dt_order (ei, fh)
       struct expr_info *ei;
-      fibheap_t fh;
  {
!   preorder_count = 0;
!   insert_euse_in_preorder_dt_order_1 (ei, fh, ENTRY_BLOCK_PTR->next_bb);
  }
  
  /* Insert the occurrences in preorder DT order, in the fibheap.  */
  static void
  insert_occ_in_preorder_dt_order_1 (ei, fh, block)
--- 713,748 ----
        tree_ref ref = VARRAY_GENERIC_PTR (bbrefs, i);
        if (ref_bb (ref) != block)
  	continue;
!       if (ref_type (ref) == E_USE || ref_type (ref) == E_PHI 
! 	  || ref_type (ref) == E_LEFT)
! 	add_ref_to_list_end (ei->euses_dt_order, ref);
      }
    EXECUTE_IF_SET_IN_SBITMAP (domchildren[block->index], 0, i, 
    {
!     insert_euse_in_preorder_dt_order_1 (ei, BASIC_BLOCK (i));
    });
  }
  
  static void
! insert_euse_in_preorder_dt_order (ei)
       struct expr_info *ei;
  {
!   insert_euse_in_preorder_dt_order_1 (ei, ENTRY_BLOCK_PTR->next_bb);
  }
  
+ static inline bool
+ is_a_call (expr)
+      tree expr;
+ {
+   STRIP_WFL (expr);
+   STRIP_NOPS (expr);
+   if (TREE_CODE (expr) == CALL_EXPR)
+     return true;
+   if (is_simple_modify_expr (expr) 
+       && TREE_CODE (TREE_OPERAND (expr, 1)) == CALL_EXPR)
+     return true;
+   return false;
+ }
  /* Insert the occurrences in preorder DT order, in the fibheap.  */
  static void
  insert_occ_in_preorder_dt_order_1 (ei, fh, block)
*************** insert_occ_in_preorder_dt_order_1 (ei, f
*** 670,697 ****
    for (i = 0; i < VARRAY_ACTIVE_SIZE (ei->occurs); i++)
      {
        tree_ref newref;
!       tree *occurexpr = VARRAY_GENERIC_PTR (ei->occurs, i);
!       tree *occurstmt = VARRAY_GENERIC_PTR (ei->occurstmts, i);
!       tree_ref occurref = VARRAY_GENERIC_PTR (ei->refs, i);
!       if (ref_bb (occurref) != block)
          continue;
!       if (TREE_CODE (*occurexpr) == CALL_EXPR)
  	{
! 	  newref = create_ref (*occurexpr,
! 				  E_KILL, 0, block, occurstmt,
! 				  occurexpr, NULL, true);
  	  VARRAY_PUSH_GENERIC_PTR (ei->erefs, newref);
  	  fibheap_insert (fh, preorder_count++, newref);
  	}
        else
  	{
  	  newref = create_ref (*occurexpr,
! 				  E_USE, 0, block, occurstmt, 
  				  occurexpr, NULL, true);
  	  VARRAY_PUSH_GENERIC_PTR (ei->erefs, newref);
  	  set_expruse_def (newref, NULL);
  	  set_exprref_class (newref, 0);
  	  set_expruse_phiop (newref, false);
  	  set_expruse_has_real_use (newref, false);
  	  fibheap_insert (fh, preorder_count++, newref);
  	}     
--- 758,801 ----
    for (i = 0; i < VARRAY_ACTIVE_SIZE (ei->occurs); i++)
      {
        tree_ref newref;
!       tree *current;
!       current = VARRAY_GENERIC_PTR (ei->occurs, i);
!       current = current ? current : VARRAY_GENERIC_PTR (ei->kills, i);
!       current = current ? current : VARRAY_GENERIC_PTR (ei->lefts, i);
!       if (bb_for_stmt (*current) != block)
          continue;
! 
!       if (VARRAY_GENERIC_PTR (ei->kills, i) != NULL)
  	{
! 	  tree *killexpr  = VARRAY_GENERIC_PTR (ei->kills, i);
! 	  
! 	  newref = create_ref (*killexpr,
! 			       E_KILL, 0, block, killexpr,
! 			       killexpr, NULL, true);
! 	  VARRAY_PUSH_GENERIC_PTR (ei->erefs, newref);
! 	  fibheap_insert (fh, preorder_count++, newref);
! 	}
!       else if (VARRAY_GENERIC_PTR (ei->lefts, i) != NULL)
! 	{
! 	  tree *leftexpr = VARRAY_GENERIC_PTR (ei->lefts, i);
! 	  newref = create_ref (*leftexpr, 
! 			       E_LEFT, 0, block, leftexpr,
! 			       leftexpr, NULL, true);
  	  VARRAY_PUSH_GENERIC_PTR (ei->erefs, newref);
  	  fibheap_insert (fh, preorder_count++, newref);
  	}
        else
  	{
+ 	  tree *occurexpr = VARRAY_GENERIC_PTR (ei->occurs, i);
  	  newref = create_ref (*occurexpr,
! 				  E_USE, 0, block, occurexpr, 
  				  occurexpr, NULL, true);
  	  VARRAY_PUSH_GENERIC_PTR (ei->erefs, newref);
  	  set_expruse_def (newref, NULL);
  	  set_exprref_class (newref, 0);
  	  set_expruse_phiop (newref, false);
+ 	  set_exprref_processed (newref, false);
+ 	  set_exprref_processed2 (newref, false);
  	  set_expruse_has_real_use (newref, false);
  	  fibheap_insert (fh, preorder_count++, newref);
  	}     
*************** insert_occ_in_preorder_dt_order_1 (ei, f
*** 705,721 ****
          {
            if (phi_at_block (ei, succ->dest) != NULL)
              {
!               tree_ref newref = create_ref (NULL, E_USE, 0, block, 0, 0, 0, true);
                tree_ref phi = phi_at_block (ei, succ->dest);
  	      VARRAY_PUSH_GENERIC_PTR (ei->erefs, newref);
                set_expruse_def (newref, NULL);
                set_exprref_class (newref, 0);
                set_expruse_phiop (newref, true);
                set_expruse_has_real_use (newref, false);
  	      set_exprref_save (newref, false);
  	      set_exprref_reload (newref, false);
  	      set_exprref_inserted (newref, false);
!               phi_operand (phi, block) = newref;
                fibheap_insert (fh, preorder_count++, newref);
              }
          }      
--- 809,829 ----
          {
            if (phi_at_block (ei, succ->dest) != NULL)
              {
!               tree_ref newref = create_ref (NULL, E_USE, 0, block, 0, 
! 					    0, 0, true);
                tree_ref phi = phi_at_block (ei, succ->dest);
  	      VARRAY_PUSH_GENERIC_PTR (ei->erefs, newref);
                set_expruse_def (newref, NULL);
                set_exprref_class (newref, 0);
                set_expruse_phiop (newref, true);
+ 	      set_expruse_phi (newref, phi);
                set_expruse_has_real_use (newref, false);
  	      set_exprref_save (newref, false);
  	      set_exprref_reload (newref, false);
  	      set_exprref_inserted (newref, false);
! 	      set_exprref_processed (newref, false);
! 	      set_exprref_processed2 (newref, false);	 
! 	      add_ephi_arg (phi, newref, succ);
                fibheap_insert (fh, preorder_count++, newref);
              }
          }      
*************** insert_occ_in_preorder_dt_order_1 (ei, f
*** 724,730 ****
  	  /* No point in inserting exit blocks into heap first, since
  	     they'll never be anything on the stack. */
  	  if (preorder_count != 0)
! 	    fibheap_insert (fh, preorder_count++, (void *) EXIT_BLOCK_PTR);
          }
            
      }
--- 832,844 ----
  	  /* No point in inserting exit blocks into heap first, since
  	     they'll never be anything on the stack. */
  	  if (preorder_count != 0)
! 	    {
! 	      tree_ref newref;
! 	      newref = create_ref (NULL, E_EXIT, 0, block, 
! 				   NULL, NULL, NULL, true);
! 	      VARRAY_PUSH_GENERIC_PTR (ei->erefs, newref);
! 	      fibheap_insert (fh, preorder_count++, newref);
! 	    }
          }
            
      }
*************** phi_opnd_from_res (ei, Z, j, b)
*** 787,797 ****
        tree_ref v = rli_ref (k);
        if (ref_type (v) == V_USE)
  	if (ei->strred_cand)
! 	  while  (is_injuring_def (ei, ref_expr (imm_reaching_def (v))))
  	    {
  	      v = find_rhs_use_for_var (imm_reaching_def (v), ref_var (v));
! 	      if (is_default_def (imm_reaching_def (v))
! 		  || ref_type (imm_reaching_def (v)) == V_PHI)
  		break;
  	      v = find_rhs_use_for_var (imm_reaching_def (v), ref_var (v));
  	    }
--- 901,910 ----
        tree_ref v = rli_ref (k);
        if (ref_type (v) == V_USE)
  	if (ei->strred_cand)
! 	  while  (is_injuring_def (ei, ref_stmt (imm_reaching_def (v))))
  	    {
  	      v = find_rhs_use_for_var (imm_reaching_def (v), ref_var (v));
! 	      if (!okay_injuring_def (imm_reaching_def (v), ref_var (v)))
  		break;
  	      v = find_rhs_use_for_var (imm_reaching_def (v), ref_var (v));
  	    }
*************** phi_opnd_from_res (ei, Z, j, b)
*** 813,819 ****
                 || ref_type (v) == V_PHI
                 || ref_type (v) == E_USE)
  	VARRAY_GENERIC_PTR (Q, i) = NULL;
!     i++;
      }
    return Q;
  }
--- 926,932 ----
                 || ref_type (v) == V_PHI
                 || ref_type (v) == E_USE)
  	VARRAY_GENERIC_PTR (Q, i) = NULL;
!       i++;
      }
    return Q;
  }
*************** rename_2 (ei, rename2_set)
*** 826,851 ****
  {
    size_t i;
    splay_tree touched_set;
-   basic_block block;
  
    /* Keep track of which phi operands we touch.  */
    touched_set = splay_tree_new (splay_tree_compare_pointers, NULL, NULL);
  
    /* For each exprphi f in the program do
  	for each operand w of f do
! 	  processed (w) = false.  */
!   for (i = 0; i < VARRAY_SIZE (ei->phis); i++)
!     {
!       tree_ref phi = VARRAY_GENERIC_PTR (ei->phis, i);
!       if (phi != NULL)
!         bitmap_clear (exprphi_processed(phi));
!     }
!   
    /* while (set_for_rename2 not empty) do { */
    while (VARRAY_ACTIVE_SIZE (*rename2_set) > 0)
      {
        tree_ref Z; 
        tree_ref phiZ;
  
        /* Remove real occurrence Z from set_for_rename2.  */
        Z = VARRAY_TOP_GENERIC_PTR (*rename2_set);
--- 939,960 ----
  {
    size_t i;
    splay_tree touched_set;
  
    /* Keep track of which phi operands we touch.  */
    touched_set = splay_tree_new (splay_tree_compare_pointers, NULL, NULL);
  
    /* For each exprphi f in the program do
  	for each operand w of f do
! 	  processed (w) = false.  
! 
! 	  This was done earlier, i'm just including the comment for reference
! 	  purposes. */
    /* while (set_for_rename2 not empty) do { */
    while (VARRAY_ACTIVE_SIZE (*rename2_set) > 0)
      {
        tree_ref Z; 
        tree_ref phiZ;
+       size_t curr_phiop;
  
        /* Remove real occurrence Z from set_for_rename2.  */
        Z = VARRAY_TOP_GENERIC_PTR (*rename2_set);
*************** rename_2 (ei, rename2_set)
*** 856,873 ****
        /* f <- phi that defines Z. */
        phiZ = expruse_def (Z);
        
!       /* for each operand w of f do { */
!       FOR_EACH_BB (block)
  	{
            tree_ref w;
! 	  i = block->index;
! 	  
!           if (phi_operand (phiZ, block) == NULL)
!             continue;
!           w = phi_operand (phiZ, block);
  	  
  	  /* if (not processed(w)) { */
!           if (!bitmap_bit_p (exprphi_processed (phiZ), i))
              {
                /* j = i because we lookup the real index in the
                   function. */
--- 965,978 ----
        /* f <- phi that defines Z. */
        phiZ = expruse_def (Z);
        
!       for (curr_phiop = 0; curr_phiop < num_ephi_args (phiZ); curr_phiop++)
  	{
            tree_ref w;
! 	  i = phi_arg_edge (ephi_arg (phiZ, curr_phiop))->src->index;
! 	  w = phi_arg_def (ephi_arg (phiZ, curr_phiop));
  	  
  	  /* if (not processed(w)) { */
!           if (!exprref_processed (w))
              {
                /* j = i because we lookup the real index in the
                   function. */
*************** rename_2 (ei, rename2_set)
*** 889,895 ****
  	        }
  
  	      /* if (X is a real occurrence) */
! 	      if (ref_type (X) == E_USE)
                  {
                    bool match = true;
  		  ref_list_iterator l;
--- 994,1000 ----
  	        }
  
  	      /* if (X is a real occurrence) */
! 	      if (ref_type (X) == E_USE || ref_type (X) == E_LEFT)
                  {
                    bool match = true;
  		  ref_list_iterator l;
*************** rename_2 (ei, rename2_set)
*** 905,917 ****
  		    if ((ref_type (op1) != V_USE))
  		      continue;
  		    if (ei->strred_cand)
! 		      while (is_injuring_def (ei, ref_expr (imm_reaching_def (op1))))
  			{
  			  op1 = find_rhs_use_for_var (imm_reaching_def (op1),
  						      ref_var (op1));
  
! 			  if (is_default_def (imm_reaching_def (op1))
! 			      || ref_type (imm_reaching_def (op1)) == V_PHI)
  			    break;
  
  			  op1 = find_rhs_use_for_var (imm_reaching_def (op1),
--- 1010,1024 ----
  		    if ((ref_type (op1) != V_USE))
  		      continue;
  		    if (ei->strred_cand)
! 		      while (is_injuring_def (ei, ref_stmt (imm_reaching_def (op1))))
  			{
+ 			  if (!maybe_find_rhs_use_for_var (imm_reaching_def (op1),
+ 							  ref_var (op1)))
+ 			    break;
  			  op1 = find_rhs_use_for_var (imm_reaching_def (op1),
  						      ref_var (op1));
  
! 			  if (!okay_injuring_def (imm_reaching_def (op1), ref_var (op1)))
  			    break;
  
  			  op1 = find_rhs_use_for_var (imm_reaching_def (op1),
*************** rename_2 (ei, rename2_set)
*** 927,942 ****
  		      op2 = imm_reaching_def (op2);
  
  		    if (ei->strred_cand)
! 		      while (is_injuring_def (ei, ref_expr (op2)))
  			{
  			  tree_ref ird;
  			  op2 = find_rhs_use_for_var (op2, ref_var
  						      (op2));
  			  ird = imm_reaching_def (op2);
! 			  if (is_default_def (ird)
! 			      || ref_type (ird) == V_PHI
! 			      || !maybe_find_rhs_use_for_var (ird, 
! 							      ref_var (op2)))
  			    {
  			      op2 = ird;
  			      break;
--- 1034,1046 ----
  		      op2 = imm_reaching_def (op2);
  
  		    if (ei->strred_cand)
! 		      while (is_injuring_def (ei, ref_stmt (op2)))
  			{
  			  tree_ref ird;
  			  op2 = find_rhs_use_for_var (op2, ref_var
  						      (op2));
  			  ird = imm_reaching_def (op2);
! 			  if (!okay_injuring_def (ird, ref_var (op2)))
  			    {
  			      op2 = ird;
  			      break;
*************** rename_2 (ei, rename2_set)
*** 1001,1007 ****
                      }
                  }
  	      /* processed (w) <- true */
! 	      bitmap_set_bit (exprphi_processed (phiZ), i);
                VARRAY_CLEAR (Y); 
              }
          }
--- 1105,1111 ----
                      }
                  }
  	      /* processed (w) <- true */
! 	      set_exprref_processed (w, true);
                VARRAY_CLEAR (Y); 
              }
          }
*************** rename_1 (ei)
*** 1017,1022 ****
--- 1121,1127 ----
    fibheap_t fh = fibheap_new ();
    tree_ref y;
    varray_type stack;
+   varray_type stack2;
    varray_type rename2_set;
    varray_type recheck_set;
    splay_tree touched_set;
*************** rename_1 (ei)
*** 1025,1031 ****
    /* count <- 0
       stack <- empty
       set_for_rename2 <- {} */
!   VARRAY_GENERIC_PTR_INIT (stack, 1, "Stack");
    VARRAY_GENERIC_PTR_INIT (rename2_set, 1, "Rename2 set");
    VARRAY_GENERIC_PTR_INIT (recheck_set, 1, "Recheck set");
    class_count = 1;
--- 1130,1137 ----
    /* count <- 0
       stack <- empty
       set_for_rename2 <- {} */
!   VARRAY_GENERIC_PTR_INIT (stack, 1, "Stack for renaming");
!   VARRAY_GENERIC_PTR_INIT (stack2, 1, "Stack for downsafety");
    VARRAY_GENERIC_PTR_INIT (rename2_set, 1, "Rename2 set");
    VARRAY_GENERIC_PTR_INIT (recheck_set, 1, "Recheck set");
    class_count = 1;
*************** rename_1 (ei)
*** 1036,1066 ****
    while (!fibheap_empty (fh))
      {
        y = fibheap_extract_min (fh);
-       if ((basic_block) y == EXIT_BLOCK_PTR)
-         {
- 	  if (VARRAY_ACTIVE_SIZE (stack) > 0)
-             {
-               tree_ref stackref = VARRAY_TOP_GENERIC_PTR (stack);
-               if (ref_type (stackref) == E_PHI)
-                 set_exprphi_downsafe (stackref, false);
-             }
-           continue;
-         }
-       if (ref_type (y) == E_KILL 
- 	  && TREE_CODE (ref_expr (y)) == CALL_EXPR)
-         {
- 	  if (VARRAY_ACTIVE_SIZE (stack) > 0)
-             {
-               tree_ref stackref = VARRAY_TOP_GENERIC_PTR (stack);
-               if (ref_type (stackref) == E_PHI)
-                 set_exprphi_downsafe (stackref, false);
- 	      VARRAY_POP_ALL (stack);
-             }
-           continue;       
-         }
-       
        /* while (Top(stack) does not dominate Y) do 
! 	   Pop(stack)  */
        while (VARRAY_ACTIVE_SIZE (stack) > 0)
          {
            tree_ref stackref = VARRAY_TOP_GENERIC_PTR (stack);
--- 1142,1149 ----
    while (!fibheap_empty (fh))
      {
        y = fibheap_extract_min (fh);
        /* while (Top(stack) does not dominate Y) do 
! 	 Pop(stack)  */
        while (VARRAY_ACTIVE_SIZE (stack) > 0)
          {
            tree_ref stackref = VARRAY_TOP_GENERIC_PTR (stack);
*************** rename_1 (ei)
*** 1068,1079 ****
              break;           
            VARRAY_POP (stack);
          }
! 
        /* if (Y is an exprphi occurrence)
             assign_new_class (Y)  */
        if (ref_type (y) == E_PHI)
          {
! 	  assign_new_class (y, &stack);
          }
        /* else if (Y is a real occurrence) */
        else if (ref_type (y) == E_USE && expruse_phiop (y) == false)
--- 1151,1178 ----
              break;           
            VARRAY_POP (stack);
          }
!       while (VARRAY_ACTIVE_SIZE (stack2) > 0)
!         {
!           tree_ref stackref = VARRAY_TOP_GENERIC_PTR (stack2);
!           if (a_dom_b (ref_bb (stackref), ref_bb (y)))
!             break;           
!           VARRAY_POP (stack2);
!         }
!       if (ref_type (y) == E_EXIT)
!         {
! 	  if (VARRAY_ACTIVE_SIZE (stack2) > 0)
!             {
!               tree_ref stackref = VARRAY_TOP_GENERIC_PTR (stack2);
!               if (ref_type (stackref) == E_PHI)
!                 set_exprphi_downsafe (stackref, false);
!             }
!           continue;
!         }
        /* if (Y is an exprphi occurrence)
             assign_new_class (Y)  */
        if (ref_type (y) == E_PHI)
          {
! 	  assign_new_class (y, &stack, &stack2);
          }
        /* else if (Y is a real occurrence) */
        else if (ref_type (y) == E_USE && expruse_phiop (y) == false)
*************** rename_1 (ei)
*** 1082,1088 ****
  	       Assign_New_Class(Y) */
            if (VARRAY_ACTIVE_SIZE (stack) == 0)
              {
!               assign_new_class ( y, &stack);
              }
            /* else */
            else
--- 1181,1187 ----
  	       Assign_New_Class(Y) */
            if (VARRAY_ACTIVE_SIZE (stack) == 0)
              {
!               assign_new_class ( y, &stack, &stack2);
              }
            /* else */
            else
*************** rename_1 (ei)
*** 1090,1117 ****
  	      /* X <- Top(stack) */
                tree_ref x = VARRAY_TOP_GENERIC_PTR (stack);
  	      
!               /* If (X is a real occurrence) */
!               if (ref_type (x) == E_USE)
                  {
                    /* If (all corresponding variables in Y and X have
                       the same SSA version) */
!                   if (defs_match_p (ei, ref_stmt (y), ref_expr (x)))
                      {
                        /* class(Y) <- class(X)
                           def(Y) <- X */
                        set_exprref_class (y, exprref_class (x));
! #if 0
!                       EXPRUSE_DEF (y) = x;
  #else
  		      set_expruse_def (y, expruse_def (x) != NULL ? expruse_def (x) : x);
  #endif
                      }
  		  /* else Assign_New_Class (Y) */
                    else
                      {
!                       assign_new_class ( y, &stack);
                      }
                  }
                else /* X is a ExprPhi occurrence. */
                  {
                    if (ref_type (x) != E_PHI)
--- 1189,1221 ----
  	      /* X <- Top(stack) */
                tree_ref x = VARRAY_TOP_GENERIC_PTR (stack);
  	      
!               /* If (X is a real occurrence or a left occurrence) */
!               if (ref_type (x) == E_USE || ref_type (x) == E_LEFT)
                  {
                    /* If (all corresponding variables in Y and X have
                       the same SSA version) */
!                   if (defs_match_p (ei, ref_stmt (y), ref_stmt (x)))
                      {
                        /* class(Y) <- class(X)
                           def(Y) <- X */
                        set_exprref_class (y, exprref_class (x));
! #if 1
! 		      set_expruse_def (y, x);
  #else
  		      set_expruse_def (y, expruse_def (x) != NULL ? expruse_def (x) : x);
  #endif
+ 		      VARRAY_PUSH_GENERIC_PTR (stack2, y);
                      }
  		  /* else Assign_New_Class (Y) */
                    else
                      {
!                       assign_new_class ( y, &stack, &stack2);
                      }
                  }
+ 	      else if (ref_type (x) == E_KILL)
+ 		{
+ 		  assign_new_class (y, &stack, &stack2);
+ 		}
                else /* X is a ExprPhi occurrence. */
                  {
                    if (ref_type (x) != E_PHI)
*************** doesn't dominate whatever  occurrences w
*** 1160,1172 ****
  we'll pop it, and if the phi isn't really going to be downsafe, we'll
  catch it in rename_2 or during downsafety propagation. */
  
! 		      VARRAY_PUSH_GENERIC_PTR (stack, y);		      
  		      VARRAY_PUSH_GENERIC_PTR (rename2_set, y);
                      }
                    else
                      {
  		      set_exprphi_downsafe (x, false);
!                       assign_new_class ( y, &stack);
                      }
                  } 
              } 
--- 1264,1277 ----
  we'll pop it, and if the phi isn't really going to be downsafe, we'll
  catch it in rename_2 or during downsafety propagation. */
  
! //		      VARRAY_PUSH_GENERIC_PTR (stack, y);
! 		      VARRAY_PUSH_GENERIC_PTR (stack2, y);
  		      VARRAY_PUSH_GENERIC_PTR (rename2_set, y);
                      }
                    else
                      {
  		      set_exprphi_downsafe (x, false);
!                       assign_new_class ( y, &stack, &stack2);
                      }
                  } 
              } 
*************** catch it in rename_2 or during downsafet
*** 1179,1207 ****
                /* def(Y) <- tack */
  	      set_expruse_def (y, NULL);
  	      set_expruse_has_real_use (y, false);
              }
            else
              {
- 
                /* X = Top(stack)
                   class(Y) <- class(X)
                   def(Y) <- X */
                tree_ref x = VARRAY_TOP_GENERIC_PTR (stack);
!               set_exprref_class (y, exprref_class (x));
!               set_expruse_def (y, x);
! 	      if (ref_type (x) != E_PHI)
! 		{
! 		  set_expruse_has_real_use (y, true);
! 		  if (expruse_def (x) && ref_type (expruse_def (x)) == E_PHI)
! 			VARRAY_PUSH_GENERIC_PTR (rename2_set, x);
  		}
  	      else
  		{
! 		  set_expruse_has_real_use (y, false);
! 		  VARRAY_PUSH_GENERIC_PTR (recheck_set, y);
  		}
  	    }
          }
        else
          abort();
      }
--- 1284,1336 ----
                /* def(Y) <- tack */
  	      set_expruse_def (y, NULL);
  	      set_expruse_has_real_use (y, false);
+ 	      set_exprref_processed (y, true);
              }
            else
              {
                /* X = Top(stack)
                   class(Y) <- class(X)
                   def(Y) <- X */
                tree_ref x = VARRAY_TOP_GENERIC_PTR (stack);
! 	      tree_ref x2 = VARRAY_TOP_GENERIC_PTR (stack2);
! 	      if (ref_type (x) == E_KILL)
! 		{		  
! 		  set_expruse_def (y, NULL);
! 		  set_exprref_processed (y, true);
! 		  if (ref_type (x2) == E_PHI)
! 		    {
! 		      set_exprphi_downsafe (x2, false);
! 		    }
  		}
  	      else
  		{
! 		  
! 		  set_exprref_class (y, exprref_class (x));
! 		  set_expruse_def (y, x);
! 		  if ((ref_type (x2) == E_USE && !expruse_phiop (x2)) 
! 		      || ref_type (x2) == E_LEFT)
! 		    {
! 		      set_expruse_has_real_use (y, true);
! 		      		  
! 		/*	if (expruse_def (x) && ref_type (expruse_def (x)) == E_PHI)
! 			  VARRAY_PUSH_GENERIC_PTR (rename2_set, x);*/
! 		    }
! 		  else
! 		    {
! 		      set_expruse_has_real_use (y, false);
! 		      VARRAY_PUSH_GENERIC_PTR (recheck_set, y);
! 		    }
  		}
  	    }
          }
+       else if (ref_type (y) == E_KILL)
+ 	{
+ 	  VARRAY_PUSH_GENERIC_PTR (stack, y);
+ 	}
+       else if (ref_type (y) == E_LEFT)
+ 	{
+ 	  assign_new_class (y, &stack, &stack2);
+ 	}
        else
          abort();
      }
*************** catch it in rename_2 or during downsafet
*** 1223,1244 ****
      {
        tree_ref ref = VARRAY_GENERIC_PTR (recheck_set, i);
        tree_ref def;
!       bool needcheck = true;
!       edge succ;
        if (!ref)
  	continue;
        def = expruse_def (ref);
!       for (succ = ref_bb (ref)->succ; succ; succ = succ->succ_next)
! 	{
! 	  if (phi_at_block (ei, succ->dest) != NULL)
! 	    {
! 	      tree_ref phi = phi_at_block (ei, succ->dest);
! 	      if (bitmap_bit_p (exprphi_processed (phi), 
! 				ref_bb (ref)->index))
! 		needcheck = false;
! 	    }
! 	}
!       if (!needcheck)
  	continue;
  
        if (def && (ref_type (def) == E_PHI))
--- 1352,1363 ----
      {
        tree_ref ref = VARRAY_GENERIC_PTR (recheck_set, i);
        tree_ref def;
! 
        if (!ref)
  	continue;
+ 
        def = expruse_def (ref);
!       if (exprref_processed (ref))
  	continue;
  
        if (def && (ref_type (def) == E_PHI))
*************** catch it in rename_2 or during downsafet
*** 1248,1320 ****
      }
    fibheap_delete (fh);
    VARRAY_CLEAR (stack);
    VARRAY_CLEAR (rename2_set);
    VARRAY_CLEAR (recheck_set);
    splay_tree_delete (touched_set);
  }
  
- /* XXX: Do this smarter */
- /* Figure out which PHI contains the operand.  */
  static tree_ref
! phi_for_operand (ei, operand)
!      struct expr_info *ei;
!      tree_ref operand;
  {
!   int count = 0;
!   tree_ref retval = NULL;
!   basic_block bb;
! 
!   FOR_EACH_BB (bb)
!     {
!       tree_ref phi = phi_at_block (ei, bb);
!       if (phi != NULL)
!         {
! 	  basic_block bb2;
! 	  FOR_EACH_BB (bb2)
! 	    {
! 	      if (phi_operand (phi, bb2) ==  operand)
! 	      {
! 		count++;
! 		retval = phi;
! 	      }	  
! 	    }
! 	}
!     }
!   /* Theoretically, phi operand to phi is a 1 to many mapping.  But we
!      don't return more than one value right now, so if we found multiple
!      phis containing this operand, abort.  */
!   if (count > 1)
!     abort();
!   
!   return retval;
  }
! 
  /* Figure out which expressions need to be saved.  */
  static void
  set_save (ei, X)
       struct expr_info *ei;
       tree_ref X;
  {
!   basic_block bb;
!   if (ref_type (X) == E_USE && !expruse_phiop (X))
      set_exprref_save (X, true);
    else if (ref_type (X) == E_PHI)
      {
        int i;
!       FOR_EACH_BB (bb)
  	{
! 	  tree_ref w = phi_operand (X, bb);
! 	  i = bb->index;
  
! 	  if (w && !bitmap_bit_p (exprphi_processed (X), i))
  	    {
! 	      bitmap_set_bit (exprphi_processed (X), i);
  	      set_save (ei, expruse_def (w));
  	    }
  	}
      }
  #if EXTRANEOUS_EPHI_REMOVAL 
!   if (ref_type (X) == E_USE && !expruse_phiop (X))
      {
        sbitmap idfs = compute_idfs (pre_dfs, ref_stmt (X));
        int i;
--- 1367,1418 ----
      }
    fibheap_delete (fh);
    VARRAY_CLEAR (stack);
+   VARRAY_CLEAR (stack2);
    VARRAY_CLEAR (rename2_set);
    VARRAY_CLEAR (recheck_set);
    splay_tree_delete (touched_set);
  }
  
  static tree_ref
! phi_operand_for_pred (phi, e)
!      tree_ref phi;
!      edge e;
  {
!   size_t i;
!   for (i = 0; i < num_ephi_args (phi); i++)
!     if (phi_arg_edge (ephi_arg (phi, i)) == e)
!       return phi_arg_def (ephi_arg (phi, i));
!   abort ();
  }
!      
  /* Figure out which expressions need to be saved.  */
  static void
  set_save (ei, X)
       struct expr_info *ei;
       tree_ref X;
  {
!   if ((ref_type (X) == E_USE && !expruse_phiop (X))
!       || ref_type (X) == E_LEFT)
      set_exprref_save (X, true);
    else if (ref_type (X) == E_PHI)
      {
        int i;
!       size_t curr_phiop;
!       for (curr_phiop = 0; curr_phiop < num_ephi_args (X); curr_phiop++)
  	{
! 	  tree_ref w = phi_arg_def (ephi_arg (X, curr_phiop));
! 	  i = phi_arg_edge (ephi_arg (X, curr_phiop))->src->index;
  
! 	  if (!exprref_processed2 (w))
  	    {
! 	      set_exprref_processed2 (w, true);
  	      set_save (ei, expruse_def (w));
  	    }
  	}
      }
  #if EXTRANEOUS_EPHI_REMOVAL 
!   if ((ref_type (X) == E_USE && !expruse_phiop (X))
!       || ref_type (X) == E_LEFT)
      {
        sbitmap idfs = compute_idfs (pre_dfs, ref_stmt (X));
        int i;
*************** set_replacement (ei, g, replacing_def)
*** 1336,1374 ****
       tree_ref g;
       tree_ref replacing_def;
  {
!   basic_block bb1;
!   FOR_EACH_BB (bb1)
      {
!       size_t k;
!       basic_block bb2;
!       tree_ref f = phi_at_block (ei, bb1);
!       if (f == NULL || !exprphi_willbeavail (f) || f == g)
! 	continue;
!       FOR_EACH_BB (bb2)
  	{
! 	  tree_ref operand = phi_operand (f, bb2);
! 	  if (operand && expruse_def (operand) == g)
  	    {
! 	      if (exprphi_extraneous (f))
! 		set_replacement (ei, f, replacing_def);
! 	      else
! 		phi_operand (f, bb2) = replacing_def;
  	    }
! 	}
!       for (k = 0; k < VARRAY_ACTIVE_SIZE (ei->erefs); k++)
! 	{
! 	  tree_ref X = VARRAY_GENERIC_PTR (ei->erefs, k);
! 	  if (ref_type (X) == E_USE 
! 	      && expruse_phiop (X) == false
! 	      && exprref_reload (X)
! 	      && expruse_def (X) == g)
  	    {
! 	      set_expruse_def (X, replacing_def);
  	    }
  	}
      }
    phi_at_block (ei, ref_bb (g)) = NULL;
!   
  }
  
  /* Second part of finalize algorithm.  */
--- 1434,1483 ----
       tree_ref g;
       tree_ref replacing_def;
  {
!   ref_list_iterator rli;
!   
!   rli = rli_start (exprref_uses (g));
!   for (; !rli_after_end (rli); rli_step (&rli))
      {
!       tree_ref x = rli_ref (rli);
!       
!       if (ref_type (x) == E_USE && expruse_phiop (x))
  	{
! 	  tree_ref f = expruse_phi (x);
! 	  if (exprphi_extraneous (f) && !exprref_processed (f))
  	    {
! 	      set_exprref_processed (f, true);
! 	      set_replacement (ei, f, replacing_def);
  	    }
! 	  else if (!exprphi_extraneous (f))
  	    {
! #if DEBUGGING_EPHI_REMOVAL 
! 	      if (dump_file)
! 		fprintf (dump_file, "Replacing id %lu with id %lu\n", ref_id (x), ref_id (replacing_def));
! #endif
! 	      set_exprref_class (x, exprref_class (replacing_def));
! 	      set_expruse_def (x, replacing_def);
  	    }
  	}
      }
+   rli = rli_start (exprref_uses (g));
+   for (; !rli_after_end (rli); rli_step (&rli))
+     {
+       tree_ref x = rli_ref (rli);
+       if (ref_type (x) == E_USE && !expruse_phiop (x) 
+ 	  && exprref_reload (x))
+ 	{
+ 	  set_exprref_class (x, exprref_class (replacing_def));
+ 	  set_expruse_def (x, replacing_def);
+ 	}
+     }
+ 
+ #if DEBUGGING_EPHI_REMOVAL
+       if (dump_file)
+ 	fprintf (dump_file, "Removing E_PHI id %lu\n", ref_id (g));
+ #endif
    phi_at_block (ei, ref_bb (g)) = NULL;
!   remove_ref_from_list (ei->euses_dt_order, g);
  }
  
  /* Second part of finalize algorithm.  */
*************** finalize_2 (ei)
*** 1382,1388 ****
        tree_ref ref = VARRAY_GENERIC_PTR (ei->erefs, i);
        if (ref_type (ref) == E_PHI)
  	{
- 	  bitmap_clear (exprphi_processed (ref));
  	  if (exprphi_willbeavail (ref))
  	    set_exprphi_extraneous (ref, true);
  	}
--- 1491,1496 ----
*************** finalize_2 (ei)
*** 1413,1429 ****
        if (exprphi_willbeavail (ref))
  	{
  	  int k;
! 	  for (k = 0; k < n_basic_blocks; k++)
  	    {
! 	      tree_ref w = phi_operand (ref, BASIC_BLOCK (k));
  	      tree_ref defw;
  	      if (!w || !expruse_def (w) )
  		continue;
  	      defw = expruse_def (w);
! 	      if ((ref_type (defw) == E_PHI 
! 		   && !exprphi_extraneous (defw))
! 		  || (ref_type (defw) == E_USE 
! 		      && !expruse_phiop (defw)))
  		set_replacement (ei, ref, expruse_def (w));  
  	    }
  	}
--- 1521,1536 ----
        if (exprphi_willbeavail (ref))
  	{
  	  int k;
! 	  for (k = 0; k < num_ephi_args (ref); k++)
  	    {
! 	      tree_ref w = phi_arg_def (ephi_arg (ref, k));
  	      tree_ref defw;
  	      if (!w || !expruse_def (w) )
  		continue;
  	      defw = expruse_def (w);
! 	      if ((ref_type (defw) == E_PHI && !exprphi_extraneous (defw))
! 		  || (ref_type (defw) == E_USE && !expruse_phiop (defw)) 
! 		  || ref_type (defw) == E_LEFT)
  		set_replacement (ei, ref, expruse_def (w));  
  	    }
  	}
*************** finalize_2 (ei)
*** 1434,1461 ****
      }
  #endif
  }
  
  /* First part of finalize algorithm.  */
! static void
  finalize_1 (ei, temp)
       struct expr_info *ei;
       tree temp;
  {
    tree_ref X;
    int x;
!   fibheap_t fh;
!   avdefs = xcalloc (class_count + 1,sizeof (tree_ref));
!   fh = fibheap_new ();
!   insert_euse_in_preorder_dt_order (ei, fh);
!   while (!fibheap_empty (fh))
      {
!       X = fibheap_extract_min (fh);
        x = exprref_class (X);
        if (ref_type (X) == E_PHI)
          {
            if (exprphi_willbeavail (X))
              avdefs[x] = X;
          }
        else if (ref_type (X) == E_USE && expruse_phiop (X) == false)
          {
            if (avdefs[x] == NULL 
--- 1541,1621 ----
      }
  #endif
  }
+ static void
+ update_old_new (ei, old, new)
+      struct expr_info *ei;
+      tree *old;
+      tree *new;
+ {
+   splay_tree_node result;
+   
+   result = splay_tree_lookup (old_new_map, (splay_tree_key)old);
+   if (result)
+     {
+       size_t i;
+       for (i = 0; i < VARRAY_ACTIVE_SIZE (ei->occurs); i++)
+ 	{
+ 	  if (VARRAY_GENERIC_PTR (ei->occurs, i) == old)
+ 	    VARRAY_GENERIC_PTR (ei->occurs, i) = (PTR) result->value;
+ 	}
+     }
+   splay_tree_insert (old_new_map, (splay_tree_key) old, (splay_tree_value) new);
+ }
+ /* This routine is a temporary thing. It is meant to fix up refs that *MUST* be
+    fixed up in order for the algorithm to continue to work properly (as opposed
+    to  those we fix up in order to update the SSA representation).  Their will
+    be  routines that do this for us eventually. */
+ static void
+ temp_fix_refs (lookin, lookfor, replacewith)
+      tree lookin;
+      tree lookfor;
+      tree *replacewith;
+ {
+   ref_list_iterator rli;
+ 
+   rli = rli_start (tree_refs (lookin));
+   for (; !rli_after_end (rli); rli_step (&rli))
+     {
+       tree_ref ref = rli_ref (rli);
+       if (ref_stmt (ref) == lookfor)
+ 	{
+ 	  ref->common.stmt_p = replacewith;
+ 	  ref->common.expr_p = replacewith;
+ 	}
+     }
+ }
+ 
  
  /* First part of finalize algorithm.  */
! static bool
  finalize_1 (ei, temp)
       struct expr_info *ei;
       tree temp;
  {
    tree_ref X;
    int x;
!   ref_list_iterator euse_rli;
!   bool made_a_reload = false;
!   
!   avdefs = xcalloc (class_count + 1,sizeof (tree_ref));  
!   ei->euses_dt_order = create_ref_list ();
!   
!   insert_euse_in_preorder_dt_order (ei);
!   
!   euse_rli = rli_start (ei->euses_dt_order);
!   for (; !rli_after_end (euse_rli); rli_step (&euse_rli))
      {
!       X = rli_ref (euse_rli);
        x = exprref_class (X);
        if (ref_type (X) == E_PHI)
          {
            if (exprphi_willbeavail (X))
              avdefs[x] = X;
          }
+       else if (ref_type (X) == E_LEFT)
+ 	{
+ 	  avdefs[x] = X;
+ 	}
        else if (ref_type (X) == E_USE && expruse_phiop (X) == false)
          {
            if (avdefs[x] == NULL 
*************** finalize_1 (ei, temp)
*** 1467,1478 ****
            else
              {
  	      set_exprref_reload (X, true);
                set_expruse_def (X, avdefs[x]);
              }
          }
        else
          {
!           tree_ref phi = phi_for_operand (ei, X);
            if (!phi)
              abort ();
            if (exprphi_willbeavail (phi))           
--- 1627,1639 ----
            else
              {
  	      set_exprref_reload (X, true);
+ 	      made_a_reload = true;
                set_expruse_def (X, avdefs[x]);
              }
          }
        else
          {
!           tree_ref phi = expruse_phi (X);
            if (!phi)
              abort ();
            if (exprphi_willbeavail (phi))           
*************** finalize_1 (ei, temp)
*** 1481,1489 ****
                  {
  		  tree stmt;
  		  tree expr;
! 		  tree *place;
  		  basic_block bb;
  		  tree endtree;
  
                    /* Insert definition of expr at end of BB containing X. */
  		  if (dump_file)
--- 1642,1652 ----
                  {
  		  tree stmt;
  		  tree expr;
! 		  tree *newexprplace;
! 		  tree *otherexprplace;
  		  basic_block bb;
  		  tree endtree;
+ 		  tree *endtreep;
  
                    /* Insert definition of expr at end of BB containing X. */
  		  if (dump_file)
*************** finalize_1 (ei, temp)
*** 1505,1530 ****
  						  deep_copy_node (ei->expr)));
  		  bb = ref_bb (X);
  		  endtree = last_stmt (bb);
  		  /* FIXME: Need DFA inserting updating to do this the right
  		     way. */
  		  /* If it's a goto, we need to insert *before* it.
  		     This might not be necessary once goto elimination
! 		     is functional.  */
! 		  if (is_ctrl_altering_stmt (endtree))
  		    {
! 		      stmt = build (COMPOUND_EXPR, void_type_node, expr, endtree);
! 		      place = &TREE_OPERAND (stmt, 0);
  		    }
  		  else
  		    {
! 		      stmt = build (COMPOUND_EXPR, void_type_node, endtree, expr);
! 		      place = &TREE_OPERAND (stmt, 1);
  		    }
! 		  
! 		  *bb->end_tree_p = stmt;
  		  TREE_CHAIN (stmt) = TREE_CHAIN (endtree);
  		  TREE_CHAIN (endtree) = NULL;
! 		  TREE_TYPE (stmt) = TREE_TYPE (expr);
  
  #if WAITING_FOR_DFA_UPDATE
  		  /* Update the SSA for the newly inserted definition.
--- 1668,1805 ----
  						  deep_copy_node (ei->expr)));
  		  bb = ref_bb (X);
  		  endtree = last_stmt (bb);
+ 		  endtreep = last_stmt_ptr (bb);
  		  /* FIXME: Need DFA inserting updating to do this the right
  		     way. */
  		  /* If it's a goto, we need to insert *before* it.
  		     This might not be necessary once goto elimination
! 		     is functional.  
! 		     If it's an empty statement, always insert before. */
! 		  if (endtree == empty_stmt_node)
  		    {
! 		      stmt = build (COMPOUND_EXPR, void_type_node,
! 				    expr, empty_stmt_node);
! 		      newexprplace = &TREE_OPERAND (stmt, 0);
! 		      otherexprplace = &TREE_OPERAND (stmt, 1);
! 		    }
! 		  else if (is_ctrl_altering_stmt (endtree))
! 		    {
! 		      stmt = build (COMPOUND_EXPR, void_type_node, 
! 				    expr, endtree);
! 		      newexprplace = &TREE_OPERAND (stmt, 0);
! 		      otherexprplace = &TREE_OPERAND (stmt, 1);
  		    }
  		  else
  		    {
! 		      stmt = build (COMPOUND_EXPR, void_type_node, 
! 				    endtree, expr);
! 		      newexprplace = &TREE_OPERAND (stmt, 1);
! 		      otherexprplace = &TREE_OPERAND (stmt, 0);
  		    }
! 		  /* FIXME: This can't be fixed without the insertion machinery
! 		     knowing what to do about it. */
! 		  if (endtree == empty_stmt_node)
! 		    abort ();
! #if 0
! 		  if (endtree == empty_stmt_node)
! 		    {
! 		      gimple_stmt_iterator gsi;
! 		      edge e;
! 		      if (bb->parent_tree_p)
! 		        {
! 				*bb->parent_tree_p = stmt;
! 				bb->end_tree_p = bb->parent_tree_p;
! 				endtreep = bb->end_tree_p;
! 				goto done;
! 			}
! #if 1
! 		      for (e = bb->pred; e; e = e->pred_next)
! 			{
! 			  for (gsi = gsi_start_bb (e->src); 
! 			       !gsi_after_end (gsi); 
! 			       gsi_step (&gsi))
! 			    {
! 			      tree temp = gsi_stmt (gsi);
! 			      STRIP_WFL (temp);
! 			      STRIP_NOPS(temp);
! 			      if (TREE_CODE (temp) == COND_EXPR)
! 				{
! 				  if (COND_EXPR_COND (temp) == endtree)
! 				    {
! 				      COND_EXPR_COND (temp) = stmt;
! 				      bb->end_tree_p = &COND_EXPR_COND (temp);
! 				    }
! 				  else if (COND_EXPR_THEN (temp) == endtree)
! 				    {
! 				      COND_EXPR_THEN (temp) = stmt;
! 				      bb->end_tree_p = &COND_EXPR_THEN (temp);
! 				    }
! 				  else if (COND_EXPR_ELSE (temp) == endtree)
! 				    {
! 				      COND_EXPR_ELSE (temp) = stmt;
! 				      bb->end_tree_p = &COND_EXPR_ELSE (temp);
! 				    }
! 				  endtreep = bb->end_tree_p;
! 				  goto done;
! 				}
! 			    }
! 			} 
! #endif
! #if 1	      
! 		      for (gsi = gsi_start_bb (parent_block (bb)); 
! 			   !gsi_after_end (gsi); 
! 			   gsi_step (&gsi))
! 			{
! 			  tree temp = gsi_stmt (gsi);
! 			  STRIP_WFL (temp);
! 			  STRIP_NOPS (temp);
! 			  if (TREE_CODE (temp) == LOOP_EXPR)
! 			    {
! 			      gsi = gsi_start (&TREE_OPERAND (LOOP_EXPR_BODY (temp), 0));
! 			      temp = gsi_stmt (gsi);
! 			      STRIP_WFL (temp);
! 			      STRIP_NOPS (temp);
! 			      
! 			    }
! 			  
! 			  if (TREE_CODE (temp) == COND_EXPR)
! 			    {
! 			      if (COND_EXPR_COND (temp) == endtree)
! 				{
! 				  COND_EXPR_COND (temp) = stmt;
! 				  bb->end_tree_p = &COND_EXPR_COND (temp);
! 				}
! 			      else if (COND_EXPR_THEN (temp) == endtree)
! 				{
! 				  COND_EXPR_THEN (temp) = stmt;
! 				  bb->end_tree_p = &COND_EXPR_THEN (temp);
! 				}
! 			      else if (COND_EXPR_ELSE (temp) == endtree)
! 				{
! 				  COND_EXPR_ELSE (temp) = stmt;
! 				  bb->end_tree_p = &COND_EXPR_ELSE (temp);
! 				}
! 			      endtreep = bb->end_tree_p;
! 			      goto done;
! 			    }
! 			}
! #endif
! done:
! 		    }
! 		    /* END TEMPORARY HACK */
! 		  else
! #endif
! 		    {
! 		      *endtreep = stmt;
! 		      update_old_new (ei, endtreep, otherexprplace);
! 		      /* REMOVE AFTER DFA UPDATE */
! 		      temp_fix_refs (*otherexprplace, stmt, otherexprplace);
! 		      /* END REMOVE AFTER DFA UPDATE */
! 		    }
! 		  /*
  		  TREE_CHAIN (stmt) = TREE_CHAIN (endtree);
  		  TREE_CHAIN (endtree) = NULL;
! 		  TREE_TYPE (stmt) = TREE_TYPE (expr);*/
  
  #if WAITING_FOR_DFA_UPDATE
  		  /* Update the SSA for the newly inserted definition.
*************** finalize_1 (ei, temp)
*** 1554,1576 ****
  		  splay_tree_insert (new_stmt_map, 
  				     (splay_tree_key) expr,
  				     (splay_tree_value)  stmt);
- 		  
- 		 
- 
  #endif
                    /*
                      expruse_def (X) = new occurrence. 
  		  */		  
  
  		  set_expruse_def (X,create_ref (expr, E_USE, 0,
! 						 ref_bb (X), bb->end_tree_p,
! 						 place, place,  true));
  		  VARRAY_PUSH_GENERIC_PTR (ei->erefs, expruse_def (X));
  		  set_exprref_reload (expruse_def (X), false);
  		  set_exprref_save (expruse_def (X), true);
  		  set_exprref_inserted (expruse_def (X), true);
  		  set_expruse_phiop (expruse_def (X), false);
  		  set_expruse_has_real_use (expruse_def (X), true);
  		  set_exprref_save (X, false);
  		  set_exprref_reload (X, false);
                  }
--- 1829,1853 ----
  		  splay_tree_insert (new_stmt_map, 
  				     (splay_tree_key) expr,
  				     (splay_tree_value)  stmt);
  #endif
                    /*
                      expruse_def (X) = new occurrence. 
  		  */		  
  
  		  set_expruse_def (X,create_ref (expr, E_USE, 0,
! 						 ref_bb (X), newexprplace,
! 						 newexprplace, newexprplace, 
! 						 true));
! 		  set_bb_for_stmt (*newexprplace, ref_bb (X));
! 		  
  		  VARRAY_PUSH_GENERIC_PTR (ei->erefs, expruse_def (X));
  		  set_exprref_reload (expruse_def (X), false);
  		  set_exprref_save (expruse_def (X), true);
  		  set_exprref_inserted (expruse_def (X), true);
  		  set_expruse_phiop (expruse_def (X), false);
  		  set_expruse_has_real_use (expruse_def (X), true);
+ 		  set_exprref_processed (X, false);
+ 		  set_exprref_processed2 (X, false);
  		  set_exprref_save (X, false);
  		  set_exprref_reload (X, false);
                  }
*************** finalize_1 (ei, temp)
*** 1581,1587 ****
              }
          }
      }
!   fibheap_delete (fh);
  }
  
  /* ExprPhi insertion algorithm.  */
--- 1858,1864 ----
              }
          }
      }
!   return made_a_reload;
  }
  
  /* ExprPhi insertion algorithm.  */
*************** expr_phi_insertion (dfs, ei)
*** 1596,1628 ****
    varphis = sbitmap_vector_alloc (2, last_basic_block);
    sbitmap_vector_zero (varphis, 2);  
  
!   for (i = 0; i < VARRAY_ACTIVE_SIZE (ei->reals); i++)
      {
!       tree real = VARRAY_TREE (ei->reals, i);
!       sbitmap temp = compute_idfs (dfs, VARRAY_TREE (ei->realstmts, i));      
        sbitmap_a_or_b (dfphis, dfphis, temp);
        sbitmap_free (temp);
!       if (is_simple_id (TREE_OPERAND (real, 0)) 
! 	  || (TREE_OPERAND (real, 1) 
! 	      && is_simple_id (TREE_OPERAND (real, 1))))
          {
            int varcount = 0;
  	  ref_list_iterator j;
  
! 	  j = rli_start (tree_refs (VARRAY_TREE (ei->realstmts, i)));
  	  for (; !rli_after_end (j); rli_step (&j))
  	  {
  	    tree_ref ref = rli_ref (j);
  	    if (ei->strred_cand)
  	      while (ref_type (ref) == V_USE
! 		     && ref_var (ref) == TREE_OPERAND (real, 0)
  		     && imm_reaching_def (ref)
! 		     && is_injuring_def (ei, ref_expr (imm_reaching_def (ref))))
  		{
  		  ref = find_rhs_use_for_var (imm_reaching_def (ref), 
  					      ref_var (ref));
! 		  if (is_default_def (imm_reaching_def (ref))
! 		      || ref_type (imm_reaching_def (ref)) == V_PHI)
  		    break;
  		  
  		  ref = find_rhs_use_for_var (imm_reaching_def (ref), 
--- 1873,1921 ----
    varphis = sbitmap_vector_alloc (2, last_basic_block);
    sbitmap_vector_zero (varphis, 2);  
  
!   for (i = 0; i < VARRAY_ACTIVE_SIZE (ei->occurs); i++)
      {
!       tree *occurp = VARRAY_GENERIC_PTR (ei->occurs, i);
!       tree occur = occurp ? *occurp : NULL;
!       tree *killp = VARRAY_GENERIC_PTR (ei->kills, i);
!       tree kill = killp ? *killp : NULL;
!       tree *leftp = VARRAY_GENERIC_PTR (ei->lefts, i);
!       tree left = leftp ? *leftp : NULL;
!       sbitmap temp;
!       if ((kill && occur) || (left && occur) || (kill && left))
! 	abort();
!       occurp = occur ? occurp : kill ? killp : leftp;      
!       occur = occur ? occur : kill ? kill : left;
!       temp = compute_idfs (dfs, occur);
        sbitmap_a_or_b (dfphis, dfphis, temp);
        sbitmap_free (temp);
!       STRIP_WFL (occur);
!       if (kill != NULL)
! 	continue;
!       occur = TREE_OPERAND (occur, 1);
!       if (is_simple_id (get_operand (occur, 0))
! 	  || (get_operand (occur, 1) 
! 	      && is_simple_id (get_operand (occur, 1))))
          {
            int varcount = 0;
  	  ref_list_iterator j;
  
! 	  j = rli_start (tree_refs (*occurp));
  	  for (; !rli_after_end (j); rli_step (&j))
  	  {
  	    tree_ref ref = rli_ref (j);
  	    if (ei->strred_cand)
  	      while (ref_type (ref) == V_USE
! 		     && ref_var (ref) == get_operand (occur, 0)
  		     && imm_reaching_def (ref)
! 		     && is_injuring_def (ei, ref_stmt (imm_reaching_def (ref))))
  		{
+ 		  if (!maybe_find_rhs_use_for_var (imm_reaching_def (ref), 
+ 						   ref_var (ref)))
+ 		    break;
  		  ref = find_rhs_use_for_var (imm_reaching_def (ref), 
  					      ref_var (ref));
! 		  if (!okay_injuring_def (imm_reaching_def (ref), ref_var (ref)))
  		    break;
  		  
  		  ref = find_rhs_use_for_var (imm_reaching_def (ref), 
*************** expr_phi_insertion (dfs, ei)
*** 1631,1643 ****
  	      /* ??? If the trees aren't shared, will the last part of this ||
  		 work right? */ 
                if (ref_type (ref) != V_USE
!                   || !is_simple_modify_expr (ref_expr (ref))
!                   /*|| TREE_OPERAND (ref_expr (ref), 1) != real*/)
!                 continue;
!               if (ref_var (ref) != TREE_OPERAND (real, 0)
!                   && (TREE_OPERAND (real, 1) == NULL 
! 		      || ref_var (ref) != TREE_OPERAND (real, 1)))
                  continue;
                if (!imm_reaching_def (ref)
  		  || ref_type (imm_reaching_def (ref)) != V_PHI)
                  continue;
--- 1924,1936 ----
  	      /* ??? If the trees aren't shared, will the last part of this ||
  		 work right? */ 
                if (ref_type (ref) != V_USE
!                   || !is_simple_modify_expr (ref_stmt (ref))
!                   /*|| TREE_OPERAND (ref_stmt (ref), 1) != real*/)
                  continue;
+               if (ref_var (ref) != get_operand (occur, 0)
+                   && (get_operand (occur, 1) == NULL 
+ 		      || ref_var (ref) != get_operand (occur, 1)))
+                 continue; 
                if (!imm_reaching_def (ref)
  		  || ref_type (imm_reaching_def (ref)) != V_PHI)
                  continue;
*************** expr_phi_insertion (dfs, ei)
*** 1654,1659 ****
--- 1947,1954 ----
                                  BASIC_BLOCK (i), 
                                  NULL, NULL, NULL, true);
      VARRAY_PUSH_GENERIC_PTR (ei->erefs, ref);
+     set_exprref_processed (ref, false);
+     set_exprref_processed2 (ref, false);
      set_exprphi_downsafe (ref, true);
      set_exprphi_canbeavail (ref, true);
      set_exprphi_later (ref, true);
*************** reset_down_safe (phiop)
*** 1670,1676 ****
       tree_ref phiop;
  {
    tree_ref phi;
!   basic_block bb;
    
    if (expruse_has_real_use (phiop))
      return;
--- 1965,1971 ----
       tree_ref phiop;
  {
    tree_ref phi;
!   size_t i;
    
    if (expruse_has_real_use (phiop))
      return;
*************** reset_down_safe (phiop)
*** 1680,1688 ****
    if (!exprphi_downsafe (phi))
      return;  
    set_exprphi_downsafe (phi, false);
!   FOR_EACH_BB (bb)
!     if (phi_operand (phi, bb) != NULL)
!       reset_down_safe (phi_operand (phi, bb));
  }
  
  /* Compute down_safety.  */
--- 1975,1982 ----
    if (!exprphi_downsafe (phi))
      return;  
    set_exprphi_downsafe (phi, false);
!   for (i = 0; i < num_ephi_args (phi); i++)
!     reset_down_safe (phi_arg_def (ephi_arg (phi, i)));
  }
  
  /* Compute down_safety.  */
*************** down_safety (ei)
*** 1694,1705 ****
    FOR_EACH_BB (block)
      {
        tree_ref phi = phi_at_block (ei, block);
!       basic_block block2;
        if (phi == NULL || exprphi_downsafe (phi))
          continue;
!       FOR_EACH_BB (block2)
!         if (phi_operand (phi, block2) != NULL)
!           reset_down_safe (phi_operand (phi, block2));
      }      
  } 
  
--- 1988,1999 ----
    FOR_EACH_BB (block)
      {
        tree_ref phi = phi_at_block (ei, block);
!       size_t i;
!       
        if (phi == NULL || exprphi_downsafe (phi))
          continue;
!       for (i = 0; i < num_ephi_args (phi); i++)       
! 	reset_down_safe (phi_arg_def (ephi_arg (phi, i)));
      }      
  } 
  
*************** requires_edge_placement (phi)
*** 1715,1721 ****
      {
        if (pred->src != ENTRY_BLOCK_PTR)
  	{
! 	  tree_ref operand = phi_operand (phi, pred->src);
  	  if (expruse_def (operand) == NULL && EDGE_CRITICAL_P (pred))
  	    return true;
  	}
--- 2009,2015 ----
      {
        if (pred->src != ENTRY_BLOCK_PTR)
  	{
! 	  tree_ref operand = phi_operand_for_pred (phi, pred);
  	  if (expruse_def (operand) == NULL && EDGE_CRITICAL_P (pred))
  	    return true;
  	}
*************** compute_can_be_avail (ei)
*** 1765,1771 ****
          {
            if (pred->src != ENTRY_BLOCK_PTR)
              {
!               tree_ref operand = phi_operand (phi, pred->src);
                if (expruse_def (operand) == NULL)
                  {
                    reset_can_be_avail (ei, phi);
--- 2059,2065 ----
          {
            if (pred->src != ENTRY_BLOCK_PTR)
              {
!               tree_ref operand = phi_operand_for_pred (phi, pred);
                if (expruse_def (operand) == NULL)
                  {
                    reset_can_be_avail (ei, phi);
*************** reset_can_be_avail (ei, phi)
*** 1781,1786 ****
--- 2075,2081 ----
       struct expr_info *ei;   
       tree_ref phi;
  {
+ #if 0
    basic_block block;
  
    set_exprphi_canbeavail (phi, false);
*************** reset_can_be_avail (ei, phi)
*** 1796,1802 ****
          {
            if (pred->src != ENTRY_BLOCK_PTR)
              {
!               tree_ref operand = phi_operand (other, pred->src);
                if (expruse_def (operand) == phi)
                  {
                    if (!expruse_has_real_use(operand))
--- 2091,2097 ----
          {
            if (pred->src != ENTRY_BLOCK_PTR)
              {
!               tree_ref operand = phi_operand_for_pred (other, pred);
                if (expruse_def (operand) == phi)
                  {
                    if (!expruse_has_real_use(operand))
*************** reset_can_be_avail (ei, phi)
*** 1809,1814 ****
--- 2104,2127 ----
              }
          }
      }
+ #else
+   ref_list_iterator rli;
+   
+   set_exprphi_canbeavail (phi, false);
+   rli = rli_start (exprref_uses (phi));
+   for (; !rli_after_end (rli); rli_step (&rli))
+     {
+       tree_ref w = rli_ref (rli);
+       
+       if (ref_type (w) == E_USE && expruse_phiop (w)
+ 		      && !expruse_has_real_use (w))
+ 	{
+ 	  tree_ref f = expruse_phi (w);
+ 	  if (!exprphi_downsafe (f) && exprphi_canbeavail (f))
+ 	    reset_can_be_avail (ei, f);
+ 	}
+     }
+ #endif
  }
  
  /*  Reset later flags.  */
*************** reset_later (ei, phi)
*** 1817,1822 ****
--- 2130,2136 ----
       struct expr_info *ei;
       tree_ref phi;
  {
+ #if 0
    basic_block block;
  
    set_exprphi_later (phi, false);
*************** reset_later (ei, phi)
*** 1832,1838 ****
          {
            if (pred->src != ENTRY_BLOCK_PTR)
              {
!               tree_ref operand = phi_operand (other, pred->src);
                if (expruse_def (operand) == phi)
                  {
                    if (exprphi_later (other))                
--- 2146,2152 ----
          {
            if (pred->src != ENTRY_BLOCK_PTR)
              {
!               tree_ref operand = phi_operand_for_pred (other, pred);
                if (expruse_def (operand) == phi)
                  {
                    if (exprphi_later (other))                
*************** reset_later (ei, phi)
*** 1841,1846 ****
--- 2155,2180 ----
              }
          }
      }
+ #else
+   ref_list_iterator rli;
+ 
+   set_exprphi_later (phi, false);  
+   rli = rli_start (exprref_uses (phi));
+   for (; !rli_after_end (rli); rli_step (&rli))
+     {
+       tree_ref w = rli_ref (rli);
+       
+       if (expruse_def (w) != phi)
+ 	abort ();
+       
+       if (ref_type (w) == E_USE && expruse_phiop (w))
+ 	{
+ 	  tree_ref f = expruse_phi (w);
+ 	  if (exprphi_later (f))
+ 	    reset_later (ei, f);
+ 	}
+     }  
+ #endif
  }
  
  /*  Compute later flags.  */
*************** compute_later (ei)
*** 1854,1860 ****
        tree_ref phi = phi_at_block (ei, block);
        if (phi == NULL)
          continue;
!       set_exprphi_later (phi,exprphi_canbeavail (phi));
      }
        
    FOR_EACH_BB (block)
--- 2188,2194 ----
        tree_ref phi = phi_at_block (ei, block);
        if (phi == NULL)
          continue;
!       set_exprphi_later (phi ,exprphi_canbeavail (phi));
      }
        
    FOR_EACH_BB (block)
*************** compute_later (ei)
*** 1870,1876 ****
          {
            if (pred->src != ENTRY_BLOCK_PTR)
              {
!               tree_ref operand = phi_operand (phi, pred->src);
                if (expruse_def (operand) != NULL 
  		  && expruse_has_real_use (operand))
  	      {
--- 2204,2210 ----
          {
            if (pred->src != ENTRY_BLOCK_PTR)
              {
!               tree_ref operand = phi_operand_for_pred (phi, pred);
                if (expruse_def (operand) != NULL 
  		  && expruse_has_real_use (operand))
  	      {
*************** set_need_repair (ei, q)
*** 1919,1927 ****
  	  || !DECL_P (TREE_OPERAND (ei->expr, i)))
  	continue;
        v = TREE_OPERAND (ei->expr, i);
!       if (ref_expr (p))
! 	vp = find_use_for_var (ref_expr (p), v);
!       vq = find_use_for_var (ref_expr (q), v);
        if (vp != vq)
  	{
  	  splay_tree_insert (need_repair_map, 
--- 2253,2261 ----
  	  || !DECL_P (TREE_OPERAND (ei->expr, i)))
  	continue;
        v = TREE_OPERAND (ei->expr, i);
!       if (ref_stmt (p))
! 	vp = find_use_for_var (ref_stmt (p), v);
!       vq = find_use_for_var (ref_stmt (q), v);
        if (vp != vq)
  	{
  	  splay_tree_insert (need_repair_map, 
*************** repair_injury (ei, use, temp, orig_euse)
*** 1976,2010 ****
    tree expr, stmt;
    basic_block bb;
    ref_list toprocess = create_ref_list();
!      
    for (i = 0; i < 2; i++)
      {
        tree incr = integer_zero_node;
        tree_ref v;
!       if (!DECL_P (TREE_OPERAND (ei->expr, i)))
  	continue;
        if (ref_type (use) == E_USE)
  	v = find_rhs_use_for_var (use, TREE_OPERAND (ei->expr, i));
        else 
  	v = use;      
! 
        if (ref_type (v) == V_DEF)
  	{
  	  ref_list_iterator j;
  
  	  /* If this isn't a def of *this* variable, ignore it, since it can't
  	   *possibly* injure it. */
! 	  if (ref_var (find_def_for_stmt (ref_stmt (v))) 
! 	      != TREE_OPERAND  (ei->expr, i))
  	    continue;
! 	  while (is_injuring_def (ei, ref_expr (v)))
  	    {
  	      add_ref_to_list_begin (toprocess, v);
  	      v = find_rhs_use_for_var (v, TREE_OPERAND (ei->expr, i));
! 	      if (is_default_def (imm_reaching_def (v))
! 		  || ref_type (imm_reaching_def (v)) == V_PHI
! 		  || !maybe_find_rhs_use_for_var (imm_reaching_def (v),
! 						  TREE_OPERAND (ei->expr, i)))
  		break;
  	      v = find_rhs_use_for_var (imm_reaching_def (v), 
  					TREE_OPERAND (ei->expr, i));
--- 2310,2349 ----
    tree expr, stmt;
    basic_block bb;
    ref_list toprocess = create_ref_list();
! 
!   if (htab_find (ei->repaired, use) != NULL)
!       return;
! 
!   *(htab_find_slot (ei->repaired, use, INSERT)) = use;
!   
    for (i = 0; i < 2; i++)
      {
        tree incr = integer_zero_node;
        tree_ref v;
!       if (!DECL_P (get_operand (ei->expr, i)))
  	continue;
        if (ref_type (use) == E_USE)
  	v = find_rhs_use_for_var (use, TREE_OPERAND (ei->expr, i));
        else 
  	v = use;      
!       
        if (ref_type (v) == V_DEF)
  	{
  	  ref_list_iterator j;
  
  	  /* If this isn't a def of *this* variable, ignore it, since it can't
  	   *possibly* injure it. */
! 	  if (is_default_def (v) 
! 	      || htab_find (ei->repaired, ref_stmt (v))
! 	      || !ref_defines (find_def_for_stmt (ref_stmt (v)), 
! 			       TREE_OPERAND (ei->expr, i)))
! 
  	    continue;
! 	  while (is_injuring_def (ei, ref_stmt (v)))
  	    {
  	      add_ref_to_list_begin (toprocess, v);
  	      v = find_rhs_use_for_var (v, TREE_OPERAND (ei->expr, i));
! 	      if (!okay_injuring_def (imm_reaching_def (v), ref_var (v)))
  		break;
  	      v = find_rhs_use_for_var (imm_reaching_def (v), 
  					TREE_OPERAND (ei->expr, i));
*************** repair_injury (ei, use, temp, orig_euse)
*** 2015,2041 ****
  	     yet. */
  	  for (j = rli_start (toprocess); !rli_after_end (j); rli_step (&j))
  	    {
  	      v = rli_ref (j);
! 	      if (htab_find (ei->repaired, ref_expr (v)) == NULL)
  		{
  #if DEBUGGING_STRRED
  		  if (dump_file)
  		      {
  			fprintf (dump_file, "Injuring def to repair is: ");
! 			print_generic_expr (dump_file, ref_expr (v), 0);
  			fprintf (dump_file, "\n");
  		      }
  #endif
! 		    incr = calculate_increment (ei, ref_expr (v));
  		    expr = build_modify_expr (temp, NOP_EXPR, 
  					      fold (build (PLUS_EXPR, 
  							  TREE_TYPE (temp),
  							  temp, incr)));
! 		    stmt = build (COMPOUND_EXPR, void_type_node, ref_stmt (v), expr);
  		    TREE_TYPE (stmt) = TREE_TYPE (expr);
  		    bb = ref_bb (use);
  		    replace_ref_stmt_with (v, stmt);
! 		    *(htab_find_slot (ei->repaired, ref_expr (v), INSERT)) = ref_expr (v);
  #if WAITING_FOR_DFA_UPDATE		  
  		    /* Update SSA for the repair.  
  		      1. Find the refs in the statement.
--- 2354,2388 ----
  	     yet. */
  	  for (j = rli_start (toprocess); !rli_after_end (j); rli_step (&j))
  	    {
+ 	      tree oldstmt;
+ 
  	      v = rli_ref (j);
! 	      if (htab_find (ei->repaired, ref_stmt (v)) == NULL)
  		{
  #if DEBUGGING_STRRED
  		  if (dump_file)
  		      {
  			fprintf (dump_file, "Injuring def to repair is: ");
! 			print_generic_stmt (dump_file, ref_stmt (v), 0);
  			fprintf (dump_file, "\n");
  		      }
  #endif
! 		    incr = calculate_increment (ei, ref_stmt (v));
  		    expr = build_modify_expr (temp, NOP_EXPR, 
  					      fold (build (PLUS_EXPR, 
  							  TREE_TYPE (temp),
  							  temp, incr)));
! 		    oldstmt = ref_stmt (v);
! 		    stmt = build (COMPOUND_EXPR, void_type_node, oldstmt,
! 				  expr);
  		    TREE_TYPE (stmt) = TREE_TYPE (expr);
  		    bb = ref_bb (use);
  		    replace_ref_stmt_with (v, stmt);
! 		    update_old_new (ei, v->common.stmt_p, &TREE_OPERAND (stmt, 0));
! 		    /* REMOVE AFTER DFA UPDATE */
! 		    temp_fix_refs (oldstmt, stmt, &TREE_OPERAND (stmt, 0));
! 		    /* END REMOVE AFTER DFA UPDATE */
! 		    *(htab_find_slot (ei->repaired, ref_stmt (v), INSERT)) = ref_stmt (v);
  #if WAITING_FOR_DFA_UPDATE		  
  		    /* Update SSA for the repair.  
  		      1. Find the refs in the statement.
*************** repair_injury (ei, use, temp, orig_euse)
*** 2058,2067 ****
  		  }
  	    }
  	}
!       else if (ref_type (imm_reaching_def (v)) == V_PHI)
  	{
  	  size_t curr_phi_operand;
! 	  tree_ref phi = imm_reaching_def (v);
  	  for (curr_phi_operand = 0; 
  	       curr_phi_operand < num_phi_args (phi); 
  	       curr_phi_operand++)
--- 2405,2415 ----
  		  }
  	    }
  	}
!       else if (ref_type (v) == V_PHI 
! 	       || ref_type (imm_reaching_def (v)) == V_PHI)
  	{
  	  size_t curr_phi_operand;
! 	  tree_ref phi = ref_type (v) == V_PHI ? v :  imm_reaching_def (v);
  	  for (curr_phi_operand = 0; 
  	       curr_phi_operand < num_phi_args (phi); 
  	       curr_phi_operand++)
*************** repair_injury (ei, use, temp, orig_euse)
*** 2069,2081 ****
  	      phi_node_arg phi_oper = phi_arg (phi, curr_phi_operand);
  	      tree_ref phi_op = phi_arg_def (phi_oper);
  	      tree_ref ephi = phi_at_block (ei, ref_bb (phi));
! 	      tree_ref ephi_op = phi_operand (ephi, 
! 					      phi_arg_edge (phi_oper)->src);
  	      repair_injury (ei, phi_op, temp, ephi_op);
  	    }
  	}
        else
! 	abort ();
      }
  }
  
--- 2417,2432 ----
  	      phi_node_arg phi_oper = phi_arg (phi, curr_phi_operand);
  	      tree_ref phi_op = phi_arg_def (phi_oper);
  	      tree_ref ephi = phi_at_block (ei, ref_bb (phi));
! 	      tree_ref ephi_op;
! 	      if (!ephi)
! 		continue;
! 	      ephi_op = phi_operand_for_pred (ephi, 
! 					      phi_arg_edge (phi_oper));
  	      repair_injury (ei, phi_op, temp, ephi_op);
  	    }
  	}
        else
! 	repair_injury (ei, imm_reaching_def (v), temp, orig_euse);
      }
  }
  
*************** find_reaching_def_of_var (var, stmtbb, p
*** 2093,2099 ****
    struct ref_list_node *fromhere;
  
    if (!stmtbb)
!     return NULL;
    
    if (phi)
      for (i = rli_start (bb_refs (ref_bb (phi)));
--- 2444,2450 ----
    struct ref_list_node *fromhere;
  
    if (!stmtbb)
!     return 0;
    
    if (phi)
      for (i = rli_start (bb_refs (ref_bb (phi)));
*************** find_reaching_def_of_var (var, stmtbb, p
*** 2132,2138 ****
        tree_ref tempref = rli_ref (i);
        if ((ref_type (tempref) != V_DEF
  	    && ref_type (tempref) != V_USE)
! 	  || ref_expr (var) == ref_expr (tempref)) 
  	continue;
        if (ref_var (tempref) == ref_var (var))
  	{
--- 2483,2489 ----
        tree_ref tempref = rli_ref (i);
        if ((ref_type (tempref) != V_DEF
  	    && ref_type (tempref) != V_USE)
! 	  || ref_stmt (var) == ref_stmt (tempref)) 
  	continue;
        if (ref_var (tempref) == ref_var (var))
  	{
*************** update_ssa_for_new_use (temp, newuse, de
*** 2197,2214 ****
       This is a bit simplified, since when i update a reaching def, we update
       the reaching def's immediate uses, etc.
    */
! 
!   for (i = rli_start (tree_refs (newuse)); !rli_after_end (i); rli_step (&i))
!     {
!       if (ref_type (rli_ref (i)) == V_DEF)
! 	{
! 	  use_orig_ref = rli_ref (i);
! 	  break;
! 	}
!     }
  #if WAITING_FOR_DFA_UPDATE
    olddefref = find_def_for_stmt (ref_stmt (use_orig_ref));
!   i = rli_start (tree_refs (ref_expr (use_orig_def)));
    for (; !rli_after_end (i); rli_step (&i))
      {
        tree_ref tempref = rli_ref (i);
--- 2548,2557 ----
       This is a bit simplified, since when i update a reaching def, we update
       the reaching def's immediate uses, etc.
    */
!   use_orig_ref = find_def_for_stmt (newuse);
  #if WAITING_FOR_DFA_UPDATE
    olddefref = find_def_for_stmt (ref_stmt (use_orig_ref));
!   i = rli_start (tree_refs (ref_stmt (use_orig_def)));
    for (; !rli_after_end (i); rli_step (&i))
      {
        tree_ref tempref = rli_ref (i);
*************** update_ssa_for_new_use (temp, newuse, de
*** 2235,2258 ****
      }
    
    for (i = rli_start (todelete); !rli_after_end (i); rli_step (&i))
!     remove_tree_ref (ref_expr (use_orig_ref), rli_ref (i));
  
!   ref_expr (use_orig_ref)->common.ann = NULL;
  #endif
!   useexpr = ref_expr (use_orig_ref);
    STRIP_WFL (useexpr);
    newmodifyexpr = build_modify_expr (TREE_OPERAND (useexpr, 0), 
  				     NOP_EXPR, temp);
!   replace_ref_expr_with (use_orig_ref, newmodifyexpr);
  
  #if WAITING_FOR_DFA_UPDATE
  
    /* FIXME: Hack.  Passing the address of local trees to create_ref is not
       correct.  We should keep statement and expression pointers here.  */
!   newdefref = create_ref (TREE_OPERAND (ref_expr (use_orig_ref), 0),
  			  V_DEF, 0, bb, ref_stmt (use_orig_ref), 
! 			  ref_expr (use_orig_ref),
! 			  &TREE_OPERAND (ref_expr (use_orig_ref), 0),
  			  true);
    add_list_to_list_end (reached_uses (newdefref), reachedtoadd);
    add_list_to_list_end (imm_uses (newdefref), immtoadd);
--- 2578,2601 ----
      }
    
    for (i = rli_start (todelete); !rli_after_end (i); rli_step (&i))
!     remove_tree_ref (ref_stmt (use_orig_ref), rli_ref (i));
  
!   ref_stmt (use_orig_ref)->common.ann = NULL;
  #endif
!   useexpr = ref_stmt (use_orig_ref);
    STRIP_WFL (useexpr);
    newmodifyexpr = build_modify_expr (TREE_OPERAND (useexpr, 0), 
  				     NOP_EXPR, temp);
!   replace_ref_stmt_with (use_orig_ref, newmodifyexpr);
  
  #if WAITING_FOR_DFA_UPDATE
  
    /* FIXME: Hack.  Passing the address of local trees to create_ref is not
       correct.  We should keep statement and expression pointers here.  */
!   newdefref = create_ref (TREE_OPERAND (ref_stmt (use_orig_ref), 0),
  			  V_DEF, 0, bb, ref_stmt (use_orig_ref), 
! 			  ref_stmt (use_orig_ref),
! 			  &TREE_OPERAND (ref_stmt (use_orig_ref), 0),
  			  true);
    add_list_to_list_end (reached_uses (newdefref), reachedtoadd);
    add_list_to_list_end (imm_uses (newdefref), immtoadd);
*************** update_ssa_for_new_use (temp, newuse, de
*** 2263,2277 ****
    /* FIXME: Hack.  Passing the address of local trees to create_ref is not
       correct.  We should keep statement and expression pointers here.  */
    newuseref = create_ref (temp, V_USE, 0, bb, ref_stmt (use_orig_ref),
! 			  ref_expr (use_orig_ref), 
! 			  find_expr_in_tree (ref_expr (use_orig_ref), temp), 
  			  true);
    if ( (ref_type (defby) != E_PHI))
      {
        /* For non-PHI's we created, the  map is euse expression -> new pretmp
  	 save stmt. */ 
        reachingnode = splay_tree_lookup (new_stmt_map, 
! 					(splay_tree_key) ref_expr (defby));
        if (!reachingnode)
  	abort();
        reachingstmt = (tree) reachingnode->value;
--- 2606,2620 ----
    /* FIXME: Hack.  Passing the address of local trees to create_ref is not
       correct.  We should keep statement and expression pointers here.  */
    newuseref = create_ref (temp, V_USE, 0, bb, ref_stmt (use_orig_ref),
! 			  ref_stmt (use_orig_ref), 
! 			  find_expr_in_tree (ref_stmt (use_orig_ref), temp), 
  			  true);
    if ( (ref_type (defby) != E_PHI))
      {
        /* For non-PHI's we created, the  map is euse expression -> new pretmp
  	 save stmt. */ 
        reachingnode = splay_tree_lookup (new_stmt_map, 
! 					(splay_tree_key) ref_stmt (defby));
        if (!reachingnode)
  	abort();
        reachingstmt = (tree) reachingnode->value;
*************** code_motion (ei, temp)
*** 2333,2374 ****
       struct expr_info *ei;
       tree temp;
  {
!   fibheap_t exprs;
    tree_ref use;
!   
    ei->injfixups = create_ref_list ();
    need_repair_map = splay_tree_new (splay_tree_compare_pointers, NULL, NULL);
!   exprs = fibheap_new ();
    if (ei->strred_cand)
      {
!       insert_euse_in_preorder_dt_order (ei, exprs);
!       while (!fibheap_empty (exprs))
  	{
! 	  use = fibheap_extract_min (exprs);
  	  if ((ref_type (use) == E_USE)
  	      && exprref_reload (use) 
  	      && !exprref_inserted (use))
  	    {
  	      repair_injury (ei, use, temp, use);
- 	      /*	    set_need_repair (ei, use);*/
  	    }
  	}
      }
!   insert_euse_in_preorder_dt_order (ei, exprs);
!   while (!fibheap_empty (exprs))
      {
!       use = fibheap_extract_min (exprs);
!       if (ref_type (use) == E_USE /*&& !EXPRUSE_PHIOP (use) */
! 	  && !exprref_inserted (use))
  	{
! 	  if (expruse_phiop (use) 
  	      && (exprref_reload (use) || exprref_save (use)))
  	    abort();
  	  if (exprref_save (use))
  	    {
  	      basic_block use_bb = ref_bb (use);
  	      tree use_stmt = ref_stmt (use);
! 	      tree use_expr = ref_expr (use);
  	      tree_ref use_orig_ref = NULL;
  	      tree newexpr, newstmt;
  	      size_t j;	      
--- 2676,2716 ----
       struct expr_info *ei;
       tree temp;
  {
! 
    tree_ref use;
!   ref_list_iterator euse_rli;
    ei->injfixups = create_ref_list ();
    need_repair_map = splay_tree_new (splay_tree_compare_pointers, NULL, NULL);
! 
    if (ei->strred_cand)
      {
!       euse_rli = rli_start (ei->euses_dt_order);
!       for (; !rli_after_end (euse_rli); rli_step (&euse_rli))
  	{
! 	  use = rli_ref (euse_rli);
  	  if ((ref_type (use) == E_USE)
  	      && exprref_reload (use) 
  	      && !exprref_inserted (use))
  	    {
  	      repair_injury (ei, use, temp, use);
  	    }
  	}
      }
!   euse_rli = rli_start (ei->euses_dt_order);
!   for (; !rli_after_end (euse_rli); rli_step (&euse_rli))
      {
!       use = rli_ref (euse_rli);
!       if ((ref_type (use) == E_USE
! 	   && !exprref_inserted (use)) || ref_type (use) == E_LEFT)
  	{
! 	  if (ref_type (use) != E_LEFT && expruse_phiop (use) 
  	      && (exprref_reload (use) || exprref_save (use)))
  	    abort();
  	  if (exprref_save (use))
  	    {
  	      basic_block use_bb = ref_bb (use);
  	      tree use_stmt = ref_stmt (use);
! 	      tree use_expr = ref_stmt (use);
  	      tree_ref use_orig_ref = NULL;
  	      tree newexpr, newstmt;
  	      size_t j;	      
*************** code_motion (ei, temp)
*** 2398,2423 ****
  			   EXPR_WFL_LINENO (use_expr));
  		}
  	      STRIP_WFL (use_expr);
! 	      newexpr = fold (build_modify_expr (temp, NOP_EXPR, 
! 						 deep_copy_node (TREE_OPERAND (use_expr, 1))));
  	      newstmt = build (COMPOUND_EXPR, void_type_node, newexpr,
  			       use_stmt);
  	      replace_ref_stmt_with (use, newstmt);
  	      use->common.stmt_p = &TREE_OPERAND (newstmt, 1);
  	      use->common.expr_p = &TREE_OPERAND (newstmt, 1);
  	      /* REMOVE AFTER DFA UPDATE */
! 	      i = rli_start (tree_refs (use_stmt));
! 	      for (; !rli_after_end (i); rli_step (&i))
! 		{
! 		  tree_ref a = rli_ref (i);
! 		  if (ref_stmt (a) == newstmt)
! 		    {
! 		      a->common.stmt_p = &TREE_OPERAND (newstmt, 1);
! 		      a->common.expr_p = &TREE_OPERAND (newstmt, 1);
! 		    }
! 		}	      
  	      /* END REMOVE AFTER DFA UPDATE */
! 	      update_ssa_for_new_use (temp, ref_expr (use), use, use_bb);
  
  #if WAITING_FOR_DFA_UPDATE
  	      /* Update the SSA representation for the new def of the
--- 2740,2761 ----
  			   EXPR_WFL_LINENO (use_expr));
  		}
  	      STRIP_WFL (use_expr);
! 	      newexpr = build_modify_expr (temp, NOP_EXPR, 
! 					   deep_copy_node (TREE_OPERAND (use_expr, 1)));
! 	      newexpr = fold (newexpr);
  	      newstmt = build (COMPOUND_EXPR, void_type_node, newexpr,
  			       use_stmt);
  	      replace_ref_stmt_with (use, newstmt);
+ 	      update_old_new (ei, use->common.stmt_p, &TREE_OPERAND (newstmt, 1));
+ 
+ 	      
  	      use->common.stmt_p = &TREE_OPERAND (newstmt, 1);
  	      use->common.expr_p = &TREE_OPERAND (newstmt, 1);
+ 
  	      /* REMOVE AFTER DFA UPDATE */
! 	      temp_fix_refs (use_stmt, newstmt, &TREE_OPERAND (newstmt, 1));
  	      /* END REMOVE AFTER DFA UPDATE */
! 	      update_ssa_for_new_use (temp, ref_stmt (use), use, use_bb);
  
  #if WAITING_FOR_DFA_UPDATE
  	      /* Update the SSA representation for the new def of the
*************** code_motion (ei, temp)
*** 2446,2454 ****
  		}
  	      
  	      splay_tree_insert (new_stmt_map, 
! 				 (splay_tree_key) ref_expr (use), 
  				 (splay_tree_value) newstmt);
! 	      update_ssa_for_new_use (temp, ref_expr (use), use, use_bb);
  #if DEBUGGING_SSA_UPDATE 
  	      if (dump_file)
  		{
--- 2784,2792 ----
  		}
  	      
  	      splay_tree_insert (new_stmt_map, 
! 				 (splay_tree_key) ref_stmt (use), 
  				 (splay_tree_value) newstmt);
! 	      update_ssa_for_new_use (temp, ref_stmt (use), use, use_bb);
  #if DEBUGGING_SSA_UPDATE 
  	      if (dump_file)
  		{
*************** code_motion (ei, temp)
*** 2462,2468 ****
  	    {
  	      basic_block use_bb = ref_bb (use);
  	      tree use_stmt = ref_stmt (use);
! 	      tree use_expr = ref_expr (use);
  	      if (dump_file)
                  {
  		  fprintf (dump_file, "In BB %d, insert reload of ", 
--- 2800,2806 ----
  	    {
  	      basic_block use_bb = ref_bb (use);
  	      tree use_stmt = ref_stmt (use);
! 	      tree use_expr = ref_stmt (use);
  	      if (dump_file)
                  {
  		  fprintf (dump_file, "In BB %d, insert reload of ", 
*************** code_motion (ei, temp)
*** 2471,2484 ****
                    fprintf (dump_file, " from ");
                    print_generic_expr (dump_file, temp, 0);
                    fprintf (dump_file, " in statement ");
!                   print_generic_expr (dump_file, TREE_OPERAND (use_stmt, 0), 0);
                    fprintf (dump_file, " on line %d\n", 
  			   EXPR_WFL_LINENO (use_stmt));
                  }
  	      /* Update the SSA representation for a new use of the temporary.
  		 Do exactly what we do for the new use generated by the save. 
  	      */
! 	      update_ssa_for_new_use (temp, ref_expr (use), expruse_def (use),
  				      ref_bb (use));
  #if DEBUGGING_SSA_UPDATE
  	      if (dump_file)
--- 2809,2822 ----
                    fprintf (dump_file, " from ");
                    print_generic_expr (dump_file, temp, 0);
                    fprintf (dump_file, " in statement ");
!                   print_generic_stmt (dump_file, use_stmt, 0);
                    fprintf (dump_file, " on line %d\n", 
  			   EXPR_WFL_LINENO (use_stmt));
                  }
  	      /* Update the SSA representation for a new use of the temporary.
  		 Do exactly what we do for the new use generated by the save. 
  	      */
! 	      update_ssa_for_new_use (temp, ref_stmt (use), expruse_def (use),
  				      ref_bb (use));
  #if DEBUGGING_SSA_UPDATE
  	      if (dump_file)
*************** code_motion (ei, temp)
*** 2555,2561 ****
  						  (splay_tree_key) defby);
  		else
  		  phidefnode = splay_tree_lookup (new_stmt_map,
! 						  (splay_tree_key) ref_expr (defby));
  		if (!phidefnode)
  		  abort();
  		tempdef = find_def_for_stmt ((tree) phidefnode->value);
--- 2893,2899 ----
  						  (splay_tree_key) defby);
  		else
  		  phidefnode = splay_tree_lookup (new_stmt_map,
! 						  (splay_tree_key) ref_stmt (defby));
  		if (!phidefnode)
  		  abort();
  		tempdef = find_def_for_stmt ((tree) phidefnode->value);
*************** code_motion (ei, temp)
*** 2585,2591 ****
      ref_list_iterator j;
      tempref = rli_ref (i);
  
!     j = rli_start (tree_refs (ref_expr (tempref)));
      for (; !rli_after_end (j); rli_step (&j))
        {
  	tree_ref tempref2 = rli_ref (j);
--- 2923,2929 ----
      ref_list_iterator j;
      tempref = rli_ref (i);
  
!     j = rli_start (tree_refs (ref_stmt (tempref)));
      for (; !rli_after_end (j); rli_step (&j))
        {
  	tree_ref tempref2 = rli_ref (j);
*************** will_be_avail (ei)
*** 2616,2622 ****
--- 2954,2983 ----
    compute_can_be_avail (ei);
    compute_later (ei);
  }
+ static bool
+ call_modifies_slot (call, expr)
+      tree_ref call;
+      tree expr;
+ {
  
+   ref_list_iterator rli;
+   
+   for (rli = rli_start (tree_refs (ref_stmt (call))); 
+        !rli_after_end (rli);
+        rli_step (&rli))
+     {
+       size_t i;
+       
+       for (i = 0; i < 2; i++)
+ 	{
+ 	  if (!TREE_OPERAND (expr, i))
+ 	    continue;
+ 	  if (ref_defines (rli_ref (rli), TREE_OPERAND (expr, i)))
+ 	    return true;
+ 	}
+     }
+   return false;
+ }
  /* Add call expression to expr-infos.  */
  static int
  add_call_to_ei (slot, data)
*************** add_call_to_ei (slot, data)
*** 2625,2633 ****
  {
    tree_ref call = (tree_ref) data;
    struct expr_info *ei = (struct expr_info *) slot;
!   VARRAY_PUSH_GENERIC_PTR (ei->occurs, call->common.expr_p);
!   VARRAY_PUSH_GENERIC_PTR (ei->occurstmts, call->common.stmt_p);
!   VARRAY_PUSH_GENERIC_PTR (ei->refs, call);
    return 0;
  }
  
--- 2986,2998 ----
  {
    tree_ref call = (tree_ref) data;
    struct expr_info *ei = (struct expr_info *) slot;
!   if (call_modifies_slot (call, ei->expr))
!     {
!       VARRAY_PUSH_GENERIC_PTR (ei->occurs, NULL);
!       VARRAY_PUSH_GENERIC_PTR (ei->lefts, NULL);
!       VARRAY_PUSH_GENERIC_PTR (ei->kills, call->common.stmt_p);
!       VARRAY_PUSH_GENERIC_PTR (ei->refs, call);
!     }
    return 0;
  }
  
*************** pre_part_1_trav (slot, data)
*** 2638,2648 ****
       void *data;
  {
    tree temp;
!   tree fnbody;
    struct expr_info *ei = (struct expr_info *) slot;
    if (VARRAY_ACTIVE_SIZE (ei->reals) < 2)
      return 0;
  
    expr_phi_insertion ((sbitmap *)data, ei);
    rename_1 (ei);
    if (dump_file)
--- 3003,3033 ----
       void *data;
  {
    tree temp;
!   size_t i;
!   bool changed = true;
    struct expr_info *ei = (struct expr_info *) slot;
+ 
    if (VARRAY_ACTIVE_SIZE (ei->reals) < 2)
      return 0;
  
+   /* Have to iterate until we are done changing, since we might have replaced
+      what we replaced (IE processing a single expression may cause a to move to
+   b, then b to c. If we don't iterate, we'll only change a to b. */ 
+   while (changed)
+     {
+       changed = false;
+       for (i = 0; i < VARRAY_ACTIVE_SIZE (ei->occurs); i++)
+ 	{
+ 	  splay_tree_node result;
+ 	  tree *occ = (tree *) VARRAY_GENERIC_PTR (ei->occurs, i);
+ 	  result = splay_tree_lookup (old_new_map, (splay_tree_key) occ);
+ 	  if (result)
+ 	    {
+ 	      changed = true;
+ 	      VARRAY_GENERIC_PTR (ei->occurs, i) = (PTR) result->value;
+ 	    }
+ 	}
+     }
    expr_phi_insertion ((sbitmap *)data, ei);
    rename_1 (ei);
    if (dump_file)
*************** pre_part_1_trav (slot, data)
*** 2664,2684 ****
    {
      tree_ref def = NULL;
      tree type_of_expr;
!     size_t i;
!     for (i = 0; i < VARRAY_ACTIVE_SIZE (ei->realstmts) && !def; i++)
!       def = find_def_for_stmt (VARRAY_TREE (ei->realstmts, 0));
! 
!     if (def != NULL)
!       type_of_expr = TREE_TYPE (ref_var (def));
!     else
!       type_of_expr = TREE_TYPE (VARRAY_TREE (ei->reals, 0));
  
      temp = create_tmp_var (type_of_expr, "pretmp");
!     finalize_1 (ei, temp);
!     finalize_2 (ei);
!     code_motion (ei, temp);
    }
-   
    return 0;
  }
  
--- 3049,3063 ----
    {
      tree_ref def = NULL;
      tree type_of_expr;
!     type_of_expr = TREE_TYPE (VARRAY_TREE (ei->reals, 0));
  
      temp = create_tmp_var (type_of_expr, "pretmp");
!     if (finalize_1 (ei, temp))
!       {
! 	finalize_2 (ei);
! 	code_motion (ei, temp);
!       }
    }
    return 0;
  }
  
*************** calculate_preorder ()
*** 2744,2749 ****
--- 3123,3194 ----
    free (stack);
    sbitmap_free (visited);
  }
+ static tree
+ get_operand (expr, num)
+      tree expr;
+      unsigned int num;
+ {
+   if (is_simple_binary_expr (expr))
+     return TREE_OPERAND (expr, num);
+   else if (TREE_CODE (expr) == INDIRECT_REF)
+     if (num == 0)
+       return expr;
+   return NULL;
+ }
+ static void
+ process_left_occs_and_kills (bexprs, slot, ref, expr)
+      varray_type bexprs;
+      struct expr_info *slot;
+      tree_ref ref; 
+      tree expr;
+ {
+   size_t k;
+   STRIP_WFL (expr);
+   if (TREE_CODE (TREE_OPERAND (expr, 1)) == CALL_EXPR)
+     {
+       tree callee = get_callee_fndecl (expr);
+       if (!callee || !DECL_IS_PURE (callee))
+ 	{		
+ 	  for (k = 0; k < VARRAY_ACTIVE_SIZE (bexprs); k++)
+ 	    if (VARRAY_GENERIC_PTR (bexprs, k) != slot)
+ 	      add_call_to_ei (VARRAY_GENERIC_PTR (bexprs, k), ref);
+ 	}
+     }  
+   else if (DECL_P (TREE_OPERAND (expr, 0)))
+     {
+       for (k = 0; k < VARRAY_ACTIVE_SIZE (bexprs); k++)
+ 	{
+ 	  struct expr_info *ei = VARRAY_GENERIC_PTR (bexprs, k);
+ 	  if (ei == slot)
+ 	    continue;
+ 	  if (TREE_CODE (ei->expr) == INDIRECT_REF)
+ 	    if (get_alias_index (TREE_OPERAND (ei->expr, 0),
+ 				 TREE_OPERAND (expr, 0)) >= 0)
+ 	      {
+ 		VARRAY_PUSH_GENERIC_PTR (ei->lefts, ref->common.stmt_p);
+ 		VARRAY_PUSH_GENERIC_PTR (ei->kills, NULL);
+ 		VARRAY_PUSH_GENERIC_PTR (ei->occurs, NULL);
+ 	      }
+ 	}
+     }
+   else if (TREE_CODE (TREE_OPERAND (expr, 0)) == INDIRECT_REF
+ 	   && DECL_P (TREE_OPERAND (TREE_OPERAND (expr, 0), 0)))
+     {
+       for (k = 0; k < VARRAY_ACTIVE_SIZE (bexprs); k++)
+ 	{
+ 	  struct expr_info *ei = VARRAY_GENERIC_PTR (bexprs, k);
+ 	  if (ei == slot)
+ 	    continue;
+ 	  if (TREE_CODE (ei->expr) == INDIRECT_REF)
+ 	    if (TREE_OPERAND (ei->expr, 0) == TREE_OPERAND (TREE_OPERAND (expr, 0), 0))
+ 	      {
+ 		VARRAY_PUSH_GENERIC_PTR (ei->lefts, ref->common.stmt_p);
+ 		VARRAY_PUSH_GENERIC_PTR (ei->kills, NULL);
+ 		VARRAY_PUSH_GENERIC_PTR (ei->occurs, NULL);
+ 	      }
+ 	}
+     }
+ }
  
  void 
  tree_perform_ssapre ()
*************** tree_perform_ssapre ()
*** 2756,2762 ****
    size_t j, k;
  
    new_stmt_map = splay_tree_new (splay_tree_compare_pointers, NULL, NULL);
!   
    VARRAY_GENERIC_PTR_INIT (bexprs, 1, "bexprs");
    
    /* Compute immediate dominators.  */
--- 3201,3208 ----
    size_t j, k;
  
    new_stmt_map = splay_tree_new (splay_tree_compare_pointers, NULL, NULL);
!   old_new_map = splay_tree_new (splay_tree_compare_pointers, NULL, NULL);
! 
    VARRAY_GENERIC_PTR_INIT (bexprs, 1, "bexprs");
    
    /* Compute immediate dominators.  */
*************** tree_perform_ssapre ()
*** 2764,2769 ****
--- 3210,3216 ----
    domchildren = sbitmap_vector_alloc (last_basic_block, last_basic_block);
    sbitmap_vector_zero (domchildren, last_basic_block);
    compute_domchildren (pre_idom, domchildren);
+ 
    /* Compute dominance frontiers.  */
    pre_dfs = sbitmap_vector_alloc (last_basic_block, last_basic_block);
    sbitmap_vector_zero (pre_dfs, last_basic_block);
*************** tree_perform_ssapre ()
*** 2779,2804 ****
        for (i = rli_start (bb_refs (bb)); !rli_after_end (i); rli_step (&i))
  	{
  	  tree_ref ref = rli_ref (i);
! 	  tree expr = ref_expr (ref);
  	  tree orig_expr = expr;
  	  tree stmt = ref_stmt (ref);
! 	  if (ref_type (ref) != V_USE)
  	    continue;
  	  STRIP_WFL (expr);
  	  if (htab_find (seen, orig_expr) != NULL)
  	    continue;
  	  if (is_simple_modify_expr (expr))
  	    {
- 	      expr = TREE_OPERAND (expr, 1);
- 	    }
- 	  if ((is_simple_binary_expr (expr)
- /*	       || is_simple_cast (expr)
- 	       || is_simple_unary_expr (expr)*/)
- 	     && TREE_CODE (expr) != INDIRECT_REF
- 	     && !is_simple_condexpr (expr))
- 	    {
- 	      struct expr_info *slot = NULL;
- 	      size_t k;
  	      for (k = 0; k < VARRAY_ACTIVE_SIZE (bexprs); k++)
  	        {
  		  slot = VARRAY_GENERIC_PTR (bexprs, k);
--- 3226,3251 ----
        for (i = rli_start (bb_refs (bb)); !rli_after_end (i); rli_step (&i))
  	{
  	  tree_ref ref = rli_ref (i);
! 	  tree expr = ref_stmt (ref);
  	  tree orig_expr = expr;
  	  tree stmt = ref_stmt (ref);
! 	  struct expr_info *slot = NULL;
! 	  
! 	  if (ref_type (ref) != V_USE
! 	      || ref_stmt (ref) == NULL_TREE)
  	    continue;
+ 
  	  STRIP_WFL (expr);
  	  if (htab_find (seen, orig_expr) != NULL)
  	    continue;
+ 
  	  if (is_simple_modify_expr (expr))
+ 	    expr = TREE_OPERAND (expr, 1);
+ 
+ 	  if (is_simple_binary_expr (expr)
+ 	      || (TREE_CODE (expr) == INDIRECT_REF 
+ 		  && DECL_P (TREE_OPERAND (expr, 0))))
  	    {
  	      for (k = 0; k < VARRAY_ACTIVE_SIZE (bexprs); k++)
  	        {
  		  slot = VARRAY_GENERIC_PTR (bexprs, k);
*************** tree_perform_ssapre ()
*** 2809,2818 ****
  	        slot = NULL;
  	      if (slot)
  		{
! 		  VARRAY_PUSH_GENERIC_PTR (slot->occurs, ref->common.expr_p);
! 		  VARRAY_PUSH_GENERIC_PTR (slot->occurstmts, ref->common.stmt_p);
! 		  VARRAY_PUSH_TREE (slot->reals, expr);
! 		  VARRAY_PUSH_TREE (slot->realstmts, stmt);
  		  VARRAY_PUSH_GENERIC_PTR (slot->refs, ref);
  		  slot->strred_cand &= is_strred_cand (orig_expr);
  		}
--- 3256,3266 ----
  	        slot = NULL;
  	      if (slot)
  		{
! 		  VARRAY_PUSH_GENERIC_PTR (slot->occurs, 
! 					   ref->common.stmt_p);
! 		  VARRAY_PUSH_GENERIC_PTR (slot->kills, NULL);
! 		  VARRAY_PUSH_GENERIC_PTR (slot->lefts, NULL);
! 		  VARRAY_PUSH_TREE (slot->reals, stmt);
  		  VARRAY_PUSH_GENERIC_PTR (slot->refs, ref);
  		  slot->strred_cand &= is_strred_cand (orig_expr);
  		}
*************** tree_perform_ssapre ()
*** 2820,2839 ****
  		{
  		  slot = ggc_alloc (sizeof (struct expr_info));
  		  slot->expr = expr;
! 		  VARRAY_GENERIC_PTR_INIT (slot->occurs, 1, "Kills and occurrence");
! 		  VARRAY_GENERIC_PTR_INIT (slot->occurstmts, 1, 
! 				    "Kills and occurrence statements");
  		  VARRAY_TREE_INIT (slot->reals, 1, "Real occurrences");
- 		  VARRAY_TREE_INIT (slot->realstmts, 1, 
- 				    "Real occurrence statements");
  		  VARRAY_GENERIC_PTR_INIT (slot->phis, last_basic_block, 
  					   "EPHIs");
  		  VARRAY_GENERIC_PTR_INIT (slot->erefs, 1, "EREFs");
  		  VARRAY_GENERIC_PTR_INIT (slot->refs, 1, "REFs");
! 		  VARRAY_PUSH_GENERIC_PTR (slot->occurs, ref->common.expr_p);
! 		  VARRAY_PUSH_GENERIC_PTR (slot->occurstmts, ref->common.stmt_p);
! 		  VARRAY_PUSH_TREE (slot->reals, expr);
! 		  VARRAY_PUSH_TREE (slot->realstmts, stmt);
  		  VARRAY_PUSH_GENERIC_PTR (slot->refs, ref);
  
  		  VARRAY_PUSH_GENERIC_PTR (bexprs, slot);
--- 3268,3288 ----
  		{
  		  slot = ggc_alloc (sizeof (struct expr_info));
  		  slot->expr = expr;
! 		  VARRAY_GENERIC_PTR_INIT (slot->occurs, 1, 
! 					   "Occurrence");
! 		  VARRAY_GENERIC_PTR_INIT (slot->kills, 1,
! 					   "Kills");
! 		  VARRAY_GENERIC_PTR_INIT (slot->lefts, 1,
! 					   "Left occurrences");
  		  VARRAY_TREE_INIT (slot->reals, 1, "Real occurrences");
  		  VARRAY_GENERIC_PTR_INIT (slot->phis, last_basic_block, 
  					   "EPHIs");
  		  VARRAY_GENERIC_PTR_INIT (slot->erefs, 1, "EREFs");
  		  VARRAY_GENERIC_PTR_INIT (slot->refs, 1, "REFs");
! 		  VARRAY_PUSH_GENERIC_PTR (slot->occurs, ref->common.stmt_p);
! 		  VARRAY_PUSH_GENERIC_PTR (slot->kills, NULL);
! 		  VARRAY_PUSH_GENERIC_PTR (slot->lefts, NULL);
! 		  VARRAY_PUSH_TREE (slot->reals, stmt);
  		  VARRAY_PUSH_GENERIC_PTR (slot->refs, ref);
  
  		  VARRAY_PUSH_GENERIC_PTR (bexprs, slot);
*************** tree_perform_ssapre ()
*** 2842,2862 ****
  						htab_eq_pointer, NULL);
  		}
  	    }
! 	  else if (TREE_CODE (expr) == CALL_EXPR 
! 		   && TREE_CODE (ref_var (ref)) == FUNCTION_DECL)
! 	    {
! 	      if (!DECL_IS_PURE (ref_var (ref)))
! 	      {
! 		for (k = 0; k < VARRAY_ACTIVE_SIZE (bexprs); k++)
! 	  	  add_call_to_ei (VARRAY_GENERIC_PTR (bexprs, k), ref);
! 	      }
! 	    }  
  	  *(htab_find_slot  (seen, orig_expr, INSERT)) = orig_expr;
  	}
      }
    for (j = 0; j < VARRAY_ACTIVE_SIZE (bexprs); j++)
       pre_part_1_trav (VARRAY_GENERIC_PTR (bexprs, j), pre_dfs);
-   /*  simplify_stmt (fn, NULL_TREE); */
    /* Debugging dump after SSA PRE */
    if (dump_file)
      {
--- 3291,3304 ----
  						htab_eq_pointer, NULL);
  		}
  	    }
! 	  process_left_occs_and_kills (bexprs, slot, ref, orig_expr);
! 	  
! 
  	  *(htab_find_slot  (seen, orig_expr, INSERT)) = orig_expr;
  	}
      }
    for (j = 0; j < VARRAY_ACTIVE_SIZE (bexprs); j++)
       pre_part_1_trav (VARRAY_GENERIC_PTR (bexprs, j), pre_dfs);
    /* Debugging dump after SSA PRE */
    if (dump_file)
      {
*************** tree_perform_ssapre ()
*** 2880,2884 ****
    sbitmap_vector_free (domchildren);
  
    splay_tree_delete (new_stmt_map);
!   
  }
--- 3322,3326 ----
    sbitmap_vector_free (domchildren);
  
    splay_tree_delete (new_stmt_map);
!   splay_tree_delete (old_new_map);  
  }
Index: tree-flow-inline.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-flow-inline.h,v
retrieving revision 1.1.2.10
diff -c -3 -p -r1.1.2.10 tree-flow-inline.h
*** tree-flow-inline.h	5 Nov 2002 23:50:38 -0000	1.1.2.10
--- tree-flow-inline.h	6 Nov 2002 16:02:52 -0000
*************** bb_for_stmt (t)
*** 200,205 ****
--- 200,230 ----
    return tree_annotation (t) ? tree_annotation (t)->bb : NULL;
  }
  
+ 
+ static inline void
+ set_bb_for_stmt (t, bb)
+      tree t;
+      basic_block bb;
+ {
+   tree_ann ann;
+ 
+   if (t == empty_stmt_node)
+     return;
+ 
+   do
+     {
+       ann = tree_annotation (t) ? tree_annotation (t) : create_tree_ann (t);
+       ann->bb = bb;
+       if (TREE_CODE (t) == COMPOUND_EXPR)
+ 	t = TREE_OPERAND (t, 0);
+       else if (TREE_CODE (t) == EXPR_WITH_FILE_LOCATION)
+ 	t = EXPR_WFL_NODE (t);
+       else
+ 	t = NULL;
+     }
+   while (t);
+ }
+ 
  static inline tree_ref
  currdef_for (decl)
       tree decl;
*************** exprref_reload (ref)
*** 488,498 ****
--- 513,577 ----
    return ref->ecommon.reload;
  }
  
+ static inline void 
+ set_exprref_processed (ref, flag)
+      tree_ref ref;
+      unsigned int flag;
+ {
+   ref->ecommon.processed = flag;
+ }
+ 
+ static inline bool
+ exprref_processed (ref)
+      tree_ref ref;
+ {
+   return ref->ecommon.processed;
+ }
+ 
+ static inline void 
+ set_exprref_processed2 (ref, flag)
+      tree_ref ref;
+      unsigned int flag;
+ {
+   ref->ecommon.processed2  = flag;
+ }
+ 
+ static inline bool
+ exprref_processed2 (ref)
+      tree_ref ref;
+ {
+   return ref->ecommon.processed2;
+ }
+ 
+ static inline ref_list
+ exprref_uses (ref)
+      tree_ref ref;
+ {
+   return ref->ecommon.uses;
+ }
+ static inline void
+ set_exprref_uses (ref, list)
+      tree_ref ref;
+      ref_list list;
+ {
+   ref->ecommon.uses = list;
+ }
+ 
  static inline void
  set_expruse_def (ref, def)
       tree_ref ref;
       tree_ref def;
  {
+   if (def)
+     {
+       if (!exprref_uses (def))
+ 	set_exprref_uses (def, create_ref_list ());
+       
+       if (expruse_def (ref))
+ 	remove_ref_from_list (exprref_uses (expruse_def (ref)), ref);
+             
+       add_ref_to_list_end (exprref_uses (def), ref);
+     }
    ref->euse.def = def;
  }
  
*************** expruse_phiop (ref)
*** 518,523 ****
--- 597,617 ----
    return ref->euse.op_occurrence;
  }
  
+ static inline void
+ set_expruse_phi (ref, phi)
+      tree_ref ref;
+      tree_ref phi;
+ {
+   ref->euse.phi = phi;
+ }
+ 
+ static inline tree_ref
+ expruse_phi (ref)
+      tree_ref ref;
+ {
+   return ref->euse.phi;
+ }
+ 
  static inline void 
  set_expruse_has_real_use (ref, flag)
       tree_ref ref;
*************** exprphi_phi_args (ref)
*** 548,553 ****
--- 642,671 ----
    return ref->ephi.phi_args;
  }
  
+ static inline unsigned int
+ num_ephi_args (phi)
+      tree_ref phi;
+ {
+   return VARRAY_ACTIVE_SIZE (phi->ephi.phi_args);
+ }
+ 
+ static inline phi_node_arg
+ ephi_arg (phi, i)
+      tree_ref phi;
+      unsigned int i;
+ {
+   return (phi_node_arg)(VARRAY_GENERIC_PTR (phi->ephi.phi_args, i));
+ }
+ 
+ static inline void
+ set_ephi_arg (phi, i, arg)
+      tree_ref phi;
+      unsigned int i;
+      phi_node_arg arg;
+ {
+   VARRAY_GENERIC_PTR (phi->ephi.phi_args, i) = (PTR)arg;
+ }
+ 
  static inline void
  set_exprphi_downsafe (ref, flag)
       tree_ref ref;
*************** exprphi_extraneous (ref)
*** 606,626 ****
       tree_ref ref;
  {
    return ref->ephi.extraneous;
- }
- 
- static inline void
- set_exprphi_processed (ref, map)
-      tree_ref ref;
-      bitmap map;
- {
-   ref->ephi.processed = map;
- }
- 
- static inline bitmap
- exprphi_processed (ref)
-      tree_ref ref;
- {
-   return ref->ephi.processed;
  }
  
  static inline bool
--- 724,729 ----
Index: tree-cfg.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-cfg.c,v
retrieving revision 1.1.4.25
diff -c -3 -p -r1.1.4.25 tree-cfg.c
*** tree-cfg.c	5 Nov 2002 23:50:38 -0000	1.1.4.25
--- tree-cfg.c	6 Nov 2002 16:02:52 -0000
*************** static void make_cond_expr_blocks	PARAMS
*** 54,60 ****
  static void make_loop_expr_blocks	PARAMS ((tree *, basic_block));
  static void make_switch_expr_blocks	PARAMS ((tree *, basic_block));
  static basic_block create_bb		PARAMS ((tree *, basic_block));
- static void set_bb_for_stmt		PARAMS ((tree, basic_block));
  static void remove_unreachable_blocks	PARAMS ((void));
  
  /* Edges.  */
--- 54,59 ----
*************** create_bb (head_p, parent_block)
*** 377,409 ****
  }
  
  
- /* Add statement T to basic block BB.  If T is a COMPOUND_EXPR or WFL
-    container, also process the nodes inside it.  */
- 
- static void
- set_bb_for_stmt (t, bb)
-      tree t;
-      basic_block bb;
- {
-   tree_ann ann;
- 
-   if (t == empty_stmt_node)
-     return;
- 
-   do
-     {
-       ann = tree_annotation (t) ? tree_annotation (t) : create_tree_ann (t);
-       ann->bb = bb;
-       if (TREE_CODE (t) == COMPOUND_EXPR)
- 	t = TREE_OPERAND (t, 0);
-       else if (TREE_CODE (t) == EXPR_WITH_FILE_LOCATION)
- 	t = EXPR_WFL_NODE (t);
-       else
- 	t = NULL;
-     }
-   while (t);
- }
- 
  
  /* Create annotations for all the blocks in the flowgraph.  */
  
--- 376,381 ----
*************** last_stmt (bb)
*** 1781,1784 ****
--- 1753,1768 ----
    STRIP_WFL (t);
    STRIP_NOPS (t);
    return t;
+ }
+ tree *
+ last_stmt_ptr (bb)
+      basic_block bb;
+ {
+   gimple_stmt_iterator i;
+   
+   if (bb == NULL || bb->index == INVALID_BLOCK)
+     return NULL;
+ 
+   i = gsi_start (bb->end_tree_p);
+   return gsi_stmt_ptr (i);
  }
Index: tree-flow.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-flow.h,v
retrieving revision 1.1.4.32
diff -c -3 -p -r1.1.4.32 tree-flow.h
*** tree-flow.h	5 Nov 2002 23:50:38 -0000	1.1.4.32
--- tree-flow.h	6 Nov 2002 16:02:52 -0000
*************** enum tree_ref_type {
*** 67,73 ****
       (see tree-ssa-pre.c)  */
    E_PHI,
    E_USE,
!   E_KILL
  };
  
  /* Tree reference modifier bitmasks.  Used when calling create_ref.  */
--- 67,75 ----
       (see tree-ssa-pre.c)  */
    E_PHI,
    E_USE,
!   E_KILL,
!   E_EXIT,
!   E_LEFT
  };
  
  /* Tree reference modifier bitmasks.  Used when calling create_ref.  */
*************** struct expr_ref_common GTY(())
*** 302,310 ****
  
    /* SSAPRE: True if expression was inserted as a PHI operand occurrence.  */
    unsigned int inserted:1;
!   
    /* SSAPRE: Redundancy class of expression.  */
    unsigned int class;
  };
  
  
--- 304,321 ----
  
    /* SSAPRE: True if expression was inserted as a PHI operand occurrence.  */
    unsigned int inserted:1;
! 
    /* SSAPRE: Redundancy class of expression.  */
    unsigned int class;
+   
+   /* SSAPRE: Processed flag 1. */
+   unsigned int processed:1;
+ 
+   /* SSAPRE: Processed flag 2. */
+   unsigned int processed2:1;
+   
+   /* SSAPRE: List of uses for this ref. */
+   ref_list uses;
  };
  
  
*************** struct expr_phi_d GTY(())
*** 313,321 ****
  {
    struct expr_ref_common common;
    
!   /* Expression PHI operands.  This is an array of size
!      last_basic_block, with operands ordered by pre-order index of the
!      BB it's from.  */
    varray_type phi_args;
  
    /* SSAPRE: True if PHI is downsafe.  */
--- 324,330 ----
  {
    struct expr_ref_common common;
    
!   /* Expression PHI operands.*/
    varray_type phi_args;
  
    /* SSAPRE: True if PHI is downsafe.  */
*************** struct expr_phi_d GTY(())
*** 330,338 ****
    /* SSAPRE: True if PHI is expression.  */
    unsigned int extraneous:1;
  
-   /* SSAPRE: Bitmap to track which operands we've processed during
-      various algorithms.  */
-   bitmap processed;
  };
  
  
--- 339,344 ----
*************** struct expr_use_d GTY(())
*** 344,354 ****
    /* Definition chain.  */
    union tree_ref_d *def;
    
!   /* True if this use is a phi operand occurrence. */
!   int op_occurrence;
  
    /* SSAPRE: True if this is an operand, and it has a real use. */
!   int has_real_use;
  };
  
  enum tree_ref_structure_enum {
--- 350,363 ----
    /* Definition chain.  */
    union tree_ref_d *def;
    
!   /* SSAPRE: True if this use is a phi operand occurrence. */
!   unsigned int op_occurrence:1;
  
    /* SSAPRE: True if this is an operand, and it has a real use. */
!   unsigned int has_real_use:1;  
! 
!   /* For phi-operands, which phi it belongs to. */
!   union tree_ref_d *phi;
  };
  
  enum tree_ref_structure_enum {
*************** static inline void set_exprref_save PARA
*** 441,446 ****
--- 450,461 ----
  static inline bool exprref_save PARAMS ((tree_ref));
  static inline void set_exprref_reload PARAMS ((tree_ref, unsigned int));
  static inline bool exprref_reload PARAMS ((tree_ref));
+ static inline void set_exprref_processed PARAMS ((tree_ref, unsigned int));
+ static inline bool exprref_processed PARAMS ((tree_ref));
+ static inline void set_exprref_processed2 PARAMS ((tree_ref, unsigned int));
+ static inline bool exprref_processed2 PARAMS ((tree_ref));
+ static inline ref_list exprref_uses PARAMS ((tree_ref));
+ static inline void set_exprref_uses PARAMS ((tree_ref, ref_list));
  
  /* For expruse. */
  static inline void set_expruse_def PARAMS ((tree_ref, tree_ref));
*************** static inline void set_expruse_phiop PAR
*** 449,455 ****
  static inline bool expruse_phiop PARAMS ((tree_ref));
  static inline void set_expruse_has_real_use PARAMS ((tree_ref, unsigned int));
  static inline bool expruse_has_real_use PARAMS ((tree_ref));
! 
  /* For exprphi. */
  static inline void set_exprphi_phi_args PARAMS ((tree_ref, varray_type));
  static inline varray_type exprphi_phi_args PARAMS ((tree_ref));
--- 464,471 ----
  static inline bool expruse_phiop PARAMS ((tree_ref));
  static inline void set_expruse_has_real_use PARAMS ((tree_ref, unsigned int));
  static inline bool expruse_has_real_use PARAMS ((tree_ref));
! static inline void set_expruse_phi PARAMS ((tree_ref, tree_ref));
! static inline tree_ref expruse_phi PARAMS ((tree_ref));
  /* For exprphi. */
  static inline void set_exprphi_phi_args PARAMS ((tree_ref, varray_type));
  static inline varray_type exprphi_phi_args PARAMS ((tree_ref));
*************** static inline void set_exprphi_later PAR
*** 461,469 ****
  static inline bool exprphi_later PARAMS ((tree_ref));
  static inline void set_exprphi_extraneous PARAMS ((tree_ref, unsigned int));
  static inline bool exprphi_extraneous PARAMS ((tree_ref));
- static inline void set_exprphi_processed PARAMS ((tree_ref, bitmap));
- static inline bitmap exprphi_processed PARAMS ((tree_ref));
  static inline bool exprphi_willbeavail PARAMS ((tree_ref));
  
  
  /*---------------------------------------------------------------------------
--- 477,487 ----
  static inline bool exprphi_later PARAMS ((tree_ref));
  static inline void set_exprphi_extraneous PARAMS ((tree_ref, unsigned int));
  static inline bool exprphi_extraneous PARAMS ((tree_ref));
  static inline bool exprphi_willbeavail PARAMS ((tree_ref));
+ static inline phi_node_arg ephi_arg PARAMS ((tree_ref, unsigned));
+ extern void add_ephi_arg  PARAMS ((tree_ref, tree_ref, edge));
+ static inline void set_ephi_arg  PARAMS ((tree_ref, unsigned, phi_node_arg));
+ static inline unsigned int num_ephi_args PARAMS ((tree_ref));
  
  
  /*---------------------------------------------------------------------------
*************** enum tree_flags
*** 518,523 ****
--- 536,542 ----
  
  static inline tree_ann tree_annotation	PARAMS ((tree));
  static inline basic_block bb_for_stmt	PARAMS ((tree));
+ static inline void set_bb_for_stmt      PARAMS ((tree, basic_block));
  static inline tree_ref currdef_for	PARAMS ((tree));
  static inline void set_currdef_for	PARAMS ((tree, tree_ref));
  static inline ref_list tree_refs	PARAMS ((tree));
*************** extern void insert_bb_before		PARAMS ((b
*** 657,662 ****
--- 676,682 ----
  extern void cleanup_tree_cfg		PARAMS ((void));
  extern tree first_stmt			PARAMS ((basic_block));
  extern tree last_stmt			PARAMS ((basic_block));
+ extern tree *last_stmt_ptr			PARAMS ((basic_block));
  extern basic_block latch_block		PARAMS ((basic_block));
  extern bool is_latch_block		PARAMS ((basic_block));
  

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

end of thread, other threads:[~2002-11-06 16:41 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-11-06  8:25 [tree-ssa]: SSAPRE Update Daniel Berlin
2002-11-06  8:41 ` Diego Novillo
2002-11-06  8:25 Daniel Berlin

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).