This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [ast-optimizer-branch] Simplify
On Mon, 18 Mar 2002, Sebastian Pop wrote:
> 2002-03-18 Sebastian Pop <s.pop@laposte.net>
> * c-simplify.c (insert_stmt_chain): Deleted.
> (simplified_condition_p, insert_after_case_labels): New.
> (simplify_stmt, simplify_for_stmt, simplify_while_stmt, simplify_do_stmt,
> new_simplified_if, simplify_switch_stmt, ): Clean :
> returns a single node, generate a chain of statements to be
> executed before the if, and a list of new variables.
> (new_simplified_if): Simplifies clauses.
> (simplify_expr): Remove unused parameter : scope.
>
Thanks. This is OK, with a couple of changes.
> +/* Interface used in [break/goto]-elimination : to be declared in a .h file. */
> +extern void insert_before_continue_end PARAMS ((tree, tree, int));
> +extern void tree_build_scope PARAMS ((tree *));
> +extern tree create_tmp_var PARAMS ((tree, tree *));
> +extern tree declare_tmp_vars PARAMS ((tree, tree));
> +extern tree copy_stmt_chain PARAMS ((tree));
> +extern tree copy_stmt PARAMS ((tree));
> +extern tree update_line_number PARAMS ((tree, int));
> +
>
I moved them to tree-simple.h. I will be adding other generic
code there as well.
> static tree
> -simplify_for_stmt (prev, stmt, next, scope)
> - tree prev, stmt, next, scope;
> +simplify_for_stmt (stmt, before_p, vars)
> + tree stmt;
> + tree *before_p, *vars;
>
We should not be changing the structure of the FOR_STMT. Don't
convert them to WHILE_STMTs. FOR_STMTs have nice properties.
> - tree new_vars = NULL;
> - simplify_expr (TREE_OPERAND (FOR_INIT_STMT (stmt), 0), &init_before,
> - &init_after, &new_vars, scope);
>
Why are you not saving the simplified expression? This seems
wrong.
> +
> + /* Step 0 : Check wether the loop condition is already simplified. */
> + if (simplified_condition_p (cond))
>
This will fail if cond == NULL. Any of the three header nodes in
a FOR_STMT can be missing. You need to account for that.
I checked in the following so that we don't get too much out of
sync. I'll be checking in several changes to the expression
simplifier shortly.
Diego.
2002-03-18 Diego Novillo <dnovillo@redhat.com>
* tree-simple.h: New file.
* Makefile.in (c-simplify.o): Add dependency on tree-simple.h
* c-simplify.c: Reformat some comments.
(tree_last_decl): Declare.
2002-03-18 Sebastian Pop <s.pop@laposte.net>
* c-simplify.c (insert_stmt_chain): Delete.
(simplified_condition_p, insert_after_case_labels): New.
(simplify_stmt, simplify_for_stmt, simplify_while_stmt,
simplify_do_stmt, new_simplified_if, simplify_switch_stmt):
Returns a single node, generate a chain of statements to be executed
before the if, and a list of new variables.
(new_simplified_if): Simplify clauses.
(simplify_expr): Remove unused parameter scope.
Index: Makefile.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Makefile.in,v
retrieving revision 1.701.2.15
diff -d -p -d -u -p -r1.701.2.15 Makefile.in
--- Makefile.in 2002/03/05 05:26:47 1.701.2.15
+++ Makefile.in 2002/03/18 19:12:22
@@ -1353,7 +1353,7 @@ tree-optimize.o : tree-optimize.c tree-o
$(SYSTEM_H) $(RTL_H) $(TREE_H) $(TM_P_H) $(BASIC_BLOCK_H) $(EXPR_H) \
$(GGC_H) output.h diagnostic.h ssa.h errors.h flags.h
c-simplify.o : c-simplify.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) errors.h \
- $(C_TREE_H) $(C_COMMON_H) diagnostic.h
+ $(C_TREE_H) $(C_COMMON_H) diagnostic.h tree-simple.h
c-pretty-print.o : c-pretty-print.c $(CONFIG_H) $(SYSTEM_H) \
$(RTL_H) $(TREE_H) $(EXPR_H) $(C_COMMON_H) errors.h diagnostic.h
stor-layout.o : stor-layout.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) flags.h \
Index: c-simplify.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/c-simplify.c,v
retrieving revision 1.1.2.4
diff -d -p -d -u -p -r1.1.2.4 c-simplify.c
--- c-simplify.c 2002/03/14 21:48:43 1.1.2.4
+++ c-simplify.c 2002/03/18 19:12:23
@@ -30,6 +30,7 @@ Software Foundation, 59 Temple Place - S
#include "errors.h"
#include "c-tree.h"
#include "c-common.h"
+#include "tree-simple.h"
#include "diagnostic.h"
/* {{{ Grammar for SIMPLE trees. */
@@ -202,27 +203,22 @@ Software Foundation, 59 Temple Place - S
/* {{{ Local declarations. */
-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 *, tree));
-static tree simplify_decl_stmt PARAMS ((tree, tree *));
-static tree simplify_expr PARAMS ((tree, 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 tree copy_stmt_chain PARAMS ((tree));
-static tree copy_stmt PARAMS ((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));
+static tree simplify_for_stmt PARAMS ((tree, tree *, tree *));
+static tree simplify_while_stmt PARAMS ((tree, tree *, tree *));
+static tree simplify_do_stmt PARAMS ((tree));
+static void simplify_switch_stmt PARAMS ((tree, tree *, tree *));
+static tree simplify_decl_stmt PARAMS ((tree, tree *));
+static tree new_simplified_if PARAMS ((tree, tree, tree, tree *, tree *, int));
+static tree simplify_expr PARAMS ((tree, tree *, tree *, tree *));
+static void make_type_writable PARAMS ((tree));
+static void add_tree PARAMS ((tree, tree *));
+static int keep_stmt_p PARAMS ((tree));
+static void insert_after_case_labels PARAMS ((tree, tree, int));
+static tree insert_before_continue PARAMS ((tree, tree));
+static int simplified_p PARAMS ((tree));
+static int simplified_rec_p PARAMS ((tree, int));
+static int simplified_condition_p PARAMS ((tree));
+static tree tree_last_decl PARAMS ((tree scope));
/* }}} */
@@ -265,69 +261,55 @@ simplify_stmt (stmt, scope)
before = NULL;
after = NULL;
new_vars = NULL;
+ next = TREE_CHAIN (stmt);
switch (TREE_CODE (stmt))
{
case COMPOUND_STMT:
simplify_stmt (COMPOUND_BODY (stmt), scope);
- /* Prepare for the next iteration. */
- next = TREE_CHAIN (stmt);
+ /* Next iteration. */
prev = stmt;
stmt = next;
continue;
- case FOR_STMT:
- prev = simplify_for_stmt (prev, stmt, TREE_CHAIN (stmt), scope);
- stmt = TREE_CHAIN (prev);
+ case SCOPE_STMT:
+ if (SCOPE_BEGIN_P (stmt))
+ /* Save a pointer to the scope. */
+ scope = stmt;
+
+ /* Next iteration. */
+ prev = stmt;
+ stmt = next;
continue;
+
+ case FOR_STMT:
+ stmt = simplify_for_stmt (stmt, &before, &new_vars);
+ break;
case WHILE_STMT:
- prev = simplify_while_stmt (prev, stmt, TREE_CHAIN (stmt), scope);
- stmt = TREE_CHAIN (prev);
- continue;
+ stmt = simplify_while_stmt (stmt, &before, &new_vars);
+ break;
case DO_STMT:
- prev = simplify_do_stmt (prev, stmt, TREE_CHAIN (stmt), scope);
- stmt = TREE_CHAIN (prev);
- continue;
+ stmt = simplify_do_stmt (stmt);
+ break;
case IF_STMT:
- next = TREE_CHAIN (stmt);
- tree_build_scope (&THEN_CLAUSE (stmt));
- tree_build_scope (&ELSE_CLAUSE (stmt));
- simplify_stmt (THEN_CLAUSE (stmt), scope);
- simplify_stmt (ELSE_CLAUSE (stmt), scope);
/* 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;
-
+ &before, &new_vars, 1);
+ break;
+
case SWITCH_STMT:
- simplify_switch_stmt (stmt, &before, &after, &new_vars, scope);
+ simplify_switch_stmt (stmt, &before, &new_vars);
break;
case EXPR_STMT:
- TREE_OPERAND (stmt, 0) = simplify_expr (TREE_OPERAND (stmt, 0),
- &before, &after,
- &new_vars, scope);
+ TREE_OPERAND (stmt, 0) =
+ simplify_expr (TREE_OPERAND (stmt, 0), &before, &after, &new_vars);
break;
case DECL_STMT:
@@ -344,8 +326,6 @@ simplify_stmt (stmt, scope)
/* 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. */
end_after = update_line_number (after, STMT_LINENO (stmt));
/* Chain the end of the AFTER block to the next stmt. */
@@ -367,19 +347,9 @@ simplify_stmt (stmt, scope)
tree e = RETURN_EXPR (stmt);
TREE_OPERAND (e, 1) = simplify_expr (TREE_OPERAND (e, 1),
&before, &after,
- &new_vars, scope);
+ &new_vars);
}
break;
-
- case SCOPE_STMT:
- if (SCOPE_BEGIN_P (stmt))
- /* Save a pointer to the scope. */
- scope = stmt;
-
- /* Next iteration. */
- prev = stmt;
- stmt = TREE_CHAIN (stmt);
- continue;
case FILE_STMT:
case LABEL_STMT:
@@ -388,8 +358,10 @@ simplify_stmt (stmt, scope)
case CASE_LABEL:
case CONTINUE_STMT:
case BREAK_STMT:
- /* Nothing to do. */
- break;
+ /* Nothing to do : next iteration. */
+ prev = stmt;
+ stmt = next;
+ continue;
default:
prep_stmt (stmt);
@@ -406,7 +378,7 @@ simplify_stmt (stmt, scope)
if (new_vars)
{
tree last = declare_tmp_vars (new_vars, scope);
-
+
/* If the previous statement was a declaration or a scope
statement, we need to re-set it to point to the last
temporary variable declaration. Otherwise, they will be
@@ -415,56 +387,33 @@ simplify_stmt (stmt, scope)
|| TREE_CODE (prev) == SCOPE_STMT)
prev = last;
}
-
+
+ /* Update line number on statements created after simplification. */
+ update_line_number (before, STMT_LINENO (stmt));
+ update_line_number (after, STMT_LINENO (stmt));
+
/* There are three tree chains that need to be dealt with: BEFORE,
- STMT and AFTER. If they all exist, the program needs to be
- transformed from:
-
- PREV -> STMT -> NEXT
- to
- PREV -> BEFORE -> STMT -> AFTER -> NEXT
-
- Since either of the three may be NULL, we need to consider all the
- possible variations. */
-
- next = TREE_CHAIN (stmt);
-
- if (before)
- {
- /* Include the nodes from the BEFORE list. */
- TREE_CHAIN (prev) = before;
+ STMT and AFTER. The following code rewires the chains as described by
+ the following schema :
- /* Update the line number and make PREV points to the last stmt in
- BEFORE list */
- prev = update_line_number (before, STMT_LINENO (stmt));
- }
+ PREV -> NULL
+ PREV -> BEFORE -> NULL
+ PREV -> BEFORE -> STMT -> NULL
+ PREV -> BEFORE -> STMT -> AFTER -> NULL
+ PREV -> BEFORE -> STMT -> AFTER -> NEXT -> ... */
- if (keep_stmt_p (stmt))
- {
- /* Include STMT, if it's worth keeping (i.e., it has not been
- nullified by the simplification process). */
- TREE_CHAIN (prev) = stmt;
-
- /* Re-compute PREV. */
- prev = stmt;
- }
-
- if (after)
- {
- /* Include the nodes from the AFTER list. */
- TREE_CHAIN (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;
+ TREE_CHAIN (prev) = NULL_TREE;
+ TREE_CHAIN (stmt) = NULL_TREE;
+ chainon (prev, before);
+ if (keep_stmt_p (stmt))
+ /* The statement hasn't been nullified by the simplification. */
+ chainon (prev, stmt);
+ chainon (prev, after);
- /* Next step of the iteration. */
+ /* Next iteration. */
+ prev = tree_last (prev);
stmt = next;
+ TREE_CHAIN (prev) = stmt;
}
}
@@ -473,182 +422,169 @@ simplify_stmt (stmt, scope)
/** {{{ simplify_for_stmt()
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. */
+ Return a pointer to the simplified version of the FOR_STMT. */
static tree
-simplify_for_stmt (prev, stmt, next, scope)
- tree prev, stmt, next, scope;
+simplify_for_stmt (stmt, before_p, vars)
+ tree stmt;
+ tree *before_p, *vars;
{
- tree cond, body, loop, last;
+ tree cond, body, loop;
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 (stmt));
+
+ /* Save some pointers. */
cond = FOR_COND (stmt);
body = FOR_BODY (stmt);
new_scope = COMPOUND_BODY (body);
- TREE_CHAIN (prev) = NULL_TREE;
-
+
/* Simplify FOR_INIT_STMT. */
- if (TREE_OPERAND (FOR_INIT_STMT (stmt), 0))
+ if (EXPR_STMT_EXPR (FOR_INIT_STMT (stmt)))
{
- tree new_vars = NULL;
- simplify_expr (TREE_OPERAND (FOR_INIT_STMT (stmt), 0), &init_before,
- &init_after, &new_vars, scope);
- /* 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);
+ tree init_before = NULL_TREE, init_after = NULL_TREE;
+ simplify_expr (EXPR_STMT_EXPR (FOR_INIT_STMT (stmt)), &init_before,
+ &init_after, vars);
+ /* Insert the simplification chains before the beginning of the loop. */
+ *before_p = chainon (*before_p, init_before);
+ if (TREE_CODE (EXPR_STMT_EXPR (FOR_INIT_STMT (stmt))) == COMPOUND_EXPR)
+ *before_p = chainon (*before_p, FOR_INIT_STMT (stmt));
+ *before_p = chainon (*before_p, init_after);
}
/* Simplify FOR_EXPR. */
if (FOR_EXPR (stmt))
{
tree new_scope_vars = NULL;
- simplify_expr (FOR_EXPR (stmt), &expr_before, &expr_after, &new_scope_vars, scope);
- /* FOR_EXPR (t) = NULL_TREE; */
-
+ simplify_expr (FOR_EXPR (stmt), &expr_before, &expr_after, &new_scope_vars);
+
/* If we created new temporary variables, create declarations for
- them in the current scope. */
+ them in the loop's 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. */
+
+ /* Step 0 : Check wether the loop condition is already simplified. */
+ if (simplified_condition_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. */
+ /* Step 1 : Insert a simplified version of 'reeval;' in loop's body. */
reeval = chainon (expr_before, expr_after);
if (reeval)
- insert_before_continue_end (reeval, FOR_BODY (stmt), STMT_LINENO (stmt));
+ insert_before_continue_end (reeval, FOR_BODY (stmt),
+ STMT_LINENO (stmt));
/* Step 2 : Construct a 'while (cond) {body}' statement. */
- loop = build_stmt (WHILE_STMT,
+ simplify_stmt (body, NULL_TREE); return 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;
+ /* WHILE_BODY */ body);
}
- /* step 1 : Insert a simplified version of 'reeval; if (!cond) break;'
- in the loop body. */
+ /* Step 1 : Insert a simplified version of
+ 'expr_before; expr_after; if (cond) {} else break;'
+ in loop's body. */
{
- tree if_stmt, reeval;
-
- /* Build 'if (cond) {} else break;'. */
- if_stmt = new_simplified_if (cond, NULL_TREE, build_stmt (BREAK_STMT),
- COMPOUND_BODY (FOR_BODY (stmt)));
+ tree if_stmt, if_vars = NULL, before_if = NULL;
+ /* Build 'if (cond) {} else break;'. */
+ if_stmt = new_simplified_if (/* IF_COND */ copy_node (cond),
+ /* THEN_CLAUSE */ NULL_TREE,
+ /* ELSE_CLAUSE */ build_stmt (BREAK_STMT),
+ &before_if, &if_vars, 0);
+
+ /* If we created new temporary variables, create declarations for them in the
+ loop body. */
+ if (if_vars)
+ declare_tmp_vars (if_vars, new_scope);
+
/* Insert the 'reeval; if_stmt;' 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));
+ end of the loop body. */
+ {
+ tree reeval;
+ reeval = chainon (expr_before, expr_after);
+ if (before_if)
+ /* There are some statements to be executed before the IF_STMT. */
+ reeval = chainon (reeval, before_if);
+ reeval = chainon (reeval, if_stmt);
+ if (reeval)
+ insert_before_continue_end (reeval, body, STMT_LINENO (stmt));
+ }
}
- /* Step 2 : Construct a 'while (1!=0) {body}' statement. For the moment don't
- initialize the loop body in order to avoid to simplify it twice. */
- tree_build_scope (&body);
- simplify_stmt (body, COMPOUND_BODY (body));
+ /* Step 2 : Construct a 'while (1!=0) {body}' statement. */
loop = build_stmt (WHILE_STMT,
/* WHILE_COND */ build (NE_EXPR, integer_type_node,
integer_one_node, integer_zero_node),
/* WHILE_BODY */ body);
-
- /* 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 : Next statement to be processed. */
- last = chainon (prev, stmt);
- last = tree_last (last);
- chainon (stmt, next);
- return last;
+
+ /* Step 3 : Include the loop in an IF_STMT : 'if (cond) while (1){body} else {}' */
+ return new_simplified_if (/* IF_COND */ cond,
+ /* THEN_CLAUSE */ loop,
+ /* ELSE_CLAUSE */ NULL_TREE,
+ before_p, vars, 1);
}
/* }}} */
/** {{{ simplify_while_stmt()
- 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. */
+ Simplifies a WHILE_STMT, returns a pointer to the simplified version. */
static tree
-simplify_while_stmt (prev, stmt, next, scope)
- tree prev, stmt, next, scope;
+simplify_while_stmt (stmt, before_p, vars)
+ tree stmt;
+ tree *before_p, *vars;
{
- tree cond, body, loop, last;
+ tree cond, body, loop;
/* Make sure that the loop body has a scope. */
tree_build_scope (&WHILE_BODY (stmt));
+
+ /* Save some pointers. */
cond = WHILE_COND (stmt);
body = WHILE_BODY (stmt);
- if (simplified_p (cond))
- /* The WHILE_COND is already simplified, simplify just the WHILE_BODY. */
+ /* Step 0 : Check wether the loop condition is already simplified. */
+ if (simplified_condition_p (cond))
+ /* 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;
+ simplify_stmt (body, NULL_TREE);
+ return stmt;
}
- /* step 1 : Insert a simplified version of 'if (!cond) break;' in the loop body. */
+ /* Step 1 : Insert a simplified version of 'if (cond) {} else break;' in the
+ loop body. */
{
- tree if_stmt;
+ tree if_stmt, if_vars = NULL, before_if = NULL, reeval;
/* Build 'if (cond) {} else break;'. */
- if_stmt = new_simplified_if (cond, NULL_TREE, build_stmt (BREAK_STMT),
- COMPOUND_BODY (WHILE_BODY (stmt)));
+ if_stmt = new_simplified_if (/* IF_COND */ copy_node (cond),
+ /* THEN_CLAUSE */ NULL_TREE,
+ /* ELSE_CLAUSE */ build_stmt (BREAK_STMT),
+ &before_if, &if_vars, 0);
- /* 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));
+ if (if_vars)
+ declare_tmp_vars (if_vars, COMPOUND_BODY (body));
+ reeval = chainon (before_if, if_stmt);
+ insert_before_continue_end (reeval, body, 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. */
- tree_build_scope (&body);
- simplify_stmt (body, COMPOUND_BODY (body));
+ /* Step 2 : Construct a 'while (1!=0) {body}' statement. */
loop = build_stmt (WHILE_STMT,
/* WHILE_COND */ build (NE_EXPR, integer_type_node,
integer_one_node, integer_zero_node),
/* WHILE_BODY */ body);
-
- /* 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 : Next statement to be processed. */
- TREE_CHAIN (prev) = NULL_TREE;
- last = chainon (prev, stmt);
- last = tree_last (last);
- chainon (stmt, next);
- return last;
+ /* Step 3 : Include the loop in an IF_STMT : 'if (cond) while (1) {body} else {}' */
+ return new_simplified_if (/* IF_COND */ cond,
+ /* THEN_CLAUSE */ loop,
+ /* ELSE_CLAUSE */ NULL_TREE,
+ before_p, vars, 1);
}
/* }}} */
@@ -660,55 +596,50 @@ simplify_while_stmt (prev, stmt, next, s
static tree
-simplify_do_stmt (prev, stmt, next, scope)
- tree prev, stmt, next, scope;
+simplify_do_stmt (stmt)
+ tree stmt;
{
- tree cond, body, loop, last;
+ tree cond, body;
/* Make sure that the loop body has a scope. */
tree_build_scope (&DO_BODY (stmt));
+
+ /* Save some pointers. */
cond = DO_COND (stmt);
body = DO_BODY (stmt);
+ /* Step 0 : Check wether the loop condition is already simplified. */
if (simplified_p (cond))
- /* The DO_COND is already simplified, simplify just the DO_BODY. */
+ /* 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;
+ simplify_stmt (body, NULL_TREE);
+ return stmt;
}
- /* step 1 : Insert a simplified version of 'if (!cond) break;' in the loop body. */
+ /* Step 1 : Insert a simplified version of 'if (cond) {} else break;' in the
+ loop body. */
{
- tree if_stmt;
+ tree if_stmt, if_vars = NULL, before_if = NULL, reeval;
/* Build 'if (cond) {} else break;'. */
- if_stmt = new_simplified_if (cond, NULL_TREE, build_stmt (BREAK_STMT),
- COMPOUND_BODY (DO_BODY (stmt)));
+ if_stmt = new_simplified_if (/* IF_COND */ copy_node (cond),
+ /* THEN_CLAUSE */ NULL_TREE,
+ /* ELSE_CLAUSE */ build_stmt (BREAK_STMT),
+ /* Before */ &before_if,
+ /* Variables */ &if_vars, 0);
- /* 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));
+ if (if_vars)
+ declare_tmp_vars (if_vars, COMPOUND_BODY (body));
+ reeval = chainon (before_if, if_stmt);
+ insert_before_continue_end (reeval, body, 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,
+ /* Step 2 : Construct a 'while (1!=0) {body}' statement. */
+ simplify_stmt (body, NULL_TREE);
+ return build_stmt (WHILE_STMT,
/* WHILE_COND */ build (NE_EXPR, integer_type_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;
+ /* WHILE_BODY */ body);
}
@@ -716,76 +647,142 @@ simplify_do_stmt (prev, stmt, next, scop
/** {{{ new_simplified_if()
- Constructs a new IF_STMT with its IF_COND under a simplified form. */
+ Constructs a new IF_STMT with its IF_COND under a simplified form. If the
+ SIMPLIFY parameter is not null, then IF clauses are simplified. Returns
+ the simplified IF_STMT and stores all side effects that should happen
+ before the evaluation of the condition in BEFORE_P. Side effects that
+ should happen after the evaluation of the condition are stored directly in
+ IF clauses. */
static tree
-new_simplified_if (cond, then_clause, else_clause, scope)
+new_simplified_if (cond, then_clause, else_clause, before_p, vars, simplify_clauses)
tree cond;
tree then_clause;
tree else_clause;
- tree scope;
+ tree *before_p;
+ tree *vars;
+ int simplify_clauses;
{
- if (scope == NULL_TREE)
- abort ();
-
+
+ /* Construct a scope for each clause. */
+ tree_build_scope (&then_clause);
+ tree_build_scope (&else_clause);
+
+ if (simplify_clauses)
+ {
+ simplify_stmt (then_clause, NULL_TREE);
+ simplify_stmt (else_clause, NULL_TREE);
+ }
+
switch (TREE_CODE (cond))
/* Simplify IF_COND. */
{
case TRUTH_ANDIF_EXPR:
{
- tree op0, op1;
+ tree op0, op1, res, before_if = NULL, if_vars = NULL;
op0 = TREE_OPERAND (cond, 0);
op1 = TREE_OPERAND (cond, 1);
- return new_simplified_if
- (op0, new_simplified_if (op1, then_clause, else_clause, scope),
- NULL_TREE, scope);
+ /* 'if (op0) { if (op1) {then_clause} else {else_clause}} else {else_clause}'.
+ The ELSE_CLAUSE is duplicated here. */
+ res = new_simplified_if
+ (/* IF_COND */ op0,
+ /* THEN_CLAUSE */ new_simplified_if (op1, then_clause, else_clause,
+ &before_if, &if_vars, 0),
+ /* ELSE_CLAUSE */ copy_stmt_chain (else_clause),
+ /* Before */ before_p,
+ /* Variables */ vars,
+ /* Simplify */ 0);
+
+ if (if_vars)
+ /* We created new variables, declare them. */
+ declare_tmp_vars (if_vars, COMPOUND_BODY (THEN_CLAUSE (res)));
+
+ if (before_if)
+ /* Pre evaluation of the condition given some statements. */
+ {
+ tree if_op1, last_decl;
+ last_decl = tree_last_decl (COMPOUND_BODY (THEN_CLAUSE (res)));
+ if_op1 = TREE_CHAIN (last_decl);
+ TREE_CHAIN (last_decl) = NULL_TREE;
+ chainon (last_decl, before_if);
+ chainon (last_decl, if_op1);
+ }
+
+ return res;
}
case TRUTH_ORIF_EXPR:
{
- tree op0, op1;
+ tree op0, op1, res, before_if = NULL, if_vars = NULL;
op0 = TREE_OPERAND (cond, 0);
op1 = TREE_OPERAND (cond, 1);
- return new_simplified_if
- (op0, then_clause,
- new_simplified_if (op1, then_clause, else_clause, scope), scope);
+ /* 'if (op0) {then_clause} else {if (op1) {then_clause} else {else_clause}}'.
+ The THEN_CLAUSE is duplicated here. */
+ res = new_simplified_if
+ (/* IF_COND */ op0,
+ /* THEN_CLAUSE */ copy_stmt_chain (then_clause),
+ /* ELSE_CLAUSE */ new_simplified_if (op1, then_clause, else_clause,
+ &before_if, &if_vars, 0),
+ /* Before */ before_p,
+ /* Variables */ vars,
+ /* Simplify */ 0);
+
+ if (if_vars)
+ /* We created new variables, declare them. */
+ declare_tmp_vars (if_vars, COMPOUND_BODY (ELSE_CLAUSE (res)));
+
+ if (before_if)
+ /* Pre evaluation of the condition given some statements. */
+ {
+ tree if_op1, last_decl;
+ last_decl = tree_last_decl (COMPOUND_BODY (ELSE_CLAUSE (res)));
+ if_op1 = TREE_CHAIN (last_decl);
+ TREE_CHAIN (last_decl) = NULL_TREE;
+ chainon (last_decl, before_if);
+ chainon (last_decl, if_op1);
+ }
+
+ return res;
}
default:
{
tree res;
- tree before, new_vars;
- before = NULL;
- new_vars = NULL;
+ tree cond_after = NULL;
- /* Build 'if (cond) then_clause; else else_clause;'. */
+ /* Build 'if (cond) {then_clause;} else {else_clause;}'. */
res = build_stmt (IF_STMT, cond, then_clause, else_clause);
-
+
/* Simplify if condition. */
{
- tree cond_before = NULL, cond_after = NULL;
tree repl;
- repl = simplify_expr (cond, &cond_before, &cond_after, &new_vars, scope);
+ /* The PRE evaluation of the condition is lifted up to the caller. */
+ repl = simplify_expr (cond, before_p, &cond_after, vars);
if (simplified_rec_p (repl, 1))
/* The simplification introduced a new temporary variable. */
IF_COND (res) = build (NE_EXPR, integer_type_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 them. */
- declare_tmp_vars (new_vars, scope);
+
+ if (cond_after)
+ /* Insert the POST evaluation of the condition in both clauses. */
+ {
+ tree tmp, last_decl;
- if (before)
- /* Insert the IF_STMT 'res' after the code contained in BEFORE. */
- res = chainon (before, res);
+ last_decl = tree_last_decl (COMPOUND_BODY (THEN_CLAUSE (res)));
+ tmp = TREE_CHAIN (last_decl);
+ TREE_CHAIN (last_decl) = NULL_TREE;
+ chainon (last_decl, copy_stmt_chain (cond_after));
+ chainon (last_decl, tmp);
+
+ last_decl = tree_last_decl (COMPOUND_BODY (ELSE_CLAUSE (res)));
+ tmp = TREE_CHAIN (last_decl);
+ TREE_CHAIN (last_decl) = NULL_TREE;
+ chainon (last_decl, cond_after);
+ chainon (last_decl, tmp);
+ }
-
return res;
}
}
@@ -798,20 +795,20 @@ new_simplified_if (cond, then_clause, el
Simplifies a SWITCH_STMT node. FIXME. */
static void
-simplify_switch_stmt (t, before_p, after_p, new_vars_p, scope)
- tree t;
+simplify_switch_stmt (stmt, before_p, new_vars_p)
+ tree stmt;
tree *before_p;
- tree *after_p;
tree *new_vars_p;
- tree scope;
{
- SWITCH_COND (t) = simplify_expr (SWITCH_COND (t), before_p,
- after_p, new_vars_p, scope);
+ tree after_sw = NULL;
+ SWITCH_COND (stmt) = simplify_expr (SWITCH_COND (stmt), before_p,
+ &after_sw, 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));
+ tree_build_scope (&SWITCH_BODY (stmt));
+
+ insert_after_case_labels (after_sw, SWITCH_BODY (stmt), STMT_LINENO (stmt));
+
+ simplify_stmt (SWITCH_BODY (stmt), NULL_TREE);
}
/* }}} */
@@ -865,7 +862,8 @@ simplify_decl_stmt (t, after_p)
/** {{{ simplify_expr()
- Simplifies the expression tree rooted at T.
+ Simplifies the expression tree rooted at T. Returns the simplified
+ version of T.
SCOPE indicates where new temporary variables should be created.
@@ -879,12 +877,11 @@ simplify_decl_stmt (t, after_p)
model T's side effects should be stored. */
static tree
-simplify_expr (expr, before_p, after_p, new_vars_p, scope)
+simplify_expr (expr, before_p, after_p, new_vars_p)
tree expr;
tree *before_p;
tree *after_p;
tree *new_vars_p;
- tree scope;
{
enum tree_code code;
tree t1, t2, lhs, rhs;
@@ -934,7 +931,7 @@ simplify_expr (expr, before_p, after_p,
case VA_ARG_EXPR:
TREE_OPERAND (expr, 0) = simplify_expr (TREE_OPERAND (expr, 0),
before_p, after_p,
- new_vars_p, scope);
+ new_vars_p);
return expr;
@@ -942,8 +939,8 @@ simplify_expr (expr, before_p, after_p,
the AFTER list. */
case POSTINCREMENT_EXPR:
case POSTDECREMENT_EXPR:
- lhs = simplify_expr (TREE_OPERAND (expr, 0), before_p, after_p, new_vars_p, scope);
- rhs = simplify_expr (TREE_OPERAND (expr, 1), before_p, after_p, new_vars_p, scope);
+ 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);
@@ -955,8 +952,8 @@ simplify_expr (expr, before_p, after_p,
the BEFORE list. */
case PREDECREMENT_EXPR:
case PREINCREMENT_EXPR:
- lhs = simplify_expr (TREE_OPERAND (expr, 0), before_p, after_p, new_vars_p, scope);
- rhs = simplify_expr (TREE_OPERAND (expr, 1), before_p, after_p, new_vars_p, scope);
+ 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);
@@ -1021,9 +1018,9 @@ simplify_expr (expr, before_p, after_p,
/* Simplify both sides of the expression. */
{
lhs = simplify_expr (TREE_OPERAND (expr, 0), before_p,
- after_p, new_vars_p, scope);
+ after_p, new_vars_p);
rhs = simplify_expr (TREE_OPERAND (expr, 1), before_p,
- after_p, new_vars_p, scope);
+ after_p, new_vars_p);
TREE_OPERAND (expr, 0) = lhs;
TREE_OPERAND (expr, 1) = rhs;
@@ -1038,7 +1035,7 @@ simplify_expr (expr, before_p, after_p,
/* 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, scope);
+ after_p, new_vars_p);
TREE_OPERAND (expr, 1) = rhs;
return expr;
}
@@ -1046,7 +1043,7 @@ simplify_expr (expr, before_p, after_p,
/* 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, scope);
+ after_p, new_vars_p);
TREE_OPERAND (expr, 0) = lhs;
return expr;
}
@@ -1054,9 +1051,9 @@ simplify_expr (expr, before_p, after_p,
case ARRAY_REF:
{
lhs = simplify_expr (TREE_OPERAND (expr, 0), before_p,
- after_p, new_vars_p, scope);
+ after_p, new_vars_p);
rhs = simplify_expr (TREE_OPERAND (expr, 1), before_p,
- after_p, new_vars_p, scope);
+ after_p, new_vars_p);
TREE_OPERAND (expr, 0) = lhs;
TREE_OPERAND (expr, 1) = rhs;
@@ -1084,7 +1081,7 @@ simplify_expr (expr, before_p, after_p,
else
return expr;
}
-
+
case COND_EXPR:
{
/* The expression hides an if.
@@ -1092,9 +1089,7 @@ simplify_expr (expr, before_p, after_p,
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;
+ FIXME : case when else is a block... */
tree tmp;
fprintf (stderr, "Got a cond_expr : \n");
@@ -1107,17 +1102,20 @@ simplify_expr (expr, before_p, after_p,
/* Build the THEN_CLAUSE. */
t1 = build_modify_expr (tmp, NOP_EXPR, TREE_OPERAND (expr, 1));
t1 = build_stmt (EXPR_STMT, t1);
- tree_build_scope (&t1);
- simplify_stmt (t1, scope); //COMPOUND_BODY (t1));
/* Build the ELSE_CLAUSE. */
t2 = build_modify_expr (tmp, NOP_EXPR, TREE_OPERAND (expr, 2));
t2 = build_stmt (EXPR_STMT, t2);
- tree_build_scope (&t2);
- simplify_stmt (t2, scope); //COMPOUND_BODY (t2));
- if_new = new_simplified_if (TREE_OPERAND (expr, 0), t1, t2, scope);
- insert_stmt_chain (before_p, if_new);
+ /* Construct a new simplified IF_STMT, and insert it in BEFORE_P chain. */
+ {
+ tree if_new;
+ if_new = new_simplified_if (/* IF_COND */ TREE_OPERAND (expr, 0),
+ /* THEN_CLAUSE */ t1,
+ /* ELSE_CLAUSE */ t2,
+ before_p, new_vars_p, 1);
+ *before_p = chainon (*before_p, if_new);
+ }
return tmp;
}
@@ -1127,27 +1125,28 @@ simplify_expr (expr, before_p, after_p,
insert in before_p its definition : the simplified version of
'if (cond) T = 1; else T = 0;' */
{
- tree tmp, if_new;
+ tree tmp;
/* 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);
- tree_build_scope (&t1);
- simplify_stmt (t1, COMPOUND_BODY (t1));
-
+
/* Build the ELSE_CLAUSE. */
t2 = build_modify_expr (tmp, NOP_EXPR, integer_zero_node);
t2 = build_stmt (EXPR_STMT, t2);
- tree_build_scope (&t2);
- simplify_stmt (t2, COMPOUND_BODY (t2));
- /* Construct the simplified IF_STMT. */
- if_new = new_simplified_if (expr, t1, t2, scope);
- insert_stmt_chain (before_p, if_new);
-
+ /* Construct a new simplified IF_STMT, and insert it in BEFORE_P chain. */
+ {
+ tree if_new;
+ if_new = new_simplified_if (/* IF_COND */ TREE_OPERAND (expr, 0),
+ /* THEN_CLAUSE */ t1,
+ /* ELSE_CLAUSE */ t2,
+ before_p, new_vars_p, 1);
+ *before_p = chainon (*before_p, if_new);
+ }
return tmp;
}
@@ -1155,9 +1154,9 @@ simplify_expr (expr, before_p, after_p,
simplified expression and return the LHS. */
case INIT_EXPR:
lhs = simplify_expr (TREE_OPERAND (expr, 0), before_p,
- after_p, new_vars_p, scope);
+ after_p, new_vars_p);
rhs = simplify_expr (TREE_OPERAND (expr, 1), before_p,
- after_p, new_vars_p, scope);
+ after_p, new_vars_p);
TREE_OPERAND (expr, 0) = lhs;
TREE_OPERAND (expr, 1) = rhs;
add_tree (build_stmt (EXPR_STMT, expr), before_p);
@@ -1165,9 +1164,9 @@ simplify_expr (expr, before_p, after_p,
case MODIFY_EXPR:
lhs = simplify_expr (TREE_OPERAND (expr, 0), before_p,
- after_p, new_vars_p, scope);
+ after_p, new_vars_p);
rhs = simplify_expr (TREE_OPERAND (expr, 1), before_p,
- after_p, new_vars_p, scope);
+ after_p, new_vars_p);
TREE_OPERAND (expr, 0) = lhs;
TREE_OPERAND (expr, 1) = rhs;
add_tree (build_stmt (EXPR_STMT, expr), before_p);
@@ -1185,11 +1184,11 @@ simplify_expr (expr, before_p, after_p,
case CALL_EXPR:
TREE_OPERAND (expr, 0) = simplify_expr (TREE_OPERAND (expr, 0),
before_p, after_p,
- new_vars_p, scope);
+ new_vars_p);
if (TREE_OPERAND (expr, 1))
TREE_OPERAND (expr, 1) = simplify_expr (TREE_OPERAND (expr, 1),
before_p, after_p,
- new_vars_p, scope);
+ new_vars_p);
return expr;
@@ -1199,7 +1198,7 @@ simplify_expr (expr, before_p, after_p,
for (op = expr; op; op = TREE_CHAIN (op))
TREE_VALUE (op) = simplify_expr (TREE_VALUE (op), before_p, after_p,
- new_vars_p, scope);
+ new_vars_p);
return expr;
}
@@ -1235,7 +1234,7 @@ simplify_expr (expr, before_p, after_p,
Create a new temporary variable declaration of type TYPE. Returns the
newly created decl and adds it to the list pointed by NEW_VARS_P. */
-static tree
+tree
create_tmp_var (type, new_vars_p)
tree type;
tree *new_vars_p;
@@ -1322,7 +1321,7 @@ make_type_writable (t)
Declares all the variables in VARS in SCOPE. Returns the last DECL_STMT
emitted. */
-static tree
+tree
declare_tmp_vars (vars, scope)
tree vars;
tree scope;
@@ -1337,9 +1336,7 @@ declare_tmp_vars (vars, scope)
/* Find the last declaration statement in the scope. Add all the new
declarations after it. */
- last = scope;
- while (TREE_CHAIN (last) && TREE_CODE (TREE_CHAIN (last)) == DECL_STMT)
- last = TREE_CHAIN (last);
+ last = tree_last_decl (scope);
for (t = vars; t; t = TREE_CHAIN (t))
{
@@ -1360,11 +1357,35 @@ declare_tmp_vars (vars, scope)
/* }}} */
+/** {{{ tree_last_decl()
+
+ Returns the last DECL_STMT in the scope SCOPE. */
+
+static tree
+tree_last_decl (scope)
+ tree scope;
+{
+ tree last;
+
+ /* Be sure that we get a scope. */
+ if (!SCOPE_BEGIN_P (scope))
+ abort ();
+
+ /* Find the last declaration statement in the scope. */
+ last = scope;
+ while (TREE_CHAIN (last) && TREE_CODE (TREE_CHAIN (last)) == DECL_STMT)
+ last = TREE_CHAIN (last);
+
+ return last;
+}
+
+/* }}} */
+
/** {{{ tree_build_scope()
Replaces T; by a COMPOUND_STMT containing {T;}. */
-static void
+void
tree_build_scope (t)
tree *t;
{
@@ -1387,7 +1408,7 @@ tree_build_scope (t)
if (TREE_CODE (*t) == COMPOUND_STMT)
{
- if (TREE_OPERAND (*t, 0) == NULL_TREE)
+ if (COMPOUND_BODY (*t) == NULL_TREE)
{
/* There's a compound statement, but no scope. */
tree start_scope, end_scope;
@@ -1398,7 +1419,7 @@ tree_build_scope (t)
TREE_OPERAND (*t, 0) = start_scope;
TREE_CHAIN (start_scope) = end_scope;
}
- else
+ else
/* The given NODE is actually a scope. */
return;
}
@@ -1471,10 +1492,61 @@ keep_stmt_p (t)
/** {{{ insert_before_continue_end()
+ Insert the REEVAL list after CASE_LABELs. Set the line number of the REEVAL
+ list to LINE. This function is used for inserting post evaluation statements
+ in a SWITCH_BODY. */
+
+static void
+insert_after_case_labels (reeval, body, line)
+ tree reeval, body;
+ int line;
+{
+ tree next, node;
+ node = body;
+
+ if (reeval == NULL_TREE || node == NULL_TREE)
+ return;
+
+ if (TREE_CODE (node) == COMPOUND_STMT)
+ node = COMPOUND_BODY (node);
+
+ next = TREE_CHAIN (node);
+ if (next == NULL_TREE)
+ return;
+
+ /* Update the line number information. */
+ {
+ tree it;
+ for (it = reeval; TREE_CHAIN (it); it = TREE_CHAIN (it))
+ update_line_number (it, line);
+ }
+
+ /* Walk through each statement in the given block up to the last one,
+ searching for CASE_LABELs. */
+
+ while (TREE_CHAIN (next) != NULL_TREE)
+
+ {
+ if (TREE_CODE (node) == CASE_LABEL)
+ /* Insert REEVAL after this node. */
+ {
+ TREE_CHAIN (node) = copy_stmt_chain (reeval);
+ node = tree_last (node);
+ TREE_CHAIN (node) = next;
+ }
+ node = TREE_CHAIN (node);
+ next = TREE_CHAIN (next);
+ }
+}
+
+/* }}} */
+
+/** {{{ 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
+void
insert_before_continue_end (reeval, body, line)
tree reeval;
tree body;
@@ -1562,7 +1634,6 @@ insert_before_continue (node, reeval)
}
break;
- //§ FIXME ... to be tested ...
case SWITCH_STMT:
/* Be sure that the SWITCH_BODY has a scope. */
tree_build_scope (&SWITCH_BODY (next));
@@ -1587,12 +1658,12 @@ insert_before_continue (node, reeval)
/* }}} */
-
/** {{{ copy_stmt_chain()
- Copy every statement from the chain CHAIN and return the new chain. */
+ Copy every statement from the chain CHAIN by calling COPY_STMT and return the
+ new chain. */
-static tree
+tree
copy_stmt_chain (chain)
tree chain;
{
@@ -1622,7 +1693,7 @@ copy_stmt_chain (chain)
Copy a statement by using copy_node when needed, but ensuring that we copy
enough information in order to have distinct statements. */
-static tree
+tree
copy_stmt (node)
tree node;
{
@@ -1641,52 +1712,76 @@ copy_stmt (node)
case FOR_STMT:
res = build_stmt (FOR_STMT,
copy_stmt (FOR_INIT_STMT (node)),
- copy_node (FOR_COND (node)),
- copy_node (FOR_EXPR (node)),
+ (FOR_COND (node) ?
+ copy_node (FOR_COND (node)) : NULL_TREE),
+ (FOR_EXPR (node) ?
+ copy_node (FOR_EXPR (node)) : NULL_TREE),
copy_stmt (FOR_BODY (node)));
break;
case WHILE_STMT:
res = build_stmt (WHILE_STMT,
- copy_node (WHILE_COND (node)),
+ (WHILE_COND (node) ?
+ copy_node (WHILE_COND (node)) : NULL_TREE),
copy_stmt (WHILE_BODY (node)));
break;
case DO_STMT:
res = build_stmt (DO_STMT,
- copy_node (DO_COND (node)),
+ (DO_COND (node) ?
+ copy_node (DO_COND (node)) : NULL_TREE),
copy_stmt (DO_BODY (node)));
break;
case IF_STMT:
res = build_stmt (IF_STMT,
- copy_node (IF_COND (node)),
+ (IF_COND (node) ?
+ copy_node (IF_COND (node)) : NULL_TREE),
copy_stmt (THEN_CLAUSE (node)),
copy_stmt (ELSE_CLAUSE (node)));
break;
case SWITCH_STMT:
res = build_stmt (SWITCH_STMT,
- copy_node (SWITCH_COND (node)),
+ (SWITCH_COND (node) ?
+ copy_node (SWITCH_COND (node)) : NULL_TREE),
copy_stmt (SWITCH_BODY (node)));
break;
case EXPR_STMT:
res = build_stmt (EXPR_STMT,
- copy_node (EXPR_STMT_EXPR (node)));
+ (EXPR_STMT_EXPR (node) ?
+ copy_node (EXPR_STMT_EXPR (node)) : NULL_TREE));
break;
case DECL_STMT:
res = build_stmt (DECL_STMT,
- copy_node (DECL_STMT_DECL (node)));
+ (DECL_STMT_DECL (node) ?
+ copy_node (DECL_STMT_DECL (node)) : NULL_TREE));
break;
case RETURN_STMT:
res = build_stmt (RETURN_STMT,
- copy_node (RETURN_EXPR (node)));
+ (RETURN_EXPR (node) ?
+ copy_node (RETURN_EXPR (node)) : NULL_TREE));
break;
case SCOPE_STMT:
+ if (SCOPE_BEGIN_P (node))
+ {
+ res = build_stmt (SCOPE_STMT,
+ (SCOPE_STMT_BLOCK (node) ?
+ copy_list (SCOPE_STMT_BLOCK (node)) :
+ NULL_TREE));
+ TREE_LANG_FLAG_0 (res) = 1;
+ }
+ else
+ {
+ res = build_stmt (SCOPE_STMT, NULL_TREE);
+ TREE_LANG_FLAG_0 (res) = 0;
+ }
+ break;
+
case FILE_STMT:
case LABEL_STMT:
case GOTO_STMT:
@@ -1705,35 +1800,12 @@ copy_stmt (node)
return res;
}
-/** {{{ 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
+tree
update_line_number (t, line)
tree t;
int line;
@@ -1808,3 +1880,28 @@ simplified_rec_p (t, depth)
return 0;
}
}
+
+/** {{{ simplified_condition_p()
+
+ Return one if T is a condition expression that is under its simplified form. */
+
+static int
+simplified_condition_p (t)
+ tree t;
+{
+ switch (TREE_CODE (t))
+ {
+ case TRUTH_ORIF_EXPR:
+ case TRUTH_ANDIF_EXPR:
+ if (simplified_condition_p (TREE_OPERAND (t, 0))
+ && simplified_condition_p (TREE_OPERAND (t, 1)))
+ return 1;
+ else
+ return 0;
+ default:
+ return simplified_p (t);
+ }
+}
+
+/* }}} */
+
Index: tree-simple.h
===================================================================
RCS file: tree-simple.h
diff -N tree-simple.h
--- /dev/null Tue May 5 13:32:27 1998
+++ tree-simple.h Mon Mar 18 11:12:23 2002
@@ -0,0 +1,34 @@
+/* Functions to analyze and validate SIMPLE trees.
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#ifndef _TREE_SIMPLE_H
+#define _TREE_SIMPLE_H 1
+
+/* Interface used in [break/goto]-elimination : to be declared in a .h file. */
+extern void insert_before_continue_end PARAMS ((tree, tree, int));
+extern void tree_build_scope PARAMS ((tree *));
+extern tree create_tmp_var PARAMS ((tree, tree *));
+extern tree declare_tmp_vars PARAMS ((tree, tree));
+extern tree copy_stmt_chain PARAMS ((tree));
+extern tree copy_stmt PARAMS ((tree));
+extern tree update_line_number PARAMS ((tree, int));
+
+#endif /* _TREE_SIMPLE_H */
+