[tree-ssa] cleanup & factoring in tree-ssa-dom.c/fold-const.c/tree.c

law@redhat.com law@redhat.com
Thu Sep 18 22:21:00 GMT 2003



This change has two primary purposes.

  1. Callers of lookup_avail_expr are now responsible for explicitly
     indicating if the expression should be inserted into the hash table
     if it is not found.

  2. The common code to update the hash tables when we update the RHS
     of a MODIFY_EXPR has been factored into a common routine which also
     looks up the new RHS in the hash tables and returns it if found.


This is preparatory work for being able to optimize stuff like:

  x = b & <const1>
  c = x & <const2>

into

  x = b & <const1>
  c = b & <const3>  [ where const3 is (const1 & const2) ]

And similar transformations.


Bootstrapped and regression tested (on a tree without Richard's recent
EH work).

	* tree-ssa-dom.c (lookup_avail_expr): New argument which indicates
	if the expression should be entered into the hash table.  All
	callers updated.
	(update_rhs_and_lookup_avail_expr): New function factored out
	of optimize_stmt.


Index: tree-ssa-dom.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa-dom.c,v
retrieving revision 1.1.2.38
diff -c -3 -p -r1.1.2.38 tree-ssa-dom.c
*** tree-ssa-dom.c	17 Sep 2003 18:44:46 -0000	1.1.2.38
--- tree-ssa-dom.c	18 Sep 2003 19:13:18 -0000
*************** static tree get_value_for (tree, htab_t)
*** 92,98 ****
  static void set_value_for (tree, tree, htab_t);
  static hashval_t var_value_hash (const void *);
  static int var_value_eq (const void *, const void *);
! static tree lookup_avail_expr (tree, varray_type *, htab_t);
  static tree get_eq_expr_value (tree, int, varray_type *, htab_t);
  static hashval_t avail_expr_hash (const void *);
  static int avail_expr_eq (const void *, const void *);
--- 92,98 ----
  static void set_value_for (tree, tree, htab_t);
  static hashval_t var_value_hash (const void *);
  static int var_value_eq (const void *, const void *);
! static tree lookup_avail_expr (tree, varray_type *, htab_t, bool);
  static tree get_eq_expr_value (tree, int, varray_type *, htab_t);
  static hashval_t avail_expr_hash (const void *);
  static int avail_expr_eq (const void *, const void *);
*************** static void record_cond_is_false (tree, 
*** 101,106 ****
--- 101,108 ----
  static void record_cond_is_true (tree, varray_type *, htab_t);
  static void thread_edge (edge, basic_block);
  static void mark_new_vars_to_rename (tree, sbitmap);
+ static tree update_rhs_and_lookup_avail_expr (tree, tree, varray_type *,
+ 					      htab_t, stmt_ann_t, bool);
  
  /* Optimize function FNDECL based on the dominator tree.  This does
     simple const/copy propagation and redundant expression elimination using
*************** optimize_block (basic_block bb, tree par
*** 573,581 ****
  	 see if we know which arm will be taken.  */
        if (stmt && TREE_CODE (stmt) == COND_EXPR)
  	{
! 	  tree cached_lhs = lookup_avail_expr (stmt,
! 					       &block_avail_exprs,
! 					       const_and_copies);
  	  if (cached_lhs)
  	    {
  	      edge taken_edge = find_taken_edge (bb->succ->dest, cached_lhs);
--- 575,583 ----
  	 see if we know which arm will be taken.  */
        if (stmt && TREE_CODE (stmt) == COND_EXPR)
  	{
! 	  tree cached_lhs = lookup_avail_expr (stmt, &block_avail_exprs,
! 					       const_and_copies, false);
! 
  	  if (cached_lhs)
  	    {
  	      edge taken_edge = find_taken_edge (bb->succ->dest, cached_lhs);
*************** record_cond_is_true (tree cond,
*** 692,698 ****
    tree stmt;
  
    stmt = build (MODIFY_EXPR, boolean_type_node, integer_one_node, cond);
!   lookup_avail_expr (stmt, block_avail_exprs_p, const_and_copies);
  }
  
  /* Enter a statement into the available expression hash table indicating
--- 694,700 ----
    tree stmt;
  
    stmt = build (MODIFY_EXPR, boolean_type_node, integer_one_node, cond);
!   lookup_avail_expr (stmt, block_avail_exprs_p, const_and_copies, true);
  }
  
  /* Enter a statement into the available expression hash table indicating
*************** record_cond_is_false (tree cond,
*** 706,712 ****
    tree stmt;
  
    stmt = build (MODIFY_EXPR, boolean_type_node, integer_zero_node, cond);
!   lookup_avail_expr (stmt, block_avail_exprs_p, const_and_copies);
  }
  
  /* Optimize the statement pointed by iterator SI into SSA form. 
--- 708,714 ----
    tree stmt;
  
    stmt = build (MODIFY_EXPR, boolean_type_node, integer_zero_node, cond);
!   lookup_avail_expr (stmt, block_avail_exprs_p, const_and_copies, true);
  }
  
  /* Optimize the statement pointed by iterator SI into SSA form. 
*************** optimize_stmt (block_stmt_iterator si, v
*** 888,894 ****
  	 reaching definition for the variable defined by this statement.  */
        tree cached_lhs = lookup_avail_expr (stmt,
  					   block_avail_exprs_p,
! 					   const_and_copies);
  
        if (TREE_CODE (stmt) == MODIFY_EXPR)
  	def = TREE_OPERAND (stmt, 0);
--- 890,898 ----
  	 reaching definition for the variable defined by this statement.  */
        tree cached_lhs = lookup_avail_expr (stmt,
  					   block_avail_exprs_p,
! 					   const_and_copies,
! 					   (TREE_CODE (stmt) == MODIFY_EXPR
! 					    ? true : false));
  
        if (TREE_CODE (stmt) == MODIFY_EXPR)
  	def = TREE_OPERAND (stmt, 0);
*************** optimize_stmt (block_stmt_iterator si, v
*** 1049,1055 ****
  
  	      /* Finally enter the statement into the available expression
  		table.  */
! 	      lookup_avail_expr (new, block_avail_exprs_p, const_and_copies);
  	    }
  	}
  
--- 1053,1060 ----
  
  	      /* Finally enter the statement into the available expression
  		table.  */
! 	      lookup_avail_expr (new, block_avail_exprs_p,
! 				const_and_copies, true);
  	    }
  	}
  
*************** optimize_stmt (block_stmt_iterator si, v
*** 1084,1099 ****
  
  	  cond = build (GT_EXPR, boolean_type_node, op, integer_zero_node);
  	  cond = build (COND_EXPR, void_type_node, cond, NULL, NULL);
! 	  val = lookup_avail_expr (cond, block_avail_exprs_p, const_and_copies);
  
  	  /* Also try with GE_EXPR if we did not get a hit with GT_EXPR.  */
  	  if (! val || ! integer_onep (val))
  	    {
  	      cond = build (GE_EXPR, boolean_type_node, op, integer_zero_node);
  	      cond = build (COND_EXPR, void_type_node, cond, NULL, NULL);
! 	      val = lookup_avail_expr (cond,
! 				       block_avail_exprs_p,
! 				       const_and_copies);
  	    }
  	    
  	  if (val && integer_onep (val))
--- 1089,1104 ----
  
  	  cond = build (GT_EXPR, boolean_type_node, op, integer_zero_node);
  	  cond = build (COND_EXPR, void_type_node, cond, NULL, NULL);
! 	  val = lookup_avail_expr (cond, block_avail_exprs_p,
! 				   const_and_copies, false);
  
  	  /* Also try with GE_EXPR if we did not get a hit with GT_EXPR.  */
  	  if (! val || ! integer_onep (val))
  	    {
  	      cond = build (GE_EXPR, boolean_type_node, op, integer_zero_node);
  	      cond = build (COND_EXPR, void_type_node, cond, NULL, NULL);
! 	      val = lookup_avail_expr (cond, block_avail_exprs_p,
! 				       const_and_copies, true);
  	    }
  	    
  	  if (val && integer_onep (val))
*************** optimize_stmt (block_stmt_iterator si, v
*** 1110,1138 ****
  			   fold (build (MINUS_EXPR, TREE_TYPE (op1),
  					op1, integer_one_node)));
  
! 	      /* Remove the old entry from the hash table.  */
! 	      if (may_optimize_p)
! 		htab_remove_elt (avail_exprs, stmt);
! 
! 	      /* Now update the RHS of the assignment to use the new node.  */
! 	      TREE_OPERAND (stmt, 1) = t;
! 
! 	      if (may_optimize_p)
! 		{
! 		  /* Now force the updated statement into the hash table.  */
! 		  lookup_avail_expr (stmt,
! 				     block_avail_exprs_p,
! 				     const_and_copies);
! 
! 		  /* Annoyingly we now have two entries for this statement in
! 		     BLOCK_AVAIL_EXPRs.  Luckily we can just pop off the newest
! 		     entry.  */
! 		  VARRAY_POP (*block_avail_exprs_p);
! 		}
! 
! 	      /* And make sure we record the fact that we modified this
! 	         statement.  */
! 	      ann->modified = 1;
  	    }
          }
  
--- 1115,1125 ----
  			   fold (build (MINUS_EXPR, TREE_TYPE (op1),
  					op1, integer_one_node)));
  
! 	      update_rhs_and_lookup_avail_expr (stmt, t,
! 						block_avail_exprs_p,
! 						const_and_copies,
! 						ann,
! 						may_optimize_p);
  	    }
          }
  
*************** optimize_stmt (block_stmt_iterator si, v
*** 1146,1152 ****
  	  cond = build (LT_EXPR, boolean_type_node, op,
  			convert (type, integer_zero_node));
  	  cond = build (COND_EXPR, void_type_node, cond, NULL, NULL);
! 	  val = lookup_avail_expr (cond, block_avail_exprs_p, const_and_copies);
  
  	  if (! val
  	      || (! integer_onep (val) && ! integer_zerop (val)))
--- 1133,1140 ----
  	  cond = build (LT_EXPR, boolean_type_node, op,
  			convert (type, integer_zero_node));
  	  cond = build (COND_EXPR, void_type_node, cond, NULL, NULL);
! 	  val = lookup_avail_expr (cond, block_avail_exprs_p,
! 				   const_and_copies, false);
  
  	  if (! val
  	      || (! integer_onep (val) && ! integer_zerop (val)))
*************** optimize_stmt (block_stmt_iterator si, v
*** 1154,1162 ****
  	      cond = build (LE_EXPR, boolean_type_node, op,
  			    convert (type, integer_zero_node));
  	      cond = build (COND_EXPR, void_type_node, cond, NULL, NULL);
! 	      val = lookup_avail_expr (cond,
! 				       block_avail_exprs_p,
! 				       const_and_copies);
  	    }
  	    
  	  if (val
--- 1142,1149 ----
  	      cond = build (LE_EXPR, boolean_type_node, op,
  			    convert (type, integer_zero_node));
  	      cond = build (COND_EXPR, void_type_node, cond, NULL, NULL);
! 	      val = lookup_avail_expr (cond, block_avail_exprs_p,
! 				       const_and_copies, false);
  	    }
  	    
  	  if (val
*************** optimize_stmt (block_stmt_iterator si, v
*** 1169,1197 ****
  	      else
  		t = op;
  
! 	      /* Remove the old entry from the hash table.  */
! 	      if (may_optimize_p)
! 		htab_remove_elt (avail_exprs, stmt);
! 
! 	      /* Now update the RHS of the assignment to use the new node.  */
! 	      TREE_OPERAND (stmt, 1) = t;
! 
! 	      if (may_optimize_p)
! 		{
! 		  /* Now force the updated statement into the hash table.  */
! 		  lookup_avail_expr (stmt,
! 				     block_avail_exprs_p,
! 				     const_and_copies);
! 
! 		  /* Annoyingly we now have two entries for this statement in
! 		     BLOCK_AVAIL_EXPRs.  Luckily we can just pop off the newest
! 		     entry.  */
! 		  VARRAY_POP (*block_avail_exprs_p);
! 		}
! 
! 	      /* And make sure we record the fact that we modified this
! 	         statement.  */
! 	      ann->modified = 1;
  	    }
          }
      }
--- 1156,1166 ----
  	      else
  		t = op;
  
! 	      update_rhs_and_lookup_avail_expr (stmt, t,
! 						block_avail_exprs_p,
! 						const_and_copies,
! 						ann,
! 						may_optimize_p);
  	    }
          }
      }
*************** optimize_stmt (block_stmt_iterator si, v
*** 1225,1230 ****
--- 1194,1257 ----
    return may_have_exposed_new_symbols;
  }
  
+ /* Replace the RHS of STMT with NEW_RHS.  If RHS can be found in the
+    available expression hashtable, then return the LHS from the hash
+    table.
+ 
+    If INSERT is true, then we also update the available expression
+    hash table to account for the changes made to STMT.  */
+ 
+ static tree
+ update_rhs_and_lookup_avail_expr (tree stmt, tree new_rhs, 
+ 				  varray_type *block_avail_exprs_p,
+ 				  htab_t const_and_copies,
+ 				  stmt_ann_t ann,
+ 				  bool insert)
+ {
+   tree cached_lhs = NULL;
+ 
+   /* Remove the old entry from the hash table.  */
+   if (insert)
+     htab_remove_elt (avail_exprs, stmt);
+ 
+   /* Now update the RHS of the assignment.  */
+   TREE_OPERAND (stmt, 1) = new_rhs;
+ 
+   /* Now lookup the updated statement in the hash table.  */
+   cached_lhs = lookup_avail_expr (stmt, block_avail_exprs_p,
+ 				  const_and_copies, insert);
+ 
+   /* We have now called lookup_avail_expr twice with two different
+      versions of this same statement, once in optimize_stmt, once here.
+ 
+      We know the call in optimize_stmt did not find an existing entry
+      in the hash table, so a new entry was created.  At the same time
+      this statement was pushed onto the BLOCK_AVAIL_EXPRS varray. 
+ 
+      If this call failed to find an existing entry on the hash table,
+      then the new version of this statement was entered into the
+      hash table.  And this statement was pushed onto BLOCK_AVAIL_EXPR
+      for the second time.  So there are two copies on BLOCK_AVAIL_EXPRs
+ 
+      If this call succeeded, we still have one copy of this statement
+      on the BLOCK_AVAIL_EXPRs varray.
+ 
+      For both cases, we need to pop the most recent entry off the
+      BLOCK_AVAIL_EXPRs varray.  For the case where we never found this
+      statement in the hash tables, that will leave precisely one
+      copy of this statement on BLOCK_AVAIL_EXPRs.  For the case where
+      we found a copy of this statement in the second hash table lookup
+      we want _no_ copies of this statement in BLOCK_AVAIL_EXPRs.  */
+   if (insert)
+     VARRAY_POP (*block_avail_exprs_p);
+ 
+   /* And make sure we record the fact that we modified this
+      statement.  */
+   ann->modified = 1;
+ 
+   return cached_lhs;
+ }
+ 
  /* Hashing and equality functions for VAR_VALUE_D.  */
  
  static hashval_t
*************** set_value_for (tree var, tree value, hta
*** 1302,1337 ****
  static tree
  lookup_avail_expr (tree stmt,
  		   varray_type *block_avail_exprs_p,
! 		   htab_t const_and_copies)
  {
    void **slot;
    tree rhs;
    tree lhs;
    tree temp;
-   int insert;
  
    /* For a COND_EXPR, the expression we care about is in operand 0, not
       operand 1.  Also note that for a COND_EXPR, we merely want to see if
       we have the expression in the hash table, we do not want to create
       a new entry in the hash table.  */
    if (TREE_CODE (stmt) == COND_EXPR)
!     {
!       rhs = TREE_OPERAND (stmt, 0);
!       insert = 0;
!     }
    /* For RETURN_EXPR, we want the RHS of the MODIFY_EXPR in operand 0
       of the RETURN_EXPR.  */
    else if (TREE_CODE (stmt) == RETURN_EXPR
  	   && TREE_OPERAND (stmt, 0))
!     {
!       rhs = TREE_OPERAND (TREE_OPERAND (stmt, 0), 1);
!       insert = 1;
!     }
    else
!     {
!       rhs = TREE_OPERAND (stmt, 1);
!       insert = 1;
!     }
  
    /* Don't bother remembering constant assignments and copy operations.
       Constants and copy operations are handled by the constant/copy 
propagator
--- 1329,1355 ----
  static tree
  lookup_avail_expr (tree stmt,
  		   varray_type *block_avail_exprs_p,
! 		   htab_t const_and_copies,
! 		   bool insert)
  {
    void **slot;
    tree rhs;
    tree lhs;
    tree temp;
  
    /* For a COND_EXPR, the expression we care about is in operand 0, not
       operand 1.  Also note that for a COND_EXPR, we merely want to see if
       we have the expression in the hash table, we do not want to create
       a new entry in the hash table.  */
    if (TREE_CODE (stmt) == COND_EXPR)
!     rhs = TREE_OPERAND (stmt, 0);
    /* For RETURN_EXPR, we want the RHS of the MODIFY_EXPR in operand 0
       of the RETURN_EXPR.  */
    else if (TREE_CODE (stmt) == RETURN_EXPR
  	   && TREE_OPERAND (stmt, 0))
!     rhs = TREE_OPERAND (TREE_OPERAND (stmt, 0), 1);
    else
!     rhs = TREE_OPERAND (stmt, 1);
  
    /* Don't bother remembering constant assignments and copy operations.
       Constants and copy operations are handled by the constant/copy 
propagator

  





More information about the Gcc-patches mailing list