This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


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

[ast-optimizer-branch]: SSA-CCP on tree-ssa


Rewrites ssa-ccp so it doesn't depend on an intermediate
representation, by abstracting what it really wants to do into
function pointers.
I then implemented the functions for tree-ssa.
It doesn't remove the dead code, and has to conservatively assume phi
nodes parms to be active when they might not be (because we don't know
which to select for which incoming edge right now, so unless the phi
node is defined in one of the predecessors, and we know *that* edge
isn't executable, we can't say it's not executable).
However, it propagates constants (anything really_constant_p says is constant).
The evaluation routine doesn't try to see if array indices are
variables/expressions with a constant value. Other than that, all
should be good.

It'll transform:


int main(void)
{
  int a;
  int b=3;
  int c=1;
  int q[3] = {0, 1, 2};
  if ((b-c) * q[0])
    {
      b = 7;
    }
  else if ((b-c) *q[1])
    {
      a = 9 * b * q[2];
    }
  c = a;
  a = a * 3;
  printf("a:%d b:%d c:%d\n", a, b, c);
}

into:

int main (void)
{
        int a;
        int b = 3;
        int c = 1;
        int q[3] = {0, 1, 2};
        if (0)
        {
                b = 7;
        }
        else if (1)
        {
                a = 54;
        }
        c = 54;
        a = 162;
        printf ("a:%d b:%d, c:%d\n", 162, 3, 54);
}



diego, i'm not sure which way to merge the tree-optimize.c and
c-decl.c changes, i couldn't remember which way was the newer way, and
which was the older.
The confusion is because I had started on the ast branch, then when
you submitted the patch for the trunk, moved to the trunk + that
patch, then moved back to the ast optimizer branch after it was
decided to keep it on the branch for longer.

The changelog for this patch is a bit large, since i documented every
single rename.
Basically the entire file changes, so i'm not sure whether to document
each small change entailed in this, or document it as one big change.

Index: ssa-ccp.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/ssa-ccp.c,v
retrieving revision 1.4
diff -c -3 -p -w -B -b -r1.4 ssa-ccp.c
*** ssa-ccp.c	2001/07/16 16:23:40	1.4
--- ssa-ccp.c	2001/10/19 20:16:16
***************
*** 1,8 ****
  /* Conditional constant propagation pass for the GNU compiler.
     Copyright (C) 2000,2001 Free Software Foundation, Inc.
!    Original framework by Daniel Berlin <dan@cgsoftware.com>
!    Fleshed out and major cleanups by Jeff Law <law@redhat.com>
!    
  This file is part of GNU CC.
     
  GNU CC is free software; you can redistribute it and/or modify it
--- 1,8 ----
  /* Conditional constant propagation pass for the GNU compiler.
     Copyright (C) 2000,2001 Free Software Foundation, Inc.
!    Original framework, tree SSA support, abstraction for multiple IL's.
!    by Daniel Berlin <dan@cgsoftware.com>
!    RTX portions fleshed out and major cleanups by Jeff Law <law@redhat.com>
  This file is part of GNU CC.
     
  GNU CC is free software; you can redistribute it and/or modify it
*************** Software Foundation, 59 Temple Place - S
*** 58,79 ****
  
      4. Fold expressions after performing constant substitutions.  */
  
- 
  #include "config.h"
  #include "system.h"
! 
  #include "rtl.h"
  #include "hard-reg-set.h"
  #include "basic-block.h"
  #include "ssa.h"
  #include "insn-config.h"
  #include "recog.h"
  #include "output.h"
  #include "errors.h"
  #include "ggc.h"
  #include "df.h"
  #include "function.h"
  
  /* Possible lattice values.  */
  
  typedef enum
--- 57,82 ----
  
      4. Fold expressions after performing constant substitutions.  */
  
  #include "config.h"
  #include "system.h"
! #include "tree.h"
  #include "rtl.h"
  #include "hard-reg-set.h"
  #include "basic-block.h"
+ #include "tree-flow.h"
  #include "ssa.h"
  #include "insn-config.h"
  #include "recog.h"
  #include "output.h"
  #include "errors.h"
  #include "ggc.h"
+ #include "expr.h"
+ #include "c-common.h"
  #include "df.h"
  #include "function.h"
  
+ static FILE *cfg_dump_file;
+ static int cfg_dump_flags;
  /* Possible lattice values.  */
  
  typedef enum
*************** typedef enum
*** 81,87 ****
    UNDEFINED,
    CONSTANT,
    VARYING
! } latticevalue;
  
  /* Main structure for CCP. 
  
--- 84,96 ----
    UNDEFINED,
    CONSTANT,
    VARYING
! }
! latticevalue;
! const char *latticename[] = {
!   "UNDEFINED",
!   "CONSTANT",
!   "VARYING"
! };
  
  /* Main structure for CCP. 
  
*************** typedef enum
*** 90,99 ****
  typedef struct
  {
    latticevalue lattice_val;
!   rtx const_value;
! } value;
  
! /* Array of values indexed by register number.  */
  static value *values;
  
  /* A bitmap to keep track of executable blocks in the CFG.  */
--- 99,109 ----
  typedef struct
  {
    latticevalue lattice_val;
!   void *const_value;
! }
! value;
  
! /* Array of values indexed by id number.  */
  static value *values;
  
  /* A bitmap to keep track of executable blocks in the CFG.  */
*************** static edge *edge_info;
*** 107,163 ****
  
  /* We need an edge list to be able to get indexes easily.  */
  static struct edge_list *edges;
- 
- /* For building/following use-def and def-use chains.  */
- static struct df *df_analyzer;
  
  /* Current edge we are operating on, from the worklist */
  static edge flow_edges;
  
  /* Bitmap of SSA edges which will need reexamination as their definition
     has changed.  */
  static sbitmap ssa_edges;
  
  /* Simple macros to simplify code */
- #define SSA_NAME(x) REGNO (SET_DEST (x))
- #define PHI_PARMS(x) XVEC (SET_SRC (x), 0)
  #define EIE(x,y) EDGE_INDEX (edges, x, y)
  
! static void visit_phi_node             PARAMS ((rtx, basic_block));
! static void visit_expression           PARAMS ((rtx, basic_block));
! static void defs_to_undefined          PARAMS ((rtx));
! static void defs_to_varying            PARAMS ((rtx));
! static void examine_flow_edges         PARAMS ((void));
  static int mark_references             PARAMS ((rtx *, void *));
- static void follow_def_use_chains      PARAMS ((void));
  static void optimize_unexecutable_edges PARAMS ((struct edge_list *, sbitmap));
- static void ssa_ccp_substitute_constants PARAMS ((void));
  static void ssa_ccp_df_delete_unreachable_insns PARAMS ((void));
  static void ssa_fast_dce PARAMS ((struct df *));
  
  /* Loop through the PHI_NODE's parameters for BLOCK and compare their
     lattice values to determine PHI_NODE's lattice value.  */
  static void
  visit_phi_node (phi_node, block)
!      rtx phi_node;
       basic_block block;
  {
    unsigned int i;
!   rtx phi_node_expr = NULL;
!   unsigned int phi_node_name = SSA_NAME (PATTERN (phi_node));
    latticevalue phi_node_lattice_val = UNDEFINED;
!   rtx pat = PATTERN (phi_node);
!   rtvec phi_vec = XVEC (SET_SRC (pat), 0);
!   unsigned int num_elem = GET_NUM_ELEM (phi_vec);
! 
!   for (i = 0; i < num_elem; i += 2)
!     {
!       if (TEST_BIT (executable_edges,
! 		    EIE (BASIC_BLOCK (INTVAL (RTVEC_ELT (phi_vec, i + 1))),
! 			 block)))
  	{
! 	  unsigned int current_parm
! 	    = REGNO (RTVEC_ELT (phi_vec, i));
  
  	  latticevalue current_parm_lattice_val
  	    = values[current_parm].lattice_val;
--- 117,351 ----
  
  /* We need an edge list to be able to get indexes easily.  */
  static struct edge_list *edges;
  
+ struct ccp_info
+ {
+   int (*get_num_phi_args) (void *);
+   int (*get_phi_arg_name) (void *, int);
+   basic_block (*get_phi_arg_bb) (void *, int);
+   void (*defs_to_value) (void *, latticevalue);
+   void (*visit_expression) (void *, basic_block);
+   unsigned int (*ssa_name) (void *);
+   unsigned int (*num_ssa_vars) (void);
+   void (*simulate_phi_nodes) (basic_block);
+   void (*simulate_block) (basic_block);
+   void (*follow_def_use_chains) (void);
+   void (*subst_consts) (void);
+   void (*init) (void);
+   void (*cleanup) (void);
+   /* Dataflow analyzer, if necessary */
+   struct df *analyzer;
+   bool use_analyzer;
+   bool do_dce;
+   bool opt_unexec_edges;
+   bool need_alias;
+ };
+ static struct ccp_info ccp_info;
  /* Current edge we are operating on, from the worklist */
  static edge flow_edges;
  
  /* Bitmap of SSA edges which will need reexamination as their definition
     has changed.  */
  static sbitmap ssa_edges;
+ /* RTX versions of the needed functions */
+ static unsigned int ssa_name_rtx PARAMS ((void *));
+ static int get_num_phi_args_rtx PARAMS ((void *));
+ static int get_phi_arg_name_rtx PARAMS ((void *, int));
+ static basic_block get_phi_arg_bb_rtx PARAMS ((void *, int));
+ static void defs_to_value_rtx PARAMS ((void *, latticevalue));
+ static void simulate_phi_nodes_rtx PARAMS ((basic_block));
+ static void simulate_block_rtx PARAMS ((basic_block));
+ static unsigned int num_ssa_vars_rtx PARAMS ((void));
+ static void visit_expression_rtx PARAMS ((void *, basic_block));
+ static void follow_def_use_chains_rtx PARAMS ((void));
+ static void subst_consts_rtx PARAMS ((void));
+ static void init_rtx PARAMS ((void));
+ static void cleanup_rtx PARAMS ((void));
+ 
+ /* Tree versions of the needed functions */
+ static unsigned int ssa_name_tree PARAMS ((void *));
+ static int get_num_phi_args_tree PARAMS ((void *));
+ static int get_phi_arg_name_tree PARAMS ((void *, int));
+ static basic_block get_phi_arg_bb_tree PARAMS ((void *, int));
+ static void defs_to_value_tree PARAMS ((void *, latticevalue));
+ static void simulate_phi_nodes_tree PARAMS ((basic_block));
+ static void simulate_block_tree PARAMS ((basic_block));
+ static int tree_constant_p PARAMS ((tree, tree));
+ static unsigned int num_ssa_vars_tree PARAMS ((void));
+ static varref find_matching_ref PARAMS ((tree, tree, enum varref_type));
+ static tree list_elt PARAMS ((tree, unsigned HOST_WIDE_INT));
+ static tree eval_subst PARAMS ((tree, tree, tree, tree, tree));
+ static void visit_expression_tree PARAMS ((void *, basic_block));
+ static void follow_def_use_chains_tree PARAMS ((void));
+ static void subst_consts_tree PARAMS ((void));
+ static void init_tree PARAMS ((void));
+ static void cleanup_tree PARAMS ((void));
+ 
+ static unsigned int
+ ssa_name_tree (refp)
+      void *refp;
+ {
+   varref ref = (varref) refp;
+   if (VARREF_TYPE (ref) == VARUSE)
+     return VARREF_ID (VARUSE_CHAIN (ref));
+   return VARREF_ID (ref);
+ }
+ static unsigned int
+ ssa_name_rtx (insnp)
+      void *insnp;
+ {
+   rtx insn = (rtx) insnp;
+   if (GET_CODE (insn) == REG)
+     return REGNO (insn);
+   else if (GET_CODE (insn) == SET)
+     return REGNO (SET_DEST (insn));
+   else if (GET_CODE (insn) == INSN)
+     return REGNO (SET_DEST (PATTERN (insn)));
+   else
+     abort ();
+ }
  
  /* Simple macros to simplify code */
  #define EIE(x,y) EDGE_INDEX (edges, x, y)
  
! static void visit_phi_node PARAMS ((void *, basic_block));
! static void visit_expression PARAMS ((void *, basic_block));
  static int mark_references PARAMS ((rtx *, void *));
  static void optimize_unexecutable_edges PARAMS ((struct edge_list *, sbitmap));
  static void ssa_ccp_df_delete_unreachable_insns PARAMS ((void));
  static void ssa_fast_dce PARAMS ((struct df *));
+ static inline unsigned int ssa_name PARAMS ((void *));
+ static inline void defs_to_value PARAMS ((void *, latticevalue));
+ static inline int get_num_phi_args PARAMS ((void *));
+ static inline int get_phi_arg_name PARAMS ((void *, int));
+ static inline basic_block get_phi_arg_bb PARAMS ((void *, int));
+ static inline int
+ get_phi_arg_name (phi, num)
+ 	void *phi;
+ 	int num;
+ {
+   return (*ccp_info.get_phi_arg_name)(phi, num);
+ }
+ static inline int
+ get_num_phi_args (phi)
+ 	void *phi;
+ {
+   return (*ccp_info.get_num_phi_args)(phi);
+ }
+ static inline basic_block
+ get_phi_arg_bb (phi, num)
+ 	void *phi;
+ 	int num;
+ {
+   return (*ccp_info.get_phi_arg_bb)(phi, num);
+ }
+ static inline unsigned int
+ ssa_name (refp)
+      void *refp;
+ {
+   return (*ccp_info.ssa_name) (refp);
+ }
+ static inline void
+ defs_to_value (def, val)
+      void *def;
+      latticevalue val;
+ {
+   (*ccp_info.defs_to_value) (def, val);
+ }
+ 
+ 
+ static unsigned int
+ num_ssa_vars_tree ()
+ {
+   return max_ref_id;
+ }
+ static unsigned int
+ num_ssa_vars_rtx ()
+ {
+   return VARRAY_SIZE (ssa_definition);
+ }
+ static int
+ get_num_phi_args_tree (refp)
+      void *refp;
+ {
+   varref ref = (varref) refp;
+   return VARRAY_ACTIVE_SIZE (VARDEF_PHI_CHAIN (ref));
+ }
+ static int
+ get_num_phi_args_rtx (insnp)
+      void *insnp;
+ {
+   rtx insn = (rtx) insnp;
+   return GET_NUM_ELEM (XVEC (SET_SRC (PATTERN (insn)), 0)) / 2;
+ }
+ static int
+ get_phi_arg_name_tree (refp, num)
+      void *refp;
+      int num;
+ {
+   varref ref = (varref) refp;
+   return ssa_name ((varref) VARRAY_GENERIC_PTR (VARDEF_PHI_CHAIN (ref), num));
+ }
+ static int
+ get_phi_arg_name_rtx (insnp, num)
+      void *insnp;
+      int num;
+ {
+   rtx insn = (rtx) insnp;
+   return REGNO (RTVEC_ELT (XVEC (SET_SRC (PATTERN (insn)), 0), num * 2));
+ }
+ 
+ static basic_block
+ get_phi_arg_bb_tree (refp, num)
+      void *refp;
+      int num;
+ {
+   varref ref = (varref) refp;
+   basic_block bb;
+   bb = VARREF_BB ((varref) VARRAY_GENERIC_PTR (VARDEF_PHI_CHAIN (ref), num));
+   return bb;
+ }
+ 
+ static basic_block
+ get_phi_arg_bb_rtx (insnp, num)
+      void *insnp;
+      int num;
+ {
+   rtx insn = (rtx) insnp;
+   return
+     BASIC_BLOCK (INTVAL
+ 		 (RTVEC_ELT
+ 		  (XVEC (SET_SRC (PATTERN (insn)), 0), num * 2 + 1)));
+ }
  
  /* Loop through the PHI_NODE's parameters for BLOCK and compare their
     lattice values to determine PHI_NODE's lattice value.  */
  static void
  visit_phi_node (phi_node, block)
!      void *phi_node;
       basic_block block;
  {
    unsigned int i;
!   void *phi_node_expr = NULL;
!   unsigned int phi_node_name = ssa_name (phi_node);
    latticevalue phi_node_lattice_val = UNDEFINED;
!   unsigned int num_elem = get_num_phi_args (phi_node);
!   if (cfg_dump_file)
      {
!       fprintf (cfg_dump_file, "Executing phi node:");
!       dump_varref (cfg_dump_file, "", phi_node, 0, 0);
!       fprintf (cfg_dump_file, " current lattice val:%s\n",
! 	       latticename[values[phi_node_name].lattice_val]);
!     }
!   for (i = 0; i < num_elem; i++)
!     {
! 
!       if (EDGE_INDEX (edges, get_phi_arg_bb (phi_node, i), block)
! 	  == EDGE_INDEX_NO_EDGE
! 	  || TEST_BIT (executable_edges,
! 		       EIE (get_phi_arg_bb (phi_node, i), block)))
! 	{
! 	  int current_parm = get_phi_arg_name (phi_node, i);
  
  	  latticevalue current_parm_lattice_val
  	    = values[current_parm].lattice_val;
*************** visit_phi_node (phi_node, block)
*** 182,188 ****
  	      break;
  	    }
  
! 	  /* If the current value of PHI_NODE is UNDEFINED and one
  	     node in PHI_NODE is CONSTANT, then the new value of the
  	     PHI is that CONSTANT.  Note this can turn into VARYING
  	     if we find another distinct constant later.  */ 
--- 370,376 ----
  	      break;
  	    }
  
! 	  /* If the current value of PHI_NODE is undefined and one
  	     node in PHI_NODE is CONSTANT, then the new value of the
  	     PHI is that CONSTANT.  Note this can turn into VARYING
  	     if we find another distinct constant later.  */
*************** visit_phi_node (phi_node, block)
*** 195,258 ****
  	      continue;
  	    }
  	}
      }
  
    /* If the value of PHI_NODE changed, then we will need to
       re-execute uses of the output of PHI_NODE.  */
!   if (phi_node_lattice_val != values[phi_node_name].lattice_val)
      {
        values[phi_node_name].lattice_val = phi_node_lattice_val;
        values[phi_node_name].const_value = phi_node_expr;
        SET_BIT (ssa_edges, phi_node_name);
      }
  }
  
- /* Sets all defs in an insn to UNDEFINED.  */
  static void
! defs_to_undefined (insn)
!      rtx insn;
  {
    struct df_link *currdef;
!   for (currdef = DF_INSN_DEFS (df_analyzer, insn); currdef;
         currdef = currdef->next)
      {
!       if (values[DF_REF_REGNO (currdef->ref)].lattice_val != UNDEFINED)
  	SET_BIT (ssa_edges, DF_REF_REGNO (currdef->ref));
!       values[DF_REF_REGNO (currdef->ref)].lattice_val = UNDEFINED;
      }
  }
  
! /* Sets all defs in an insn to VARYING.  */
! static void
! defs_to_varying (insn)
!      rtx insn;
  {
!   struct df_link *currdef;
!   for (currdef = DF_INSN_DEFS (df_analyzer, insn); currdef;
!        currdef = currdef->next)
      {
!       if (values[DF_REF_REGNO (currdef->ref)].lattice_val != VARYING)
! 	SET_BIT (ssa_edges, DF_REF_REGNO (currdef->ref));
!       values[DF_REF_REGNO (currdef->ref)].lattice_val = VARYING;
      }
  }
  
  /* Go through the expression, call the approriate evaluation routines
     to attempt cprop */
  static void
! visit_expression (insn, block)
!      rtx insn;
       basic_block block;
  {
!   rtx src, dest, set;
  
!   set = single_set (insn);
    if (! set)
      {
!       defs_to_varying (insn);
        return;
      }
- 
    src = SET_SRC (set);
    dest = SET_DEST (set);
  
--- 383,903 ----
  	      continue;
  	    }
  	}
+       else
+ 	{
+ 	  if (cfg_dump_file)
+ 	    {
+ 	      fprintf (cfg_dump_file, "Phi arg %d not executed, \n", i);
+ 	    }
+ 	}
      }
  
    /* If the value of PHI_NODE changed, then we will need to
       re-execute uses of the output of PHI_NODE.  */
!   if (phi_node_lattice_val != values[phi_node_name].lattice_val
!       || phi_node_expr != values[phi_node_name].const_value)
      {
        values[phi_node_name].lattice_val = phi_node_lattice_val;
        values[phi_node_name].const_value = phi_node_expr;
        SET_BIT (ssa_edges, phi_node_name);
+       if (cfg_dump_file)
+ 	fprintf (cfg_dump_file, "new lattice val:%s\n",
+ 		 latticename[values[ssa_name (phi_node)].lattice_val]);
+     }
  }
+ static varref
+ find_matching_ref (expr, tomatch, type)
+      tree expr;
+      tree tomatch;
+      enum varref_type type;
+ {
+   varray_type refs = TREE_REFS (tomatch);
+   unsigned int i;
+   for (i = 0; i < VARRAY_ACTIVE_SIZE (refs); i++)
+     {
+       varref currref = (varref) VARRAY_GENERIC_PTR (refs, i);
+       if (VARREF_TYPE (currref) == type && VARREF_EXPR (currref) == expr)
+ 	return currref;
      }
+   abort ();
+ }
  
  static void
! defs_to_value_tree (refp, val)
!      void *refp;
!      latticevalue val;
  {
+   varref ref = (varref) refp;
+   if (VARREF_TYPE (ref) == VARUSE)
+     return;
+   if (values[ssa_name (ref)].lattice_val != val)
+     SET_BIT (ssa_edges, ssa_name (ref));
+   values[ssa_name (ref)].lattice_val = val;
+ }
+ 
+ static void
+ defs_to_value_rtx (insnp, val)
+      void *insnp;
+      latticevalue val;
+ {
+   rtx insn = (rtx) insnp;
    struct df_link *currdef;
!   for (currdef = DF_INSN_DEFS (ccp_info.analyzer, insn); currdef;
         currdef = currdef->next)
      {
!       if (values[DF_REF_REGNO (currdef->ref)].lattice_val != val)
  	SET_BIT (ssa_edges, DF_REF_REGNO (currdef->ref));
!       values[DF_REF_REGNO (currdef->ref)].lattice_val = val;
      }
  }
+ static tree
+ list_elt (list, elt)
+      tree list;
+      unsigned HOST_WIDE_INT elt;
+ {
+   while (elt)
+     {
+       elt--;
+       list = TREE_CHAIN (list);
+     }
+   return TREE_VALUE (list);
+ }
  
! /* ARG is a tree that is known to contain just arithmetic operations and
!    comparisons.  Evaluate the operations in the tree substituting constants
!    for var_decls, when possible. */
! 
! static tree
! eval_subst (arg, old0, new0, old1, new1)
!      tree arg;
!      tree old0, new0, old1, new1;
  {
!   tree type = TREE_TYPE (arg);
!   enum tree_code code = TREE_CODE (arg);
!   char class = TREE_CODE_CLASS (code);
! 
!   /* We can handle some of the 'e' cases here.  */
!   if (class == 'e' && code == TRUTH_NOT_EXPR)
!     class = '1';
!   else if (class == 'e'
! 	   && (code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR))
!     class = '2';
! 
!   switch (class)
      {
!     case '1':
!       if (TREE_CODE (TREE_OPERAND (arg, 0)) == VAR_DECL)
! 	{
! 	  varref ref = find_matching_ref (arg, TREE_OPERAND (arg, 0), VARUSE);
! 	  if (values[ssa_name (ref)].lattice_val == CONSTANT)
! 	    {
! 	      return fold (build1 (code, type,
! 				   eval_subst (values[ssa_name (ref)].
! 					       const_value, old0, new0, old1,
! 					       new1)));
! 	    }
  	}
+       else
+ 	return fold (build1 (code, type,
+ 			     eval_subst (TREE_OPERAND (arg, 0),
+ 					 old0, new0, old1, new1)));
+ 
+     case '2':
+       {
+ 	tree arg0 = TREE_OPERAND (arg, 0);
+ 	tree arg1 = TREE_OPERAND (arg, 1);
+ 	if (TREE_CODE (arg0) == VAR_DECL)
+ 	  {
+ 	    varref ref = find_matching_ref (arg, arg0, VARUSE);
+ 	    if (values[ssa_name (ref)].lattice_val == CONSTANT)
+ 	      arg0 = values[ssa_name (ref)].const_value;
+ 	  }
+ 	if (TREE_CODE (arg1) == VAR_DECL)
+ 	  {
+ 	    varref ref = find_matching_ref (arg, arg1, VARUSE);
+ 	    if (values[ssa_name (ref)].lattice_val == CONSTANT)
+ 	      arg1 = values[ssa_name (ref)].const_value;
+ 	  }
+ 	return fold (build (code, type,
+ 			    eval_subst (arg0,
+ 					old0, new0, old1, new1),
+ 			    eval_subst (arg1, old0, new0, old1, new1)));
+       }
+     case 'r':
+       switch (code)
+ 	{
+ 	case ARRAY_REF:
+ 	  if (tree_constant_p (TREE_OPERAND (arg, 0), arg)
+ 	      && TREE_CODE (TREE_OPERAND (arg, 1)) == INTEGER_CST)
+ 	    {
+ 	      varref matched_ref = find_matching_ref (arg,
+ 						      TREE_OPERAND (arg, 0),
+ 						      VARUSE);
+ 	      unsigned int refname = ssa_name (matched_ref);
+ 	      if (TREE_CODE ((tree) values[refname].const_value) ==
+ 		  CONSTRUCTOR)
+ 		return
+ 		  list_elt (CONSTRUCTOR_ELTS (values[refname].const_value),
+ 			    TREE_INT_CST_LOW (TREE_OPERAND (arg, 1)));
+ 	    }
+ 	default:
+ 	  break;
+ 	}
+ 
+     case 'e':
+       switch (code)
+ 	{
+ 	case SAVE_EXPR:
+ 	  return eval_subst (TREE_OPERAND (arg, 0), old0, new0, old1, new1);
+ 
+ 	case COMPOUND_EXPR:
+ 	  return eval_subst (TREE_OPERAND (arg, 1), old0, new0, old1, new1);
+ 
+ 	case COND_EXPR:
+ 	  return fold (build (code, type,
+ 			      eval_subst (TREE_OPERAND (arg, 0),
+ 					  old0, new0, old1, new1),
+ 			      eval_subst (TREE_OPERAND (arg, 1),
+ 					  old0, new0, old1, new1),
+ 			      eval_subst (TREE_OPERAND (arg, 2),
+ 					  old0, new0, old1, new1)));
+ 	default:
+ 	  break;
+ 	}
+       /* fall through - ??? */
+ 
+     case '<':
+       {
+ 	tree arg0 = TREE_OPERAND (arg, 0);
+ 	tree arg1 = TREE_OPERAND (arg, 1);
+ 
+ 	/* We need to check both for exact equality and tree equality.  The
+ 	   former will be true if the operand has a side-effect.  In that
+ 	   case, we know the operand occurred exactly once.  */
+ 
+ 	if (arg0 == old0 || operand_equal_p (arg0, old0, 0))
+ 	  arg0 = new0;
+ 	else if (arg0 == old1 || operand_equal_p (arg0, old1, 0))
+ 	  arg0 = new1;
+ 
+ 	if (arg1 == old0 || operand_equal_p (arg1, old0, 0))
+ 	  arg1 = new0;
+ 	else if (arg1 == old1 || operand_equal_p (arg1, old1, 0))
+ 	  arg1 = new1;
+ 
+ 	return fold (build (code, type, arg0, arg1));
+       }
+ 
+     default:
+       if (arg == old0)
+ 	return new0;
+       if (arg == old1)
+ 	return new1;
+       return arg;
+     }
+ }
+ 
+ static int
+ tree_constant_p (exp, src)
+      tree exp;
+      tree src;
+ {
+   return values[ssa_name (find_matching_ref (src, exp, VARUSE))].
+     lattice_val == CONSTANT;
  }
  
  /* Go through the expression, call the approriate evaluation routines
     to attempt cprop */
  static void
! visit_expression_tree (insnp, block)
!      void *insnp;
       basic_block block;
+ {
+   varray_type treerefs = TREE_REFS (VARREF_STMT ((varref) insnp));
+   varref insn;
+   unsigned int currrefnum;
+   for (currrefnum = 0; currrefnum < VARRAY_ACTIVE_SIZE (treerefs);
+        currrefnum++)
+     {
+       insn = (varref) VARRAY_GENERIC_PTR (treerefs, currrefnum);
+       if (VARREF_TYPE (insn) != VARPHI)
+ 	{
+ 	  tree src, dest, set;
+ 	  set = VARREF_EXPR (insn);
+ 	  if (cfg_dump_file)
+ 	    {
+ 	      fprintf (cfg_dump_file, "Executing expression %d:",
+ 		       VARREF_ID (insn));
+ 	      dump_varref (cfg_dump_file, "", insn, 0, 0);
+ 	      fprintf (cfg_dump_file, " current lattice val:%s",
+ 		       latticename[values[ssa_name (insn)].lattice_val]);
+ 	      if (values[ssa_name (insn)].lattice_val == CONSTANT)
+ 		{
+ 		  fprintf (cfg_dump_file, " current constant value:");
+ 		  print_node_brief (cfg_dump_file, "",
+ 				    values[ssa_name (insn)].const_value, 0);
+ 		  fprintf (cfg_dump_file, "\n");
+ 		}
+ 	      else
+ 		fprintf (cfg_dump_file, "\n");
+ 	    }
+ 	  if (!is_ctrl_stmt (VARREF_STMT (insn)))
+ 	    {
+ 	      switch (TREE_CODE (set))
+ 		{
+ 		case DECL_STMT:
+ 		  if (DECL_INITIAL (DECL_STMT_DECL (set)))
+ 		    {
+ 		      src = DECL_INITIAL (DECL_STMT_DECL (set));
+ 		      dest = DECL_STMT_DECL (set);
+ 		    }
+ 		  else
+ 		    {
+ 		      defs_to_value (insn, UNDEFINED);
+ 		      continue;
+ 		    }
+ 		  break;
+ 		case MODIFY_EXPR:
+ 		case INIT_EXPR:
+ 		  src = TREE_OPERAND (set, 1);
+ 		  dest = TREE_OPERAND (set, 0);
+ 		  break;
+ 		default:
+ 		  defs_to_value (insn, VARYING);
+ 		  continue;
+ 		}
+ 	    }
+ 	  else
+ 	    {
+ 	      set = VARREF_STMT (insn);
+ 	      src = set;
+ 	      dest = set;
+ 	    }
+ 	  STRIP_NOPS (src);
+ 	  STRIP_NOPS (dest);
+ 	  /* If this is assigning DEST to a constant, record that fact.  */
+ 	  if (TREE_CODE (dest) == VAR_DECL && really_constant_p (src))
+ 	    {
+ 	      unsigned int resultreg =
+ 		ssa_name (find_matching_ref (set, dest, VARDEF));
+ 
+ 	      values[resultreg].lattice_val = CONSTANT;
+ 	      values[resultreg].const_value = src;
+ 	      SET_BIT (ssa_edges, resultreg);
+ 	    }
+ 	  /* If this is a copy operation, then we can copy the lattice values.  */
+ 	  else if (TREE_CODE (src) == VAR_DECL
+ 		   && TREE_CODE (dest) == VAR_DECL)
+ 	    {
+ 	      unsigned int old_value =
+ 		ssa_name (find_matching_ref (set, src, VARUSE));
+ 	      latticevalue old_lattice_value = values[old_value].lattice_val;
+ 	      unsigned int new_value =
+ 		ssa_name (find_matching_ref (set, dest, VARDEF));
+ 
+ 	      /* Unless the lattice value is going to change, don't bother
+ 	         adding the "new value" into the worklist.  */
+ 	      if (values[new_value].lattice_val != old_lattice_value
+ 		  || (values[new_value].const_value !=
+ 		      values[old_value].const_value))
+ 		SET_BIT (ssa_edges, new_value);
+ 
+ 	      /* Copy the old lattice node info into the new value lattice node.  */
+ 	      values[new_value].lattice_val = old_lattice_value;
+ 	      values[new_value].const_value = values[old_value].const_value;
+ 	    }
+ 	  /* Handle jumps.  */
+ 	  else if (is_ctrl_stmt (set))
+ 	    {
+ 	      switch (TREE_CODE (set))
+ 		{
+ 		case IF_STMT:
+ 		  {
+ 		    tree condition = IF_COND (set);
+ 		    int name = ssa_name (insn);
+ 		    if (values[name].lattice_val == CONSTANT)
+ 		      {
+ 			condition = eval_subst (condition, VARREF_SYM (insn),
+ 						values[name].const_value,
+ 						VARREF_SYM (insn),
+ 						values[name].const_value);
+ 		      }
+ 		    if (really_constant_p (condition))
+ 		      {
+ 			tree executed_stmt =
+ 			  compare_tree_int (condition,
+ 					    0) ==
+ 			  0 ? ELSE_CLAUSE (set) : THEN_CLAUSE (set);
+ 			if (cfg_dump_file)
+ 			  {
+ 			    fprintf (cfg_dump_file,
+ 				     "Skipping non-executed-branch of if stmt:");
+ 			    print_node_brief (cfg_dump_file, "", set, 0);
+ 			    fprintf (cfg_dump_file,
+ 				     " new condition is valued at:");
+ 			    print_node_brief (cfg_dump_file, "", condition,
+ 					      0);
+ 			    fprintf (cfg_dump_file, "\n");
+ 			  }
+ 			if (executed_stmt)
+ 			  {
+ 			    int index =
+ 			      EIE (block,
+ 				   BB_FOR_STMT (first_exec_stmt
+ 						(executed_stmt)));
+ 
+ 			    if (TEST_BIT (executable_edges, index))
+ 			      break;
+ 
+ 			    SET_BIT (executable_edges, index);
+ 			    edge_info[index] = flow_edges;
+ 			    flow_edges = INDEX_EDGE (edges, index);
+ 			    continue;
+ 			  }
+ 		      }
+ 		  }
+ 		default:
+ 		  {
+ 		    edge curredge;
+ 
+ 		    /* This is a computed jump, table jump, or an unconditional
+ 		       jump.  For all these cases we want to mark all successor
+ 		       blocks as executable if they have not already been
+ 		       marked.
+ 
+ 		       One day we may try do better with swtich tables and
+ 		       other computed jumps.  */
+ 		    for (curredge = block->succ; curredge;
+ 			 curredge = curredge->succ_next)
+ 		      {
+ 			int index = EIE (curredge->src, curredge->dest);
+ 
+ 			if (TEST_BIT (executable_edges, index))
+ 			  continue;
+ 
+ 			SET_BIT (executable_edges, index);
+ 			edge_info[index] = flow_edges;
+ 			flow_edges = curredge;
+ 		      }
+ 		  }
+ 		}
+ 	    }
+ 	  else if (!(VARREF_TYPE (insn) == VARPHI))
+ 	    {
+ 	      tree simplified = NULL;
+ 
+ 	      /* We've got some kind of INSN.  If it's simple, try to evaluate
+ 	         it and record the results. 
+ 
+ 	         We already know this insn is a single_set and that it sets
+ 	         a pseudo register.   So we just need to extract the source
+ 	         arguments, simplify them to constants if possible, then
+ 	         simplify the expression as a whole if possible.  */
+ 	      switch (TREE_CODE_CLASS (TREE_CODE (src)))
+ 		{
+ 		case '1':
+ 		  {
+ 		    tree src0 = TREE_OPERAND (src, 0);
+ 		    tree src0new = src0;
+ 		    unsigned int src0name = -1;
+ 		    STRIP_NOPS (src0);
+ 		    if (TREE_CODE (src0) == VAR_DECL)
+ 		      src0name =
+ 			ssa_name (find_matching_ref (src, src0, VARUSE));
+ 		    /* If either is undefined, then the result is undefined.  */
+ 		    if ((TREE_CODE (src0) == VAR_DECL
+ 			 && values[src0name].lattice_val == UNDEFINED))
+ 		      {
+ 			defs_to_value (insn, UNDEFINED);
+ 			break;
+ 		      }
+ 
+ 		    /* Simplify source operands to whatever known values they
+ 		       may have.  */
+ 		    if (TREE_CODE (src0) == VAR_DECL
+ 			&& values[src0name].lattice_val == CONSTANT)
+ 		      src0new = values[src0name].const_value;
+ 		    simplified =
+ 		      eval_subst (src, src0, src0new, src0, src0new);
+ 		    break;
+ 
+ 		  }
+ 		case '2':
+ 		case 'c':
+ 		case '<':
  		  {
! 		    tree src0 = TREE_OPERAND (src, 0);
! 		    tree src1 = TREE_OPERAND (src, 1);
! 		    tree src0new = src0;
! 		    tree src1new = src1;
! 		    unsigned int src0name = -1;
! 		    unsigned int src1name = -1;
! 		    STRIP_NOPS (src0);
! 		    STRIP_NOPS (src1);
! 		    if (TREE_CODE (src0) == VAR_DECL)
! 		      src0name =
! 			ssa_name (find_matching_ref (src, src0, VARUSE));
! 		    if (TREE_CODE (src1) == VAR_DECL)
! 		      src1name =
! 			ssa_name (find_matching_ref (src, src1, VARUSE));
! 		    /* If either is undefined, then the result is undefined.  */
! 		    if ((TREE_CODE (src0) == VAR_DECL
! 			 && values[src0name].lattice_val == UNDEFINED)
! 			|| (TREE_CODE (src1) == VAR_DECL
! 			    && values[src1name].lattice_val == UNDEFINED))
! 		      {
! 			defs_to_value (insn, UNDEFINED);
! 			break;
! 		      }
  
! 		    /* Simplify source operands to whatever known values they
! 		       may have.  */
! 		    if (TREE_CODE (src0) == VAR_DECL
! 			&& values[src0name].lattice_val == CONSTANT)
! 		      src0new = values[src0name].const_value;
! 
! 		    if (TREE_CODE (src1) == VAR_DECL
! 			&& values[src1name].lattice_val == CONSTANT)
! 		      src1new = values[src1name].const_value;
! 		    simplified =
! 		      eval_subst (src, src0, src0new, src1, src1new);
! 		    break;
! 
! 		  }
! 		default:
! 		  defs_to_value (insn, VARYING);
! 		}
! 
! 	      if (simplified && really_constant_p (simplified))
! 		{
! 		  unsigned int name =
! 		    ssa_name (find_matching_ref (set, dest, VARDEF));
! 		  if (values[name].lattice_val != CONSTANT
! 		      || values[name].const_value != simplified)
! 		    SET_BIT (ssa_edges, name);
! 
! 		  values[name].lattice_val = CONSTANT;
! 		  values[name].const_value = simplified;
! 		}
! 	      else
! 		defs_to_value (insn, VARYING);
! 	    }
! 	}
!     }
! }
! static void
! visit_expression_rtx (insnp, block)
!      void *insnp;
!      basic_block block;
! {
!   rtx insn = (rtx) insnp;
!   rtx set = single_set (insn);
!   rtx src, dest;
    if (!set)
      {
!       defs_to_value (insn, VARYING);
        return;
      }
    src = SET_SRC (set);
    dest = SET_DEST (set);
  
*************** visit_expression (insn, block)
*** 259,274 ****
    /* We may want to refine this some day.  */
    if (GET_CODE (dest) != REG && dest != pc_rtx)
      {
!       defs_to_varying (insn);
        return;
      }
  
    /* Hard registers are not put in SSA form and thus we must consider
!      them varying.  All the more reason to avoid hard registers in 
       RTL until as late as possible in the compilation.  */
    if (GET_CODE (dest) == REG && REGNO (dest) < FIRST_PSEUDO_REGISTER)
      {
!       defs_to_varying (insn);
        return;
      }
  
--- 904,919 ----
    /* We may want to refine this some day.  */
    if (GET_CODE (dest) != REG && dest != pc_rtx)
      {
!       defs_to_value (insn, VARYING);
        return;
      }
  
    /* Hard registers are not put in SSA form and thus we must consider
!      them VARYING.  All the more reason to avoid hard registers in 
       RTL until as late as possible in the compilation.  */
    if (GET_CODE (dest) == REG && REGNO (dest) < FIRST_PSEUDO_REGISTER)
      {
!       defs_to_value (insn, VARYING);
        return;
      }
  
*************** visit_expression (insn, block)
*** 345,354 ****
  	  if ((GET_CODE (comparison_src0) == REG
  	       && values[REGNO (comparison_src0)].lattice_val == UNDEFINED)
  	      || (GET_CODE (comparison_src1) == REG
! 	          && values[REGNO (comparison_src1)].lattice_val == UNDEFINED))
  	    return;
  
! 	  /* If either operand is varying, then we must consider all
  	     paths as executable.  */
  	  if ((GET_CODE (comparison_src0) == REG
  	       && values[REGNO (comparison_src0)].lattice_val == VARYING)
--- 990,1000 ----
  	  if ((GET_CODE (comparison_src0) == REG
  	       && values[REGNO (comparison_src0)].lattice_val == UNDEFINED)
  	      || (GET_CODE (comparison_src1) == REG
! 		  && values[REGNO (comparison_src1)].lattice_val ==
! 		  UNDEFINED))
  	    return;
  
! 	  /* If either operand is VARYING, then we must consider all
  	     paths as executable.  */
  	  if ((GET_CODE (comparison_src0) == REG
  	       && values[REGNO (comparison_src0)].lattice_val == VARYING)
*************** visit_expression (insn, block)
*** 386,393 ****
  						   GET_MODE (XEXP (src, 0)),
  						   comparison_src0,
  						   comparison_src1),
! 					  XEXP (src, 1),
! 					  XEXP (src, 2));
  
  	  /* Walk through all the outgoing edges from this block and see
  	     which (if any) we should mark as executable.  */
--- 1032,1038 ----
  						   GET_MODE (XEXP (src, 0)),
  						   comparison_src0,
  						   comparison_src1),
! 					  XEXP (src, 1), XEXP (src, 2));
  
  	  /* Walk through all the outgoing edges from this block and see
  	     which (if any) we should mark as executable.  */
*************** visit_expression (insn, block)
*** 447,453 ****
  		  || (GET_CODE (src1) == REG
  		      && values[REGNO (src1)].lattice_val == UNDEFINED))
  		{
! 		  defs_to_undefined (insn);
  		  break;
  		}
  		
--- 1092,1098 ----
  		|| (GET_CODE (src1) == REG
  		    && values[REGNO (src1)].lattice_val == UNDEFINED))
  	      {
! 		defs_to_value (insn, UNDEFINED);
  		break;
  	      }
  
*************** visit_expression (insn, block)
*** 481,487 ****
  	      if (GET_CODE (src0) == REG
  		   && values[REGNO (src0)].lattice_val == UNDEFINED)
  		{
! 		  defs_to_undefined (insn);
  		  break;
  		}
  		
--- 1126,1132 ----
  	    if (GET_CODE (src0) == REG
  		&& values[REGNO (src0)].lattice_val == UNDEFINED)
  	      {
! 		defs_to_value (insn, UNDEFINED);
  		break;
  	      }
  
*************** visit_expression (insn, block)
*** 495,502 ****
  		 computes a constant value.  */
  	      simplified = simplify_unary_operation (GET_CODE (src),
  						     GET_MODE (src),
! 						     src0,
! 						     GET_MODE (src0));
  	      break;
  	    }
  
--- 1140,1146 ----
  	       computes a constant value.  */
  	    simplified = simplify_unary_operation (GET_CODE (src),
  						   GET_MODE (src),
! 						   src0, GET_MODE (src0));
  	    break;
  	  }
  
*************** visit_expression (insn, block)
*** 512,518 ****
  		  || (GET_CODE (src1) == REG
  		      && values[REGNO (src1)].lattice_val == UNDEFINED))
  		{
! 		  defs_to_undefined (insn);
  		  break;
  		}
  		
--- 1156,1162 ----
  		|| (GET_CODE (src1) == REG
  		    && values[REGNO (src1)].lattice_val == UNDEFINED))
  	      {
! 		defs_to_value (insn, UNDEFINED);
  		break;
  	      }
  
*************** visit_expression (insn, block)
*** 549,555 ****
  		  || (GET_CODE (src2) == REG
  		      && values[REGNO (src2)].lattice_val == UNDEFINED))
  		{
! 		  defs_to_undefined (insn);
  		  break;
  		}
  		
--- 1193,1199 ----
  		|| (GET_CODE (src2) == REG
  		    && values[REGNO (src2)].lattice_val == UNDEFINED))
  	      {
! 		defs_to_value (insn, UNDEFINED);
  		break;
  	      }
  
*************** visit_expression (insn, block)
*** 577,583 ****
  	    }
  	
  	  default:
! 	    defs_to_varying (insn);
  	}
  
        if (simplified && GET_CODE (simplified) == CONST_INT)
--- 1221,1227 ----
  	  }
  
  	default:
! 	  defs_to_value (insn, VARYING);
  	}
  
        if (simplified && GET_CODE (simplified) == CONST_INT)
*************** visit_expression (insn, block)
*** 590,599 ****
  	  values[REGNO (dest)].const_value = simplified;
  	}
        else
!         defs_to_varying (insn);
      }
  }
  
  /* Iterate over the FLOW_EDGES work list.  Simulate the target block
     for each edge.  */
  static void
--- 1234,1253 ----
  	  values[REGNO (dest)].const_value = simplified;
  	}
        else
! 	defs_to_value (insn, VARYING);
      }
  }
  
+ /* Go through the expression, call the approriate evaluation routines
+    to attempt cprop */
+ static void
+ visit_expression (insn, block)
+      void *insn;
+      basic_block block;
+ {
+   (*ccp_info.visit_expression) (insn, block);
+ }
+ 
  /* Iterate over the FLOW_EDGES work list.  Simulate the target block
     for each edge.  */
  static void
*************** examine_flow_edges (void)
*** 602,609 ****
    while (flow_edges != NULL)
      {
        basic_block succ_block;
-       rtx curr_phi_node;
- 
        /* Pull the next block to simulate off the worklist.  */
        succ_block = flow_edges->dest;
        flow_edges = edge_info[EIE (flow_edges->src, flow_edges->dest)];
--- 1256,1261 ----
*************** examine_flow_edges (void)
*** 611,648 ****
        /* There is nothing to do for the exit block.  */
        if (succ_block == EXIT_BLOCK_PTR)
  	continue;
- 
        /* Always simulate PHI nodes, even if we have simulated this block
! 	 before.  Note that all PHI nodes are consecutive within a block.  */
!       for (curr_phi_node = first_insn_after_basic_block_note (succ_block);
! 	   PHI_NODE_P (curr_phi_node);
! 	   curr_phi_node = NEXT_INSN (curr_phi_node))
! 	visit_phi_node (curr_phi_node, succ_block);
  
        /* If this is the first time we've simulated this block, then we
  	 must simulate each of its insns.  */
        if (!TEST_BIT (executable_blocks, succ_block->index))
  	{
- 	  rtx currinsn;
  	  edge succ_edge = succ_block->succ;
- 
  	  /* Note that we have simulated this block.  */
  	  SET_BIT (executable_blocks, succ_block->index);
  
- 	  /* Simulate each insn within the block.  */
- 	  currinsn = succ_block->head;
- 	  while (currinsn != succ_block->end)
- 	    {
- 	      if (INSN_P (currinsn))
- 		visit_expression (currinsn, succ_block);
- 
- 	      currinsn = NEXT_INSN (currinsn);
- 	    }
- 	  
- 	  /* Don't forget the last insn in the block.  */
- 	  if (INSN_P (currinsn))
- 	    visit_expression (currinsn, succ_block);
- 	  
  	  /* If we haven't looked at the next block, and it has a
  	     single successor, add it onto the worklist.  This is because
  	     if we only have one successor, we know it gets executed,
--- 1263,1281 ----
        /* There is nothing to do for the exit block.  */
        if (succ_block == EXIT_BLOCK_PTR)
  	continue;
        /* Always simulate PHI nodes, even if we have simulated this block
!          before. */
!       (*ccp_info.simulate_phi_nodes) (succ_block);
  
        /* If this is the first time we've simulated this block, then we
           must simulate each of its insns.  */
        if (!TEST_BIT (executable_blocks, succ_block->index))
  	{
  	  edge succ_edge = succ_block->succ;
  	  /* Note that we have simulated this block.  */
  	  SET_BIT (executable_blocks, succ_block->index);
+ 	  (*ccp_info.simulate_block) (succ_block);
  
  	  /* If we haven't looked at the next block, and it has a
  	     single successor, add it onto the worklist.  This is because
  	     if we only have one successor, we know it gets executed,
*************** examine_flow_edges (void)
*** 661,685 ****
      }
  }
  
  /* Follow the def-use chains for each definition on the worklist and
     simulate the uses of the definition.  */
  
  static void
! follow_def_use_chains ()
  {
    /* Iterate over all the entries on the SSA_EDGES worklist.  */
    while (sbitmap_first_set_bit (ssa_edges) >= 0)
      {
        int member;
-       struct df_link *curruse;
  
        /* Pick an entry off the worklist (it does not matter which
  	 entry we pick).  */
        member = sbitmap_first_set_bit (ssa_edges); 
        RESET_BIT (ssa_edges, member);
  
!       /* Iterate through all the uses of this entry.  */
!       for (curruse = df_analyzer->regs[member].uses; curruse;
  	   curruse = curruse->next)
  	{
  	  rtx useinsn;
--- 1294,1434 ----
      }
  }
  
+ static void
+ simulate_phi_nodes_tree (block)
+      basic_block block;
+ {
+   varray_type blockrefs;
+   unsigned int i;
+   blockrefs = BB_REFS (block);
+   if (!blockrefs)
+     return;
+   for (i = 0; i < VARRAY_ACTIVE_SIZE (blockrefs); i++)
+     if (VARREF_TYPE ((varref) VARRAY_GENERIC_PTR (blockrefs, i)) == VARPHI)
+       visit_phi_node ((varref) VARRAY_GENERIC_PTR (blockrefs, i), block);
+ }
+ static void
+ simulate_block_tree (block)
+      basic_block block;
+ {
+   edge curredge;
+   varray_type blockrefs;
+   varref currinsn;
+   unsigned int i;
+   blockrefs = BB_REFS (block);
+   if (!blockrefs)
+     return;
+ 
+   for (i = 0; i < VARRAY_ACTIVE_SIZE (blockrefs); i++)
+     {
+       /* Simulate each insn within the block.  */
+       currinsn = (varref) VARRAY_GENERIC_PTR (blockrefs, i);
+       if (VARREF_TYPE (currinsn) != VARPHI)
+ 	visit_expression (currinsn, block);
+     }
+   if (!VARRAY_ACTIVE_SIZE (blockrefs))
+     {
+       for (curredge = block->succ; curredge; curredge = curredge->succ_next)
+ 	{
+ 	  int index = EIE (curredge->src, curredge->dest);
+ 
+ 	  if (TEST_BIT (executable_edges, index))
+ 	    continue;
+ 
+ 	  SET_BIT (executable_edges, index);
+ 	  edge_info[index] = flow_edges;
+ 	  flow_edges = curredge;
+ 	}
+ 
+     }
+ }
+ 
  /* Follow the def-use chains for each definition on the worklist and
     simulate the uses of the definition.  */
  
  static void
! follow_def_use_chains_tree ()
  {
    /* Iterate over all the entries on the SSA_EDGES worklist.  */
    while (sbitmap_first_set_bit (ssa_edges) >= 0)
      {
        int member;
  
+       varray_type refs;
+       unsigned int i;
        /* Pick an entry off the worklist (it does not matter which
           entry we pick).  */
        member = sbitmap_first_set_bit (ssa_edges);
        RESET_BIT (ssa_edges, member);
+       refs =
+ 	VARDEF_IMM_USES ((varref) VARRAY_GENERIC_PTR (all_varrefs, member));
+       if (!refs)
+ 	continue;
+       for (i = 0; i < VARRAY_ACTIVE_SIZE (refs); i++)
+ 	{
+ 	  varref ref = (varref) VARRAY_GENERIC_PTR (refs, i);
+ 	  if (VARREF_TYPE (ref) != VARPHI)
+ 	    {
+ 	      if (TEST_BIT (executable_blocks, VARREF_BB (ref)->index))
+ 		visit_expression (ref, VARREF_BB (ref));
+ 	    }
+ 	  else if (VARREF_TYPE (ref) == VARPHI)
+ 	    {
+ 	      if (TEST_BIT (executable_blocks, VARREF_BB (ref)->index))
+ 		visit_phi_node (ref, VARREF_BB (ref));
+ 	    }
+ 	}
+     }
+ }
+ static void
+ simulate_block_rtx (block)
+      basic_block block;
+ {
+ 
+   rtx currinsn;
+   /* simulate each insn within the block.  */
+   currinsn = block->head;
+   while (currinsn != block->end)
+     {
+       if (INSN_P (currinsn))
+ 	visit_expression (currinsn, block);
+ 
+       currinsn = NEXT_INSN (currinsn);
+     }
+ 
+   /* don't forget the last insn in the block.  */
+   if (INSN_P (currinsn))
+     visit_expression (currinsn, block);
+ }
+ static void
+ simulate_phi_nodes_rtx (block)
+      basic_block block;
+ {
+   rtx curr_phi_node;
+   for (curr_phi_node = first_insn_after_basic_block_note (block);
+        PHI_NODE_P (curr_phi_node); curr_phi_node = NEXT_INSN (curr_phi_node))
+     visit_phi_node (curr_phi_node, block);
+ }
+ 
+ /* follow the def-use chains for each definition on the worklist and
+    simulate the uses of the definition.  */
+ 
+ static void
+ follow_def_use_chains_rtx ()
+ {
+   /* iterate over all the entries on the ssa_edges worklist.  */
+   while (sbitmap_first_set_bit (ssa_edges) >= 0)
+     {
+       int member;
+       struct df_link *curruse;
+ 
+       /* pick an entry off the worklist (it does not matter which
+          entry we pick).  */
+       member = sbitmap_first_set_bit (ssa_edges);
+       RESET_BIT (ssa_edges, member);
  
!       /* iterate through all the uses of this entry.  */
!       for (curruse = ccp_info.analyzer->regs[member].uses; curruse;
  	   curruse = curruse->next)
  	{
  	  rtx useinsn;
*************** optimize_unexecutable_edges (edges, exec
*** 735,741 ****
  		  if (rtl_dump_file)
  		    fprintf (rtl_dump_file,
  			     "Removing alternative for bb %d of phi %d\n", 
! 			     edge->src->index, SSA_NAME (PATTERN (insn)));
  		  insn = NEXT_INSN (insn);
  		}
  	    }
--- 1484,1490 ----
  		  if (rtl_dump_file)
  		    fprintf (rtl_dump_file,
  			     "Removing alternative for bb %d of phi %d\n",
! 			     edge->src->index, ssa_name (insn));
  		  insn = NEXT_INSN (insn);
  		}
  	    }
*************** optimize_unexecutable_edges (edges, exec
*** 748,754 ****
  	}
      }
  
!   /* We have removed all the unexecutable edges from the CFG.  Fix up
       the conditional jumps at the end of any affected block.
  
       We have three cases to deal with:
--- 1497,1503 ----
  	}
      }
  
!   /* We have removed all the unexecutable edges from the cfg.  fix up
       the conditional jumps at the end of any affected block.
  
       We have three cases to deal with:
*************** optimize_unexecutable_edges (edges, exec
*** 797,813 ****
  	  else
  	    {
  	      SET_SRC (PATTERN (insn)) = gen_rtx_LABEL_REF (Pmode,
! 							    JUMP_LABEL (insn));
  	      emit_barrier_after (insn);
  	      INSN_CODE (insn) = -1;
  	    }
  
  	  /* Inform the DF analyzer that this insn changed.  */
! 	  df_insn_modify (df_analyzer, BLOCK_FOR_INSN (insn), insn);
  	}
      }
  }
   
  /* Perform substitution of known values for pseudo registers.
  
     ??? Note we do not do simplifications or constant folding here, it
--- 1546,1632 ----
  	  else
  	    {
  	      SET_SRC (PATTERN (insn)) = gen_rtx_LABEL_REF (Pmode,
! 							    JUMP_LABEL
! 							    (insn));
  	      emit_barrier_after (insn);
  	      INSN_CODE (insn) = -1;
  	    }
  
  	  /* Inform the DF analyzer that this insn changed.  */
! 	  df_insn_modify (ccp_info.analyzer, BLOCK_FOR_INSN (insn), insn);
  	}
      }
  }
+ static void
+ subst_consts_tree ()
+ {
+   int i;
  
+   for (i = 0; i < max_ref_id; i++)
+     {
+       if (values[i].lattice_val == CONSTANT)
+ 	{
+ 	  unsigned int j;
+ 	  varray_type refs;
+ 	  varref ref;
+ 	  refs =
+ 	    VARDEF_IMM_USES ((varref) VARRAY_GENERIC_PTR (all_varrefs, i));
+ 	  ref = (varref) VARRAY_GENERIC_PTR (all_varrefs, i);
+ 	  if (VARREF_TYPE (ref) == VARDEF && !IS_GHOST_DEF (ref))
+ 	    {
+ 	      if (cfg_dump_file)
+ 		{
+ 		  fprintf (cfg_dump_file, "Replacing init of:");
+ 		  print_node_brief (cfg_dump_file, "", VARREF_SYM (ref), 0);
+ 		  fprintf (cfg_dump_file, " in:");
+ 		  print_node_brief (cfg_dump_file, "", VARREF_EXPR (ref), 0);
+ 		  fprintf (cfg_dump_file, " with constant:");
+ 		  print_node_brief (cfg_dump_file, "", values[i].const_value,
+ 				    0);
+ 		  fprintf (cfg_dump_file, "\n");
+ 		  fflush (cfg_dump_file);
+ 		}
+ 	      TREE_OPERAND (VARREF_EXPR (ref), 1) = values[i].const_value;
+ 	      for (j = 0; j < VARRAY_ACTIVE_SIZE (refs); j++)
+ 		{
+ 		  varref ref = (varref) VARRAY_GENERIC_PTR (refs, j);
+ 		  if (VARREF_TYPE (ref) == VARUSE)
+ 		    {
+ 		      if (TREE_CODE (VARREF_EXPR (ref)) == MODIFY_EXPR)
+ 			replace_expr_in_tree (TREE_OPERAND
+ 					      (VARREF_EXPR (ref), 1),
+ 					      VARREF_SYM (ref),
+ 					      values[i].const_value);
+ 		      else
+ 			replace_expr_in_tree (VARREF_EXPR (ref),
+ 					      VARREF_SYM (ref),
+ 					      values[i].const_value);
+ 		    }
+ 		}
+ 	    }
+ 	  else if (VARREF_TYPE (ref) == VARPHI)
+ 	    {
+ 	      for (j = 0; j < VARRAY_ACTIVE_SIZE (refs); j++)
+ 		{
+ 		  varref ref = (varref) VARRAY_GENERIC_PTR (refs, j);
+ 		  if (VARREF_TYPE (ref) == VARUSE)
+ 		    {
+ 		      if (TREE_CODE (VARREF_EXPR (ref)) == MODIFY_EXPR)
+ 			replace_expr_in_tree (TREE_OPERAND
+ 					      (VARREF_EXPR (ref), 1),
+ 					      VARREF_SYM (ref),
+ 					      values[i].const_value);
+ 		      else
+ 			replace_expr_in_tree (VARREF_EXPR (ref),
+ 					      VARREF_SYM (ref),
+ 					      values[i].const_value);
+ 		    }
+ 		}
+ 	    }
+ 	}
+     }
+ }
+ 
  /* Perform substitution of known values for pseudo registers.
  
     ??? Note we do not do simplifications or constant folding here, it
*************** optimize_unexecutable_edges (edges, exec
*** 821,831 ****
     replace uses with the known constant value.  */
  
  static void
! ssa_ccp_substitute_constants ()
  {
    unsigned int i;
  
!   for (i = FIRST_PSEUDO_REGISTER; i < VARRAY_SIZE (ssa_definition); i++)
      {
        if (values[i].lattice_val == CONSTANT)
  	{
--- 1640,1650 ----
     replace uses with the known constant value.  */
  
  static void
! subst_consts_rtx ()
  {
    unsigned int i;
  
!   for (i = FIRST_PSEUDO_REGISTER; i < (*ccp_info.num_ssa_vars) (); i++)
      {
        if (values[i].lattice_val == CONSTANT)
  	{
*************** ssa_ccp_substitute_constants ()
*** 844,863 ****
  	    {
  	      if (rtl_dump_file)
  		fprintf (rtl_dump_file,
! 			 "Register %d is now set to a constant\n",
! 			 SSA_NAME (PATTERN (def)));
  	      SET_SRC (set) = values[i].const_value;
  	      INSN_CODE (def) = -1;
! 	      df_insn_modify (df_analyzer, BLOCK_FOR_INSN (def), def);
  	    }
  
  	  /* Iterate through all the uses of this entry and try replacements
  	     there too.  Note it is not particularly profitable to try
  	     and fold/simplify expressions here as most of the common
  	     cases were handled above.  */
! 	  for (curruse = df_analyzer->regs[i].uses;
! 	       curruse;
! 	       curruse = curruse->next)
  	    {
  	      rtx useinsn;
  
--- 1663,1681 ----
  	    {
  	      if (rtl_dump_file)
  		fprintf (rtl_dump_file,
! 			 "register %d is now set to a constant\n",
! 			 ssa_name (set));
  	      SET_SRC (set) = values[i].const_value;
  	      INSN_CODE (def) = -1;
! 	      df_insn_modify (ccp_info.analyzer, BLOCK_FOR_INSN (def), def);
  	    }
  
  	  /* Iterate through all the uses of this entry and try replacements
  	     there too.  Note it is not particularly profitable to try
  	     and fold/simplify expressions here as most of the common
  	     cases were handled above.  */
! 	  for (curruse = ccp_info.analyzer->regs[i].uses;
! 	       curruse; curruse = curruse->next)
  	    {
  	      rtx useinsn;
  
*************** ssa_ccp_substitute_constants ()
*** 869,887 ****
  		  && (GET_CODE (useinsn) == INSN
  		      || GET_CODE (useinsn) == JUMP_INSN))
  		{
- 		  
  		  if (validate_replace_src (regno_reg_rtx [i],
! 					values[i].const_value,
! 					    useinsn))
  		    {
  		      if (rtl_dump_file)
  			fprintf (rtl_dump_file, 
  				 "Register %d in insn %d replaced with constant\n",
  				 i, INSN_UID (useinsn));
  		      INSN_CODE (useinsn) = -1;
! 		      df_insn_modify (df_analyzer,
! 				      BLOCK_FOR_INSN (useinsn),
! 				      useinsn);
  		    }
  		  
  		}
--- 1687,1702 ----
  		  && (GET_CODE (useinsn) == INSN
  		      || GET_CODE (useinsn) == JUMP_INSN))
  		{
  		  if (validate_replace_src (regno_reg_rtx[i],
! 					    values[i].const_value, useinsn))
  		    {
  		      if (rtl_dump_file)
  			fprintf (rtl_dump_file,
  				 "Register %d in insn %d replaced with constant\n",
  				 i, INSN_UID (useinsn));
  		      INSN_CODE (useinsn) = -1;
! 		      df_insn_modify (ccp_info.analyzer,
! 				      BLOCK_FOR_INSN (useinsn), useinsn);
  		    }
  
  		}
*************** ssa_ccp_df_delete_unreachable_insns ()
*** 935,941 ****
  	      if (GET_CODE (start) == INSN
  		  || GET_CODE (start) == CALL_INSN
  		  || GET_CODE (start) == JUMP_INSN)
! 		df_insn_delete (df_analyzer, BLOCK_FOR_INSN (start), start);
  
  	      if (start == end)
  		break;
--- 1750,1757 ----
  	      if (GET_CODE (start) == INSN
  		  || GET_CODE (start) == CALL_INSN
  		  || GET_CODE (start) == JUMP_INSN)
! 		df_insn_delete (ccp_info.analyzer, BLOCK_FOR_INSN (start),
! 				start);
  
  	      if (start == end)
  		break;
*************** ssa_ccp_df_delete_unreachable_insns ()
*** 944,992 ****
  	}
      }
  }
  
  
! /* Main entry point for SSA Conditional Constant Propagation.
  
     Long term it should accept as input the specific flow graph to
     operate on so that it can be called for sub-graphs.  */
! 
! void
! ssa_const_prop (void)
  {
    unsigned int i;
    edge curredge;
  
!   /* We need alias analysis (for what?) */
    init_alias_analysis ();
! 
!   df_analyzer = df_init ();
!   df_analyse (df_analyzer, 0,
  	      DF_RD_CHAIN | DF_RU_CHAIN | DF_REG_INFO | DF_HARD_REGS);
- 
-   /* We need mappings from insn to its containing block.  */
    compute_bb_for_insn (get_max_uid ());
! 
    /* Perform a quick and dirty dead code elimination pass.  This is not
       as aggressive as it could be, but it's good enough to clean up a
       lot of unwanted junk and it is fast.  */
!   ssa_fast_dce (df_analyzer);
! 
    /* Build an edge list from the CFG.  */
    edges = create_edge_list ();
  
    /* Initialize the values array with everything as undefined.  */
!   values = (value *) xmalloc (VARRAY_SIZE (ssa_definition) * sizeof (value));
!   for (i = 0; i < VARRAY_SIZE (ssa_definition); i++)
      {
-       if (i < FIRST_PSEUDO_REGISTER)
-         values[i].lattice_val = VARYING;
-       else
  	values[i].lattice_val = UNDEFINED;
        values[i].const_value = NULL;
      }
  
!   ssa_edges = sbitmap_alloc (VARRAY_SIZE (ssa_definition));
    sbitmap_zero (ssa_edges);
  
    executable_blocks = sbitmap_alloc (n_basic_blocks);
--- 1760,1830 ----
  	}
      }
  }
+ static void
+ init_tree ()
+ {
+   tree_cleanup_cfg ();
  
+ }
+ static void
+ init_rtx ()
+ {
+   unsigned int i;
+   for (i = 0; i < (*ccp_info.num_ssa_vars) (); i++)
+     {
+       if (i < FIRST_PSEUDO_REGISTER)
+ 	values[i].lattice_val = VARYING;
+     }
+   compute_bb_for_insn (get_max_uid ());
+ }
+ static void
+ cleanup_tree ()
+ {
+   tree_cleanup_cfg ();
+ }
+ static void
+ cleanup_rtx ()
+ {
+ }
  
! /* Main routine for SSA Conditional Constant Propagation.
  
     Long term it should accept as input the specific flow graph to
     operate on so that it can be called for sub-graphs.  */
! static void
! ssa_const_prop_1 (void)
  {
    unsigned int i;
    edge curredge;
  
!   if (ccp_info.need_alias)
      init_alias_analysis ();
!   if (ccp_info.use_analyzer)
!     {
!       df_analyse (ccp_info.analyzer, 0,
  		  DF_RD_CHAIN | DF_RU_CHAIN | DF_REG_INFO | DF_HARD_REGS);
        compute_bb_for_insn (get_max_uid ());
!     }
!   if (ccp_info.do_dce)
!     {
        /* Perform a quick and dirty dead code elimination pass.  This is not
           as aggressive as it could be, but it's good enough to clean up a
           lot of unwanted junk and it is fast.  */
!       ssa_fast_dce (ccp_info.analyzer);
!     }
    /* Build an edge list from the CFG.  */
    edges = create_edge_list ();
  
    /* Initialize the values array with everything as undefined.  */
!   values = (value *) xmalloc ((*ccp_info.num_ssa_vars) () * sizeof (value));
!   for (i = 0; i < (*ccp_info.num_ssa_vars) (); i++)
      {
        values[i].lattice_val = UNDEFINED;
        values[i].const_value = NULL;
      }
  
!   (*ccp_info.init) ();
!   ssa_edges = sbitmap_alloc ((*ccp_info.num_ssa_vars) ());
    sbitmap_zero (ssa_edges);
  
    executable_blocks = sbitmap_alloc (n_basic_blocks);
*************** ssa_const_prop (void)
*** 1012,1024 ****
    do
      {
        examine_flow_edges ();
!       follow_def_use_chains ();
      }
    while (flow_edges != NULL);
- 
-   /* Now perform substitutions based on the known constant values.  */
-   ssa_ccp_substitute_constants ();
  
    /* Remove unexecutable edges from the CFG and make appropriate
       adjustments to PHI nodes.  */
    optimize_unexecutable_edges (edges, executable_edges);
--- 1850,1863 ----
    do
      {
        examine_flow_edges ();
!       (*ccp_info.follow_def_use_chains) ();
      }
    while (flow_edges != NULL);
  
+   /* now perform substitutions based on the known constant values.  */
+   (*ccp_info.subst_consts) ();
+   if (ccp_info.opt_unexec_edges)
+     {
        /* Remove unexecutable edges from the CFG and make appropriate
           adjustments to PHI nodes.  */
        optimize_unexecutable_edges (edges, executable_edges);
*************** ssa_const_prop (void)
*** 1026,1032 ****
    /* Now remove all unreachable insns and update the DF information.
       as appropriate.  */
    ssa_ccp_df_delete_unreachable_insns ();
! 
  #if 0
    /* The DF analyzer expects the number of blocks to remain constant,
       so we can't remove unreachable blocks.
--- 1865,1871 ----
        /* Now remove all unreachable insns and update the DF information.
           as appropriate.  */
        ssa_ccp_df_delete_unreachable_insns ();
!     }
  #if 0
    /* The DF analyzer expects the number of blocks to remain constant,
       so we can't remove unreachable blocks.
*************** ssa_const_prop (void)
*** 1037,1050 ****
  
       So, there is no way to do an incremental update of the DF data
       at this point.  */
!   df_analyse (df_analyzer, 0,
  	      DF_RD_CHAIN | DF_RU_CHAIN | DF_REG_INFO | DF_HARD_REGS);
  #endif
! 
    /* Clean up any dead code exposed by SSA-CCP, do this after updating
       the dataflow information!  */
!   ssa_fast_dce (df_analyzer);
! 
    free (values);
    values = NULL;
  
--- 1876,1890 ----
  
       So, there is no way to do an incremental update of the DF data
       at this point.  */
!   df_analyse (ccp_info.analyzer, 0,
  	      DF_RD_CHAIN | DF_RU_CHAIN | DF_REG_INFO | DF_HARD_REGS);
  #endif
!   if (ccp_info.do_dce)
!     {
        /* Clean up any dead code exposed by SSA-CCP, do this after updating
           the dataflow information!  */
!       ssa_fast_dce (ccp_info.analyzer);
!     }
    free (values);
    values = NULL;
  
*************** ssa_const_prop (void)
*** 1060,1069 ****
    sbitmap_free (executable_edges);
    executable_edges = NULL;
  
!   df_finish (df_analyzer);
    end_alias_analysis ();
  }
  
  static int
  mark_references (current_rtx, data)
       rtx *current_rtx;
--- 1900,1962 ----
    sbitmap_free (executable_edges);
    executable_edges = NULL;
  
!   if (ccp_info.use_analyzer)
!     df_finish (ccp_info.analyzer);
!   (*ccp_info.cleanup) ();
!   if (ccp_info.need_alias)
      end_alias_analysis ();
  }
  
+ void
+ tree_ssa_const_prop (void)
+ {
+   cfg_dump_file = dump_begin (TDI_cfg, &cfg_dump_flags);
+   ccp_info.analyzer = NULL;
+   ccp_info.ssa_name = &ssa_name_tree;
+   ccp_info.defs_to_value = &defs_to_value_tree;
+   ccp_info.get_num_phi_args = &get_num_phi_args_tree;
+   ccp_info.get_phi_arg_name = &get_phi_arg_name_tree;
+   ccp_info.get_phi_arg_bb = &get_phi_arg_bb_tree;
+   ccp_info.num_ssa_vars = &num_ssa_vars_tree;
+   ccp_info.visit_expression = &visit_expression_tree;
+   ccp_info.simulate_block = &simulate_block_tree;
+   ccp_info.simulate_phi_nodes = &simulate_phi_nodes_tree;
+   ccp_info.follow_def_use_chains = &follow_def_use_chains_tree;
+   ccp_info.subst_consts = &subst_consts_tree;
+   ccp_info.cleanup = &cleanup_tree;
+   ccp_info.init = &init_tree;
+   ccp_info.use_analyzer = 0;
+   ccp_info.do_dce = 0;
+   ccp_info.opt_unexec_edges = 0;
+   ccp_info.need_alias = 0;
+   ssa_const_prop_1 ();
+   if (cfg_dump_file)
+     dump_end (TDI_cfg, cfg_dump_file);
+ }
+ 
+ void
+ ssa_const_prop (void)
+ {
+   ccp_info.analyzer = df_init ();
+   ccp_info.ssa_name = &ssa_name_rtx;
+   ccp_info.defs_to_value = &defs_to_value_rtx;
+   ccp_info.get_num_phi_args = &get_num_phi_args_rtx;
+   ccp_info.get_phi_arg_name = &get_phi_arg_name_rtx;
+   ccp_info.get_phi_arg_bb = &get_phi_arg_bb_rtx;
+   ccp_info.num_ssa_vars = &num_ssa_vars_rtx;
+   ccp_info.visit_expression = &visit_expression_rtx;
+   ccp_info.simulate_block = &simulate_block_rtx;
+   ccp_info.simulate_phi_nodes = &simulate_phi_nodes_rtx;
+   ccp_info.follow_def_use_chains = &follow_def_use_chains_rtx;
+   ccp_info.subst_consts = &subst_consts_rtx;
+   ccp_info.cleanup = &cleanup_rtx;
+   ccp_info.init = &init_rtx;
+   ccp_info.use_analyzer = 1;
+   ccp_info.do_dce = 1;
+   ccp_info.opt_unexec_edges = 1;
+   ccp_info.need_alias = 1;
+   ssa_const_prop_1 ();
+ }
  static int
  mark_references (current_rtx, data)
       rtx *current_rtx;
*************** static void
*** 1121,1127 ****
  ssa_fast_dce (df)
       struct df *df;
  {
!   sbitmap worklist = sbitmap_alloc (VARRAY_SIZE (ssa_definition));
    sbitmap_ones (worklist);
  
    /* Iterate on the worklist until there's no definitions left to
--- 2014,2020 ----
  ssa_fast_dce (df)
       struct df *df;
  {
!   sbitmap worklist = sbitmap_alloc ((*ccp_info.num_ssa_vars) ());
    sbitmap_ones (worklist);
  
    /* Iterate on the worklist until there's no definitions left to
*************** ssa_fast_dce (df)
*** 1159,1165 ****
  	      && ! (GET_CODE (DF_REF_INSN (curruse->ref)) == NOTE
  		    && (NOTE_LINE_NUMBER (DF_REF_INSN (curruse->ref))
  			== NOTE_INSN_DELETED))
! 	      && DF_REF_INSN (curruse->ref) != VARRAY_RTX (ssa_definition, reg))
  	    {
  	      found_use = 1;
  	      break;
--- 2052,2059 ----
  	      && !(GET_CODE (DF_REF_INSN (curruse->ref)) == NOTE
  		   && (NOTE_LINE_NUMBER (DF_REF_INSN (curruse->ref))
  		       == NOTE_INSN_DELETED))
! 	      && DF_REF_INSN (curruse->ref) != VARRAY_RTX (ssa_definition,
! 							   reg))
  	    {
  	      found_use = 1;
  	      break;
*************** ssa_fast_dce (df)
*** 1173,1179 ****
  	{
  	  rtx def = VARRAY_RTX (ssa_definition, reg);
  
! 	  /* Add all registers referenced by INSN to the work
  	     list.  */
  	  for_each_rtx (&PATTERN (def), mark_references, worklist);
  
--- 2067,2073 ----
  	{
  	  rtx def = VARRAY_RTX (ssa_definition, reg);
  
! 	  /* Add all registers referenced by insn to the work
  	     list.  */
  	  for_each_rtx (&PATTERN (def), mark_references, worklist);
  
*************** ssa_fast_dce (df)
*** 1193,1211 ****
  	      else if (def == BLOCK_FOR_INSN (def)->head)
  	        {
  		  BLOCK_FOR_INSN (def)->head = NEXT_INSN (def);
! 		  flow_delete_insn (def);
  		}
  	      else if (def == BLOCK_FOR_INSN (def)->end)
  		{
  		  BLOCK_FOR_INSN (def)->end = PREV_INSN (def);
! 		  flow_delete_insn (def);
  		}
  	      else
! 		flow_delete_insn (def);
  	    }
  	  else
  	    {
! 	      flow_delete_insn (def);
  	    }
  	  VARRAY_RTX (ssa_definition, reg) = NULL;
  	}
--- 2087,2105 ----
  	      else if (def == BLOCK_FOR_INSN (def)->head)
  		{
  		  BLOCK_FOR_INSN (def)->head = NEXT_INSN (def);
! 		  delete_insn (def);
  		}
  	      else if (def == BLOCK_FOR_INSN (def)->end)
  		{
  		  BLOCK_FOR_INSN (def)->end = PREV_INSN (def);
! 		  delete_insn (def);
  		}
  	      else
! 		delete_insn (def);
  	    }
  	  else
  	    {
! 	      delete_insn (def);
  	    }
  	  VARRAY_RTX (ssa_definition, reg) = NULL;
  	}
Index: tree-dfa.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-dfa.c,v
retrieving revision 1.1.2.10
diff -c -3 -p -w -B -b -r1.1.2.10 tree-dfa.c
*** tree-dfa.c	2001/10/15 17:55:04	1.1.2.10
--- tree-dfa.c	2001/10/19 20:16:16
*************** static void add_ref_symbol PARAMS ((tree
*** 54,60 ****
--- 54,63 ----
  
  varray_type referenced_symbols;
  
+ /* Array of all refs, indexed by id. */
+ varray_type all_varrefs;
  
+ 
  /* Find variable references in the code.  */
  
  /* {{{ tree_find_varrefs()
*************** find_refs_in_expr (expr, ref_type, bb, p
*** 442,447 ****
--- 445,451 ----
  
  /* }}} */
  
+ int max_ref_id = 0;
  
  /* Create references and associations to symbols and basic blocks.  */
  
*************** create_varref (sym, ref_type, bb, parent
*** 468,473 ****
--- 472,481 ----
  
    ref = (varref) ggc_alloc (sizeof (*ref));
    memset ((void *) ref, 0, sizeof (*ref));
+   VARREF_ID (ref) = max_ref_id++;
+   if (VARREF_ID (ref) >= VARRAY_SIZE (all_varrefs))
+     all_varrefs = VARRAY_GROW (all_varrefs, VARRAY_SIZE (all_varrefs) * 2);
+   VARRAY_GENERIC_PTR (all_varrefs, VARREF_ID (ref)) = ref;
  
    VARREF_SYM (ref) = sym;
    VARREF_TYPE (ref) = ref_type;
*************** create_varref (sym, ref_type, bb, parent
*** 492,499 ****
    /* Add this reference to the list of references for the symbol.  */
    VARRAY_PUSH_GENERIC_PTR (get_tree_ann (sym)->refs, ref);
  
!   /* Add this reference to the list of references for the containing
!      statement.  */
    if (parent_stmt)
      VARRAY_PUSH_GENERIC_PTR (get_tree_ann (parent_stmt)->refs, ref);
  
--- 500,506 ----
    /* Add this reference to the list of references for the symbol.  */
    VARRAY_PUSH_GENERIC_PTR (get_tree_ann (sym)->refs, ref);
    
!   /* Add this reference to the list of references for the statement.  */
    if (parent_stmt)
      VARRAY_PUSH_GENERIC_PTR (get_tree_ann (parent_stmt)->refs, ref);
  
*************** dump_varref (outf, prefix, ref, indent, 
*** 757,762 ****
--- 764,773 ----
  	{
  	  fputs (" phi-args:\n", outf);
  	  dump_varref_list (outf, prefix, VARDEF_PHI_CHAIN (ref), indent + 4, 0);
+ 	  fputs (" immediate uses:\n", outf);
+ 	  dump_varref_list (outf, prefix, VARDEF_IMM_USES (ref), indent + 4,
+ 			    0);
+ 
  	}
        else if (VARREF_TYPE (ref) == VARDEF && VARDEF_IMM_USES (ref))
  	{
Index: tree-flow.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-flow.h,v
retrieving revision 1.1.2.10
diff -c -3 -p -w -B -b -r1.1.2.10 tree-flow.h
*** tree-flow.h	2001/10/15 01:06:59	1.1.2.10
--- tree-flow.h	2001/10/19 20:16:16
*************** union varref_def;
*** 34,39 ****
--- 34,42 ----
  
  struct varref_common
  {
+   /* Reference ID */
+   unsigned int id;
+ 
    /* Base symbol.  */
    tree sym;
  
*************** union varref_def
*** 111,116 ****
--- 113,119 ----
  
  typedef union varref_def *varref;
  
+ #define VARREF_ID(r) (r)->common.id
  #define VARREF_TYPE(r) (r)->common.type
  #define VARREF_BB(r) (r)->common.bb
  #define VARREF_EXPR(r) (r)->common.expr
*************** typedef struct bb_ann_def *bb_ann;
*** 223,228 ****
--- 226,234 ----
  
  /* {{{ Global declarations.  */
  
+ extern int max_ref_id;
+ extern varray_type all_varrefs;
+ 
  /* Nonzero to warn about variables used before they are initialized.  */
  
  extern int tree_warn_uninitialized;
*************** extern void delete_ssa PARAMS ((void));
*** 311,314 ****
--- 317,325 ----
  
  /* }}} */
  
+ /* {{{ Functions in ssa-ccp.c  */
+ 
+ extern void tree_ssa_const_prop PARAMS ((void));
+ 
+ /* }}} */
  #endif /* _TREE_FLOW_H  */
Index: tree-optimize.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-optimize.c,v
retrieving revision 1.1.2.6
diff -c -3 -p -w -B -b -r1.1.2.6 tree-optimize.c
*** tree-optimize.c	2001/10/15 01:06:59	1.1.2.6
--- tree-optimize.c	2001/10/19 20:16:16
*************** static void init_tree_flow PARAMS ((void
*** 40,46 ****
  
  /* {{{ optimize_tree()
  
!    Main entry point to the tree SSA transformation routines.  */
  
  void
  optimize_tree (t)
--- 40,46 ----
  
  /* {{{ optimize_tree()
  
!    Main entry point to the tree SSA analysis routines.  */
  
  void
  optimize_tree (t)
*************** optimize_tree (t)
*** 50,74 ****
    if (errorcount || sorrycount)
      return;
  
-   /* Build the SSA representation for the function.  */
-   build_tree_ssa (t);
- 
-   /* Flush out flow graph and SSA data.  */
-   delete_cfg ();
-   delete_ssa ();
-   VARRAY_FREE (referenced_symbols);
- }
- 
- /* }}} */
- 
- /* {{{ build_tree_ssa()
- 
-    Main entry point to the tree SSA analysis routines.  */
- 
- void
- build_tree_ssa (t)
-      tree t;
- {
    /* Initialize flow data.  */
    init_flow ();
    init_tree_flow ();
--- 50,55 ----
*************** build_tree_ssa (t)
*** 80,86 ****
--- 61,74 ----
        tree_find_varrefs ();
        tree_build_ssa ();
        tree_compute_rdefs ();
+       tree_ssa_const_prop ();
      }
+ 
+   /* Flush out DFA and SSA data.  */
+   delete_cfg ();
+   delete_ssa ();
+   VARRAY_FREE (referenced_symbols);
+   VARRAY_FREE (all_varrefs);
  }
  
  /* }}} */
*************** static void
*** 93,98 ****
--- 81,87 ----
  init_tree_flow ()
  {
    VARRAY_TREE_INIT (referenced_symbols, 20, "referenced_symbols");
+   VARRAY_GENERIC_PTR_INIT (all_varrefs, 20, "all_varrefs");
  
    /* If -Wuninitialized was used, set tree_warn_uninitialized and clear
       warn_uninitialized to avoid duplicate warnings.  */




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