This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[tree-ssa] CCP and variable reference fixes [patch]
- From: Diego Novillo <dnovillo at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Thu, 7 Nov 2002 07:36:17 -0500
- Subject: [tree-ssa] CCP and variable reference fixes [patch]
- Organization: Red Hat Canada
- Removes unnecessary fields from tree_ref structure. We don't
need to keep pointers into the expression nor operand for each
reference. This makes it possible for a pass to replicate a
statement and replace references from the original statement
into the copy.
Useful when a pass needs to try a replacement before committing
changes. References inside a statement should be replaced with
calls to replace_ref_in.
- Changes the way CCP operates. Instead of traversing
references, we now traverse statements in a block. It's
actually sparser that way. We were visiting the same statement
multiple times before.
- Fixes a bug in visit_phi_node. We were not checking for
killing definitions reaching the PHI node. We were also not
checking whether the PHI node was volatile.
Bootstrapped and tested on x86.
Diego.
* Makefile.in (tree-ssa-ccp.o): Add dependency on tree-inline.h
* tree-cfg.c (find_taken_edge): New function.
(cleanup_cond_expr_graph): Call it.
(disconnect_unreachable_case_labels): Call it.
* tree-dfa.c (struct clobber_data_d): Remove field
parent_expr_p. Update all users.
(find_refs_in_expr): Remove argument parent_expr_p. Update all users.
(create_ref): Remove arguments parent_expr_p and operand_p. Update
all users.
(replace_ref_in): Rename from replace_ref_operand_with. Update all
users. Find the operand in the statement and replace it with a new
operand.
(replace_ref_r): New local function.
(is_killing_def): Also handle V_PHI references.
(output_ref): Move from tree-flow-inline.h
* tree-flow-inline.h (ref_expr): Remove. Update all users.
(restore_ref_operand): Remove. Update all users.
(set_output_ref): Remove. Update all users.
(is_assignment_stmt): New function.
(is_may_def, is_may_use, is_partial_def, is_partial_use,
is_volatile_def, is_volatile_use, is_default_def,
is_clobbering_def, is_initializing_def, is_relocating_def,
is_addressof_use, is_pure_use): Check reference type first.
(is_pure_def): New function.
* tree-flow.h (struct tree_ref_common): Remove fields expr_p,
operand_p and orig_operand. Update all users.
(struct tree_ann_d): Remove field output_ref. Update all users.
* tree-ssa-ccp.c: Include tree-inline.h.
(simulate_block): Simulate every statement in the block, not its
references
(simulate_def_use_chains): Simulate statements containing uses
reached by the definition.
(substitute_and_fold): Traverse statements, not references.
Call fold_stmt.
(visit_phi_node): If PHI node is marked volatile, assume varying.
(visit_stmt): Rename from visit_expression_for. Work on a
statement, not a reference.
(visit_assignment): Rename from visit_assignment_for. Work on a
statement, not a reference.
(visit_cond_stmt): Rename from visit_condexpr_for. Work on a
statement, not a reference.
(evaluate_stmt): Rename from evaluate_expr. Work on a statement,
not a reference.
(initialize): Initialize special definitions to varying.
(replace_uses_in): Work on a statement, not an expression.
(fold_stmt): Rename from ccp_fold. Work on a statement, not an
expression.
(get_rhs): New local function.
(set_rhs): New local function.
Index: Makefile.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Makefile.in,v
retrieving revision 1.903.2.47
diff -d -u -p -r1.903.2.47 Makefile.in
--- Makefile.in 6 Nov 2002 12:20:55 -0000 1.903.2.47
+++ Makefile.in 7 Nov 2002 04:37:46 -0000
@@ -1567,7 +1567,7 @@ ssa-ccp.o : ssa-ccp.c $(CONFIG_H) system
$(BASIC_BLOCK_H) ssa.h insn-config.h $(RECOG_H) output.h \
errors.h $(GGC_H) df.h function.h
tree-ssa-ccp.o : tree-ssa-ccp.c $(CONFIG_H) system.h errors.h $(TREE_H) \
- $(RTL_H) $(TM_P_H) $(TREE_FLOW_H) diagnostic.h
+ $(RTL_H) $(TM_P_H) $(TREE_FLOW_H) diagnostic.h tree-inline.h
df.o : df.c $(CONFIG_H) system.h $(RTL_H) insn-config.h $(RECOG_H) \
function.h $(REGS_H) $(OBSTACK_H) hard-reg-set.h $(BASIC_BLOCK_H) df.h \
$(FIBHEAP_H)
Index: tree-cfg.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-cfg.c,v
retrieving revision 1.1.4.26
diff -d -u -p -r1.1.4.26 tree-cfg.c
--- tree-cfg.c 6 Nov 2002 22:22:34 -0000 1.1.4.26
+++ tree-cfg.c 7 Nov 2002 04:37:47 -0000
@@ -1074,6 +1074,7 @@ cleanup_cond_expr_graph (bb)
{
tree cond_expr = first_stmt (bb);
tree val;
+ edge taken_edge;
#if defined ENABLE_CHECKING
if (TREE_CODE (cond_expr) != COND_EXPR)
@@ -1081,30 +1082,10 @@ cleanup_cond_expr_graph (bb)
#endif
val = COND_EXPR_COND (cond_expr);
- if (really_constant_p (val))
+ taken_edge = find_taken_edge (bb, val);
+ if (taken_edge)
{
- bool always_false;
- edge e, taken_edge, next;
-
- /* Determine which branch of the if() will be taken. */
- taken_edge = NULL;
- always_false = (simple_cst_equal (val, integer_zero_node) == 1);
- for (e = bb->succ; e; e = e->succ_next)
- {
- if (((e->flags & EDGE_TRUE_VALUE) && !always_false)
- || ((e->flags & EDGE_FALSE_VALUE) && always_false))
- {
- taken_edge = e;
- break;
- }
- }
-
- if (taken_edge == NULL)
- {
- /* If E is not going to the THEN nor the ELSE clause, then it's
- the fallthru edge to the successor block of the if() block. */
- taken_edge = find_edge (bb, successor_block (bb));
- }
+ edge e, next;
/* Remove all the edges except the one that is always executed. */
for (e = bb->succ; e; e = next)
@@ -1162,61 +1143,134 @@ static void
disconnect_unreachable_case_labels (bb)
basic_block bb;
{
- edge e, default_edge, taken_edge;
+ edge taken_edge;
tree switch_val;
- default_edge = NULL;
- taken_edge = NULL;
-
switch_val = SWITCH_COND (first_stmt (bb));
- if (!really_constant_p (switch_val))
- return;
+ taken_edge = find_taken_edge (bb, switch_val);
+ if (taken_edge)
+ {
+ edge e, next;
- /* See if the switch() value matches one of the case labels. */
- for (e = bb->succ; e; e = e->succ_next)
+ /* Remove all the edges that go to case labels that will never
+ be taken. */
+ for (e = bb->succ; e; e = next)
+ {
+ next = e->succ_next;
+ if (e != taken_edge)
+ remove_edge (e);
+ }
+ }
+}
+
+
+/* Given a control block BB and a constant value VAL, return the edge
+ that will be taken out of BLOCK. If VAL does not match a unique edge,
+ NULL is returned. */
+
+edge
+find_taken_edge (bb, val)
+ basic_block bb;
+ tree val;
+{
+ tree stmt;
+ edge e, taken_edge;
+
+ stmt = first_stmt (bb);
+
+#if defined ENABLE_CHECKING
+ if (!is_ctrl_stmt (stmt))
+ abort ();
+#endif
+
+ /* If VAL is not a constant, we can't determine which edge might
+ be taken. */
+ if (val == NULL || !really_constant_p (val))
+ return NULL;
+
+ taken_edge = NULL;
+ if (TREE_CODE (stmt) == COND_EXPR)
{
- tree val;
- edge dest_edge = e;
- tree dest_t = first_stmt (dest_edge->dest);
+ bool always_false;
+ bool always_true;
- if (TREE_CODE (dest_t) != CASE_LABEL_EXPR)
- continue;
+ /* Determine which branch of the if() will be taken. */
+ always_false = (simple_cst_equal (val, integer_zero_node) == 1);
+ always_true = (simple_cst_equal (val, integer_one_node) == 1);
- val = CASE_LOW (dest_t);
- if (val == NULL_TREE)
+ /* If VAL is a constant but it can't be reduced to a 0 or a 1, then
+ we don't really know which edge will be taken at runtime. This
+ may happen when comparing addresses (e.g., if (&var1 == 4)) */
+ if (!always_false && !always_true)
+ return NULL;
+
+ for (e = bb->succ; e; e = e->succ_next)
{
- /* Remember that we found a default label, just in case no other
- label matches the switch() value. */
- default_edge = dest_edge;
+ if (((e->flags & EDGE_TRUE_VALUE) && always_true)
+ || ((e->flags & EDGE_FALSE_VALUE) && always_false))
+ {
+ taken_edge = e;
+ break;
+ }
}
- else if (simple_cst_equal (val, switch_val) == 1)
+
+ if (taken_edge == NULL)
{
- /* We found the unique label that will be taken by the switch.
- No need to keep looking. All the other labels are never
- reached directly from the switch(). */
- taken_edge = dest_edge;
- break;
+ /* If E is not going to the THEN nor the ELSE clause, then it's
+ the fallthru edge to the successor block of the if() block. */
+ taken_edge = find_edge (bb, successor_block (bb));
}
}
-
- /* If no case exists for the value used in the switch(), we use the
- default label. */
- if (taken_edge == NULL)
- taken_edge = default_edge;
-
- /* Remove all the edges that go to case labels that will never be taken. */
- if (taken_edge)
+ else if (TREE_CODE (stmt) == SWITCH_EXPR)
{
- edge next;
- for (e = bb->succ; e; e = next)
+ edge default_edge = NULL;
+
+ /* See if the switch() value matches one of the case labels. */
+ for (e = bb->succ; e; e = e->succ_next)
{
- next = e->succ_next;
- if (e != taken_edge)
- remove_edge (e);
+ tree label_val;
+ edge dest_edge = e;
+ tree dest_t = first_stmt (dest_edge->dest);
+
+ /* Remember the edge out of the switch() just in case there is no
+ matching label in the body. */
+ if (TREE_CODE (dest_t) != CASE_LABEL_EXPR)
+ continue;
+
+ label_val = CASE_LOW (dest_t);
+ if (label_val == NULL_TREE)
+ {
+ /* Remember that we found a default label, just in case no other
+ label matches the switch() value. */
+ default_edge = dest_edge;
+ }
+ else if (simple_cst_equal (label_val, val) == 1)
+ {
+ /* We found the unique label that will be taken by the switch.
+ No need to keep looking. All the other labels are never
+ reached directly from the switch(). */
+ taken_edge = dest_edge;
+ break;
+ }
}
+
+ /* If no case exists for the value used in the switch(), we use the
+ default label. If the switch() has no label, we use the edge
+ going out of the switch() body. */
+ if (taken_edge == NULL)
+ taken_edge = default_edge
+ ? default_edge
+ : find_edge (bb, successor_block (bb));
}
-}
+ else
+ {
+ /* LOOP_EXPR nodes are always followed by their successor block. */
+ taken_edge = bb->succ;
+ }
+
+ return taken_edge;
+}
/*---------------------------------------------------------------------------
Index: tree-dfa.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-dfa.c,v
retrieving revision 1.1.4.41
diff -d -u -p -r1.1.4.41 tree-dfa.c
--- tree-dfa.c 6 Nov 2002 22:22:33 -0000 1.1.4.41
+++ tree-dfa.c 7 Nov 2002 04:37:47 -0000
@@ -37,7 +37,6 @@ Boston, MA 02111-1307, USA. */
#include "tree-simple.h"
#include "tree-flow.h"
#include "tree-inline.h"
-
#include "tree-alias-common.h"
/* Local declarations. */
@@ -45,9 +44,13 @@ struct clobber_data_d
{
basic_block bb;
tree *parent_stmt_p;
- tree *parent_expr_p;
};
+struct replace_data_d
+{
+ tree old;
+ tree new;
+};
/* DFA Statistics. */
struct dfa_stats_d
@@ -79,7 +82,7 @@ extern int tree_ssa_dump_flags;
/* Local functions. */
static void find_refs_in_expr PARAMS ((tree *, enum tree_ref_type,
- unsigned, basic_block, tree *,
+ unsigned, basic_block,
tree *));
static void add_referenced_var PARAMS ((tree));
static void dump_if_different PARAMS ((FILE *, const char * const,
@@ -94,10 +97,10 @@ static tree clobber_vars_r PARAMS ((tre
static void compute_may_aliases PARAMS ((void));
static void find_may_aliases_for PARAMS ((tree));
static void add_may_alias PARAMS ((tree, tree));
-static inline bool may_alias_p PARAMS ((tree, tree));
-static bool is_visible_to PARAMS ((tree, tree));
+static inline bool may_alias_p PARAMS ((tree, tree));
static size_t tree_ref_size PARAMS ((enum tree_ref_type));
static inline tree create_indirect_ref PARAMS ((tree));
+static tree replace_ref_r PARAMS ((tree *, int *, void *));
/* Global declarations. */
@@ -167,37 +170,29 @@ find_refs_in_stmt (stmt_p, bb)
switch (code)
{
case COND_EXPR:
- find_refs_in_expr (&COND_EXPR_COND (stmt), V_USE, 0, bb, stmt_p,
- &COND_EXPR_COND (stmt));
+ find_refs_in_expr (&COND_EXPR_COND (stmt), V_USE, 0, bb, stmt_p);
break;
case SWITCH_EXPR:
- find_refs_in_expr (&SWITCH_COND (stmt), V_USE, 0, bb, stmt_p,
- &SWITCH_COND (stmt));
+ find_refs_in_expr (&SWITCH_COND (stmt), V_USE, 0, bb, stmt_p);
break;
case ASM_EXPR:
- find_refs_in_expr (&ASM_INPUTS (stmt), V_USE, 0, bb, stmt_p,
- &ASM_INPUTS (stmt));
- find_refs_in_expr (&ASM_OUTPUTS (stmt), V_DEF, TRM_CLOBBER, bb, stmt_p,
- &ASM_OUTPUTS (stmt));
- find_refs_in_expr (&ASM_CLOBBERS (stmt), V_DEF, TRM_CLOBBER, bb, stmt_p,
- &ASM_CLOBBERS (stmt));
+ find_refs_in_expr (&ASM_INPUTS (stmt), V_USE, 0, bb, stmt_p);
+ find_refs_in_expr (&ASM_OUTPUTS (stmt), V_DEF, TRM_CLOBBER, bb, stmt_p);
+ find_refs_in_expr (&ASM_CLOBBERS (stmt), V_DEF, TRM_CLOBBER, bb, stmt_p);
break;
case RETURN_EXPR:
- find_refs_in_expr (&TREE_OPERAND (stmt, 0), V_USE, 0, bb, stmt_p,
- &TREE_OPERAND (stmt, 0));
+ find_refs_in_expr (&TREE_OPERAND (stmt, 0), V_USE, 0, bb, stmt_p);
break;
case GOTO_EXPR:
- find_refs_in_expr (&GOTO_DESTINATION (stmt), V_USE, 0, bb, stmt_p,
- &GOTO_DESTINATION (stmt));
+ find_refs_in_expr (&GOTO_DESTINATION (stmt), V_USE, 0, bb, stmt_p);
break;
case LABEL_EXPR:
- find_refs_in_expr (&LABEL_EXPR_LABEL (stmt), V_USE, 0, bb, stmt_p,
- &LABEL_EXPR_LABEL (stmt));
+ find_refs_in_expr (&LABEL_EXPR_LABEL (stmt), V_USE, 0, bb, stmt_p);
break;
/* These nodes contain no variable references. */
@@ -207,7 +202,7 @@ find_refs_in_stmt (stmt_p, bb)
break;
default:
- find_refs_in_expr (stmt_p, V_USE, 0, bb, stmt_p, stmt_p);
+ find_refs_in_expr (stmt_p, V_USE, 0, bb, stmt_p);
}
}
@@ -219,29 +214,19 @@ find_refs_in_stmt (stmt_p, bb)
REF_MOD is the set of modifier flags for REF_TYPE.
- BB, PARENT_STMT_P and PARENT_EXPR_P give the location of *EXPR_P in the
- program.
-
- NOTE: PARENT_EXPR_P and PARENT_STMT_P may point to the same tree. For
- instance, given the statement 'a = b + c;', they both point to the
- MODIFY_EXPR tree.
-
- However, given 'if (a > b)', PARENT_STMT_P will point to the
- COND_EXPR tree, while PARENT_EXPR_P will point to the GT_EXPR tree. */
+ BB and PARENT_STMT_P give the location of *EXPR_P in the program. */
static void
-find_refs_in_expr (expr_p, ref_type, ref_mod, bb, parent_stmt_p, parent_expr_p)
+find_refs_in_expr (expr_p, ref_type, ref_mod, bb, parent_stmt_p)
tree *expr_p;
enum tree_ref_type ref_type;
unsigned ref_mod;
basic_block bb;
tree *parent_stmt_p;
- tree *parent_expr_p;
{
enum tree_code code;
char class;
tree expr = *expr_p;
- tree parent_expr = *parent_expr_p;
tree parent_stmt = *parent_stmt_p;
if (expr == NULL || expr == error_mark_node)
@@ -260,18 +245,16 @@ find_refs_in_expr (expr_p, ref_type, ref
return;
/* If this reference is associated with a non SIMPLE expression, then we
- mark the parent expression non SIMPLE and recursively clobber every
- variable referenced by PARENT_EXPR. FIXME: TREE_NOT_GIMPLE must die. */
- if (parent_stmt && parent_expr && TREE_NOT_GIMPLE (expr))
+ mark the statement non GIMPLE and recursively clobber every
+ variable referenced by PARENT_STMT. FIXME TREE_NOT_GIMPLE must die. */
+ if (parent_stmt && TREE_NOT_GIMPLE (expr))
{
struct clobber_data_d clobber_data;
- TREE_NOT_GIMPLE (parent_expr) = 1;
TREE_NOT_GIMPLE (parent_stmt) = 1;
clobber_data.bb = bb;
- clobber_data.parent_expr_p = parent_expr_p;
clobber_data.parent_stmt_p = parent_stmt_p;
- walk_tree (parent_expr_p, clobber_vars_r, &clobber_data, NULL);
+ walk_tree (parent_stmt_p, clobber_vars_r, &clobber_data, NULL);
return;
}
@@ -285,8 +268,7 @@ find_refs_in_expr (expr_p, ref_type, ref
/* If we found a _DECL node, create a reference to it and return. */
if (code == VAR_DECL || code == PARM_DECL)
{
- create_ref (expr, ref_type, ref_mod, bb, parent_stmt_p, parent_expr_p,
- expr_p, 1);
+ create_ref (expr, ref_type, ref_mod, bb, parent_stmt_p, 1);
/* If we just created a V_DEF reference for a pointer variable 'p',
we have to clobber the associated '*p' variable, because now 'p'
@@ -298,7 +280,7 @@ find_refs_in_expr (expr_p, ref_type, ref
set_indirect_var (expr, create_indirect_ref (expr));
create_ref (indirect_var (expr), V_DEF, TRM_RELOCATE, bb,
- parent_stmt_p, parent_expr_p, NULL, 1);
+ parent_stmt_p, 1);
}
return;
@@ -337,8 +319,7 @@ find_refs_in_expr (expr_p, ref_type, ref
tree ptr_sym = get_base_symbol (ptr);
/* Create a V_USE reference for the pointer variable itself. */
- find_refs_in_expr (&TREE_OPERAND (expr, 0), V_USE, 0, bb, parent_stmt_p,
- parent_expr_p);
+ find_refs_in_expr (&TREE_OPERAND (expr, 0), V_USE, 0, bb, parent_stmt_p);
/* If this is the first INDIRECT_REF node we find for PTR, set EXPR
to be the indirect variable used to represent all dereferences of
@@ -347,7 +328,7 @@ find_refs_in_expr (expr_p, ref_type, ref
set_indirect_var (ptr_sym, expr);
create_ref (indirect_var (ptr_sym), ref_type, ref_mod, bb, parent_stmt_p,
- parent_expr_p, expr_p, 1);
+ 1);
return;
}
@@ -363,12 +344,10 @@ find_refs_in_expr (expr_p, ref_type, ref
/* Change the reference type to a partial def/use when processing
the LHS of the reference. */
find_refs_in_expr (&TREE_OPERAND (expr, 0), ref_type,
- ref_mod | TRM_PARTIAL, bb, parent_stmt_p,
- parent_expr_p);
+ ref_mod | TRM_PARTIAL, bb, parent_stmt_p);
/* References on the RHS of the array are always used as indices. */
- find_refs_in_expr (&TREE_OPERAND (expr, 1), V_USE, 0, bb, parent_stmt_p,
- parent_expr_p);
+ find_refs_in_expr (&TREE_OPERAND (expr, 1), V_USE, 0, bb, parent_stmt_p);
return;
}
@@ -390,8 +369,7 @@ find_refs_in_expr (expr_p, ref_type, ref
/* Modify the reference to be a partial reference of the LHS of the
expression. */
find_refs_in_expr (&TREE_OPERAND (expr, 0), ref_type,
- ref_mod | TRM_PARTIAL, bb, parent_stmt_p,
- parent_expr_p);
+ ref_mod | TRM_PARTIAL, bb, parent_stmt_p);
return;
}
@@ -399,10 +377,8 @@ find_refs_in_expr (expr_p, ref_type, ref
references. */
if (code == INIT_EXPR || code == MODIFY_EXPR)
{
- find_refs_in_expr (&TREE_OPERAND (expr, 1), V_USE, 0, bb, parent_stmt_p,
- parent_expr_p);
- find_refs_in_expr (&TREE_OPERAND (expr, 0), V_DEF, 0, bb, parent_stmt_p,
- parent_expr_p);
+ find_refs_in_expr (&TREE_OPERAND (expr, 1), V_USE, 0, bb, parent_stmt_p);
+ find_refs_in_expr (&TREE_OPERAND (expr, 0), V_DEF, 0, bb, parent_stmt_p);
return;
}
@@ -419,11 +395,9 @@ find_refs_in_expr (expr_p, ref_type, ref
tree callee;
int flags;
- find_refs_in_expr (&TREE_OPERAND (expr, 0), V_USE, 0, bb, parent_stmt_p,
- parent_expr_p);
+ find_refs_in_expr (&TREE_OPERAND (expr, 0), V_USE, 0, bb, parent_stmt_p);
- find_refs_in_expr (&TREE_OPERAND (expr, 1), V_USE, 0, bb, parent_stmt_p,
- parent_expr_p);
+ find_refs_in_expr (&TREE_OPERAND (expr, 1), V_USE, 0, bb, parent_stmt_p);
callee = get_callee_fndecl (expr);
flags = (callee) ? flags_from_decl_or_type (callee) : 0;
@@ -432,10 +406,8 @@ find_refs_in_expr (expr_p, ref_type, ref
may-use followed by a clobbering definition of GLOBAL_VAR. */
if (! (flags & (ECF_CONST | ECF_PURE)))
{
- create_ref (global_var, V_USE, TRM_MAY, bb, parent_stmt_p, NULL,
- NULL, 1);
- create_ref (global_var, V_DEF, TRM_CLOBBER, bb, parent_stmt_p, NULL,
- NULL, 1);
+ create_ref (global_var, V_USE, TRM_MAY, bb, parent_stmt_p, 1);
+ create_ref (global_var, V_DEF, TRM_CLOBBER, bb, parent_stmt_p, 1);
}
return;
@@ -446,7 +418,7 @@ find_refs_in_expr (expr_p, ref_type, ref
if (code == ADDR_EXPR)
{
find_refs_in_expr (&TREE_OPERAND (expr, 0), V_USE, TRM_ADDRESSOF, bb,
- parent_stmt_p, parent_expr_p);
+ parent_stmt_p);
return;
}
@@ -457,7 +429,7 @@ find_refs_in_expr (expr_p, ref_type, ref
for (op = expr; op; op = TREE_CHAIN (op))
find_refs_in_expr (&TREE_VALUE (op), ref_type, ref_mod, bb,
- parent_stmt_p, parent_expr_p);
+ parent_stmt_p);
return;
}
@@ -467,7 +439,7 @@ find_refs_in_expr (expr_p, ref_type, ref
|| code == VA_ARG_EXPR)
{
find_refs_in_expr (&TREE_OPERAND (expr, 0), ref_type, ref_mod, bb,
- parent_stmt_p, parent_expr_p);
+ parent_stmt_p);
return;
}
@@ -481,9 +453,9 @@ find_refs_in_expr (expr_p, ref_type, ref
|| code == CONSTRUCTOR)
{
find_refs_in_expr (&TREE_OPERAND (expr, 0), ref_type, ref_mod, bb,
- parent_stmt_p, parent_expr_p);
+ parent_stmt_p);
find_refs_in_expr (&TREE_OPERAND (expr, 1), ref_type, ref_mod, bb,
- parent_stmt_p, parent_expr_p);
+ parent_stmt_p);
return;
}
@@ -796,9 +768,9 @@ tree_ref_size (ref_type)
bitmask built from the TRM_* constants. This bitmask is used to set
the corresponding bitfield in the various tree_ref structures.
- BB, PARENT_STMT_P, PARENT_EXPR_P and OPERAND_P give the exact location
- of the reference. The last three can be NULL in the case of
- artificial references (PHI nodes, default definitions, etc).
+ BB and PARENT_STMT_P give the location of the reference. PARENT_STMT_P
+ can be NULL in the case of artificial references (PHI nodes, default
+ definitions, etc).
ADD_TO_BB should be 1 if the caller wants the reference to be added
to the list of references for BB (i.e., bb_refs (BB)). In that case,
@@ -810,21 +782,17 @@ tree_ref_size (ref_type)
responsible for the placement of the newly created reference. */
tree_ref
-create_ref (var, ref_type, ref_mod, bb, parent_stmt_p, parent_expr_p, operand_p,
- add_to_bb)
+create_ref (var, ref_type, ref_mod, bb, parent_stmt_p, add_to_bb)
tree var;
enum tree_ref_type ref_type;
unsigned ref_mod;
basic_block bb;
tree *parent_stmt_p;
- tree *parent_expr_p;
- tree *operand_p;
int add_to_bb;
{
size_t size;
tree_ref ref;
tree parent_stmt = (parent_stmt_p) ? *parent_stmt_p : NULL_TREE;
- tree parent_expr = (parent_expr_p) ? *parent_expr_p : NULL_TREE;
#if defined ENABLE_CHECKING
if (bb == NULL)
@@ -852,9 +820,6 @@ create_ref (var, ref_type, ref_mod, bb,
ref->common.type = ref_type;
ref->common.bb = bb;
ref->common.stmt_p = parent_stmt_p;
- ref->common.expr_p = parent_expr_p;
- ref->common.operand_p = operand_p;
- ref->common.orig_operand = (operand_p) ? *operand_p : NULL;
/* Set the reference type modifier flags. */
if (ref_mod & TRM_MAY)
@@ -926,15 +891,10 @@ create_ref (var, ref_type, ref_mod, bb,
/* Add this reference to the list of references for the variable. */
add_tree_ref (var, ref);
- /* Add the reference to the list of references for the parent
- expression. */
- if (parent_expr)
- add_tree_ref (parent_expr, ref);
-
/* In some cases the parent statement and parent expression are the
same tree node. For instance 'a = 5;'. Avoid adding the same
reference twice to the same list in these cases. */
- if (parent_stmt && parent_stmt != parent_expr)
+ if (parent_stmt)
add_tree_ref (parent_stmt, ref);
}
@@ -943,19 +903,6 @@ create_ref (var, ref_type, ref_mod, bb,
if (add_to_bb)
add_ref_to_list_end (bb_refs (bb), ref);
- /* If this is an unmodified V_DEF reference, then this reference
- represents the output of its parent statement (i.e., the reference is
- the LHS of an assignment). In this case, tell the parent statement
- about it.
-
- This is useful for algorithms like constant propagation when
- evaluating expressions, the output reference for the expression is
- where the lattice value of the expression can be stored. */
- if (ref_type == V_DEF
- && ref_mod == 0
- && !TREE_NOT_GIMPLE (parent_stmt))
- set_output_ref (parent_stmt, ref);
-
return ref;
}
@@ -1021,33 +968,119 @@ add_referenced_var (var)
Code replacement
---------------------------------------------------------------------------*/
-/* Replace the operand for a reference with a new operand.
+/* Replace reference REF in statement STMT with a new variable or constant OP.
FIXME: Need to properly update DFA information (create new references,
update SSA links, etc). */
void
-replace_ref_operand_with (ref, op)
+replace_ref_in (stmt, ref, op)
+ tree stmt;
tree_ref ref;
tree op;
{
- if (ref->common.operand_p)
- *(ref->common.operand_p) = op;
-}
+ enum tree_code code;
+ struct replace_data_d replace_data;
+ STRIP_WFL (stmt);
+ STRIP_NOPS (stmt);
-/* Replace the expression for a reference with a new expression.
+#if defined ENABLE_CHECKING
+ if (!really_constant_p (op) && !DECL_P (op))
+ abort ();
- FIXME: Need to properly update DFA information (create new references,
- update SSA links, etc). */
+ if (ref_type (ref) != V_DEF && ref_type (ref) != V_USE)
+ abort ();
-void
-replace_ref_expr_with (ref, expr)
- tree_ref ref;
- tree expr;
+ if (ref_type (ref) == V_DEF && !DECL_P (op))
+ abort ();
+
+ if (DECL_P (stmt))
+ abort ();
+#endif
+
+ replace_data.old = ref_var (ref);
+ replace_data.new = op;
+ code = TREE_CODE (stmt);
+ switch (code)
+ {
+ case INIT_EXPR:
+ case MODIFY_EXPR:
+ if (ref_type (ref) == V_DEF)
+ walk_tree (&TREE_OPERAND (stmt, 0), replace_ref_r, &replace_data, NULL);
+ else
+ walk_tree (&TREE_OPERAND (stmt, 1), replace_ref_r, &replace_data, NULL);
+ break;
+
+ case CALL_EXPR:
+ walk_tree (&TREE_OPERAND (stmt, 0), replace_ref_r, &replace_data, NULL);
+ walk_tree (&TREE_OPERAND (stmt, 1), replace_ref_r, &replace_data, NULL);
+ break;
+
+ case COND_EXPR:
+ walk_tree (&COND_EXPR_COND (stmt), replace_ref_r, &replace_data, NULL);
+ break;
+
+ case SWITCH_EXPR:
+ walk_tree (&SWITCH_COND (stmt), replace_ref_r, &replace_data, NULL);
+ break;
+
+ case ASM_EXPR:
+ if (ref_type (ref) == V_USE)
+ walk_tree (&ASM_INPUTS (stmt), replace_ref_r, &replace_data, NULL);
+ else
+ {
+ walk_tree (&ASM_OUTPUTS (stmt), replace_ref_r, &replace_data, NULL);
+ walk_tree (&ASM_CLOBBERS (stmt), replace_ref_r, &replace_data, NULL);
+ }
+ break;
+
+ case RETURN_EXPR:
+ walk_tree (&TREE_OPERAND (stmt, 0), replace_ref_r, &replace_data, NULL);
+ break;
+
+ case GOTO_EXPR:
+ walk_tree (&GOTO_DESTINATION (stmt), replace_ref_r, &replace_data, NULL);
+ break;
+
+ case LABEL_EXPR:
+ walk_tree (&LABEL_EXPR_LABEL (stmt), replace_ref_r, &replace_data, NULL);
+ break;
+
+ /* These nodes contain no variable references. */
+ case LOOP_EXPR:
+ case BIND_EXPR:
+ case CASE_LABEL_EXPR:
+ break;
+
+ default:
+ abort ();
+ }
+}
+
+
+/* Call back for walk_tree to replace references in expression *TP. */
+
+static tree
+replace_ref_r (tp, walk_subtrees, data)
+ tree *tp;
+ int *walk_subtrees ATTRIBUTE_UNUSED;
+ void *data;
{
- if (ref->common.expr_p)
- *(ref->common.expr_p) = expr;
+ struct replace_data_d *replace_data = (struct replace_data_d *)data;
+ tree t = *tp;
+ tree old = replace_data->old;
+ tree new = replace_data->new;
+
+ /* INDIRECT_REF nodes cannot be compared directly. */
+ if (TREE_CODE (old) == INDIRECT_REF
+ && TREE_CODE (t) == INDIRECT_REF
+ && TREE_OPERAND (old, 0) == TREE_OPERAND (t, 0))
+ *tp = new;
+ else if (old == t)
+ *tp = new;
+
+ return NULL_TREE;
}
@@ -1166,8 +1199,8 @@ dump_ref (outf, prefix, ref, indent, det
fprintf (outf, "): line %d, bb %d, id %lu, ", lineno, bbix, ref_id (ref));
- if (ref_expr (ref))
- print_generic_expr (outf, ref_expr (ref), 0);
+ if (ref_stmt (ref))
+ print_generic_stmt (outf, ref_stmt (ref), TDF_SLIM);
else
fprintf (outf, "<nil>");
@@ -1772,10 +1805,9 @@ clobber_vars_r (tp, walk_subtrees, data)
/* Create may-use and clobber references for every *_DECL in sight. */
if (code == VAR_DECL || code == PARM_DECL)
{
- create_ref (*tp, V_USE, TRM_MAY, clobber->bb, clobber->parent_stmt_p,
- clobber->parent_expr_p, NULL, 1);
+ create_ref (*tp, V_USE, TRM_MAY, clobber->bb, clobber->parent_stmt_p, 1);
create_ref (*tp, V_DEF, TRM_CLOBBER, clobber->bb, clobber->parent_stmt_p,
- clobber->parent_expr_p, NULL, 1);
+ 1);
}
return NULL;
@@ -1849,8 +1881,7 @@ may_alias_p (ptr, var_sym)
if (var_sym == ptr_sym
|| !POINTER_TYPE_P (TREE_TYPE (ptr_sym))
|| !TREE_ADDRESSABLE (var_sym)
- || DECL_ARTIFICIAL (var_sym)
- || !is_visible_to (var_sym, ptr_sym))
+ || DECL_ARTIFICIAL (var_sym))
return false;
ptr_alias_set = get_alias_set (TREE_TYPE (ptr));
@@ -1889,23 +1920,6 @@ find_may_aliases_for (ptr)
}
-
-
-/* Return true if SYM1 and SYM2 are visible to each other. Visibility is
- determined based on the scopes where each variable is declared. Both
- scopes must be the same or one must be enclosed in the other. */
-
-static bool
-is_visible_to (sym1, sym2)
- tree sym1;
- tree sym2;
-{
- /* FIXME This should be implemented by traversing the SUPERCONTEXT and
- SUBBLOCKS links for the each symbol's BIND_EXPR node. */
- return true;
-}
-
-
/* Return true if REF is a V_DEF reference for VAR. This function handles
relocations of pointers. Relocating a pointer, clobbers any dereference
of the pointer, but it does not affect any of its aliases. For
@@ -1957,13 +1971,13 @@ is_killing_def (def, use)
tree use_var = ref_var (use);
if ((ref_type (def) != V_DEF && ref_type (def) != V_PHI)
- || ref_type (use) != V_USE)
+ || (ref_type (use) != V_USE && ref_type (use) != V_PHI))
return false;
/* Partial, potential and volatile definitions are no killers. */
- if (is_partial_def (def)
- || is_volatile_def (def)
- || is_may_def (def))
+ if (is_partial_ref (def)
+ || is_volatile_ref (def)
+ || is_may_ref (def))
return false;
/* Common case. Both references are for the same variable. */
@@ -2111,6 +2125,29 @@ find_decl_location (decl, block)
tree *loc = find_decl_location (decl, sub);
if (loc)
return loc;
+ }
+
+ return NULL;
+}
+
+
+/* Return the V_DEF reference at the LHS of an assignment statement T. */
+
+tree_ref
+output_ref (t)
+ tree t;
+{
+ STRIP_WFL (t);
+ STRIP_NOPS (t);
+ if (is_assignment_stmt (t))
+ {
+ ref_list_iterator i;
+ for (i = rli_start (tree_refs (t)); !rli_after_end (i); rli_step (&i))
+ {
+ tree_ref def = rli_ref (i);
+ if (ref_type (def) == V_DEF && !def->vdef.m_clobber)
+ return def;
+ }
}
return NULL;
Index: tree-flow-inline.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-flow-inline.h,v
retrieving revision 1.1.2.11
diff -d -u -p -r1.1.2.11 tree-flow-inline.h
--- tree-flow-inline.h 6 Nov 2002 22:22:34 -0000 1.1.2.11
+++ tree-flow-inline.h 7 Nov 2002 04:37:47 -0000
@@ -47,13 +47,6 @@ ref_bb (ref)
}
static inline tree
-ref_expr (ref)
- tree_ref ref;
-{
- return ref->common.expr_p ? *(ref->common.expr_p) : NULL_TREE;
-}
-
-static inline tree
ref_stmt (ref)
tree_ref ref;
{
@@ -176,14 +169,6 @@ set_phi_arg (phi, i, arg)
VARRAY_GENERIC_PTR (phi->vphi.phi_args, i) = (PTR)arg;
}
-static inline void
-restore_ref_operand (ref)
- tree_ref ref;
-{
- if (ref->common.operand_p)
- *(ref->common.operand_p) = ref->common.orig_operand;
-}
-
static inline tree_ann
tree_annotation (t)
tree t;
@@ -325,32 +310,6 @@ get_filename (expr)
return "???";
}
-static inline tree_ref
-output_ref (t)
- tree t;
-{
- return tree_annotation (t) ? tree_annotation (t)->output_ref : NULL;
-}
-
-static inline void
-set_output_ref (t, def)
- tree t;
- tree_ref def;
-{
- tree_ann ann;
-#if defined ENABLE_CHECKING
- {
- tree w = t;
- STRIP_WFL (w);
- STRIP_NOPS (w);
- if (TREE_CODE (w) != MODIFY_EXPR && TREE_CODE (w) != INIT_EXPR)
- abort ();
- }
-#endif
- ann = tree_annotation (t) ? tree_annotation (t) : create_tree_ann (t);
- ann->output_ref = def;
-}
-
static inline void
set_tree_flag (t, flag)
tree t;
@@ -772,6 +731,15 @@ is_exec_stmt (t)
}
static inline bool
+is_assignment_stmt (t)
+ tree t;
+{
+ STRIP_WFL (t);
+ STRIP_NOPS (t);
+ return (TREE_CODE (t) == MODIFY_EXPR || TREE_CODE (t) == INIT_EXPR);
+}
+
+static inline bool
is_may_ref (ref)
tree_ref ref;
{
@@ -782,14 +750,14 @@ static inline bool
is_may_def (ref)
tree_ref ref;
{
- return is_may_ref (ref) && ref_type (ref) == V_DEF;
+ return ref_type (ref) == V_DEF && is_may_ref (ref);
}
static inline bool
is_may_use (ref)
tree_ref ref;
{
- return is_may_ref (ref) && ref_type (ref) == V_USE;
+ return ref_type (ref) == V_USE && is_may_ref (ref);
}
static inline bool
@@ -803,14 +771,14 @@ static inline bool
is_partial_def (ref)
tree_ref ref;
{
- return is_partial_ref (ref) && ref_type (ref) == V_DEF;
+ return ref_type (ref) == V_DEF && is_partial_ref (ref);
}
static inline bool
is_partial_use (ref)
tree_ref ref;
{
- return is_partial_ref (ref) && ref_type (ref) == V_USE;
+ return ref_type (ref) == V_USE && is_partial_ref (ref);
}
static inline bool
@@ -824,60 +792,74 @@ static inline bool
is_volatile_def (ref)
tree_ref ref;
{
- return is_volatile_ref (ref) && ref_type (ref) == V_DEF;
+ return ref_type (ref) == V_DEF && is_volatile_ref (ref);
}
static inline bool
is_volatile_use (ref)
tree_ref ref;
{
- return is_volatile_ref (ref) && ref_type (ref) == V_USE;
+ return ref_type (ref) == V_USE && is_volatile_ref (ref);
}
static inline bool
is_default_def (ref)
tree_ref ref;
{
- return ref->vdef.m_default && ref_type (ref) == V_DEF;
+ return ref_type (ref) == V_DEF && ref->vdef.m_default;
}
static inline bool
is_clobbering_def (ref)
tree_ref ref;
{
- return ref->vdef.m_clobber && ref_type (ref) == V_DEF;
+ return ref_type (ref) == V_DEF && ref->vdef.m_clobber;
}
static inline bool
is_initializing_def (ref)
tree_ref ref;
{
- return ref->vdef.m_initial && ref_type (ref) == V_DEF;
+ return ref_type (ref) == V_DEF && ref->vdef.m_initial;
}
static inline bool
is_relocating_def (ref)
tree_ref ref;
{
- return ref->vdef.m_relocate && ref_type (ref) == V_DEF;
+ return ref_type (ref) == V_DEF && ref->vdef.m_relocate;
}
static inline bool
is_addressof_use (ref)
tree_ref ref;
{
- return ref->vuse.m_addressof && ref_type (ref) == V_USE;
+ return ref_type (ref) == V_USE && ref->vuse.m_addressof;
}
static inline bool
is_pure_use (ref)
tree_ref ref;
{
- return !ref->vuse.m_addressof
+ return ref_type (ref) == V_USE
+ && !ref->vuse.m_addressof
&& !is_may_ref (ref)
&& !is_partial_ref (ref)
- && !is_volatile_ref (ref)
- && ref_type (ref) == V_USE;
+ && !is_volatile_ref (ref);
+}
+
+static inline bool
+is_pure_def (ref)
+ tree_ref ref;
+{
+ return ref_type (ref) == V_DEF
+ && !ref->vdef.m_default
+ && !ref->vdef.m_clobber
+ && !ref->vdef.m_initial
+ && !ref->vdef.m_relocate
+ && !is_may_ref (ref)
+ && !is_partial_ref (ref)
+ && !is_volatile_ref (ref);
}
/* Return TRUE if we reached the end of the list with iterator I. */
Index: tree-flow.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-flow.h,v
retrieving revision 1.1.4.33
diff -d -u -p -r1.1.4.33 tree-flow.h
--- tree-flow.h 6 Nov 2002 22:22:34 -0000 1.1.4.33
+++ tree-flow.h 7 Nov 2002 04:37:47 -0000
@@ -46,11 +46,7 @@ enum tree_ref_type {
represents a killing definition of the associated variable via an
assignment expression (i.e., all the bits of the variable are
modified). Note that unmodified V_DEF references are only allowed for
- MODIFY_EXPR and INIT_EXPR expressions.
-
- In this case, this reference will represent the output value of the
- associated expression. For instance, 'a = 3' creates a V_DEF
- reference for 'a' and calling output_ref('a = 3') returns this V_DEF. */
+ MODIFY_EXPR and INIT_EXPR expressions. */
V_DEF,
/* A V_USE reference represents a read operation from the associated
@@ -120,28 +116,14 @@ struct tree_ref_common GTY(())
/* Reference type. */
enum tree_ref_type type;
- /* Variable being referenced. This may be a _DECL or an INDIRECT_REF
- node. */
+ /* Variable being referenced. This may be a _DECL, an INDIRECT_REF
+ node or an expression (in the case of E_* references). */
tree var;
/* Statement containing the reference. Maybe NULL for special references
(e.g., default definitions inserted at the start of every function). */
tree * GTY((skip (""))) stmt_p;
- /* Expression tree containing the reference. Maybe NULL for special
- references (e.g., default definitions inserted at the start of every
- function). */
- tree * GTY((skip (""))) expr_p;
-
- /* Pointer to operand of EXPR containing VAR. Used when substituting the
- operand with some other value in transformations like constant
- propagation. Maybe NULL for special references (e.g., default
- definitions inserted at the start of every function). */
- tree * GTY((skip (""))) operand_p;
-
- /* Original value stored in *OPERAND_P. Used by restore_ref_operand. */
- tree orig_operand;
-
/* Basic block containing the reference. */
basic_block GTY((skip (""))) bb;
@@ -395,12 +377,9 @@ typedef union tree_ref_d *tree_ref;
static inline enum tree_ref_type ref_type PARAMS ((tree_ref));
static inline tree ref_var PARAMS ((tree_ref));
static inline tree ref_stmt PARAMS ((tree_ref));
-static inline tree ref_expr PARAMS ((tree_ref));
static inline basic_block ref_bb PARAMS ((tree_ref));
static inline unsigned long ref_id PARAMS ((tree_ref));
-static inline void restore_ref_operand PARAMS ((tree_ref));
-extern void replace_ref_operand_with PARAMS ((tree_ref, tree));
-extern void replace_ref_expr_with PARAMS ((tree_ref, tree));
+extern void replace_ref_in PARAMS ((tree, tree_ref, tree));
extern void replace_ref_stmt_with PARAMS ((tree_ref, tree));
@@ -433,6 +412,7 @@ static inline bool is_initializing_def
static inline bool is_relocating_def PARAMS ((tree_ref));
static inline bool is_addressof_use PARAMS ((tree_ref));
static inline bool is_pure_use PARAMS ((tree_ref));
+static inline bool is_pure_def PARAMS ((tree_ref));
/* For phi_node_arg. */
static inline edge phi_arg_edge PARAMS ((phi_node_arg));
@@ -511,10 +491,6 @@ struct tree_ann_d GTY(())
/* Flags used to mark optimization-dependent state. See TF_* below. */
HOST_WIDE_INT flags;
- /* Output reference. This is the V_DEF reference at the LHS of
- assignments (MODIFY_EXPR and INIT_EXPR). */
- tree_ref output_ref;
-
/* Set of variables that may be aliases of this variable. */
varray_type may_aliases;
};
@@ -546,8 +522,6 @@ static inline void set_tree_flag PARAMS
static inline void clear_tree_flag PARAMS ((tree, enum tree_flags));
static inline enum tree_flags tree_flags PARAMS ((tree));
static inline void reset_tree_flags PARAMS ((tree));
-static inline tree_ref output_ref PARAMS ((tree));
-static inline void set_output_ref PARAMS ((tree, tree_ref));
static inline tree indirect_var PARAMS ((tree));
static inline void set_indirect_var PARAMS ((tree, tree));
static inline tree may_alias PARAMS ((tree, size_t));
@@ -555,6 +529,7 @@ static inline size_t num_may_alias PARAM
static inline int get_lineno PARAMS ((tree));
static inline const char *get_filename PARAMS ((tree));
static inline bool is_exec_stmt PARAMS ((tree));
+static inline bool is_assignment_stmt PARAMS ((tree));
/*---------------------------------------------------------------------------
@@ -679,6 +654,7 @@ extern tree last_stmt PARAMS ((basic_b
extern tree *last_stmt_ptr PARAMS ((basic_block));
extern basic_block latch_block PARAMS ((basic_block));
extern bool is_latch_block PARAMS ((basic_block));
+extern edge find_taken_edge PARAMS ((basic_block, tree));
/* In tree-dfa.c */
@@ -687,7 +663,7 @@ extern void find_refs_in_stmt
extern tree_ann create_tree_ann PARAMS ((tree));
extern tree_ref create_ref PARAMS ((tree, enum tree_ref_type,
unsigned, basic_block, tree *,
- tree *, tree *, int));
+ int));
extern void debug_ref PARAMS ((tree_ref));
extern void dump_ref PARAMS ((FILE *, const char *, tree_ref,
int, int));
@@ -726,8 +702,9 @@ extern bool ref_defines PARAMS ((tree_
extern bool is_killing_def PARAMS ((tree_ref, tree_ref));
extern int get_alias_index PARAMS ((tree, tree));
extern enum tree_ref_structure_enum tree_ref_structure PARAMS ((tree_ref));
-void remove_decl PARAMS ((tree));
-tree * find_decl_location PARAMS ((tree, tree));
+extern void remove_decl PARAMS ((tree));
+extern tree * find_decl_location PARAMS ((tree, tree));
+extern tree_ref output_ref PARAMS ((tree));
/* In tree-ssa.c */
Index: tree-ssa-ccp.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa-ccp.c,v
retrieving revision 1.1.2.29
diff -d -u -p -r1.1.2.29 tree-ssa-ccp.c
--- tree-ssa-ccp.c 5 Nov 2002 23:50:39 -0000 1.1.2.29
+++ tree-ssa-ccp.c 7 Nov 2002 04:37:47 -0000
@@ -45,6 +45,7 @@ Software Foundation, 59 Temple Place - S
#include "hard-reg-set.h"
#include "basic-block.h"
#include "diagnostic.h"
+#include "tree-inline.h"
#include "tree-flow.h"
#include "tree-simple.h"
@@ -88,27 +89,28 @@ static struct edge_list *edges;
nodes that need to be visited are accessed using imm_uses (D). */
ref_list ssa_edges;
-static void initialize PARAMS ((void));
-static void finalize PARAMS ((void));
-static void visit_phi_node PARAMS ((tree_ref));
-static value cp_lattice_meet PARAMS ((value, value));
-static void visit_expression_for PARAMS ((tree_ref));
-static void visit_condexpr_for PARAMS ((tree_ref));
-static void visit_assignment_for PARAMS ((tree_ref));
-static void add_outgoing_control_edges PARAMS ((basic_block));
-static void add_control_edge PARAMS ((edge));
-static void def_to_undefined PARAMS ((tree_ref));
-static void def_to_varying PARAMS ((tree_ref));
-static void set_lattice_value PARAMS ((tree_ref, value));
-static void simulate_block PARAMS ((basic_block));
-static void simulate_def_use_chains PARAMS ((tree_ref));
-static void substitute_and_fold PARAMS ((void));
-static value evaluate_expr PARAMS ((tree));
-static void dump_lattice_value PARAMS ((FILE *, const char *, value));
-static tree widen_bitfield PARAMS ((tree, tree, tree));
-static void replace_uses_in PARAMS ((tree));
-static void restore_expr PARAMS ((tree));
-static tree ccp_fold PARAMS ((tree));
+static void initialize PARAMS ((void));
+static void finalize PARAMS ((void));
+static void visit_phi_node PARAMS ((tree_ref));
+static value cp_lattice_meet PARAMS ((value, value));
+static void visit_stmt PARAMS ((tree));
+static void visit_cond_stmt PARAMS ((tree));
+static void visit_assignment PARAMS ((tree));
+static void add_outgoing_control_edges PARAMS ((basic_block));
+static void add_control_edge PARAMS ((edge));
+static void def_to_undefined PARAMS ((tree_ref));
+static void def_to_varying PARAMS ((tree_ref));
+static void set_lattice_value PARAMS ((tree_ref, value));
+static void simulate_block PARAMS ((basic_block));
+static void simulate_def_use_chains PARAMS ((tree_ref));
+static void substitute_and_fold PARAMS ((void));
+static value evaluate_stmt PARAMS ((tree));
+static void dump_lattice_value PARAMS ((FILE *, const char *, value));
+static tree widen_bitfield PARAMS ((tree, tree, tree));
+static bool replace_uses_in PARAMS ((tree));
+static void fold_stmt PARAMS ((tree));
+static tree get_rhs PARAMS ((tree));
+static void set_rhs PARAMS ((tree, tree));
/* Debugging dumps. */
@@ -137,7 +139,6 @@ tree_ssa_ccp (fndecl)
{
/* Pull the next block to simulate off the worklist. */
basic_block dest_block;
-
dest_block = ((edge)VARRAY_TOP_GENERIC_PTR (edge_info))->dest;
VARRAY_POP (edge_info);
simulate_block (dest_block);
@@ -177,7 +178,7 @@ tree_ssa_ccp (fndecl)
}
-/* Simulate the execution of BLOCK. Evaluate the expression associated
+/* Simulate the execution of BLOCK. Evaluate the statement associated
with each variable reference inside the block. */
static void
@@ -191,53 +192,43 @@ simulate_block (block)
if (block == EXIT_BLOCK_PTR)
return;
- /* Similarly, if the block contains no references, we have nothing to do. */
- blockrefs = bb_refs (block);
- if (blockrefs == NULL)
- return;
+#if defined ENABLE_CHECKING
+ if (block->index < 0 || block->index > last_basic_block)
+ abort ();
+#endif
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "\nSimulating block %d\n", block->index);
/* Always simulate PHI nodes, even if we have simulated this block
before. Note that all PHI nodes are consecutive within a block. */
+ blockrefs = bb_refs (block);
for (i = rli_start (blockrefs); !rli_after_end (i); rli_step (&i))
if (ref_type (rli_ref (i)) == V_PHI)
visit_phi_node (rli_ref (i));
-#if defined ENABLE_CHECKING
- if (block->index < 0 || block->index > last_basic_block)
- abort ();
-#endif
-
/* If this is the first time we've simulated this block, then we
- must simulate each of its insns. */
+ must simulate each of its statements. */
if (!TEST_BIT (executable_blocks, block->index))
{
- edge succ_edge = block->succ;
+ gimple_stmt_iterator j;
/* Note that we have simulated this block. */
SET_BIT (executable_blocks, block->index);
- for (i = rli_start (blockrefs); !rli_after_end (i); rli_step (&i))
- {
- /* Simulate each reference within the block. */
- if (ref_type (rli_ref (i)) != V_PHI)
- visit_expression_for (rli_ref (i));
- }
+ for (j = gsi_start_bb (block); !gsi_after_end (j); gsi_step_bb (&j))
+ visit_stmt (gsi_stmt (j));
- /* If we haven't looked at the next block, and it has a
- single successor, add it onto the worklist. This is because
- if we only have one successor, we know it gets executed,
- so we don't have to wait for cprop to tell us. */
- if (succ_edge && succ_edge->succ_next == NULL)
- add_control_edge (succ_edge);
+ /* If the block has a single successor, it will always get executed.
+ Add it to the worklist. */
+ if (block->succ && block->succ->succ_next == NULL)
+ add_control_edge (block->succ);
}
}
/* Follow the def-use chains for definition DEF and simulate all the
- expressions reached by it. */
+ statements reached by it. */
static void
simulate_def_use_chains (def)
@@ -253,11 +244,13 @@ simulate_def_use_chains (def)
{
tree_ref ref = rli_ref (i);
- /* Note that we only visit unmodified V_USE references. We don't
- want to deal with any modifiers here. */
+ /* Visit the statement containing the use reached by DEF, only if the
+ destination block is marked executable. Note that we only visit
+ unmodified V_USE references. We don't want to deal with any
+ modifiers here. */
if (is_pure_use (ref)
&& TEST_BIT (executable_blocks, ref_bb (ref)->index))
- visit_expression_for (ref);
+ visit_stmt (ref_stmt (ref));
/* PHI nodes are always visited, regardless of whether or not the
destination block is executable. */
@@ -275,52 +268,40 @@ substitute_and_fold ()
basic_block bb;
if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, "\nSubstituing constants and folding expressions\n\n");
+ fprintf (dump_file, "\nSubstituing constants and folding statements\n\n");
- /* Substitute constants in every expression of every basic block. */
+ /* Substitute constants in every statement of every basic block. */
FOR_EACH_BB (bb)
{
- tree new_expr;
- ref_list_iterator i;
+ gimple_stmt_iterator i;
- for (i = rli_start (bb_refs (bb)); !rli_after_end (i); rli_step (&i))
+ for (i = gsi_start_bb (bb); !gsi_after_end (i); gsi_step_bb (&i))
{
- tree_ref ref = rli_ref (i);
- tree expr = ref_expr (ref);
- tree stmt = ref_stmt (ref);
-
- /* Skip references not attached to statements and expressions. */
- if (expr == NULL_TREE)
- continue;
-
- /* We are only interested in expressions that contain unmodified
- V_USE references. */
- if (!is_pure_use (ref))
- continue;
+ tree stmt = gsi_stmt (i);
/* Skip statements that have been folded already. */
- if (tree_flags (stmt) & TF_FOLDED)
+ if (tree_flags (stmt) & TF_FOLDED
+ || !is_exec_stmt (stmt))
continue;
- /* Replace the expression with its folded version in the statement
- and mark it folded. Note that in the case of assignment
- expressions, we fold their RHS (fold() does not handle
- assignments). */
+ /* Replace the statement with its folded version and mark it
+ folded. */
if (dump_file && (dump_flags & TDF_DETAILS))
{
- fprintf (dump_file, "Line %d: replaced ", get_lineno (expr));
- print_generic_stmt (dump_file, expr, TDF_SLIM);
+ fprintf (dump_file, "Line %d: replaced ", get_lineno (stmt));
+ print_generic_stmt (dump_file, stmt, TDF_SLIM);
}
- replace_uses_in (expr);
- new_expr = ccp_fold (expr);
- replace_ref_expr_with (ref, new_expr);
- set_tree_flag (stmt, TF_FOLDED);
+ if (replace_uses_in (stmt))
+ {
+ fold_stmt (stmt);
+ set_tree_flag (stmt, TF_FOLDED);
+ }
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, " with ");
- print_generic_stmt (dump_file, new_expr, TDF_SLIM);
+ print_generic_stmt (dump_file, stmt, TDF_SLIM);
fprintf (dump_file, "\n");
}
}
@@ -346,41 +327,55 @@ visit_phi_node (phi_node)
phi_val.lattice_val = UNDEFINED;
phi_val.const_value = NULL_TREE;
- /* Compute the meet operator over all the PHI arguments. */
- for (i = 0; i < num_phi_args (phi_node); i++)
- {
- phi_node_arg arg = phi_arg (phi_node, i);
- edge e = phi_arg_edge (arg);
+ if (!is_volatile_ref (phi_node))
+ for (i = 0; i < num_phi_args (phi_node); i++)
+ {
+ /* Compute the meet operator over all the PHI arguments. */
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file, "\n Argument #%d (%d -> %d %sexecutable)\n",
- i, e->src->index, e->dest->index,
- (e->flags & EDGE_EXECUTABLE) ? "" : "not ");
- }
+ phi_node_arg arg = phi_arg (phi_node, i);
+ edge e = phi_arg_edge (arg);
- /* If the incoming edge is executable, Compute the meet operator for
- the existing value of the PHI node and the current PHI argument. */
- if (e->flags & EDGE_EXECUTABLE)
- {
- tree_ref rdef;
- value rdef_val;
-
- rdef = phi_arg_def (arg);
- rdef_val = values[ref_id (rdef)];
- phi_val = cp_lattice_meet (phi_val, rdef_val);
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "\n Argument #%d (%d -> %d %sexecutable)\n",
+ i, e->src->index, e->dest->index,
+ (e->flags & EDGE_EXECUTABLE) ? "" : "not ");
+ }
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- dump_ref (dump_file, "\t", phi_arg_def (arg), 0, 0);
- dump_lattice_value (dump_file, "\tValue: ", rdef_val);
- fprintf (dump_file, "\n");
- }
+ /* If the incoming edge is executable, Compute the meet operator for
+ the existing value of the PHI node and the current PHI argument. */
+ if (e->flags & EDGE_EXECUTABLE)
+ {
+ tree_ref rdef;
+ value rdef_val;
+
+ rdef = phi_arg_def (arg);
- if (phi_val.lattice_val == VARYING)
- break;
- }
- }
+ if (is_killing_def (rdef, phi_node))
+ {
+ rdef_val = values[ref_id (rdef)];
+ phi_val = cp_lattice_meet (phi_val, rdef_val);
+ }
+ else
+ {
+ /* If RDEF is a non-killing definition, we cannot assume
+ anything about this PHI's node value. In that case, set
+ its value to VARYING. */
+ phi_val.lattice_val = VARYING;
+ phi_val.const_value = NULL_TREE;
+ }
+
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ dump_ref (dump_file, "\t", phi_arg_def (arg), 0, 0);
+ dump_lattice_value (dump_file, "\tValue: ", rdef_val);
+ fprintf (dump_file, "\n");
+ }
+
+ if (phi_val.lattice_val == VARYING)
+ break;
+ }
+ }
if (dump_file && (dump_flags & TDF_DETAILS))
{
@@ -436,99 +431,73 @@ cp_lattice_meet (val1, val2)
}
-/* Evaluate the expression associated with REF. If the expression produces
- an output value and its evaluation changes the lattice value of its
- output, do the following:
+/* Evaluate statement STMT. If the statement produces an output value and
+ its evaluation changes the lattice value of its output, do the following:
- - If the expression is an assignment, add all the SSA edges starting at
+ - If the statement is an assignment, add all the SSA edges starting at
this definition.
- - If the expression controls a conditional branch:
- . If the expression evaluates to non-constant, add all edges to
+ - If the statement is a conditional branch:
+ . If the statement evaluates to non-constant, add all edges to
worklist.
- . If the expression is constant, add the edge executed as the
+ . If the statement is constant, add the edge executed as the
result of the branch. */
static void
-visit_expression_for (ref)
- tree_ref ref;
+visit_stmt (stmt)
+ tree stmt;
{
- tree expr;
-
-#if defined ENABLE_CHECKING
- /* PHI references should be handled by visit_phi_node. */
- if (ref_type (ref) == V_PHI)
- abort ();
-#endif
-
- /* First examine the reference to see if it's a special definition
- (clobbering, partial or may-def), mark it varying and add SSA edges
- that may be coming out of it. */
- if (is_clobbering_def (ref)
- || is_partial_def (ref)
- || is_may_def (ref)
- || is_relocating_def (ref))
- def_to_varying (ref);
-
- expr = ref_expr (ref);
-
- /* No need to do anything if the reference is not associated with an
- expression. */
- if (expr == NULL)
+ /* FIXME: This is lame. All statements should be in GIMPLE form. */
+ if (TREE_NOT_GIMPLE (stmt))
return;
if (dump_file && (dump_flags & TDF_DETAILS))
{
- fprintf (dump_file, "\nVisiting expression: ");
- print_generic_expr (dump_file, expr, 0);
- dump_ref (dump_file, "\nfor reference: ", ref, 0, 0);
+ fprintf (dump_file, "\nVisiting statement: ");
+ print_generic_stmt (dump_file, stmt, TDF_SLIM);
+ fprintf (dump_file, "\n");
}
- /* Now examine the expression. If the expression produces an output
- value, evaluate the expression to see if the lattice value of its
- output has changed. */
- if (output_ref (expr))
- visit_assignment_for (ref);
+ /* Now examine the statement. If the statement produces an output
+ value, evaluate it to see if the lattice value of its output has
+ changed. */
+ if (is_assignment_stmt (stmt))
+ visit_assignment (stmt);
- /* If the expression is the predicate of a control statement, see if we
- can determine which branch will be taken. */
- else if (is_simple_condexpr (expr) && ref_bb (ref)->flags & BB_CONTROL_EXPR)
- visit_condexpr_for (ref);
+ /* If STMT is a control statement, see if we can determine which branch
+ will be taken. */
+ else if (is_ctrl_stmt (stmt))
+ visit_cond_stmt (stmt);
- /* If the expression is a computed goto, mark all the output edges
+ /* If STMT is a computed goto, mark all the output edges
executable. */
- else if (is_computed_goto (ref_stmt (ref)))
- add_outgoing_control_edges (ref_bb (ref));
+ else if (is_computed_goto (stmt))
+ add_outgoing_control_edges (bb_for_stmt (stmt));
}
-/* Visit the assignment expression holding reference REF. */
+/* Visit the assignment statement STMT. Set the value of its LHS to the
+ value computed by the RHS. */
static void
-visit_assignment_for (ref)
- tree_ref ref;
+visit_assignment (stmt)
+ tree stmt;
{
- tree expr;
value val;
- expr = ref_expr (ref);
- STRIP_WFL (expr);
- STRIP_NOPS (expr);
-
#if defined ENABLE_CHECKING
- if (TREE_CODE (expr) != MODIFY_EXPR
- && TREE_CODE (expr) != INIT_EXPR)
+ if (!is_assignment_stmt (stmt))
abort ();
#endif
- /* Evaluate the expression. */
- val = evaluate_expr (expr);
+ /* Evaluate the statement. */
+ val = evaluate_stmt (stmt);
/* FIXME: Hack. If this was a definition of a bitfield, we need to widen
the constant value into the type of the destination variable. This
should not be necessary if GCC represented bitfields properly. */
{
- tree lhs = TREE_OPERAND (expr, 0);
+ tree lhs = TREE_OPERAND (stmt, 0);
if (val.lattice_val == CONSTANT
&& TREE_CODE (lhs) == COMPONENT_REF
&& DECL_BIT_FIELD (TREE_OPERAND (lhs, 1)))
@@ -543,55 +512,44 @@ visit_assignment_for (ref)
val.const_value = NULL;
}
}
- }
+ }
- /* Set the lattice value of the expression's output. */
- set_lattice_value (output_ref (expr), val);
+ /* Set the lattice value of the statement's output. */
+ set_lattice_value (output_ref (stmt), val);
}
-/* Visit the conditional expression that contains reference REF. If it
- evaluates to a constant value, mark outgoing edges appropriately. */
+/* Visit the conditional statement STMT. If it evaluates to a constant value,
+ mark outgoing edges appropriately. */
static void
-visit_condexpr_for (ref)
- tree_ref ref;
+visit_cond_stmt (stmt)
+ tree stmt;
{
- edge curredge;
+ edge e;
value val;
- basic_block block = ref_bb (ref);
- tree expr = ref_expr (ref);
-
- val = evaluate_expr (expr);
+ basic_block block;
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- tree t = ref_stmt (ref);
- STRIP_WFL (t);
- STRIP_NOPS (t);
- fprintf (dump_file, "Predicate is for a control statement: %s\n",
- tree_code_name[TREE_CODE (t)]);
- dump_lattice_value (dump_file, "value: ", val);
- fprintf (dump_file, "\n");
- }
+#if defined ENABLE_CHECKING
+ if (!is_ctrl_stmt (stmt))
+ abort ();
+#endif
- /* Mark successor blocks on executable edges as executable (if they
- have not already been marked). */
- for (curredge = block->succ; curredge; curredge = curredge->succ_next)
- {
- /* If this is an edge for TRUE values but the predicate is false,
- then skip it. */
- if ((curredge->flags & EDGE_TRUE_VALUE)
- && simple_cst_equal (val.const_value, integer_zero_node) == 1)
- continue;
+ block = bb_for_stmt (stmt);
+ val = evaluate_stmt (stmt);
- /* Similarly for FALSE edges. */
- if ((curredge->flags & EDGE_FALSE_VALUE)
- && simple_cst_equal (val.const_value, integer_one_node) == 1)
- continue;
+ /* If the predicate is undefined, do nothing. */
+ if (val.lattice_val == UNDEFINED)
+ return;
- add_control_edge (curredge);
- }
+ /* Find which edge out of the conditional block will be taken and add it
+ to the worklist. If no single edge can be determined statically, add
+ all outgoing edges from BLOCK. */
+ e = find_taken_edge (block, val.const_value);
+ if (e)
+ add_control_edge (e);
+ else
+ add_outgoing_control_edges (block);
}
@@ -627,38 +585,28 @@ add_control_edge (e)
}
-/* Evaluate the expression EXPR. */
+/* Evaluate statement STMT. */
static value
-evaluate_expr (expr)
- tree expr;
+evaluate_stmt (stmt)
+ tree stmt;
{
value val;
- tree simplified;
-
-#if defined ENABLE_CHECKING
- /* FIXME: This test is lame. All expressions should be in GIMPLE form. */
- if (TREE_NOT_GIMPLE (expr))
- abort ();
-#endif
+ tree simplified, copy;
val.lattice_val = VARYING;
val.const_value = NULL_TREE;
- simplified = NULL_TREE;
- /* Replace all V_USE references in the expression with their immediate
- reaching definition. */
- replace_uses_in (expr);
-
- /* Fold the expression. */
- simplified = ccp_fold (deep_copy_node (expr));
-
- STRIP_WFL (simplified);
- STRIP_NOPS (simplified);
- if (TREE_CODE (simplified) == INIT_EXPR
- || TREE_CODE (simplified) == MODIFY_EXPR)
- simplified = TREE_OPERAND (simplified, 1);
+ /* Evaluate a copy of the original statement. */
+ STRIP_WFL (stmt);
+ STRIP_NOPS (stmt);
+ copy = stmt;
+ walk_tree (©, copy_tree_r, NULL, NULL);
+ if (replace_uses_in (copy))
+ fold_stmt (copy);
+ /* Extract the folded value from the statement. */
+ simplified = get_rhs (copy);
if (simplified && really_constant_p (simplified))
{
val.lattice_val = CONSTANT;
@@ -668,8 +616,8 @@ evaluate_expr (expr)
/* Debugging dumps. */
if (dump_file && (dump_flags & TDF_DETAILS))
{
- fprintf (dump_file, "Expression evaluates to ");
- print_generic_expr (dump_file, expr, 0);
+ fprintf (dump_file, "Statement evaluates to ");
+ print_generic_stmt (dump_file, copy, TDF_SLIM);
fprintf (dump_file, " which is ");
if (val.lattice_val == CONSTANT)
{
@@ -684,7 +632,6 @@ evaluate_expr (expr)
fprintf (dump_file, "\n");
}
- restore_expr (expr);
return val;
}
@@ -822,6 +769,14 @@ initialize ()
values[id].const_value = DECL_INITIAL (var);
}
}
+
+ /* Special definitions (clobbering, partial or may-def) are all
+ considered VARYING. */
+ else if (!is_pure_def (r))
+ {
+ values[id].lattice_val = VARYING;
+ values[id].const_value = NULL_TREE;
+ }
}
}
@@ -929,14 +884,15 @@ set_lattice_value (def, val)
}
-/* Replace USE reference in the expression EXPR with their immediate reaching
- definition. */
+/* Replace USE references in statement STMT with their immediate reaching
+ definition. Return true if at least one reference was replaced. */
-static void
-replace_uses_in (expr)
- tree expr;
+static bool
+replace_uses_in (stmt)
+ tree stmt;
{
- ref_list refs = tree_refs (expr);
+ bool replaced = false;
+ ref_list refs = tree_refs (stmt);
ref_list_iterator i;
for (i = rli_start (refs); !rli_after_end (i); rli_step (&i))
@@ -949,8 +905,8 @@ replace_uses_in (expr)
if (!is_pure_use (use))
continue;
- /* The lattice value of a USE reference is the value of its
- immediately reaching definition. */
+ /* The lattice value of a USE reference is the value of its immediately
+ reaching definition. */
rdef = imm_reaching_def (use);
/* We are only interested in killing definitions. If we are reached
@@ -962,74 +918,78 @@ replace_uses_in (expr)
rdef_id = ref_id (rdef);
if (values[rdef_id].lattice_val == CONSTANT)
{
-#if defined ENABLE_CHECKING
- if (values[rdef_id].const_value == NULL_TREE)
- abort ();
-#endif
- /* The reference is a constant, substitute it into the
- expression. */
- replace_ref_operand_with (use, values[rdef_id].const_value);
- }
- else
- {
- /* The reference is not a constant, restore its original value. */
- restore_ref_operand (use);
+ replace_ref_in (stmt, use, values[rdef_id].const_value);
+ replaced = true;
}
}
+
+ return replaced;
}
-/* Restore expression EXPR to its original form. */
+/* Fold statement STMT. */
static void
-restore_expr (expr)
- tree expr;
+fold_stmt (stmt)
+ tree stmt;
{
- ref_list refs = tree_refs (expr);
- ref_list_iterator i;
+ tree rhs, result;
- for (i = rli_start (refs); !rli_after_end (i); rli_step (&i))
+ STRIP_WFL (stmt);
+ STRIP_NOPS (stmt);
+ rhs = get_rhs (stmt);
+ if (rhs)
{
- /* Only restore pure V_USE references (those are the only types
- of references changed by replace_uses_in. */
- if (is_pure_use (rli_ref (i)))
- restore_ref_operand (rli_ref (i));
+ result = fold (rhs);
+ set_rhs (stmt, result);
}
}
-/* Fold EXPR. If EXPR is an assignment, fold its RHS and return a new
- assignment with the folded RHS (fold does not handle assignment
- expressions). */
+/* Get the main expression from statement STMT. */
static tree
-ccp_fold (expr)
- tree expr;
+get_rhs (stmt)
+ tree stmt;
{
- tree result, to_fold, w_expr;
+ enum tree_code code = TREE_CODE (stmt);
- /* If the expression is an assignment, get its RHS. */
- w_expr = expr;
- STRIP_WFL (w_expr);
- STRIP_NOPS (w_expr);
- if (TREE_CODE (w_expr) == MODIFY_EXPR
- || TREE_CODE (w_expr) == INIT_EXPR)
- to_fold = TREE_OPERAND (w_expr, 1);
+ if (code == MODIFY_EXPR || code == INIT_EXPR)
+ return TREE_OPERAND (stmt, 1);
+ if (code == COND_EXPR)
+ return COND_EXPR_COND (stmt);
+ else if (code == SWITCH_EXPR)
+ return SWITCH_COND (stmt);
+ else if (code == RETURN_EXPR)
+ return TREE_OPERAND (stmt, 0);
+ else if (code == GOTO_EXPR)
+ return GOTO_DESTINATION (stmt);
+ else if (code == LABEL_EXPR)
+ return LABEL_EXPR_LABEL (stmt);
else
- to_fold = expr;
+ return stmt;
+}
- result = fold (to_fold);
- /* If we folded the RHS of the original expression, store the folded
- expression there and return the original expression (which will have
- the new folded RHS). */
- if (TREE_CODE (w_expr) == MODIFY_EXPR
- || TREE_CODE (w_expr) == INIT_EXPR)
- {
- TREE_OPERAND (w_expr, 1) = result;
- return expr;
- }
- else
- /* Otherwise, return the folded expression. */
- return result;
+/* Set the main expression of STMT to EXPR. */
+
+static void
+set_rhs (stmt, expr)
+ tree stmt;
+ tree expr;
+{
+ enum tree_code code = TREE_CODE (stmt);
+
+ if (code == MODIFY_EXPR || code == INIT_EXPR)
+ TREE_OPERAND (stmt, 1) = expr;
+ if (code == COND_EXPR)
+ COND_EXPR_COND (stmt) = expr;
+ else if (code == SWITCH_EXPR)
+ SWITCH_COND (stmt) = expr;
+ else if (code == RETURN_EXPR)
+ TREE_OPERAND (stmt, 0) = expr;
+ else if (code == GOTO_EXPR)
+ GOTO_DESTINATION (stmt) = expr;
+ else if (code == LABEL_EXPR)
+ LABEL_EXPR_LABEL (stmt) = expr;
}
Index: tree-ssa-pre.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa-pre.c,v
retrieving revision 1.1.4.32
diff -d -u -p -r1.1.4.32 tree-ssa-pre.c
--- tree-ssa-pre.c 6 Nov 2002 22:22:34 -0000 1.1.4.32
+++ tree-ssa-pre.c 7 Nov 2002 04:37:48 -0000
@@ -772,27 +772,21 @@ insert_occ_in_preorder_dt_order_1 (ei, f
{
tree *killexpr = VARRAY_GENERIC_PTR (ei->kills, i);
- newref = create_ref (*killexpr,
- E_KILL, 0, block, killexpr,
- killexpr, NULL, true);
+ newref = create_ref (*killexpr, E_KILL, 0, block, killexpr, 1);
VARRAY_PUSH_GENERIC_PTR (ei->erefs, newref);
fibheap_insert (fh, preorder_count++, newref);
}
else if (VARRAY_GENERIC_PTR (ei->lefts, i) != NULL)
{
tree *leftexpr = VARRAY_GENERIC_PTR (ei->lefts, i);
- newref = create_ref (*leftexpr,
- E_LEFT, 0, block, leftexpr,
- leftexpr, NULL, true);
+ newref = create_ref (*leftexpr, E_LEFT, 0, block, leftexpr, 1);
VARRAY_PUSH_GENERIC_PTR (ei->erefs, newref);
fibheap_insert (fh, preorder_count++, newref);
}
else
{
tree *occurexpr = VARRAY_GENERIC_PTR (ei->occurs, i);
- newref = create_ref (*occurexpr,
- E_USE, 0, block, occurexpr,
- occurexpr, NULL, true);
+ newref = create_ref (*occurexpr, E_USE, 0, block, occurexpr, 1);
VARRAY_PUSH_GENERIC_PTR (ei->erefs, newref);
set_expruse_def (newref, NULL);
set_exprref_class (newref, 0);
@@ -812,8 +806,7 @@ insert_occ_in_preorder_dt_order_1 (ei, f
{
if (phi_at_block (ei, succ->dest) != NULL)
{
- tree_ref newref = create_ref (NULL, E_USE, 0, block, 0,
- 0, 0, true);
+ tree_ref newref = create_ref (NULL, E_USE, 0, block, 0, 1);
tree_ref phi = phi_at_block (ei, succ->dest);
VARRAY_PUSH_GENERIC_PTR (ei->erefs, newref);
set_expruse_def (newref, NULL);
@@ -837,8 +830,7 @@ insert_occ_in_preorder_dt_order_1 (ei, f
if (preorder_count != 0)
{
tree_ref newref;
- newref = create_ref (NULL, E_EXIT, 0, block,
- NULL, NULL, NULL, true);
+ newref = create_ref (NULL, E_EXIT, 0, block, NULL, 1);
VARRAY_PUSH_GENERIC_PTR (ei->erefs, newref);
fibheap_insert (fh, preorder_count++, newref);
}
@@ -1564,10 +1556,7 @@ temp_fix_refs (lookin, lookfor, replacew
{
tree_ref ref = rli_ref (rli);
if (ref_stmt (ref) == lookfor)
- {
- ref->common.stmt_p = replacewith;
- ref->common.expr_p = replacewith;
- }
+ ref->common.stmt_p = replacewith;
}
}
@@ -1820,10 +1809,8 @@ done:
expruse_def (X) = new occurrence.
*/
- set_expruse_def (X,create_ref (expr, E_USE, 0,
- ref_bb (X), newexprplace,
- newexprplace, newexprplace,
- true));
+ set_expruse_def (X,create_ref (expr, E_USE, 0, ref_bb (X),
+ newexprplace, 1));
set_bb_for_stmt (*newexprplace, ref_bb (X));
VARRAY_PUSH_GENERIC_PTR (ei->erefs, expruse_def (X));
@@ -1920,9 +1907,7 @@ expr_phi_insertion (dfs, ei)
EXECUTE_IF_SET_IN_SBITMAP(dfphis, 0, i,
{
- tree_ref ref = create_ref (ei->expr, E_PHI, 0,
- BASIC_BLOCK (i),
- NULL, NULL, NULL, true);
+ tree_ref ref = create_ref (ei->expr, E_PHI, 0, BASIC_BLOCK (i), NULL, 1);
VARRAY_PUSH_GENERIC_PTR (ei->erefs, ref);
set_exprref_processed (ref, false);
set_exprref_processed2 (ref, false);
@@ -2730,7 +2715,6 @@ code_motion (ei, temp)
use->common.stmt_p = &TREE_OPERAND (newstmt, 1);
- use->common.expr_p = &TREE_OPERAND (newstmt, 1);
/* REMOVE AFTER DFA UPDATE */
temp_fix_refs (use_stmt, newstmt, &TREE_OPERAND (newstmt, 1));
Index: tree-ssa.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa.c,v
retrieving revision 1.1.4.28
diff -d -u -p -r1.1.4.28 tree-ssa.c
--- tree-ssa.c 5 Nov 2002 23:50:39 -0000 1.1.4.28
+++ tree-ssa.c 7 Nov 2002 04:37:48 -0000
@@ -808,7 +808,7 @@ add_phi_node (bb, var)
first executable statement. This is for debugging convenience.
This way, the PHI node will have line number information. */
stmt_p = !bb_empty_p (bb) ? bb->head_tree_p : NULL;
- phi = create_ref (var, V_PHI, 0, bb, stmt_p, NULL, NULL, false);
+ phi = create_ref (var, V_PHI, 0, bb, stmt_p, 0);
add_ref_to_list_begin (bb_refs (bb), phi);
VARRAY_TREE (added, bb->index) = var;
@@ -951,7 +951,7 @@ create_default_def (var)
mod = TRM_DEFAULT;
/* Create a default definition and set it to be CURRDEF(var). */
- def = create_ref (var, V_DEF, mod, decl_bb, NULL, NULL, NULL, false);
+ def = create_ref (var, V_DEF, mod, decl_bb, NULL, 0);
add_ref_to_list_begin (bb_refs (decl_bb), def);
set_currdef_for (var, def);