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]

[ast-optimizer-branch] Simplify (4/5)



The following stabilizes the simplification of some nodes.
An important feature added is the simplification of 
TRUTH_ANDIF_EXPR and TRUTH_ORIF_EXPR.  Its implementation is 
still not complete, since I introduce BREAK_STMTs in loop statements.
These breaks have to be transformed into a proper control flow 
containing just IF_STMTs.  

(work in progress... the break elimination is similar to the 
goto elimination pass on which I've worked last week-end 
and described in the papers from McGill : 
http://www.sable.mcgill.ca/~hendren/ftp/papers/ICCL94.ps.gz
"Taming Control Flow: A Structured Approach to Eliminating Goto Statements," 
 Ana M. Erosa and Laurie J. Hendren, 
 in Proceedings of the 1994 International Conference on Computer Languages, 
 Toulouse, France, pp. 229-240, May 1994. )


Seb.


2002-02-28  Sebastian Pop  <s.pop@laposte.net>

	* c-simplify.c (simplify_if_stmt): Deleted.
	(new_simplified_if): New function.
	(make_type_writable): New function.
	(insert_before_continue_end): New function.
	(insert_before_continue): New function.
	(copy_stmt_chain): New function.
	(insert_stmt_chain): New function.
	(update_line_number): New function.
	(simplified_p): New function.
	(simplified_rec_p) New function.
	(simplify_stmt): Modify the way to call simplification 
	of COMPOUND_STMT, FOR_STMT, WHILE_STMT, DO_STMT, IF_STMT, 
	and SCOPE_STMT in order to avoid to execute the code after 
	the switch.  Add FILE_STMT, LABEL_STMT, GOTO_STMT, ASM_STMT cases.
	Simplified a little the code after the switch.
	(simplify_for_stmt): Change functions parameters.
	Add code to simplify the FOR_INIT_STMT, FOR_COND, FOR_EXPR. 
	(simplify_while_stmt): Change functions parameters.
	Add code to simplify the WHILE_COND.
	(simplify_do_stmt): Change functions parameters.
	Add code to simplify the DO_COND.
	(simplify_switch_stmt): Change functions parameters.
	(simplify_expr): Remove scope parameter.
	Avoid to introduce a new temporary variable for an expression 
	that is already simplified.
	[ARRAY|COMPONENT]_REF, COND_EXPR : handle them apart.
	TRUTH_ANDIF_EXPR, TRUTH_ORIF_EXPR : Avoid to evaluate the second 
	operand if the value can be deduced from the first one.
	(keep_stmt_p): Add some other cases in which we don't need to keep 
	a statement after its simplification.
	
	

Index: gcc/c-simplify.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/c-simplify.c,v
retrieving revision 1.1.2.2
diff -d -p -d -u -p -r1.1.2.2 c-simplify.c
--- gcc/c-simplify.c	2002/01/25 22:13:49	1.1.2.2
+++ gcc/c-simplify.c	2002/02/28 01:56:20
@@ -202,18 +202,26 @@ Software Foundation, 59 Temple Place - S
 
 /* {{{ Local declarations.  */
 
-static void simplify_for_stmt PARAMS ((tree, tree, tree *, tree *, tree *));
-static void simplify_while_stmt PARAMS ((tree, tree, tree *, tree *, tree *));
-static void simplify_do_stmt PARAMS ((tree, tree, tree *, tree *, tree *));
-static void simplify_if_stmt PARAMS ((tree, tree, tree *, tree *, tree *));
-static void simplify_switch_stmt PARAMS ((tree, tree, tree *, tree *, tree *));
+static tree simplify_for_stmt PARAMS ((tree, tree, tree, tree));
+static tree simplify_while_stmt PARAMS ((tree, tree, tree, tree));
+static tree simplify_do_stmt PARAMS ((tree, tree, tree, tree));
+static tree new_simplified_if PARAMS ((tree, tree, tree, tree));
+static void simplify_switch_stmt PARAMS ((tree, tree *, tree *, tree *));
 static tree simplify_decl_stmt PARAMS ((tree, tree *));
-static tree simplify_expr PARAMS ((tree, tree, tree *, tree *, tree *));
+static tree simplify_expr PARAMS ((tree, tree *, tree *, tree *));
 static tree create_tmp_var PARAMS ((tree, tree *));
+static void make_type_writable PARAMS ((tree));
 static void tree_build_scope PARAMS ((tree *));
 static tree declare_tmp_vars PARAMS ((tree, tree));
 static void add_tree PARAMS ((tree, tree *));
 static int keep_stmt_p PARAMS ((tree));
+static void insert_before_continue_end PARAMS ((tree, tree, int));
+static tree insert_before_continue PARAMS ((tree, tree));
+static void copy_stmt_chain PARAMS ((tree *, tree));
+static void insert_stmt_chain PARAMS ((tree *, tree));
+static tree update_line_number PARAMS ((tree, int));
+static int simplified_p PARAMS ((tree));
+static int simplified_rec_p PARAMS ((tree, int));
 
 /* }}} */
 
@@ -230,7 +238,7 @@ simplify_stmt (stmt, scope)
      tree scope;
 {
   tree next, prev, before, after, new_vars;
-
+  
   /* Don't bother doing anything if the program has errors.  */
   if (errorcount || sorrycount)
     return;
@@ -256,61 +264,124 @@ simplify_stmt (stmt, scope)
       before = NULL;
       after = NULL;
       new_vars = NULL;
-
+      
       switch (TREE_CODE (stmt))
 	{
 	case COMPOUND_STMT:
 	  simplify_stmt (COMPOUND_BODY (stmt), scope);
-	  break;
-
+	  
+	  /* Prepare for the next iteration.  */
+	  next = TREE_CHAIN (stmt);
+	  prev = stmt;
+	  stmt = next;
+	  continue;
+	  
 	case FOR_STMT:
-	  simplify_for_stmt (stmt, scope, &before, &after, &new_vars);
-	  break;
-
+	  prev = simplify_for_stmt (prev, stmt, TREE_CHAIN (stmt), scope);
+	  stmt = TREE_CHAIN (prev);
+#if 0
+	  next = simplify_for_stmt (prev, stmt, TREE_CHAIN (stmt), scope);
+	  prev = stmt;
+	  stmt = next;
+#endif
+	  continue;
+	  
 	case WHILE_STMT:
-	  simplify_while_stmt (stmt, scope, &before, &after, &new_vars);
-	  break;
+	  prev = simplify_while_stmt (prev, stmt, TREE_CHAIN (stmt), scope);
+	  stmt = TREE_CHAIN (prev);
+	  continue;
 
 	case DO_STMT:
-	  simplify_do_stmt (stmt, scope, &before, &after, &new_vars);
-	  break;
+	  prev = simplify_do_stmt (prev, stmt, TREE_CHAIN (stmt), scope);
+	  stmt = TREE_CHAIN (prev);
+	  continue;
 
 	case IF_STMT:
-	  simplify_if_stmt (stmt, scope, &before, &after, &new_vars);
-	  break;
+	  next = TREE_CHAIN (stmt);
+	  /* Construct a simplified version of this IF_STMT.  */
+	  stmt = new_simplified_if (IF_COND (stmt), THEN_CLAUSE (stmt), ELSE_CLAUSE (stmt), scope);
+	  TREE_CHAIN (prev) = stmt;
+	
+	  /* Insert the simplified IF_STMT in the tree.  */
+	  { 
+	    /* Place an iterator on the last node in the simplified IF_STMT.  */
+	    tree it;
+	    it = tree_last (stmt);
 
+	    /* Add the rest of the tree after the generated STMT.  */
+	    TREE_CHAIN (it) = next;
+
+	    /* Next iteration.  */
+	    prev = it; 
+	    stmt = TREE_CHAIN (it);
+	  }
+	  continue;
+	
 	case SWITCH_STMT:
-	  simplify_switch_stmt (stmt, scope, &before, &after, &new_vars);
+	  simplify_switch_stmt (stmt, &before, &after, &new_vars);
 	  break;
 
 	case EXPR_STMT:
 	  TREE_OPERAND (stmt, 0) = simplify_expr (TREE_OPERAND (stmt, 0), 
-	                                          scope, &before, &after,
+						  &before, &after,
 						  &new_vars);
 	  break;
 
 	case DECL_STMT:
 	  /* Simplify all the declarations at once.  */
-	  prev = simplify_decl_stmt (stmt, &after);
-	  stmt = prev;
-	  break;
+	  stmt = simplify_decl_stmt (stmt, &after);
+	  
+	  if (after)
+	    /* Insert AFTER in the tree.  */
+	    {
+	      /* Save a pointer to the next stmt.  */
+	      next = TREE_CHAIN (stmt);
+	      
+	      /* Include the nodes from AFTER list.  */
+	      TREE_CHAIN (stmt) = after;
+	      
+	      /* Update the line number and make PREV points to the last stmt in 
+		 AFTER list.  */
+	      prev = update_line_number (after, STMT_LINENO (stmt));
+	      
+	      /* Chain the end of the AFTER block to the next stmt.  */
+	      stmt = next;
+	      TREE_CHAIN (prev) = stmt;
+	    }
+	  else
+	    /* Declaration block has no initial values, so nothing to 
+	       be simplified : we can go to the next stmt.  */
+	    {
+	      prev = stmt;
+	      stmt = TREE_CHAIN (stmt);
+	    }
+          continue;
 
 	case RETURN_STMT:
-	  if (RETURN_EXPR (stmt))
+	  if (TREE_CODE (TREE_TYPE (TREE_TYPE (current_function_decl))) != VOID_TYPE
+	      && RETURN_EXPR (stmt))
 	    {
 	      tree e = RETURN_EXPR (stmt);
-	      
 	      TREE_OPERAND (e, 1) = simplify_expr (TREE_OPERAND (e, 1),
-						   scope, &before, &after,
+						   &before, &after,
 						   &new_vars);
 	    }
 	  break;
-
+	  
 	case SCOPE_STMT:
 	  if (SCOPE_BEGIN_P (stmt))
-	    scope = stmt;
-	  break;
+	    /* Save a pointer to the scope.  */
+	    scope = stmt; 
+	    	  
+	  /* Next iteration.  */
+	  prev = stmt;
+	  stmt = TREE_CHAIN (stmt);
+	  continue;
 
+	case FILE_STMT:
+	case LABEL_STMT:
+	case GOTO_STMT:
+	case ASM_STMT:
 	case CASE_LABEL:
 	case CONTINUE_STMT:
 	case BREAK_STMT:
@@ -355,151 +426,525 @@ simplify_stmt (stmt, scope)
 
       next = TREE_CHAIN (stmt);
 
-      /* Include the nodes in the BEFORE list.  Update line number
-	 information on each node and re-compute PREV.  */
       if (before)
 	{
+	  /* Include the nodes from the BEFORE list.  */
 	  TREE_CHAIN (prev) = before;
-
-	  for (; TREE_CHAIN (before); before = TREE_CHAIN (before))
-	    STMT_LINENO (before) = STMT_LINENO (stmt);
-	  STMT_LINENO (before) = STMT_LINENO (stmt);
 
-	  prev = before;
-
+	  /* Update the line number and make PREV points to the last stmt in 
+	     BEFORE list  */
+	  prev = update_line_number (before, STMT_LINENO (stmt));
+	}
+      
+      if (keep_stmt_p (stmt))
+	{
 	  /* Include STMT, if it's worth keeping (i.e., it has not been
-	     nullified by the simplification process) and re-compute PREV.  */
-	  if (keep_stmt_p (stmt))
-	    {
-	      TREE_CHAIN (prev) = stmt;
-	      prev = stmt;
-	    }
+	     nullified by the simplification process).  */
+	  TREE_CHAIN (prev) = stmt;
+	  
+	  /* Re-compute PREV.  */
+	  prev = stmt;
 	}
-      else
-	prev = stmt;
-
-      /* Include the nodes in the AFTER list.  Update line number
-	 information on each node and re-compute PREV.  */
+	
       if (after)
 	{
+	  /* Include the nodes from the AFTER list.  */
 	  TREE_CHAIN (prev) = after;
 
-	  for (; TREE_CHAIN (after); after = TREE_CHAIN (after))
-	    STMT_LINENO (after) = STMT_LINENO (stmt);
-	  STMT_LINENO (after) = STMT_LINENO (stmt);
-
-	  prev = after;
+	  /* Update the line number and make PREV points to the last stmt in 
+	     AFTER list.  */
+	  prev = update_line_number (after, STMT_LINENO (stmt));
 	}
 
       /* Make sure that PREV is chained to NEXT (just in case it was
 	 re-computed above)  */
       TREE_CHAIN (prev) = next;
 
+      /* Next step of the iteration.  */
       stmt = next;
     }
 }
 
 /* }}} */
 
-/** {{{ simplify_for_stmt()
+/** {{{  simplify_for_stmt()
 
-   Simplify a FOR_STMT node.  FIXME.  */
+    Simplifies the given FOR_STMT.
+    Return a pointer to the last statment of the simplified region.  
+    This becomes the PREV pointer. The next statement to be simplified
+    is the next stmt in the chain.  */
 
-static void
-simplify_for_stmt (t, scope, before_p, after_p, new_vars_p)
-     tree t;
-     tree scope;
-     tree *before_p;
-     tree *after_p;
-     tree *new_vars_p;
+static tree
+simplify_for_stmt (prev, stmt, next, scope)
+     tree prev, stmt, next, scope;
 {
-  /* It's unsafe to decompose the FOR_COND, and the FOR_EXPR 
-     (reevaluation of the condition).  Thus for simplifying these nodes 
-     apply before this pass the loop decomposition.  */
+  tree cond, body, loop, last;
+  tree new_scope;
+  tree init_before = NULL_TREE, init_after = NULL_TREE;
+  tree expr_before = NULL_TREE, expr_after = NULL_TREE;
 
   /* Make sure that the loop body has a scope.  */
-  tree_build_scope (&FOR_BODY (t));
+  tree_build_scope (&FOR_BODY (stmt));
+  cond = FOR_COND (stmt);
+  body = FOR_BODY (stmt);
+  new_scope = COMPOUND_BODY (body);
+  TREE_CHAIN (prev) = NULL_TREE;
 
-  /* Decompose the loop body.  */
-  simplify_stmt (FOR_BODY (t), scope);
+  /* Simplify FOR_INIT_STMT.  */
+  if (TREE_OPERAND (FOR_INIT_STMT (stmt), 0))
+    {
+      tree new_vars = NULL;
+      simplify_expr (TREE_OPERAND (FOR_INIT_STMT (stmt), 0), &init_before, 
+		     &init_after, &new_vars);
+      /* FOR_INIT_STMT (t) = build1 (EXPR_STMT, NULL_TREE, NULL_TREE); */
+
+      /* Insert the simplification chains before the beginning of the loop.  */
+      chainon (prev, init_before);
+      if (TREE_CODE (TREE_OPERAND (FOR_INIT_STMT (stmt), 0)) == COMPOUND_EXPR)
+	chainon (prev, FOR_INIT_STMT (stmt));
+      chainon (prev, init_after);
+      
+      /* If we created new temporary variables, create declarations for
+	 them in the current scope.  */
+      if (new_vars)
+	declare_tmp_vars (new_vars, scope);
+      
+    }
+  
+  /* Simplify FOR_EXPR.  */
+  if (FOR_EXPR (stmt))
+    {
+      tree new_scope_vars = NULL;
+      simplify_expr (FOR_EXPR (stmt), &expr_before, &expr_after, &new_scope_vars);
+      /* FOR_EXPR (t) = NULL_TREE;  */
+      
+      /* If we created new temporary variables, create declarations for
+	 them in the current scope.  */
+      if (new_scope_vars)
+	declare_tmp_vars (new_scope_vars, new_scope);
+    }
+    
+  if (simplified_p (cond))
+    /* The FOR_COND is already simplified, simplify just the FOR_BODY.  */
+    {
+      tree reeval;
+
+      /* step 1 : Insert a simplified version of 'reeval;' in the loop body.  */
+      reeval = chainon (expr_before, expr_after);
+      if (reeval)
+	insert_before_continue_end (reeval, FOR_BODY (stmt), STMT_LINENO (stmt));
+      
+      /* Step 2 : Construct a 'while (cond) {body}' statement.  */
+      loop = build_stmt (WHILE_STMT, 
+			 /* WHILE_COND */ FOR_COND (stmt),
+			 /* WHILE_BODY */ NULL_TREE);
+      
+      /* Step 4 : Initialize the loop body.  */
+      simplify_stmt (body, scope);
+      WHILE_BODY (loop) = body;
+      
+      /* Step 5 : Next statement to be processed.  */
+      last = chainon (prev, loop);
+      last = tree_last (last);
+      chainon (loop, next);
+      return last;
+    }
+
+  /* step 1 : Insert a simplified version of 'reeval; if (!cond) break;' 
+     in the loop body.  */
+  {
+    tree new_cond, if_stmt, reeval;
+    
+    /* Build 'if (!cond) break;'.  */
+    if (TREE_CODE (cond) == EQ_EXPR)
+      new_cond = build (NE_EXPR, TREE_TYPE (cond), 
+			copy_node (TREE_OPERAND (cond, 0)), 
+			copy_node (TREE_OPERAND (cond, 1)));
+    else if (TREE_CODE (cond) == NE_EXPR)
+      new_cond = build (EQ_EXPR, TREE_TYPE (cond), 
+			copy_node (TREE_OPERAND (cond, 0)), 
+			copy_node (TREE_OPERAND (cond, 1)));
+    else
+      new_cond = build (EQ_EXPR, TREE_TYPE (cond), 
+			copy_node (cond), 
+			integer_zero_node);
+
+    if_stmt = new_simplified_if (new_cond, build_stmt (BREAK_STMT), 
+				 NULL_TREE, COMPOUND_BODY (FOR_BODY (stmt)));
+    
+    /* Insert the 'reeval; if (!cond) break;' before CONTINUE_STMT and at the 
+       end of the loop block.  */
+    reeval = chainon (expr_before, chainon (expr_after, if_stmt));
+    if (reeval)
+      insert_before_continue_end (reeval, FOR_BODY (stmt), STMT_LINENO (stmt));
+  }
+  
+  /* Step 2 : Construct a 'while (1!=0) {}' statement.  For the moment don't 
+     initialize the loop body in order to avoid to simplify it twice.  */
+  loop = build_stmt (WHILE_STMT, 
+		     /* WHILE_COND */ build (NE_EXPR, TREE_TYPE (integer_one_node), 
+					     integer_one_node, integer_zero_node),
+		     /* WHILE_BODY */ NULL_TREE);
+  
+  /* Step 3 : Include the loop in an IF_STMT : 'if (cond) while (1){}'  */
+  stmt = new_simplified_if (copy_node (cond), loop, NULL_TREE, scope);
+
+  /* Step 4 : Initialize the loop body.  */
+  simplify_stmt (body, scope);
+  WHILE_BODY (loop) = body;
+
+  /* Step 5 : Next statement to be processed.  */
+  last = chainon (prev, stmt);
+  last = tree_last (last);
+  chainon (stmt, next);
+  return last;
 }
 
 /* }}} */
 
-/** {{{ simplify_while_stmt()
+/** {{{  simplify_while_stmt()
 
-   Simplify a WHILE_STMT node.  FIXME.  */
+    Simplifies the given WHILE_STMT : 
+    while (cond) {X; continue; Y;} 
+    into a simplified version :
+    if (cond) while (1) {X; if (!cond) break; continue; Y; if (!cond) break;}  
+    Return a pointer to the last statement of the simplified region.  */
 
-static void
-simplify_while_stmt (t, scope, before_p, after_p, new_vars_p)
-     tree t;
-     tree scope;
-     tree *before_p;
-     tree *after_p;
-     tree *new_vars_p;
+static tree
+simplify_while_stmt (prev, stmt, next, scope)
+     tree prev, stmt, next, scope;
 {
+  tree cond, body, loop, last;
+
   /* Make sure that the loop body has a scope.  */
-  tree_build_scope (&WHILE_BODY (t));
+  tree_build_scope (&WHILE_BODY (stmt));
+  cond = WHILE_COND (stmt);
+  body = WHILE_BODY (stmt);
 
-  /* Decompose the loop body.  */
-  simplify_stmt (WHILE_BODY (t), scope);
+  if (simplified_p (cond))
+    /* The WHILE_COND is already simplified, simplify just the WHILE_BODY.  */
+    {
+      simplify_stmt (WHILE_BODY (stmt), COMPOUND_BODY (WHILE_BODY (stmt)));
+      /* The last statement in the simplified region is the current one.  */
+      last = stmt;
+      return last;
+    }
+
+  /* step 1 : Insert a simplified version of 'if (!cond) break;' in the loop body.  */
+  {
+    tree new_cond, if_stmt;
+    
+    /* Build 'if (!cond) break;'.  */
+    if (TREE_CODE (cond) == EQ_EXPR)
+      new_cond = build (NE_EXPR, TREE_TYPE (cond), 
+			copy_node (TREE_OPERAND (cond, 0)), 
+			copy_node (TREE_OPERAND (cond, 1)));
+    else if (TREE_CODE (cond) == NE_EXPR)
+      new_cond = build (EQ_EXPR, TREE_TYPE (cond), 
+			copy_node (TREE_OPERAND (cond, 0)), 
+			copy_node (TREE_OPERAND (cond, 1)));
+    else
+      new_cond = build (EQ_EXPR, TREE_TYPE (cond), 
+			copy_node (cond), 
+			integer_zero_node);
+
+    if_stmt = new_simplified_if (new_cond, build_stmt (BREAK_STMT), 
+				 NULL_TREE, COMPOUND_BODY (WHILE_BODY (stmt)));
+    
+    /* Insert the 'if (!cond) break;' before CONTINUE_STMT and at the end 
+       of the loop block.  */
+    insert_before_continue_end (if_stmt, WHILE_BODY (stmt), STMT_LINENO (stmt));
+  }
+  
+  /* Step 2 : Construct a 'while (1!=0) {}' statement.  For the moment don't 
+     initialize the loop body in order to avoid to simplify it twice.  */
+  loop = build_stmt (WHILE_STMT, 
+		     /* WHILE_COND */ build (NE_EXPR, TREE_TYPE (integer_one_node), 
+					     integer_one_node, integer_zero_node),
+		     /* WHILE_BODY */ NULL_TREE);
+    
+  /* Step 3 : Include the loop in an IF_STMT : 'if (cond) while (1){}'  */
+  stmt = new_simplified_if (copy_node (cond), loop, NULL_TREE, scope);
+
+  /* Step 4 : Initialize the loop body.  */
+  simplify_stmt (body, scope);
+  WHILE_BODY (loop) = body;
+
+  /* Step 5 : Next statement to be processed.  */
+  TREE_CHAIN (prev) = NULL_TREE;
+  last = chainon (prev, stmt);
+  last = tree_last (last);
+  chainon (stmt, next);
+  return last;
 }
 
 /* }}} */
 
 /** {{{ simplify_do_stmt()
 
-   Simplify a DO_STMT node.  FIXME.  */
+   Simplify a DO_STMT node.
+   Return a pointer to the last statement of the simplified region.  */
 
-static void
-simplify_do_stmt (t, scope, before_p, after_p, new_vars_p)
-     tree t;
-     tree scope;
-     tree *before_p;
-     tree *after_p;
-     tree *new_vars_p;
+
+static tree
+simplify_do_stmt (prev, stmt, next, scope)
+     tree prev, stmt, next, scope;
 {
+  tree cond, body, loop, last;
+
   /* Make sure that the loop body has a scope.  */
-  tree_build_scope (&DO_BODY (t));
+  tree_build_scope (&DO_BODY (stmt));
+  cond = DO_COND (stmt);
+  body = DO_BODY (stmt);
 
-  /* Decompose the loop body.  */
-  simplify_stmt (DO_BODY (t), scope);
+  if (simplified_p (cond))
+    /* The DO_COND is already simplified, simplify just the DO_BODY.  */
+    {
+      simplify_stmt (DO_BODY (stmt), COMPOUND_BODY (DO_BODY (stmt)));
+      /* The last statement in the simplified region is the current one.  */
+      last = stmt;
+      return last;
+    }
+
+  /* step 1 : Insert a simplified version of 'if (!cond) break;' in the loop body.  */
+  {
+    tree new_cond, if_stmt;
+    
+    /* Build 'if (!cond) break;'.  */
+    if (TREE_CODE (cond) == EQ_EXPR)
+      new_cond = build (NE_EXPR, TREE_TYPE (cond), 
+			copy_node (TREE_OPERAND (cond, 0)), 
+			copy_node (TREE_OPERAND (cond, 1)));
+    else if (TREE_CODE (cond) == NE_EXPR)
+      new_cond = build (EQ_EXPR, TREE_TYPE (cond), 
+			copy_node (TREE_OPERAND (cond, 0)), 
+			copy_node (TREE_OPERAND (cond, 1)));
+    else
+      new_cond = build (EQ_EXPR, TREE_TYPE (cond), 
+			copy_node (cond), 
+			integer_zero_node);
+
+    if_stmt = new_simplified_if (new_cond, build_stmt (BREAK_STMT), 
+				 NULL_TREE, COMPOUND_BODY (DO_BODY (stmt)));
+    
+    /* Insert the 'if (!cond) break;' before CONTINUE_STMT and at the end 
+       of the loop block.  */
+    insert_before_continue_end (if_stmt, DO_BODY (stmt), STMT_LINENO (stmt));
+  }
+  
+  /* Step 2 : Construct a 'while (1!=0) {}' statement.  For the moment don't 
+     initialize the loop body in order to avoid to simplify it twice.  */
+  loop = build_stmt (WHILE_STMT, 
+		     /* WHILE_COND */ build (NE_EXPR, TREE_TYPE (integer_one_node), 
+					     integer_one_node, integer_zero_node),
+		     /* WHILE_BODY */ NULL_TREE);
+    
+  /* Step 4 : Initialize the loop body.  */
+  simplify_stmt (body, scope);
+  WHILE_BODY (loop) = body;
+
+  /* Step 5 : Next statement to be processed.  */
+  TREE_CHAIN (prev) = NULL_TREE;
+  last = chainon (prev, loop);
+  last = tree_last (last);
+  chainon (loop, next);
+  return last;
 }
 
+
 /* }}} */
 
-/** {{{ simplify_if_stmt()
+/** {{{ new_simplified_if()
 
-    Simplifies an IF_STMT node.  FIXME.  */
+    Constructs a new IF_STMT under its simplified form. 
+    FIXME : When the caller provides a scope, then avoid to create a new one.  */
 
-static void
-simplify_if_stmt (t, scope, before_p, after_p, new_vars_p)
-     tree t;
+static tree 
+new_simplified_if (cond, then_clause, else_clause, scope)
+     tree cond;
+     tree then_clause;
+     tree else_clause;
      tree scope;
-     tree *before_p;
-     tree *after_p;
-     tree *new_vars_p;
 {
-  /* FIXME.  BEFORE_P and AFTER_P should be expanded here.  */
-  IF_COND (t) = simplify_expr (IF_COND (t), scope, before_p, after_p,
-      new_vars_p);
+  tree res, begin_scope, end_scope, before, new_vars;
+  before = NULL;
+  new_vars = NULL;
+  
 
-  if (THEN_CLAUSE (t))
+  /* Build 'if (cond) then_clause; else else_clause;'.  */
+  res = build_stmt (IF_STMT, cond, then_clause, else_clause);
+
+  /* if (scope == NULL_TREE) */
+    /* Create a scope around res.  */
     {
-      /* Make sure that the branch has a scope.  */
-      tree_build_scope (&THEN_CLAUSE (t));
+      tree_build_scope (&res);
+      //      scope = res;
+      begin_scope = TREE_OPERAND (res, 0);
+      end_scope = TREE_CHAIN (TREE_CHAIN (begin_scope));
 
-      /* Decompose the THEN branch.  */
-      simplify_stmt (THEN_CLAUSE (t), scope);
-    }
 
-  if (ELSE_CLAUSE (t))
-    {
-      /* Make sure that the branch has a scope.  */
-      tree_build_scope (&ELSE_CLAUSE (t));
+      /* Simplify IF_COND, THEN_CLAUSE, ELSE_CLAUSE.  */
+      {
+	tree if_orig = TREE_CHAIN (begin_scope);
+	tree if0, if1;
+	tree op0, op1;
+	tree op0_before = NULL, op0_after = NULL, op0_new_vars = NULL;
+	tree op1_before = NULL, op1_after = NULL, op1_new_vars = NULL;
 
-      /* Decompose the ELSE branch.  */
-      simplify_stmt (ELSE_CLAUSE (t), scope);
+	/* Check : be sure that we work on an IF_STMT.  */
+	if (TREE_CODE (if_orig) != IF_STMT)
+	  abort ();
+	
+	/* Simplify THEN_CLAUSE.  */
+	{
+	  /* Make sure that the branch has a scope.  */
+	  tree_build_scope (&THEN_CLAUSE (if_orig));
+	  
+	  /* Decompose the THEN branch.  */
+	  simplify_stmt (/* stmt */ THEN_CLAUSE (if_orig), 
+			 /* scope */ COMPOUND_BODY (THEN_CLAUSE (if_orig)));
+	}
+	
+	if (ELSE_CLAUSE (if_orig))
+	  /* Simplify ELSE_CLAUSE.  */
+	  {
+	    /* Make sure that the branch has a scope.  */
+	    tree_build_scope (&ELSE_CLAUSE (if_orig));
+	    
+	    /* Decompose the ELSE branch.  */
+	    simplify_stmt (/* stmt */ ELSE_CLAUSE (if_orig), 
+			   /* scope */ COMPOUND_BODY (ELSE_CLAUSE (if_orig)));
+	  }
+	  		
+	switch (TREE_CODE (IF_COND (if_orig)))
+	  /* Simplify IF_COND.  */
+	  {
+	  case TRUTH_ANDIF_EXPR:
+	  case TRUTH_ORIF_EXPR:
+	    op0 = TREE_OPERAND (IF_COND (if_orig), 0);
+	    op1 = TREE_OPERAND (IF_COND (if_orig), 1);
+	    
+	    /* Simplify op0 and op1.  */
+	    {
+	      op0 = simplify_expr (op0, &op0_before, &op0_after, &op0_new_vars);
+	      op1 = simplify_expr (op1, &op1_before, &op1_after, &op1_new_vars);
+	      
+	      if (simplified_rec_p (op0, 1))
+		/* The simplification introduced a new temporary variable.  */
+		op0 = build (NE_EXPR, TREE_TYPE (integer_zero_node), op0, integer_zero_node);
+	      
+	      if (simplified_rec_p (op1, 1))
+		/* The simplification introduced a new temporary variable.  */
+		op1 = build (NE_EXPR, TREE_TYPE (integer_zero_node), op1, integer_zero_node);
+	    }
+	    
+	    if (TREE_CODE (IF_COND (if_orig)) == TRUTH_ANDIF_EXPR)
+	      /* if_orig (op0 && op1) {then_clause;} else {else_clause;}
+		 to be transformed in 
+		 if0 (op0) { if1 (op1) {then_clause;} else {else_clause}} else {else_clause;}  */
+	      {
+		if (ELSE_CLAUSE (if_orig))
+		  {
+		    if1 = build_stmt (IF_STMT, op1, THEN_CLAUSE (if_orig), copy_node (ELSE_CLAUSE (if_orig)));
+		  }
+		else 
+		  {
+		    if1 = build_stmt (IF_STMT, op1, THEN_CLAUSE (if_orig), NULL_TREE);
+		  }
+	      }
+	    else
+	      /* if_orig (op0 || op1) {THEN_CLAUSE;} else {ELSE_CLAUSE;}
+		 to be transformed in 
+		 if0 (op0) {THEN_CLAUSE;} else if1 (op1) {THEN_CLAUSE;} else {ELSE_CLAUSE;}  */
+	      {
+		if1 = build_stmt (IF_STMT, op1, copy_node (THEN_CLAUSE (if_orig)), ELSE_CLAUSE (if_orig));
+	      }
+	    
+	    if (op1_before || op1_after)
+	      /* Insert the result of the simplification of op1.  */
+	      {
+		tree s_beg, s_if, s_end;
+		
+		/* Construct a scope around if1.  */
+		tree_build_scope (&if1);
+		
+		/* Save some pointers.  */
+		s_beg = COMPOUND_BODY (if1);
+		s_if = TREE_CHAIN (s_beg);
+		s_end = TREE_CHAIN (TREE_CHAIN (s_beg));
+		
+		/* Insert op1_before and op1_after before the IF_STMT.  */
+		TREE_CHAIN (s_beg) = NULL_TREE;
+		insert_stmt_chain (&s_beg, op1_before);
+		insert_stmt_chain (&s_beg, op1_after);
+		insert_stmt_chain (&s_beg, s_if);
+		
+		/* Declare the variables in the current scope.  */
+		declare_tmp_vars (op1_new_vars, s_beg);
+	      }
+	    
+	    if (TREE_CODE (IF_COND (if_orig)) == TRUTH_ANDIF_EXPR)
+	      if0 = build_stmt (IF_STMT, op0, if1, ELSE_CLAUSE (if_orig));
+	    else
+	      if0 = build_stmt (IF_STMT, op0, THEN_CLAUSE (if_orig), if1);
+	    
+	    /* The evaluation of the operand 0 precedes the 
+	       evaluation of the operand 1.  */
+	    if (op0_new_vars)
+	      /* If we created new temporary variables, create declarations for these
+		 variables in the new scope.  */
+	      {
+		tree last_decl;
+		last_decl = declare_tmp_vars (op0_new_vars, begin_scope);
+		
+		/* Insert the simplified code between LAST_DECL and FIRST_STMT.  */
+		TREE_CHAIN (last_decl) = op0_before;
+		chainon (last_decl, op0_after);
+		chainon (last_decl, if0);
+		chainon (last_decl, end_scope);
+	      }
+	    else
+	      {
+		TREE_CHAIN (begin_scope) = if0;
+		chainon (begin_scope, end_scope);
+	      }
+	    break;
+	    
+	  default:
+	    /* Simplify the IF_STMT.  */
+	    {
+	      	      
+	      /* Simplify if condition.  */
+	      {
+		tree cond_before = NULL, cond_after = NULL;
+		tree repl;
+		repl = simplify_expr (IF_COND (if_orig), &cond_before, &cond_after, &new_vars);
+		
+		if (simplified_rec_p (repl, 1))
+		  /* The simplification introduced a new temporary variable.  */
+		  IF_COND (if_orig) = build (NE_EXPR, TREE_TYPE (integer_zero_node), repl, integer_zero_node);
+		
+		/* Expand IF_COND before the beginning of the IF_STMT.  */
+		insert_stmt_chain (&before, cond_before);
+		insert_stmt_chain (&before, cond_after);
+	      }
+	    }
+	    
+	    if (new_vars)
+	      /* If we created new temporary variables, create declarations for these
+		 variables in the new scope.  */
+	      {
+		tree last_decl; 
+		last_decl = declare_tmp_vars (new_vars, begin_scope);
+		
+		/* Insert the simplified code between LAST_DECL and FIRST_STMT.  */
+		TREE_CHAIN (last_decl) = before;
+		chainon (last_decl, if_orig);
+	      }
+	    break;
+	  }
+      }
+      return res;
     }
 }
 
@@ -510,16 +955,19 @@ simplify_if_stmt (t, scope, before_p, af
     Simplifies a SWITCH_STMT node.  FIXME.  */
 
 static void
-simplify_switch_stmt (t, scope, before_p, after_p, new_vars_p)
+simplify_switch_stmt (t, before_p, after_p, new_vars_p)
      tree t;
-     tree scope;
      tree *before_p;
      tree *after_p;
      tree *new_vars_p;
 {
-  SWITCH_COND (t) = simplify_expr (SWITCH_COND (t), scope, before_p,
-      after_p, new_vars_p);
-  simplify_stmt (SWITCH_BODY (t), scope);
+  SWITCH_COND (t) = simplify_expr (SWITCH_COND (t), before_p,
+				   after_p, new_vars_p);
+
+  /* Make sure that the loop body has a scope.  */
+  tree_build_scope (&SWITCH_BODY (t));
+  simplify_stmt (/* stmt */ SWITCH_BODY (t), 
+		 /* scope */ TREE_OPERAND (SWITCH_BODY (t), 0));
 }
 
 /* }}} */
@@ -551,13 +999,20 @@ simplify_decl_stmt (t, after_p)
     {
       tree decl = DECL_STMT_DECL (t);
 
-      /* If there is an initializer for the variable, queue it up to be
-	 processed after all the declarations.  */
-      if (DECL_INITIAL (decl))
+      /* If there is an initializer for the variable,  */
+      if (DECL_INITIAL (decl)
+	  /* and if the declaration is not declared as a const,  */	  
+	  && !TREE_READONLY (decl)
+#if 0
+	  /* and if the declaration is not declared as register,  */
+	  && !DECL_REGISTER (decl)
+#endif
+	  )
+	/* queue it up to be processed after all the declarations.  */
 	{
 	  tree assign = build_modify_expr (decl, NOP_EXPR, DECL_INITIAL (decl));
 	  add_tree (build_stmt (EXPR_STMT, assign), after_p);
-	  DECL_INITIAL (decl) = NULL;
+	  DECL_INITIAL (decl) = NULL_TREE;
 	}
 
       prev = t;
@@ -585,9 +1040,8 @@ simplify_decl_stmt (t, after_p)
 	model T's side effects should be stored.  */
 
 static tree
-simplify_expr (expr, scope, before_p, after_p, new_vars_p)
+simplify_expr (expr, before_p, after_p, new_vars_p)
      tree expr;
-     tree scope;
      tree *before_p;
      tree *after_p;
      tree *new_vars_p;
@@ -600,7 +1054,7 @@ simplify_expr (expr, scope, before_p, af
 
   code = TREE_CODE (expr);
 
-  switch (TREE_CODE (expr))
+  switch (code)
     {
       /* Unary expressions that do not compute a new value.  Nothing to do.  */
     case VAR_DECL:
@@ -615,7 +1069,7 @@ simplify_expr (expr, scope, before_p, af
     case STRING_CST:
     case ADDR_EXPR:
       return expr;
-
+      
 
       /* Unary expressions that compute a new value.  Re-write the operand
 	 and return the modified expression.  */
@@ -639,7 +1093,7 @@ simplify_expr (expr, scope, before_p, af
     case TRUTH_NOT_EXPR:
     case VA_ARG_EXPR:
       TREE_OPERAND (expr, 0) = simplify_expr (TREE_OPERAND (expr, 0), 
-	                                      scope, before_p, after_p,
+	                                      before_p, after_p,
 					      new_vars_p);
       return expr;
 
@@ -648,10 +1102,8 @@ simplify_expr (expr, scope, before_p, af
 	 the AFTER list.  */
     case POSTINCREMENT_EXPR:
     case POSTDECREMENT_EXPR:
-      lhs = simplify_expr (TREE_OPERAND (expr, 0), scope, before_p,
-	  after_p, new_vars_p);
-      rhs = simplify_expr (TREE_OPERAND (expr, 1), scope, before_p,
-	  after_p, new_vars_p);
+      lhs = simplify_expr (TREE_OPERAND (expr, 0), before_p, after_p, new_vars_p);
+      rhs = simplify_expr (TREE_OPERAND (expr, 1), before_p, after_p, new_vars_p);
       t1 = build ((code == POSTINCREMENT_EXPR) ? PLUS_EXPR : MINUS_EXPR,
 	          TREE_TYPE (expr), lhs, rhs);
       t2 = build_modify_expr (lhs, NOP_EXPR, t1);
@@ -663,10 +1115,8 @@ simplify_expr (expr, scope, before_p, af
 	 the BEFORE list.  */
     case PREDECREMENT_EXPR:
     case PREINCREMENT_EXPR:
-      lhs = simplify_expr (TREE_OPERAND (expr, 0), scope, before_p,
-	  after_p, new_vars_p);
-      rhs = simplify_expr (TREE_OPERAND (expr, 1), scope, before_p,
-	  after_p, new_vars_p);
+      lhs = simplify_expr (TREE_OPERAND (expr, 0), before_p, after_p, new_vars_p);
+      rhs = simplify_expr (TREE_OPERAND (expr, 1), before_p, after_p, new_vars_p);
       t1 = build ((code == PREINCREMENT_EXPR) ? PLUS_EXPR : MINUS_EXPR,
 	          TREE_TYPE (expr), lhs, rhs);
       t2 = build_modify_expr (lhs, NOP_EXPR, t1);
@@ -676,8 +1126,6 @@ simplify_expr (expr, scope, before_p, af
 
       /* Binary arithmetic expressions.  Simplify each operand, assign the
 	 result of the operation to a new temporary T and return T.  */
-    case COMPONENT_REF:
-    case ARRAY_REF:
     case BIT_AND_EXPR:
     case BIT_ANDTC_EXPR:
     case BIT_IOR_EXPR:
@@ -700,14 +1148,11 @@ simplify_expr (expr, scope, before_p, af
     case TRUNC_DIV_EXPR:
     case TRUNC_MOD_EXPR:
     case TRUTH_AND_EXPR:
-    case TRUTH_ANDIF_EXPR:
     case TRUTH_OR_EXPR:
-    case TRUTH_ORIF_EXPR:
     case TRUTH_XOR_EXPR:
     case COMPLEX_EXPR:
     case COMPOUND_EXPR:
     case CONSTRUCTOR:
-    case COND_EXPR:
     case EQ_EXPR:
     case GE_EXPR:
     case GT_EXPR:
@@ -723,26 +1168,158 @@ simplify_expr (expr, scope, before_p, af
     case UNLE_EXPR:
     case UNLT_EXPR:
     case UNORDERED_EXPR:
-      lhs = simplify_expr (TREE_OPERAND (expr, 0), scope, before_p,
-	  after_p, new_vars_p);
-      rhs = simplify_expr (TREE_OPERAND (expr, 1), scope, before_p,
-	  after_p, new_vars_p);
-      TREE_OPERAND (expr, 0) = lhs;
-      TREE_OPERAND (expr, 1) = rhs;
-      t1 = create_tmp_var (TREE_TYPE (expr), new_vars_p);
-      t2 = build_modify_expr (t1, NOP_EXPR, expr);
-      add_tree (build_stmt (EXPR_STMT, t2), before_p);
-      return t1;
+      {
+	int s0, s1;
+	s0 = simplified_p (TREE_OPERAND (expr, 0));
+	s1 = simplified_p (TREE_OPERAND (expr, 1));
+	
+	if (s0 && s1)
+	  /* Don't simplify an expression that is already simple enough.  */
+	  return expr;
+	
+	if (!s0 && !s1)
+	  /* Simplify both sides of the expression.  */
+	  {
+	    lhs = simplify_expr (TREE_OPERAND (expr, 0), before_p,
+				 after_p, new_vars_p);
+	    rhs = simplify_expr (TREE_OPERAND (expr, 1), before_p,
+				 after_p, new_vars_p);
+	    
+	    TREE_OPERAND (expr, 0) = lhs;
+	    TREE_OPERAND (expr, 1) = rhs;
+	    
+	    t1 = create_tmp_var (TREE_TYPE (expr), new_vars_p);
+	    t2 = build_modify_expr (t1, NOP_EXPR, expr);
+	    add_tree (build_stmt (EXPR_STMT, t2), before_p);
+	    return t1;
+	  }
+	
+	if (s0)
+	  /* Simplify just the rhs, and don't construct any temporary variable.  */
+	  {
+	    rhs = simplify_expr (TREE_OPERAND (expr, 1), before_p,
+				 after_p, new_vars_p);
+	    TREE_OPERAND (expr, 1) = rhs;
+	    return expr;
+	  }
 
+	/* if (s1)  */
+	/* Simplify just the lhs, and don't construct any temporary variable.  */
+	lhs = simplify_expr (TREE_OPERAND (expr, 0), before_p,
+			     after_p, new_vars_p);
+	TREE_OPERAND (expr, 0) = lhs;
+	return expr;
+      }
+
+    case ARRAY_REF:
+      {
+	lhs = simplify_expr (TREE_OPERAND (expr, 0), before_p,
+			     after_p, new_vars_p);
+	rhs = simplify_expr (TREE_OPERAND (expr, 1), before_p,
+			     after_p, new_vars_p);
+	TREE_OPERAND (expr, 0) = lhs;
+	TREE_OPERAND (expr, 1) = rhs;
+      	
+	return expr;
+      }
+
+    case COMPONENT_REF:
+      /* Simplification of x = a.b.c.d[7] into 
+	 int *T1;  T1 = &a.b.c.d;  x = *T1[7];  */
+      {
+	tree type;
+	type = TREE_TYPE (expr);
+	if (TREE_CODE (type) == ARRAY_TYPE)
+	  {
+	    tree type_p; 
+	    type_p = build_pointer_type (TREE_TYPE (type));
+
+	    t1 = create_tmp_var (type_p, new_vars_p);
+	    t2 = build_modify_expr (t1, NOP_EXPR, build1 (ADDR_EXPR, type_p, expr));
+	    
+	    add_tree (build_stmt (EXPR_STMT, t2), before_p);
+	    // FIXME : work, but incorrect ?  
+	    return build1 (INDIRECT_REF, TREE_TYPE (expr), t1); 
+	  }
+	else
+	  return expr;
+      }
+
+    case COND_EXPR:
+      {
+	/* The expression hides an if.
+	   (cond) ? then_clause : else_clause;
+	   Transform it in an IF_STMT, 
+	   if (cond) tmp = then_clause; else tmp = else_clause;
+	   and simplify it correctly.  
+	   FIXME : case when else is a block...
+	*/
+	tree if_new;
+	tree tmp;
+	
+	fprintf (stderr, "Got a cond_expr : \n");
+	debug_c_node (expr);
+	fprintf (stderr, "\n");
+	
+	/* FIXME: What happens if the type is a pointer ? function pointer ? ... */
+	tmp = create_tmp_var (TREE_TYPE (expr), new_vars_p);
+	
+	/* Build the THEN_CLAUSE.  */
+	t1 = build_modify_expr (tmp, NOP_EXPR, TREE_OPERAND (expr, 1));
+	t1 = build_stmt (EXPR_STMT, t1);
+
+	/* Build the ELSE_CLAUSE.  */
+	t2 = build_modify_expr (tmp, NOP_EXPR, TREE_OPERAND (expr, 2));
+	t2 = build_stmt (EXPR_STMT, t2);
+	
+	if_new = new_simplified_if (TREE_OPERAND (expr, 0), t1, t2, NULL_TREE);
+	insert_stmt_chain (before_p, if_new);
+	return tmp;
+      }
+
+    case TRUTH_ANDIF_EXPR:
+    case TRUTH_ORIF_EXPR:
+      /* Transform this expression into T, 
+	 insert in before_p its definition : the simplified version of 
+	 'if (cond) T = 1; else T = 0;'  */
+      {
+	tree tmp, if_new;
+	
+	/* Create a temporary variable.  */
+	tmp = create_tmp_var (TREE_TYPE (expr), new_vars_p);
+
+	/* Build the THEN_CLAUSE.  */
+	t1 = build_modify_expr (tmp, NOP_EXPR, integer_one_node);
+	t1 = build_stmt (EXPR_STMT, t1);
+
+	/* Build the ELSE_CLAUSE.  */
+	t2 = build_modify_expr (tmp, NOP_EXPR, integer_zero_node);
+	t2 = build_stmt (EXPR_STMT, t2);
+	
+	/* Construct the simplified IF_STMT.  */
+	if_new = new_simplified_if (expr, t1, t2, NULL_TREE);
+	insert_stmt_chain (before_p, if_new);
 
+	return tmp;
+      }
+
       /* Assignment and initialization.  Simplify both sides, queue up the
 	 simplified expression and return the LHS.  */
     case INIT_EXPR:
+      lhs = simplify_expr (TREE_OPERAND (expr, 0), before_p,
+			   after_p, new_vars_p);
+      rhs = simplify_expr (TREE_OPERAND (expr, 1), before_p,
+			   after_p, new_vars_p);
+      TREE_OPERAND (expr, 0) = lhs;
+      TREE_OPERAND (expr, 1) = rhs;
+      add_tree (build_stmt (EXPR_STMT, expr), before_p);
+      return lhs;
+
     case MODIFY_EXPR:
-      lhs = simplify_expr (TREE_OPERAND (expr, 0), scope, before_p,
-	  after_p, new_vars_p);
-      rhs = simplify_expr (TREE_OPERAND (expr, 1), scope, before_p,
-	  after_p, new_vars_p);
+      lhs = simplify_expr (TREE_OPERAND (expr, 0), before_p,
+			   after_p, new_vars_p);
+      rhs = simplify_expr (TREE_OPERAND (expr, 1), before_p,
+			   after_p, new_vars_p);
       TREE_OPERAND (expr, 0) = lhs;
       TREE_OPERAND (expr, 1) = rhs;
       add_tree (build_stmt (EXPR_STMT, expr), before_p);
@@ -759,11 +1336,11 @@ simplify_expr (expr, scope, before_p, af
 	 reference and re-write the call.  */
     case CALL_EXPR:
       TREE_OPERAND (expr, 0) = simplify_expr (TREE_OPERAND (expr, 0), 
-					      scope, before_p, after_p,
+					      before_p, after_p,
 					      new_vars_p);
       if (TREE_OPERAND (expr, 1))
 	TREE_OPERAND (expr, 1) = simplify_expr (TREE_OPERAND (expr, 1),
-						scope, before_p, after_p,
+						before_p, after_p,
 						new_vars_p);
 
       return expr;
@@ -773,7 +1350,7 @@ simplify_expr (expr, scope, before_p, af
 	tree op;
 
 	for (op = expr; op; op = TREE_CHAIN (op))
-	  TREE_VALUE (op) = simplify_expr (TREE_VALUE (op), scope,
+	  TREE_VALUE (op) = simplify_expr (TREE_VALUE (op),
 	                                   before_p, after_p, new_vars_p);
 
 	return expr;
@@ -829,11 +1406,7 @@ create_tmp_var (type, new_vars_p)
   TREE_READONLY (tmp_var) = 0;
 
   /* Make the type of the variable writable.  */
-  if (TYPE_READONLY (TREE_TYPE (tmp_var)))
-    {
-      TREE_TYPE (tmp_var) = copy_node (TREE_TYPE (tmp_var));
-      TYPE_READONLY (TREE_TYPE (tmp_var)) = 0;
-    }
+  make_type_writable (tmp_var);
 
   /* Set the declaration context.  */
   DECL_CONTEXT (tmp_var) = current_function_decl;
@@ -849,6 +1422,53 @@ create_tmp_var (type, new_vars_p)
 
 /* }}} */
 
+/** {{{ make_type_writable()
+
+    Change the flags for the type of the node T to make it writtable.  */
+
+static void 
+make_type_writable (t)
+     tree t;
+{
+  if (t == NULL_TREE)
+    abort();
+
+  if (TYPE_READONLY (TREE_TYPE (t))
+      || ((TREE_CODE (TREE_TYPE (t)) == RECORD_TYPE
+	   || TREE_CODE (TREE_TYPE (t)) == UNION_TYPE)
+	  && C_TYPE_FIELDS_READONLY (TREE_TYPE (t))))
+    {
+      /* Make a copy of the type declaration.  */
+      TREE_TYPE (t) = build_type_copy (TREE_TYPE (t));
+      TYPE_READONLY (TREE_TYPE (t)) = 0;
+      
+      /* If the type is a structure that contains a field readonly.  */
+      if ((TREE_CODE (TREE_TYPE (t)) == RECORD_TYPE
+	   || TREE_CODE (TREE_TYPE (t)) == UNION_TYPE)
+	  && C_TYPE_FIELDS_READONLY (TREE_TYPE (t)))
+	{
+	  C_TYPE_FIELDS_READONLY (TREE_TYPE (t)) = 0;
+
+	  /* Make the fields of the structure writable.  */
+	  {
+	    tree it;
+	    it = TYPE_FIELDS (TREE_TYPE (t));
+	    while (it)
+	      {
+		/* Make the field writable.  */
+		TREE_READONLY (it) = 0;
+		
+		/* Make the type of the field writable.  */
+		make_type_writable (it);
+		it = TREE_CHAIN (it);
+	      }
+	  }
+	}
+    }
+}
+
+/* }}} */
+
 /** {{{ declare_tmp_vars()
 
     Declares all the variables in VARS in SCOPE.  Returns the last DECL_STMT
@@ -894,14 +1514,28 @@ declare_tmp_vars (vars, scope)
 
 /** {{{ tree_build_scope()
    
-   Replaces T by a scope containing T.  */
+   Replaces T; by a COMPOUND_STMT containing {T;}.  */
 
 static void
 tree_build_scope (t)
      tree *t;
 {
   if (*t == NULL_TREE)
-    return;
+    {
+      /* Construct a compound statement and a scope.  */
+      tree body, start_scope, end_scope;
+      body = make_node (COMPOUND_STMT);
+      start_scope = make_node (SCOPE_STMT);
+      end_scope = make_node (SCOPE_STMT);
+      TREE_LANG_FLAG_0 (start_scope) = 1;
+      TREE_LANG_FLAG_0 (end_scope) = 0;
+      TREE_OPERAND (body, 0) = start_scope;
+      /* Construct an empty body.  */
+      TREE_CHAIN (start_scope) = end_scope;
+      /* Replace the node by the constructed body.  */
+      *t = body;
+      return;
+    }
 
   if (TREE_CODE (*t) == COMPOUND_STMT)
     {
@@ -974,7 +1608,11 @@ keep_stmt_p (t)
      declaration (e.g., 'a;') should be discarded.  */
   if (TREE_CODE (t) == EXPR_STMT
       && TREE_OPERAND (t, 0)
-      && TREE_CODE (TREE_OPERAND (t, 0)) == VAR_DECL
+      && (TREE_CODE (TREE_OPERAND (t, 0)) == VAR_DECL ||
+	  TREE_CODE (TREE_OPERAND (t, 0)) == PARM_DECL ||
+	  TREE_CODE (TREE_OPERAND (t, 0)) == INDIRECT_REF ||
+	  TREE_CODE (TREE_OPERAND (t, 0)) == ARRAY_REF ||
+	  TREE_CODE (TREE_OPERAND (t, 0)) == COMPONENT_REF)
       && !TYPE_VOLATILE (TREE_TYPE (TREE_OPERAND (t, 0))))
     return 0;
 
@@ -982,3 +1620,266 @@ keep_stmt_p (t)
 }
 
 /* }}} */
+
+/** {{{ insert_before_continue_end()
+    
+    Insert the REEVAL list before CONTINUE_STMTs and at the end of the loop body BODY.  
+    Set the line number of the REEVAL list to LINE.  */
+
+static void
+insert_before_continue_end (reeval, body, line)
+     tree reeval;
+     tree body;
+     int line;
+{
+  tree last, forelast;
+
+  /* Update the line number information.  */
+  {
+    tree it;
+    for (it = reeval; TREE_CHAIN (it); it = TREE_CHAIN (it))
+      update_line_number (it, line);
+  }
+
+  /* Make sure that the loop body has a scope.  */
+  tree_build_scope (&body);
+
+  /* Insert the reevaluation list before every CONTINUE_STMT.  */
+  /*  TREE_CHAIN (reeval) = NULL_TREE; */
+  forelast = insert_before_continue (body, reeval);
+  last = TREE_CHAIN (forelast);
+  
+  /* If the last statement of the WHILE_BODY is not a CONTINUE_STMT, 
+     then insert reeval at the end of the loop block.  */
+  if (TREE_CODE (forelast) != CONTINUE_STMT)
+    {
+      TREE_CHAIN (forelast) = NULL_TREE;
+      copy_stmt_chain (&forelast, reeval);
+      forelast = tree_last (forelast);
+      TREE_CHAIN (forelast) = last;
+    }
+}
+
+/* }}} */
+
+/** {{{ insert_before_continue()
+    
+    Insert the list REEVAL of statements before each CONTINUE_STMT in the block 
+    pointed to by NODE.  At the end returns a pointer to the forelast node in 
+    the block NODE.  The caller can insert then the last loop reevaluation at 
+    the end of the loop block.  */
+
+static tree
+insert_before_continue (node, reeval)
+     tree node, reeval;
+{
+  tree next;
+
+  if (reeval == NULL_TREE || node == NULL_TREE)
+    return NULL_TREE;
+  
+  if (TREE_CODE (node) == COMPOUND_STMT)
+    node = COMPOUND_BODY (node);
+  
+  next = TREE_CHAIN (node);
+  if (next == NULL_TREE)
+    return NULL_TREE;
+
+  /* Walk through each statement in the given block up to the last one, 
+     searching for CONTINUE_STMTs.  */
+  for ( ;TREE_CHAIN (next) != NULL_TREE; 
+	node = TREE_CHAIN (node), next = TREE_CHAIN (next))
+    {
+      switch (TREE_CODE (next))
+	{
+
+	case CONTINUE_STMT:
+	  /* Insert the reeval of statements before continue.  */
+	  TREE_CHAIN (node) = NULL_TREE;
+	  copy_stmt_chain (&node, reeval);
+	  node = tree_last (node);
+	  TREE_CHAIN (node) = next;
+	  break;
+	  
+	case IF_STMT:
+	  /* Be sure that the THEN_CLAUSE has a scope.  */
+	  tree_build_scope (&THEN_CLAUSE (next));
+
+	  /* Insert the code REEVAL in the block of the THEN_CLAUSE.  */
+	  insert_before_continue (COMPOUND_BODY (THEN_CLAUSE (next)), reeval);
+	  
+	  /* Same thing for the ELSE_CLAUSE.  */
+	  if (ELSE_CLAUSE (TREE_CHAIN (node)))
+	    {
+	      tree_build_scope (&ELSE_CLAUSE (next));
+	      insert_before_continue (COMPOUND_BODY (ELSE_CLAUSE (next)), reeval);
+	    }
+	  break;
+
+	  //§ FIXME ... to be tested ...
+	case SWITCH_STMT:
+	  /* Be sure that the SWITCH_BODY has a scope.  */
+	  tree_build_scope (&SWITCH_BODY (next));
+
+	  /* Insert the code REEVAL in the SWITCH_BODY.  */
+	  insert_before_continue (COMPOUND_BODY (SWITCH_BODY (next)), reeval);
+	  break;
+
+	case COMPOUND_STMT:
+	  /* Insert in the inner block.  */
+	  insert_before_continue (COMPOUND_BODY (next), reeval);
+	  break;
+
+	default:
+	  /* Don't enter in sub loops...  The continue statement has an effect 
+	     only at a depth 1.  */
+	  break;
+	}
+    }
+  return node;
+}
+
+/* }}} */
+
+
+/** {{{ copy_stmt_chain()
+    
+    Copy the contents of the list op2 at the end of the list op1 by creating new
+    statements.  */
+
+static void
+copy_stmt_chain (op1, op2)
+     tree *op1, op2;
+{
+  tree t1, t2;
+  if (op1 == NULL)
+    abort ();
+  
+  if (op2 == NULL_TREE)
+    /* Nothing to copy.  */
+    return;
+  
+  if (*op1)
+    {
+      /* Place t1 at the end of op1.  */
+      for (t1 = *op1; TREE_CHAIN (t1); t1 = TREE_CHAIN (t1))
+	;
+      t2 = op2;
+    }
+  else
+    {
+      /* Construct a first statement in the op1 list.  */
+      *op1 = build_stmt (EXPR_STMT, copy_node (EXPR_STMT_EXPR (op2)));
+      t1 = *op1;
+      t2 = TREE_CHAIN (op2);
+    }
+  /* Copy every statement form t2.  */
+  for (; t2; t2 = TREE_CHAIN (t2), t1 = TREE_CHAIN (t1))
+    TREE_CHAIN (t1) = copy_node (t2);
+}
+
+/* }}} */
+
+/** {{{ insert_stmt_chain()
+
+    Insert the chain op2 at the end of the chain *op1.  */
+
+static void 
+insert_stmt_chain (op1, op2)
+     tree *op1, op2;
+{
+  tree last;
+  if (op1 == NULL)
+    abort ();
+
+  if (*op1 == NULL_TREE)
+    *op1 = op2;
+  else
+    {
+      last = tree_last (*op1);
+      TREE_CHAIN (last) = op2;
+    }
+}
+
+/* }}} */
+
+/** {{{ update_line_number()
+
+    Updates the STMT_LINENO of each stmt in the tree t to the line number LINE. 
+    Returns the last stmt in the tree chain.  */
+
+static tree
+update_line_number (t, line)
+     tree t;
+     int line;
+{
+  if (t == NULL_TREE)
+    return NULL_TREE;
+
+  for (; TREE_CHAIN (t); t = TREE_CHAIN (t))
+    STMT_LINENO (t) = line;
+  STMT_LINENO (t) = line;
+  return t;
+}
+
+/* }}} */
+
+/** {{{ simplified_p()
+
+    Return one if T is an expression that is under its simplified form.  */
+
+static int
+simplified_p (t)
+     tree t;
+{
+  return simplified_rec_p (t, 0);
+}
+
+/* }}} */
+
+/** {{{ simplified_p()
+    
+    Return one if T is an expression that is under its simplified form.
+    DEPTH is the nest level of recursion, call this function with DEPTH=0.  */
+
+static int
+simplified_rec_p (t, depth)
+     tree t;
+     int depth;
+{
+  switch (TREE_CODE (t))
+    {
+    case INTEGER_CST:
+    case REAL_CST:
+    case COMPLEX_CST:
+    case STRING_CST:
+    case CONST_DECL:
+    case VAR_DECL:
+    case PARM_DECL:
+    case FIELD_DECL:
+      return 1;
+
+    case MODIFY_EXPR:
+    case LT_EXPR:
+    case LE_EXPR:
+    case GT_EXPR:
+    case GE_EXPR:
+    case EQ_EXPR:
+    case NE_EXPR:
+    case UNLT_EXPR:
+    case UNLE_EXPR:
+    case UNGT_EXPR:
+    case UNGE_EXPR:
+    case UNEQ_EXPR:
+      /* Binary expressions : both sides must be simplified.  */
+      if (depth == 0 &&
+	  simplified_rec_p (TREE_OPERAND (t, 0), 1) &&
+	  simplified_rec_p (TREE_OPERAND (t, 1), 1))
+	return 1;
+      else 
+	return 0;
+
+    default:
+      return 0;
+    }
+}


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