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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[tree-ssa-branch] various dfa/cfg fixes [patch]


This patch fixes several bugs in the CFG and varref code:

- When removing unreachable blocks from loop constructs, we were
  not updating the pointers kept inside the entry block.

- We were not saving enough information inside varrefs to be able
  to replace them in their parent expression.  We now keep a
  pointer to the operand location inside the expression.  An
  added advantage is that we don't need to traverse the
  expression tree looking for the reference we want to replace.

- When looking for references inside compound references
  (structures, unions, complex types, arrays), we were not
  creating a reference for the whole reference.  For instance:

  	a.b.c.d = 5;

  was creating a reference to a, b, c and d separately.  All
  those definitions were assigning 5 to each member.  We now
  correctly note 4 definitions in the above statement: the
  assignment of 5 to a.b.c.d and the clobber of a.b.c, a.b and a.


Bootstrapped and tested on x86.


Diego.


	* basic-block.h (BB_CONTROL_EXPR): Update value.
	(BB_LOOP_CONTROL_EXPR): Define.
	(BB_CONTROL_ENTRY): Update value.
	* tree-cfg.c (make_for_stmt_blocks): Flag header blocks with
	BB_LOOP_CONTROL_EXPR.
	(make_while_stmt_blocks): Ditto.
	(make_do_stmt_blocks): Ditto.
	(tree_delete_bb): Update annotations in the loop entry block when
	removing one of the loop expression blocks.

	* tree-dfa.c (tree_find_varrefs): Disregard empty blocks.
	(find_refs_in_stmt): Handle all the loop expression blocks in
	FOR_STMT and DO_STMT nodes.
	(find_refs_in_expr): Change first argument to tree *.  Update all
	callers.
	Force all references to be definitions when the expression is not
	in SIMPLE form.
	Also create references for compound variables and array references.
	Not just their individual components.
	Always use the original parent expression when making recursive
	calls.
	(create_ref): Add new argument operand_p.  Update all callers.
	(remove_tree_ann): New function.
	(dump_varref): Don't assume that the referenced symbol is a _DECL
	node.
	* tree-flow.h (treeref_common): Add field operand_p.
	(VARREF_OPERAND_P): Define.
	(BB_EMPTY_P): Define.
	(remove_tree_ann): Declare.
	(create_ref): Add new argument operand_p.
	* tree-simple.c (get_base_symbol): New function.
	* tree-simple.h (get_base_symbol): Declare.
	* tree-ssa-ccp.c (visit_assignment): Call it.
	(ssa_ccp_substitute_constants): Use VARREF_OPERAND_P to replace
	values into the expression.
	(evaluate_expr_for): Ditto.
	Do not try to evaluate the expression if the reference is not of
	the same type as the expression.
	After evaluation, restore the expression to its original form.
	* tree-ssa-pre.c (insert_occ_in_preorder_dt_order_): Update calls
	to create_ref.
	(finalize_): Ditto.
	(expr_phi_insertion): Ditto.
	* tree-ssa.c (tree_build_ssa): Ditto.
	(insert_phi_terms): Ditto.
	(delete_ssa): Call remove_tree_ann.


Index: basic-block.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/basic-block.h,v
retrieving revision 1.153.2.7
diff -d -u -p -r1.153.2.7 basic-block.h
--- basic-block.h	7 Aug 2002 16:02:57 -0000	1.153.2.7
+++ basic-block.h	16 Aug 2002 13:28:30 -0000
@@ -241,10 +241,13 @@ typedef struct basic_block_def {
 #define BB_VISITED		8
 
 /* Block contains a control flow expression.  */
-#define BB_CONTROL_EXPR		8
+#define BB_CONTROL_EXPR		16
+
+/* Block contains a control flow expression for a loop.  */
+#define BB_LOOP_CONTROL_EXPR	32
 
 /* Block is the entry block to a control statement but contains no code.  */
-#define BB_CONTROL_ENTRY	16
+#define BB_CONTROL_ENTRY	64
 
 /* Number of basic blocks in the current function.  */
 
Index: tree-cfg.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-cfg.c,v
retrieving revision 1.1.4.7
diff -d -u -p -r1.1.4.7 tree-cfg.c
--- tree-cfg.c	15 Aug 2002 21:50:47 -0000	1.1.4.7
+++ tree-cfg.c	16 Aug 2002 13:28:32 -0000
@@ -264,25 +264,25 @@ make_for_stmt_blocks (t, control_parent,
      An expression block avoids having multiple back edges to the condition
      block.  This, in turn, helps the natural loop recognizer identify only
      one loop instead of several shared ones.  */
-  cond = (FOR_COND (t)) ? FOR_COND (t) : build_int_2 (1, 0);
-  expr = (FOR_EXPR (t)) ? FOR_EXPR (t) : build_int_2 (1, 0);
+  cond = (FOR_COND (t)) ? FOR_COND (t) : integer_one_node;
+  expr = (FOR_EXPR (t)) ? FOR_EXPR (t) : integer_one_node;
 
   entry = create_bb (t, t, control_parent, prev_chain_p, NULL);
   entry->flags |= BB_CONTROL_ENTRY;
 
   bb = create_maximal_bb (FOR_INIT_STMT (t), entry, compound_stmt,
                           &(FOR_INIT_STMT (t)));
-  bb->flags |= BB_CONTROL_EXPR;
+  bb->flags |= BB_CONTROL_EXPR | BB_LOOP_CONTROL_EXPR;
   FOR_INIT_STMT_BB (entry) = bb;
 
   bb = create_maximal_bb (cond, entry, compound_stmt, &(FOR_COND (t)));
-  bb->flags |= BB_CONTROL_EXPR;
+  bb->flags |= BB_CONTROL_EXPR | BB_LOOP_CONTROL_EXPR;
   FOR_COND_BB (entry) = bb;
 
   make_blocks (FOR_BODY (t), entry, compound_stmt, &(FOR_BODY (t)));
 
   bb = create_maximal_bb (expr, entry, compound_stmt, &(FOR_EXPR (t)));
-  bb->flags |= BB_CONTROL_EXPR;
+  bb->flags |= BB_CONTROL_EXPR | BB_LOOP_CONTROL_EXPR;
   FOR_EXPR_BB (entry) = bb;
 }
 
@@ -300,14 +300,14 @@ make_while_stmt_blocks (t, control_paren
   basic_block bb, entry;
   
   entry = create_bb (t, t, control_parent, prev_chain_p, NULL);
-  entry->flags |= BB_CONTROL_ENTRY | BB_CONTROL_EXPR;
+  entry->flags |= BB_CONTROL_ENTRY | BB_CONTROL_EXPR | BB_LOOP_CONTROL_EXPR;
   
   make_blocks (WHILE_BODY (t), entry, compound_stmt, &(WHILE_BODY (t)));
 
   /* END_WHILE block.  Needed to avoid multiple back edges that would
      result in multiple natural loops instead of just one.  */
-  bb = create_maximal_bb (build_int_2 (1, 0), entry, compound_stmt, NULL);
-  bb->flags |= BB_CONTROL_ENTRY;
+  bb = create_maximal_bb (integer_one_node, entry, compound_stmt, NULL);
+  bb->flags |= BB_CONTROL_EXPR | BB_LOOP_CONTROL_EXPR;
   END_WHILE_BB (entry) = bb;
 }
 
@@ -330,7 +330,7 @@ make_do_stmt_blocks (t, control_parent, 
   make_blocks (DO_BODY (t), entry, compound_stmt, &(DO_BODY (t)));
 
   bb = create_maximal_bb (DO_COND (t), entry, compound_stmt, &(DO_COND (t)));
-  bb->flags |= BB_CONTROL_EXPR;
+  bb->flags |= BB_CONTROL_EXPR | BB_LOOP_CONTROL_EXPR;
   DO_COND_BB (entry) = bb;
 }
 
@@ -1159,6 +1159,41 @@ tree_delete_bb (bb)
 
   bb->pred = NULL;
   bb->succ = NULL;
+
+  /* When removing the blocks controlling a loop construct, we need to
+     update related blocks.  */
+  if (bb->flags & BB_LOOP_CONTROL_EXPR
+      /* If this is the entry block, do nothing.  The whole structure is
+	 going to disappear anyway.  */
+      && !(bb->flags & BB_CONTROL_ENTRY)
+      /* If the parent block has disappeared, we don't need to do anything
+	 else.  */
+      && BB_PARENT (bb)->index != INVALID_BLOCK)
+    {
+      basic_block entry_bb;
+      tree stmt;
+      
+      entry_bb = BB_PARENT (bb);
+      stmt = entry_bb->head_tree;
+
+      if (TREE_CODE (stmt) == FOR_STMT)
+	{
+	  if (FOR_COND_BB (entry_bb) == bb)
+	    FOR_COND_BB (entry_bb) = NULL;
+	  else if (FOR_EXPR_BB (entry_bb) == bb)
+	    FOR_EXPR_BB (entry_bb) = NULL;
+	  else if (FOR_INIT_STMT_BB (entry_bb) == bb)
+	    FOR_INIT_STMT_BB (entry_bb) = NULL;
+	  else
+	    abort ();
+	}
+      else if (TREE_CODE (stmt) == WHILE_STMT && END_WHILE_BB (entry_bb) == bb)
+	END_WHILE_BB (entry_bb) = NULL;
+      else if (TREE_CODE (stmt) == DO_STMT && DO_COND_BB (entry_bb) == bb)
+	DO_COND_BB (entry_bb) = NULL;
+      else
+	abort ();
+    }
 
   /* Remove the basic block from the array.  */
   expunge_block (bb);
Index: tree-dfa.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-dfa.c,v
retrieving revision 1.1.4.6
diff -d -u -p -r1.1.4.6 tree-dfa.c
--- tree-dfa.c	11 Aug 2002 23:02:52 -0000	1.1.4.6
+++ tree-dfa.c	16 Aug 2002 13:28:32 -0000
@@ -46,7 +46,7 @@ static int dump_flags;
 
 /* Local functions.  */
 static void find_refs_in_stmt PARAMS ((tree, basic_block));
-static void find_refs_in_expr PARAMS ((tree, enum treeref_type, basic_block,
+static void find_refs_in_expr PARAMS ((tree *, enum treeref_type, basic_block,
 				       tree, tree));
 static void create_tree_ann PARAMS ((tree));
 static void add_ref_symbol PARAMS ((tree));
@@ -76,19 +76,20 @@ tree_find_varrefs ()
     {
       tree t = bb->head_tree;
 
+      if (BB_EMPTY_P (bb))
+	continue;
+
       while (t)
 	{
+	  /* Some basic blocks are composed exclusively of expressions
+	     (e.g., FOR_* and DO_COND nodes), these are handled when
+	     find_refs_in_stmt processes their entry node.  */
 	  if (statement_code_p (TREE_CODE (t)))
 	    {
 	      find_refs_in_stmt (t, bb);
 	      if (t == bb->end_tree || is_ctrl_stmt (t))
 		break;
 	    }
-	  else
-	    {
-	      tree parent = BB_PARENT (bb)->head_tree;
-	      find_refs_in_expr (t, VARUSE, bb, parent, t);
-	    }
 
 	  t = TREE_CHAIN (t);
 	}
@@ -137,64 +138,73 @@ find_refs_in_stmt (t, bb)
   switch (code)
     {
     case EXPR_STMT:
-      find_refs_in_expr (EXPR_STMT_EXPR (t), VARUSE, bb, t, t);
+      find_refs_in_expr (&EXPR_STMT_EXPR (t), VARUSE, bb, t,
+	                 EXPR_STMT_EXPR (t));
       break;
 
-      /* The condition nodes for IF_STMT, SWITCH_STMT and WHILE_STMT are not
-	 modeled in the flowgraph, so they need to be looked at separately.  */
     case IF_STMT:
-      find_refs_in_expr (IF_COND (t), VARUSE, bb, t, t);
+      find_refs_in_expr (&IF_COND (t), VARUSE, bb, t, IF_COND (t));
       break;
       
     case SWITCH_STMT:
-      find_refs_in_expr (SWITCH_COND (t), VARUSE, bb, t, t);
+      find_refs_in_expr (&SWITCH_COND (t), VARUSE, bb, t, SWITCH_COND (t));
       break;
 
     case WHILE_STMT:
-      find_refs_in_expr (WHILE_COND (t), VARUSE, bb, t, t);
+      find_refs_in_expr (&WHILE_COND (t), VARUSE, bb, t, WHILE_COND (t));
       break;
 
-      /* There is no need to check the children nodes for DO_STMTs and
-	 FOR_STMTs, because they're in separate basic blocks.  */
     case FOR_STMT:
+      /* Grr, the FOR_INIT_STMT node of a FOR_STMT is also a statement,
+	 which is handled by the main loop in tree_find_varrefs.  */
+      if (FOR_COND_BB (bb))
+	find_refs_in_expr (&FOR_COND (t), VARUSE, FOR_COND_BB (bb), t,
+			   FOR_COND (t));
+
+      if (FOR_EXPR_BB (bb))
+	find_refs_in_expr (&FOR_EXPR (t), VARUSE, FOR_EXPR_BB (bb), t,
+			   FOR_EXPR (t));
+      break;
+
     case DO_STMT:
-      break;	                        /* Nothing to do.  */
+      if (DO_COND_BB (bb))
+	find_refs_in_expr (&DO_COND (t), VARUSE, DO_COND_BB (bb), t,
+	                   DO_COND (t));
+      break;
 
     case ASM_STMT:
-      find_refs_in_expr (ASM_INPUTS (t), VARUSE, bb, t, t);
-      find_refs_in_expr (ASM_OUTPUTS (t), VARDEF, bb, t, t);
-      find_refs_in_expr (ASM_CLOBBERS (t), VARDEF, bb, t, t);
+      find_refs_in_expr (&ASM_INPUTS (t), VARUSE, bb, t, ASM_INPUTS (t));
+      find_refs_in_expr (&ASM_OUTPUTS (t), VARDEF, bb, t, ASM_OUTPUTS (t));
+      find_refs_in_expr (&ASM_CLOBBERS (t), VARDEF, bb, t, ASM_CLOBBERS (t));
       break;
 
     case RETURN_STMT:
-      find_refs_in_expr (RETURN_EXPR (t), VARUSE, bb, t, t);
+      find_refs_in_expr (&RETURN_EXPR (t), VARUSE, bb, t, RETURN_EXPR (t));
       break;
 
     case GOTO_STMT:
-      find_refs_in_expr (GOTO_DESTINATION (t), VARUSE, bb, t, t);
+      find_refs_in_expr (&GOTO_DESTINATION (t), VARUSE, bb, t, t);
       break;
 
     case DECL_STMT:
-      if (TREE_CODE (DECL_STMT_DECL (t)) == VAR_DECL)
-	{
-	  tree decl = DECL_STMT_DECL (t);
-	  if (DECL_INITIAL (decl))
-	    find_refs_in_expr (decl, VARDEF, bb, t, t);
-	}
+      if (TREE_CODE (DECL_STMT_DECL (t)) == VAR_DECL
+	  && DECL_INITIAL (DECL_STMT_DECL (t)))
+	find_refs_in_expr (&DECL_STMT_DECL (t), VARDEF, bb, t,
+			   DECL_STMT_DECL (t));
       break;
 
     case CLEANUP_STMT:
-      if (TREE_CODE (CLEANUP_DECL (t)) == VAR_DECL)
-	{
-	  tree decl = TREE_OPERAND (t, 0);
-	  if (DECL_INITIAL (decl))
-	    find_refs_in_expr (decl, VARDEF, bb, t, t);
-	}
-      find_refs_in_expr (CLEANUP_EXPR (t), VARUSE, bb, t, t);
+      if (TREE_CODE (CLEANUP_DECL (t)) == VAR_DECL
+	  && DECL_INITIAL (TREE_OPERAND (t, 0)))
+	find_refs_in_expr (&TREE_OPERAND (t, 0), VARDEF, bb, t,
+			   TREE_OPERAND (t, 0));
+
+      find_refs_in_expr (&CLEANUP_EXPR (t), VARUSE, bb, t, CLEANUP_EXPR (t));
       break;
 
     case LABEL_STMT:
-      find_refs_in_expr (LABEL_STMT_LABEL (t), VARUSE, bb, t, t);
+      find_refs_in_expr (&LABEL_STMT_LABEL (t), VARUSE, bb, t,
+			 LABEL_STMT_LABEL (t));
       break;
 
     case STMT_EXPR:
@@ -224,58 +234,83 @@ find_refs_in_stmt (t, bb)
 }
 
 
-/*  Recursively scan the expression tree EXPR looking for variable
-    references.
+/* Recursively scan the expression tree pointed by EXPR_P looking for
+   variable references.
    
-    REF_TYPE indicates what type of reference should be created.
+   REF_TYPE indicates what type of reference should be created.
 
-    BB, PARENT_STMT and PARENT_EXPR are the block, statement and expression
-      trees containing EXPR.  */
+   BB, PARENT_STMT and PARENT_EXPR are the block, statement and expression
+      trees containing *EXPR_P.
+      
+   NOTE: PARENT_EXPR is the root node of the expression tree hanging off of
+      PARENT_STMT.  For instance, given the statement 'a = b + c;', the
+      parent expression for all references inside the statement is the '='
+      node.  */
 
 static void
-find_refs_in_expr (expr, ref_type, bb, parent_stmt, parent_expr)
-     tree expr;
+find_refs_in_expr (expr_p, ref_type, bb, parent_stmt, parent_expr)
+     tree *expr_p;
      enum treeref_type ref_type;
      basic_block bb;
      tree parent_stmt;
      tree parent_expr;
 {
   enum tree_code code;
+  tree expr = *expr_p;
 
   if (expr == NULL || expr == error_mark_node)
     return;
 
+  /* If this reference is associated with a non SIMPLE expression, then we
+     change the reference type to VARDEF (regardless of the original
+     reference type) to indicate to the optimizers that this tree clobbers
+     the referenced variable.  */
+  if (TREE_ANN (expr) && (TREE_FLAGS (expr) & TF_NOT_SIMPLE))
+    return;
+
   code = TREE_CODE (expr);
 
+  /* If we found a _DECL node, create a reference to it and return.  */
   if (code == VAR_DECL
       || code == FUNCTION_DECL
-      || code == PARM_DECL
-      || code == FIELD_DECL)
+      || code == PARM_DECL)
     {
-      create_ref (expr, ref_type, bb, parent_stmt, parent_expr);
+      create_ref (expr, ref_type, bb, parent_stmt, parent_expr, expr_p);
       return;
     }
 
-  switch (code)
+  /* References to compound variables: indirect references, complex types
+     and component references.  We create a reference for the whole
+     expression and find more references on the left operand.  This way a
+     reference of the form 'a.b.c.d = 5;' will create definitions for
+     'a.b.c.d', 'a.b.c', 'a.b' and 'a'.  */
+  if (code == INDIRECT_REF
+      || code == IMAGPART_EXPR
+      || code == REALPART_EXPR
+      || code == COMPONENT_REF)
     {
-      /* Structure and union references.  Use the same reference type that
-	 was given by our caller.  */
-    case COMPONENT_REF:
-      find_refs_in_expr (TREE_OPERAND (expr, 0), ref_type, bb, parent_stmt,
-			 expr);
-      find_refs_in_expr (TREE_OPERAND (expr, 1), ref_type, bb, parent_stmt,
-			 expr);
-      break;
+      create_ref (expr, ref_type, bb, parent_stmt, parent_expr, expr_p);
+      find_refs_in_expr (&TREE_OPERAND (expr, 0), ref_type, bb, parent_stmt,
+	                 parent_expr);
+      return;
+    }
 
-      /* Array references.  Use the same reference type for the array, but
-	 default to VARUSE for the index expression.  */
-    case ARRAY_REF:
-      find_refs_in_expr (TREE_OPERAND (expr, 0), ref_type, bb, parent_stmt,
-			 expr);
-      find_refs_in_expr (TREE_OPERAND (expr, 1), VARUSE, bb, parent_stmt,
-			 expr);
-      break;
+  /* Array references are treated similarly.  Create a new reference for
+     the whole array reference using the incoming reference type.
+     Additionally, we must recurse into the RHS of the array reference to
+     look for variables used as index expressions.  */
+  if (code == ARRAY_REF)
+    {
+      create_ref (expr, ref_type, bb, parent_stmt, parent_expr, expr_p);
+      find_refs_in_expr (&TREE_OPERAND (expr, 0), ref_type, bb, parent_stmt,
+			 parent_expr);
+      find_refs_in_expr (&TREE_OPERAND (expr, 1), VARUSE, bb, parent_stmt,
+			 parent_expr);
+      return;
+    }
 
+  switch (code)
+    {
       /* Unary expressions.  */
     case COMPLEX_CST:
     case INTEGER_CST:
@@ -297,32 +332,29 @@ find_refs_in_expr (expr, ref_type, bb, p
     case FIX_ROUND_EXPR:
     case FIX_TRUNC_EXPR:
     case FLOAT_EXPR:
-    case IMAGPART_EXPR:
-    case INDIRECT_REF:
     case NEGATE_EXPR:
     case NON_LVALUE_EXPR:
     case NOP_EXPR:
-    case REALPART_EXPR:
     case REFERENCE_EXPR:
-      find_refs_in_expr (TREE_OPERAND (expr, 0), ref_type, bb, parent_stmt,
-			 expr);
+      find_refs_in_expr (&TREE_OPERAND (expr, 0), ref_type, bb, parent_stmt,
+			 parent_expr);
       break;
 
     case BIT_NOT_EXPR:
     case TRUTH_NOT_EXPR:
     case VA_ARG_EXPR:
-      find_refs_in_expr (TREE_OPERAND (expr, 0), VARDEF, bb, parent_stmt,
-			 expr);
+      find_refs_in_expr (&TREE_OPERAND (expr, 0), VARDEF, bb, parent_stmt,
+			 parent_expr);
       break;
 
     case POSTDECREMENT_EXPR:
     case POSTINCREMENT_EXPR:
     case PREDECREMENT_EXPR:
     case PREINCREMENT_EXPR:
-      find_refs_in_expr (TREE_OPERAND (expr, 0), VARUSE, bb, parent_stmt,
-			 expr);
-      find_refs_in_expr (TREE_OPERAND (expr, 0), VARDEF, bb, parent_stmt,
-			 expr);
+      find_refs_in_expr (&TREE_OPERAND (expr, 0), VARUSE, bb, parent_stmt,
+			 parent_expr);
+      find_refs_in_expr (&TREE_OPERAND (expr, 0), VARDEF, bb, parent_stmt,
+			 parent_expr);
       break;
 
 
@@ -372,47 +404,48 @@ find_refs_in_expr (expr, ref_type, bb, p
     case UNLE_EXPR:
     case UNLT_EXPR:
     case UNORDERED_EXPR:
-      find_refs_in_expr (TREE_OPERAND (expr, 0), VARUSE, bb, parent_stmt,
-			 expr);
-      find_refs_in_expr (TREE_OPERAND (expr, 1), VARUSE, bb, parent_stmt,
-			 expr);
+      find_refs_in_expr (&TREE_OPERAND (expr, 0), VARUSE, bb, parent_stmt,
+			 parent_expr);
+      find_refs_in_expr (&TREE_OPERAND (expr, 1), VARUSE, bb, parent_stmt,
+			 parent_expr);
       break;
 
     case INIT_EXPR:
     case MODIFY_EXPR:
-      find_refs_in_expr (TREE_OPERAND (expr, 1), VARUSE, bb, parent_stmt,
-			 expr);
-      find_refs_in_expr (TREE_OPERAND (expr, 0), VARDEF, bb, parent_stmt,
-			 expr);
+      find_refs_in_expr (&TREE_OPERAND (expr, 1), VARUSE, bb, parent_stmt,
+			 parent_expr);
+      find_refs_in_expr (&TREE_OPERAND (expr, 0), VARDEF, bb, parent_stmt,
+			 parent_expr);
       break;
 
 
       /* Ternary operations.  */
     case BIT_FIELD_REF:
     case SAVE_EXPR:
-      find_refs_in_expr (TREE_OPERAND (expr, 0), ref_type, bb, parent_stmt,
-			 expr);
-      find_refs_in_expr (TREE_OPERAND (expr, 1), VARUSE, bb, parent_stmt,
-			 expr);
-      find_refs_in_expr (TREE_OPERAND (expr, 2), VARUSE, bb, parent_stmt,
-			 expr);
+      find_refs_in_expr (&TREE_OPERAND (expr, 0), ref_type, bb, parent_stmt,
+			 parent_expr);
+      find_refs_in_expr (&TREE_OPERAND (expr, 1), VARUSE, bb, parent_stmt,
+			 parent_expr);
+      find_refs_in_expr (&TREE_OPERAND (expr, 2), VARUSE, bb, parent_stmt,
+			 parent_expr);
       break;
 
       /* N-ary operations.  */
     case CALL_EXPR:
       {
 	tree op;
-	tree addr = TREE_OPERAND (expr, 0);
-	tree decl;
+	tree *addr_p = &TREE_OPERAND (expr, 0);
+	tree *decl_p;
 
-	if (TREE_CODE (addr) == ADDR_EXPR)
-	  decl = TREE_OPERAND (addr, 0);
+	if (TREE_CODE (*addr_p) == ADDR_EXPR)
+	  decl_p = &TREE_OPERAND (*addr_p, 0);
 	else
-	  decl = addr;
+	  decl_p = addr_p;
 
-	find_refs_in_expr (decl, VARUSE, bb, parent_stmt, expr);
+	find_refs_in_expr (decl_p, VARUSE, bb, parent_stmt, parent_expr);
 	for (op = TREE_OPERAND (expr, 1); op; op = TREE_CHAIN (op))
-	  find_refs_in_expr (TREE_VALUE (op), VARUSE, bb, parent_stmt, expr);
+	  find_refs_in_expr (&TREE_VALUE (op), VARUSE, bb, parent_stmt, 
+	                     parent_expr);
 	break;
       }
 
@@ -421,8 +454,8 @@ find_refs_in_expr (expr, ref_type, bb, p
 	tree op;
 
 	for (op = expr; op; op = TREE_CHAIN (op))
-	  find_refs_in_expr (TREE_VALUE (op), ref_type, bb, parent_stmt,
-			     expr);
+	  find_refs_in_expr (&TREE_VALUE (op), ref_type, bb, parent_stmt,
+			     parent_expr);
 	break;
       }
 
@@ -434,8 +467,8 @@ find_refs_in_expr (expr, ref_type, bb, p
 
       /* File and line number annotations.  */
     case EXPR_WITH_FILE_LOCATION:
-      find_refs_in_expr (TREE_OPERAND (expr, 0), ref_type, bb, parent_stmt,
-	                 expr);
+      find_refs_in_expr (&TREE_OPERAND (expr, 0), ref_type, bb, parent_stmt,
+	                 parent_expr);
       break;
 
     case COMPOUND_LITERAL_EXPR:
@@ -452,6 +485,7 @@ find_refs_in_expr (expr, ref_type, bb, p
     }
 }
 
+
 /* Create and return an empty list of references.  */
 
 ref_list
@@ -462,8 +496,10 @@ create_ref_list (void)
   return list;
 }
 
+
 /* Free the nodes in LIST, but keep the empty list around.  
-   (IE empty the list).  */
+   (i.e., empty the list).  */
+
 void 
 empty_ref_list (list)
      ref_list list;
@@ -480,8 +516,10 @@ empty_ref_list (list)
   list->first = list->last = NULL;
 }
 
+
 /* Delete LIST, including the list itself.
-   (IE destroy the list).  */
+   (i.e., destroy the list).  */
+
 void
 delete_ref_list (list)
      ref_list list;
@@ -526,6 +564,7 @@ remove_ref_from_list (list, ref)
     }
 }
 
+
 /* Add REF to the beginning of LIST.  */
 
 void
@@ -547,6 +586,7 @@ add_ref_to_list_begin (list, ref)
   list->first = node;
 }
 
+
 /* Add REF to the end of LIST.  */
 
 void
@@ -568,23 +608,25 @@ add_ref_to_list_end (list, ref)
   list->last = node;
 }
 
+
 /* Create references and associations to symbols and basic blocks.  */
 
-/*  Create a new variable reference for symbol SYM and add it to the list
-    of references for SYM and the basic block that holds the reference.
+/* Create a new variable reference for symbol SYM.
 
-    REF_TYPE is the type of reference to create (def, use, phi, etc).
+   REF_TYPE is the type of reference to create (def, use, phi, etc).
     
-    BB, PARENT_STMT and PARENT_EXPR give the exact location of the
-      reference.  */
+   BB, PARENT_STMT, PARENT_EXPR and OPERAND_P give the exact location of the
+      reference.  PARENT_STMT, PARENT_EXPR and OPERAND_P can be NULL in the
+      case of artificial references (PHI nodes, ghost definitions, etc).  */
 
 varref
-create_ref (sym, ref_type, bb, parent_stmt, parent_expr)
+create_ref (sym, ref_type, bb, parent_stmt, parent_expr, operand_p)
      tree sym;
      enum treeref_type ref_type;
      basic_block bb;
      tree parent_stmt;
      tree parent_expr;
+     tree *operand_p;
 {
   varref ref;
 
@@ -596,21 +638,13 @@ create_ref (sym, ref_type, bb, parent_st
   ref = (varref) ggc_alloc (sizeof (*ref));
   memset ((void *) ref, 0, sizeof (*ref));
 
-  /* If this reference is associated with a non SIMPLE expression, then we
-     change the reference type to VARDEF (regardless of the original
-     reference type) to indicate to the optimizers that this tree clobbers
-     the referenced variable.  */
-  if (parent_expr
-      && TREE_ANN (parent_expr)
-      && (TREE_FLAGS (parent_expr) & TF_NOT_SIMPLE))
-    ref_type = VARDEF;
-
   VARREF_ID (ref) = next_varref_id++;
   VARREF_SYM (ref) = sym;
   VARREF_TYPE (ref) = ref_type;
   VARREF_STMT (ref) = parent_stmt;
   VARREF_BB (ref) = bb;
   VARREF_EXPR (ref) = parent_expr;
+  VARREF_OPERAND_P (ref) = operand_p;
 
   /* Create containers according to the type of reference.  */
   if (ref_type == VARDEF || ref_type == VARPHI)
@@ -717,6 +751,20 @@ create_tree_ann (t)
   t->common.aux = (void *) ann;
 }
 
+/* Remove the annotation for tree T.  */
+
+void
+remove_tree_ann (t)
+     tree t;
+{
+  tree_ann ann = TREE_ANN (t);
+
+  ann->bb = NULL;
+  delete_ref_list (ann->refs);
+  ann->currdef = NULL;
+  ann->compound_stmt = NULL;
+  t->common.aux = NULL;
+}
 
 
 /* Miscellaneous helpers.  */
@@ -849,7 +897,7 @@ dump_varref (outf, prefix, ref, indent, 
      int details;
 {
   int lineno, bbix;
-  const char *sym, *type;
+  const char *type;
   char *s_indent;
 
   if (ref == NULL)
@@ -861,13 +909,6 @@ dump_varref (outf, prefix, ref, indent, 
 
   lineno = (VARREF_STMT (ref)) ? STMT_LINENO (VARREF_STMT (ref)) : -1;
 
-  sym = (VARREF_SYM (ref) 
-	 && VARREF_TYPE (ref) != EXPRPHI 
-	 && VARREF_TYPE (ref) != EXPRUSE
-	 && VARREF_TYPE (ref) != EXPRKILL
-	 && DECL_NAME (VARREF_SYM (ref)))
-    ? IDENTIFIER_POINTER (DECL_NAME (VARREF_SYM (ref))) : "nil";
-
   bbix = (VARREF_BB (ref)) ? VARREF_BB (ref)->index : -1;
 
   type = (VARREF_TYPE (ref) == VARDEF) ? "DEF" :
@@ -879,8 +920,14 @@ dump_varref (outf, prefix, ref, indent, 
 	 (VARREF_TYPE (ref) == EXPRINJ) ? "EXPRINJ" :
 	 "???";
 
-  fprintf (outf, "%s%s%s(%s): line %d, bb %d, id %d, ", s_indent, prefix, type,
-	   sym, lineno, bbix, VARREF_ID (ref));
+  fprintf (outf, "%s%s%s(", s_indent, prefix, type);
+
+  if (VARREF_SYM (ref))
+    print_c_node (outf, VARREF_SYM (ref));
+  else
+    fprintf (outf, "nil");
+
+  fprintf (outf, "): line %d, bb %d, id %d, ", lineno, bbix, VARREF_ID (ref));
 
   if (VARREF_EXPR (ref))
     print_c_node (outf, VARREF_EXPR (ref));
Index: tree-flow.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-flow.h,v
retrieving revision 1.1.4.6
diff -d -u -p -r1.1.4.6 tree-flow.h
--- tree-flow.h	11 Aug 2002 22:00:08 -0000	1.1.4.6
+++ tree-flow.h	16 Aug 2002 13:28:32 -0000
@@ -41,9 +41,12 @@ struct treeref_common
   /* Statement containing the reference.  */
   tree stmt;
 
-  /* Sub-tree containing the reference.  */
+  /* Expression tree containing the reference.  */
   tree expr;
 
+  /* Pointer to operand of EXPR containing the reference.  */
+  tree *operand_p;
+
   /* Basic block containing the reference.  */
   basic_block bb;
 
@@ -217,6 +220,7 @@ typedef union varref_def *varref;
 #define VARREF_TYPE(r) (r)->common.type
 #define VARREF_BB(r) (r)->common.bb
 #define VARREF_EXPR(r) (r)->common.expr
+#define VARREF_OPERAND_P(r) (r)->common.operand_p
 #define VARREF_STMT(r) (r)->common.stmt
 #define VARREF_SYM(r) (r)->common.sym
 
@@ -355,6 +359,11 @@ typedef struct bb_ann_def *bb_ann;
 #define END_WHILE_BB(BLOCK)	BB_LOOP_HDR (BLOCK)->end_while_bb
 #define DO_COND_BB(BLOCK)	BB_LOOP_HDR (BLOCK)->do_cond_bb
 
+/* Some basic blocks are nothing but markers used to give structure to the
+   flow graph (see make_while_stmt_blocks).  They contain no useful
+   instructions.  */
+#define BB_EMPTY_P(BLOCK)	((BLOCK)->head_tree == integer_one_node \
+                                 && (BLOCK)->end_tree == integer_one_node)
 
 /* Global declarations.  */
 
@@ -421,8 +430,9 @@ extern basic_block tree_split_bb PARAMS 
 
 extern void tree_find_varrefs PARAMS ((void));
 extern tree_ann get_tree_ann PARAMS ((tree));
+extern void remove_tree_ann PARAMS ((tree));
 extern varref create_ref PARAMS ((tree, enum treeref_type,
-				  basic_block, tree, tree));
+				  basic_block, tree, tree, tree *));
 extern void debug_varref PARAMS ((varref));
 extern void dump_varref PARAMS ((FILE *, const char *, varref, int, int));
 extern void debug_varref_list PARAMS ((ref_list));
Index: tree-simple.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-simple.c,v
retrieving revision 1.1.4.10
diff -d -u -p -r1.1.4.10 tree-simple.c
--- tree-simple.c	13 Aug 2002 14:27:23 -0000	1.1.4.10
+++ tree-simple.c	16 Aug 2002 13:28:32 -0000
@@ -935,3 +935,32 @@ rationalize_compound_expr (top)
     }
   return top;
 }
+
+/* Given a SIMPLE varname (an ID, an arrayref or a compref), return the
+   base symbol for the object.  */
+
+tree
+get_base_symbol (t)
+     tree t;
+{
+  switch (TREE_CODE (t))
+    {
+    case VAR_DECL:
+    case FUNCTION_DECL:
+    case PARM_DECL:
+    case FIELD_DECL:
+    case LABEL_DECL:
+      return t;
+
+    case ARRAY_REF:
+    case COMPONENT_REF:
+    case INDIRECT_REF:
+    case REALPART_EXPR:
+    case IMAGPART_EXPR:
+      return get_base_symbol (TREE_OPERAND (t, 0));
+
+    default:
+      return NULL;
+    }
+}
+
Index: tree-simple.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-simple.h,v
retrieving revision 1.1.4.8
diff -d -u -p -r1.1.4.8 tree-simple.h
--- tree-simple.h	14 Aug 2002 15:38:54 -0000	1.1.4.8
+++ tree-simple.h	16 Aug 2002 13:28:32 -0000
@@ tree-simple.h		       PARAMS ((tree 
 						int (*) PARAMS ((tree)),
 						fallback_t));
 
+/* Miscellaneous helpers.  */
+tree get_base_symbol                   PARAMS ((tree));
+
 #endif /* _TREE_SIMPLE_H */
Index: tree-ssa-ccp.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa-ccp.c,v
retrieving revision 1.1.2.6
diff -d -u -p -r1.1.2.6 tree-ssa-ccp.c
--- tree-ssa-ccp.c	13 Aug 2002 14:27:23 -0000	1.1.2.6
+++ tree-ssa-ccp.c	16 Aug 2002 13:28:32 -0000
@@ -480,12 +480,13 @@ static void
 visit_assignment (ref)
      varref ref;
 {
-  tree set, src, dest;
+  tree set, src, dest, base_sym;
   value val;
 
+  dest = VARREF_SYM (ref);
+  base_sym = get_base_symbol (dest);
   set = VARREF_EXPR (ref);
   src = TREE_OPERAND (set, 1);
-  dest = TREE_OPERAND (set, 0);
 
   val = evaluate_expr_for (ref);
 
@@ -494,7 +495,7 @@ visit_assignment (ref)
   else if (val.lattice_val == VARYING)
     def_to_varying (ref);
   else if (TREE_ADDRESSABLE (dest)
-	   || DECL_CONTEXT (dest) == NULL
+	   || DECL_CONTEXT (base_sym) == NULL
 	   || TREE_THIS_VOLATILE (dest))
     {
       /* Certain types of variables cannot be proven constant even if they
@@ -696,8 +697,7 @@ ssa_ccp_substitute_constants ()
 
 	      /* Replace the constant inside the expression and mark the
 		 expression for folding.  */
-	      replace_expr_in_tree (VARREF_EXPR (ref), VARREF_SYM (ref),
-				    values[id].const_value);
+	      *(VARREF_OPERAND_P (ref)) = values[id].const_value;
 	      TREE_FLAGS (VARREF_EXPR (ref)) |= TF_FOLD;
 	    }
 	}
@@ -718,8 +718,13 @@ ssa_ccp_substitute_constants ()
 	      && (TREE_FLAGS (VARREF_EXPR (ref)) & TF_FOLD))
 	    {
 	      /* Fold the expression and clean the fold bit.  */
-	      replace_expr_in_tree (stmt, expr, fold (expr));
 	      TREE_FLAGS (VARREF_EXPR (ref)) &= ~TF_FOLD;
+	      
+	      if (TREE_CODE (expr) == MODIFY_EXPR
+		  || TREE_CODE (expr) == INIT_EXPR)
+		expr = TREE_OPERAND (expr, 1);
+
+	      replace_expr_in_tree (stmt, expr, fold (expr));
 	    }
 	}
     }
@@ -781,14 +786,22 @@ evaluate_expr_for (ref)
 
   /* Make a deep copy of the expression, but get the expression references
      first because deep copies do not copy the 'aux' field.  */
-  refs = TREE_REFS (VARREF_STMT (ref));
-  expr = deep_copy_node (VARREF_EXPR (ref));
+  refs = TREE_REFS (VARREF_EXPR (ref));
+  expr = VARREF_EXPR (ref);
 
   /* If any USE reference in the expression is known to be VARYING or
      UNDEFINED, then the expression is not a constant.  */
   val.lattice_val = VARYING;
   val.const_value = NULL_TREE;
 
+  /* If the expression and the referenced symbol are of different types,
+     then the reference cannot be a constant.  For instance, a.b = 5; is a
+     constant only when considering reference 'a.b'.  Although that
+     expression also defines symbol 'a', we cannot assign the value 5 to
+     symbol 'a'.  */
+  if (TREE_TYPE (expr) != TREE_TYPE (VARREF_SYM (ref)))
+    goto dont_fold;
+
   FOR_EACH_REF (r, tmp, refs)
     {
       unsigned int id;
@@ -820,7 +833,7 @@ evaluate_expr_for (ref)
 
 	  /* The reference is a constant, substitute it into the
 	     expression.  */
-	  replace_expr_in_tree (expr, VARREF_SYM (r), values[id].const_value);
+	  *(VARREF_OPERAND_P (r)) = values[id].const_value;
 	}
     }
 
@@ -834,11 +847,18 @@ evaluate_expr_for (ref)
 
   /* Fold the expression.  If it results in a constant, set the lattice
       value for the LHS of the assignment to CONSTANT.  */
-  simplified = fold (expr);
+  simplified = fold (deep_copy_node (expr));
   if (simplified && really_constant_p (simplified))
     {
       val.lattice_val = CONSTANT;
       val.const_value = simplified;
+    }
+
+  /* Restore the expression to its original form.  */
+  FOR_EACH_REF (r, tmp, refs)
+    {
+      if (VARREF_TYPE (r) == VARUSE)
+	*(VARREF_OPERAND_P (r)) = VARREF_SYM (r);
     }
 
 dont_fold:
Index: tree-ssa-pre.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa-pre.c,v
retrieving revision 1.1.4.10
diff -d -u -p -r1.1.4.10 tree-ssa-pre.c
--- tree-ssa-pre.c	15 Aug 2002 18:09:30 -0000	1.1.4.10
+++ tree-ssa-pre.c	16 Aug 2002 13:28:32 -0000
@@ -468,7 +468,7 @@ insert_occ_in_preorder_dt_order_1 (ei, f
 	{
 	  newref = create_ref (VARRAY_TREE (ei->occurs, i),
 				  EXPRKILL, block, occurstmt,
-				  VARRAY_TREE (ei->occurs, i));
+				  VARRAY_TREE (ei->occurs, i), NULL);
 	  VARRAY_PUSH_GENERIC_PTR (ei->erefs, newref);
 	  fibheap_insert (fh, preorder_count++, newref);
 	}
@@ -476,7 +476,7 @@ insert_occ_in_preorder_dt_order_1 (ei, f
 	{
 	  newref = create_ref (VARRAY_TREE (ei->occurs, i), 
 				  EXPRUSE, block, occurstmt, 
-				  VARRAY_TREE (ei->occurs, i));
+				  VARRAY_TREE (ei->occurs, i), NULL);
 	  VARRAY_PUSH_GENERIC_PTR (ei->erefs, newref);
 	  EXPRUSE_DEF (newref) = NULL;
 	  EXPRREF_CLASS (newref) = 0;
@@ -494,7 +494,7 @@ insert_occ_in_preorder_dt_order_1 (ei, f
         {
           if (phi_at_block (ei, succ->dest) != NULL)
             {
-              varref newref = create_ref (NULL, EXPRUSE, block, 0, 0);
+              varref newref = create_ref (NULL, EXPRUSE, block, 0, 0, 0);
               varref phi = phi_at_block (ei, succ->dest);
 	      VARRAY_PUSH_GENERIC_PTR (ei->erefs, newref);
               EXPRUSE_DEF (newref) = NULL;
@@ -1253,7 +1253,8 @@ finalize_1 (ei, temp)
 		    insert_stmt_tree_after (stmt, endtree, bb);
 		  
 		  EXPRUSE_DEF (X) = create_ref (expr, EXPRUSE, 
-						EXPRREF_BB (X), stmt, expr);
+						EXPRREF_BB (X), stmt, expr,
+						&TREE_OPERAND (stmt, 0));
 		  VARRAY_PUSH_GENERIC_PTR (ei->erefs, EXPRUSE_DEF (X));
 		  EXPRREF_RELOAD (EXPRUSE_DEF (X)) = 0;
 		  EXPRREF_SAVE (EXPRUSE_DEF (X)) = 1;
@@ -1324,7 +1325,7 @@ expr_phi_insertion (dfs, ei)
   {
     varref ref = create_ref (NULL, EXPRPHI, 
                                 BASIC_BLOCK (i), 
-                                NULL, ei->expr);
+                                NULL, ei->expr, NULL);
     VARRAY_PUSH_GENERIC_PTR (ei->erefs, ref);
     EXPRPHI_DOWNSAFE (ref) = 1;
     EXPRPHI_CANBEAVAIL (ref) = 1;
Index: tree-ssa.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa.c,v
retrieving revision 1.1.4.8
diff -d -u -p -r1.1.4.8 tree-ssa.c
--- tree-ssa.c	11 Aug 2002 23:02:52 -0000	1.1.4.8
+++ tree-ssa.c	16 Aug 2002 13:28:32 -0000
@@ -90,7 +90,7 @@ tree_build_ssa ()
      definitions).  */
   for (i = 0; i < NREF_SYMBOLS; i++)
     create_ref (REF_SYMBOL (i), VARDEF, ENTRY_BLOCK_PTR->succ->dest, NULL,
-	        NULL);
+	        NULL, NULL);
 
   /* Insert the PHI terms and build FUD chains.  */
   insert_phi_terms (dfs);
@@ -205,7 +205,7 @@ insert_phi_terms (dfs)
 		    stmt_bb = BB_PARENT (stmt_bb);
 
 		  phi = create_ref (sym, VARPHI, bb, stmt_bb->head_tree,
-		                       NULL);
+		                    NULL, NULL);
 		  VARRAY_TREE (added, w) = sym;
 
 		  if (VARRAY_TREE (in_work, w) != sym)
@@ -376,8 +376,11 @@ delete_ssa ()
 {
   size_t i;
 
+  /* Remove annotations from every symbol.  We should only need to remove
+     annotations from global symbols, because those are the only ones who
+     might be re-used in other functions.  But better be safe.  */
   for (i = 0; i < NREF_SYMBOLS; i++)
-    delete_ref_list (TREE_REFS (REF_SYMBOL (i)));
+    remove_tree_ann (REF_SYMBOL (i));
 }
 
 


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