tree.h (VALUE_HANDLE_VUSES): New.

2005-12-29  Daniel Berlin  <dberlin@dberlin.org>

	* tree.h (VALUE_HANDLE_VUSES): New.
	(struct tree_value_handle): Add vuses.

	* tree-vn.c (struct val_expr_pair_d): Remove stmt, add vuses.
	(vn_compute): Remove stmt argument.
	Don't use vuses in hash value computation.
	(val_expr_pair_eq): Compare vuse lists.
	(copy_vuses_from_stmt): New function.
	(shared_vuses_from_stmt): Ditto.
	(vn_add): Rewrite in terms of vn_add_with_vuses.
	(vn_add_with_vuses): New function.
	(vn_lookup): Rewrite in terms of vn_lookup_with_vuses.
	(vn_lookup_with_vuses): New function.
	(vuses_compare): New function.
	(print_creation_to_file): Ditto.
	(vn_lookup_or_add): Rewrite to handle vuses.
	(sort_vuses): New function.
	(vn_lookup_or_add_with_vuses): Ditto.
	(vn_init): Initialize shared_lookup_vuses.
	(vn_delete): Free shared_lookup_vuses.

	* tree-ssa-pre.c: Update todo list.
	(bb_value_sets_t): Add rvuse_in, rvuse_out, rvuse_gen, and
	rvuse_kill.
	(RVUSE_IN): New macro.
	(RVUSE_GEN): Ditto.
	(RVUSE_KILL): Ditto.
	(RVUSE_OUT): Ditto.
	(modify_expr_node_pool): New function.
	(pretemp): New.
	(storetemp): Ditto.
	(mergephitemp): Ditto.
	(prephitemp): Ditto.
	(struct expr_pred_trans_d): Add vuses member.
	(expr_pred_trans_eq): Compare vuses.
	(phi_trans_lookup): Add vuses argument.
	(phi_trans_add): Ditto.
	(translate_vuses_through_block): New function.
	(phi_translate): Use vuses to ask about those expressions that can
	have vuses.
	Properly translate virtual uses through phis, and use
	vn_lookup_or_add_with vuses.  Handle tcc_reference.
	(phi_translate_set): Don't add pointless translations to the
	cache.
	(get_representative): New function.
	(vuses_dies_in_block_x): Ditto.
	(valid_in_set): Add block argument.  Check virtual use validity.
	(clean): Add block argument. Update call to valid_in_set
	(compute_antic_aux): Update call to clean.
	(dump_bitmap_of_names): New function.
	(compute_vuse_representatives): Ditto.
	(compute_rvuse): Ditto.
	(can_value_number_call): Modified to accept calls with vuses.
	(can_value_number_operation): New function.
	(can_PRE_operation): Ditto.
	(need_creation): New vector of stores that may need creation.
	(find_or_generate_expression): use can_PRE_operation.
	(create_expression_by_pieces): Handle INDIRECT_REF.
	Only create one temp until we have to change types.
	Mark new vars for renaming.
	(insert_into_preds_of_block): Ignore loopiness of loads.
	Use can_PRE_operation.
	Only create one temp until we have to chnge types.
	(insert_aux): Use can_PRE_operation.
	Don't pass name to insert_into_preds_of_block.
	(insert_extra_phis): Only use one temp until we have to change
	types.
	(poolify_tree): New function.
	(modify_expr_template): New var.
	(poolify_modify_expr): New function.
	(insert_fake_stores): Ditto.
	(realify_fake_stores): Ditto.
	(compute_avail): Use can_value_number_operation.
	(mark_operand_necessary): Return NULL for non-SSA names.
	(remove_dead_inserted_code): Update comment.
	(init_pre): Initialize pretemp, need_creation, storetemp,
	mergephitemp, prephitemp.
	Create modify_expr_node_pool.
	(fini_pre): Free modify_expr_node_pool and need_creation array.
	(execute_pre): Call insert_fake_stores, compute_rvuse, and
	realify_fake_stores. 
	* tree-flow.h (vn_compute): Fix prototype.
	(vn_add): Ditto.
	(vn_lookup): Ditto.
	(sort_vuses): New.
	(vn_lookup_or_add_with_vuses): Ditto.
	(vn_add_with_vuses): Ditto.
	(vn_lookup_with_vuses): Ditto.
	* passes.c (pass_may_alias): Add.

From-SVN: r109180
This commit is contained in:
Daniel Berlin 2005-12-30 18:43:00 +00:00 committed by Daniel Berlin
parent a176426f35
commit c90186eb1a
14 changed files with 1442 additions and 152 deletions

View File

@ -1,3 +1,95 @@
2005-12-29 Daniel Berlin <dberlin@dberlin.org>
* tree.h (VALUE_HANDLE_VUSES): New.
(struct tree_value_handle): Add vuses.
* tree-vn.c (struct val_expr_pair_d): Remove stmt, add vuses.
(vn_compute): Remove stmt argument.
Don't use vuses in hash value computation.
(val_expr_pair_eq): Compare vuse lists.
(copy_vuses_from_stmt): New function.
(shared_vuses_from_stmt): Ditto.
(vn_add): Rewrite in terms of vn_add_with_vuses.
(vn_add_with_vuses): New function.
(vn_lookup): Rewrite in terms of vn_lookup_with_vuses.
(vn_lookup_with_vuses): New function.
(vuses_compare): New function.
(print_creation_to_file): Ditto.
(vn_lookup_or_add): Rewrite to handle vuses.
(sort_vuses): New function.
(vn_lookup_or_add_with_vuses): Ditto.
(vn_init): Initialize shared_lookup_vuses.
(vn_delete): Free shared_lookup_vuses.
* tree-ssa-pre.c: Update todo list.
(bb_value_sets_t): Add rvuse_in, rvuse_out, rvuse_gen, and
rvuse_kill.
(RVUSE_IN): New macro.
(RVUSE_GEN): Ditto.
(RVUSE_KILL): Ditto.
(RVUSE_OUT): Ditto.
(modify_expr_node_pool): New function.
(pretemp): New.
(storetemp): Ditto.
(mergephitemp): Ditto.
(prephitemp): Ditto.
(struct expr_pred_trans_d): Add vuses member.
(expr_pred_trans_eq): Compare vuses.
(phi_trans_lookup): Add vuses argument.
(phi_trans_add): Ditto.
(translate_vuses_through_block): New function.
(phi_translate): Use vuses to ask about those expressions that can
have vuses.
Properly translate virtual uses through phis, and use
vn_lookup_or_add_with vuses. Handle tcc_reference.
(phi_translate_set): Don't add pointless translations to the
cache.
(get_representative): New function.
(vuses_dies_in_block_x): Ditto.
(valid_in_set): Add block argument. Check virtual use validity.
(clean): Add block argument. Update call to valid_in_set
(compute_antic_aux): Update call to clean.
(dump_bitmap_of_names): New function.
(compute_vuse_representatives): Ditto.
(compute_rvuse): Ditto.
(can_value_number_call): Modified to accept calls with vuses.
(can_value_number_operation): New function.
(can_PRE_operation): Ditto.
(need_creation): New vector of stores that may need creation.
(find_or_generate_expression): use can_PRE_operation.
(create_expression_by_pieces): Handle INDIRECT_REF.
Only create one temp until we have to change types.
Mark new vars for renaming.
(insert_into_preds_of_block): Ignore loopiness of loads.
Use can_PRE_operation.
Only create one temp until we have to chnge types.
(insert_aux): Use can_PRE_operation.
Don't pass name to insert_into_preds_of_block.
(insert_extra_phis): Only use one temp until we have to change
types.
(poolify_tree): New function.
(modify_expr_template): New var.
(poolify_modify_expr): New function.
(insert_fake_stores): Ditto.
(realify_fake_stores): Ditto.
(compute_avail): Use can_value_number_operation.
(mark_operand_necessary): Return NULL for non-SSA names.
(remove_dead_inserted_code): Update comment.
(init_pre): Initialize pretemp, need_creation, storetemp,
mergephitemp, prephitemp.
Create modify_expr_node_pool.
(fini_pre): Free modify_expr_node_pool and need_creation array.
(execute_pre): Call insert_fake_stores, compute_rvuse, and
realify_fake_stores.
* tree-flow.h (vn_compute): Fix prototype.
(vn_add): Ditto.
(vn_lookup): Ditto.
(sort_vuses): New.
(vn_lookup_or_add_with_vuses): Ditto.
(vn_add_with_vuses): Ditto.
(vn_lookup_with_vuses): Ditto.
* passes.c (pass_may_alias): Add.
2005-12-30 Gabriel Dos Reis <gdr@integrable-solutions.net>
* c-pretty-print.h (struct c_pretty_print_info): Add new member

View File

@ -554,6 +554,7 @@ init_optimization_passes (void)
NEXT_PASS (pass_cse_reciprocals);
NEXT_PASS (pass_split_crit_edges);
NEXT_PASS (pass_pre);
NEXT_PASS (pass_may_alias);
NEXT_PASS (pass_sink_code);
NEXT_PASS (pass_tree_loop);
NEXT_PASS (pass_reassoc);

View File

@ -0,0 +1,18 @@
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-pre-stats" } */
int main(int *a, int argc)
{
int c;
int d, e;
/* Should be able to eliminate the second load of *a along the main path. */
d = *a;
if (argc)
{
a = &c;
}
e = *a;
return d + e;
}
/* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre"} } */
/* { dg-final { cleanup-tree-dump "pre" } } */

View File

@ -0,0 +1,18 @@
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-pre-stats" } */
int main(int *a, int argc)
{
int b;
int i;
int d, e;
/* Should be able to hoist this out of the loop. */
for (i = 0; i < argc; i++)
{
e = *a;
}
return d + e;
}
/* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre"} } */
/* { dg-final { cleanup-tree-dump "pre" } } */

View File

@ -0,0 +1,24 @@
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-pre-stats" } */
int main(int **a,int argc)
{
int b;
int d, e;
if (argc)
{
d = *(*a);
}
else
{
}
/* Should be able to eliminate one of the *(*a)'s along the if path
by pushing it into the else path. We will also eliminate
one of the *a's. */
e = *(*a);
return d + e;
}
/* { dg-final { scan-tree-dump-times "Eliminated: 2" 1 "pre"} } */
/* { dg-final { cleanup-tree-dump "pre" } } */

View File

@ -0,0 +1,21 @@
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-pre-stats" } */
int main(int *a, int argc)
{
int b;
int c;
int i;
int d, e;
/* With smarter load PRE, we'd be able to recompute the value at the
kill point. arguably not worth it. */
for (i = 0; i < argc; i++)
{
e = *a;
*a = 9;
}
return d + e;
}
/* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre" { xfail *-*-* } } } */
/* { dg-final { cleanup-tree-dump "pre" } } */

View File

@ -0,0 +1,22 @@
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-pre-stats" } */
int p;
int r;
int a(void)
{
return p;
}
int main(int argc)
{
int q;
q = a();
/* We should be able to move the call to a into the if path.
in a perfect world, we'd actually decide that it can't touch
r, and not recompute it at all!. */
if (argc)
r = 9;
return q + a();
}
/* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre"} } */
/* { dg-final { cleanup-tree-dump "pre" } } */

View File

@ -0,0 +1,74 @@
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-pre-stats" } */
union tree_node;
typedef union tree_node *tree;
struct tree_common
{
tree chain;
};
struct tree_list
{
struct tree_common common;
tree value;
};
union tree_node
{
struct tree_common common;
struct tree_list list;
};
extern void abort (void) __attribute__((noreturn));
void __attribute__((noinline))
foo (void)
{
abort ();
}
void __attribute__((noinline))
remove_useless_vars (tree *unexpanded_var_list, int dump_file)
{
tree var, *cell;
int c = 0;
for (cell = unexpanded_var_list; *cell; )
{
var = (*cell)->list.value;
if (var)
{
if (dump_file)
foo ();
*cell = ((*cell)->common.chain);
continue;
}
cell = &((*cell)->common.chain);
}
}
extern void *malloc (int) __attribute__ ((malloc));
int
main (void)
{
int i;
tree unexpanded_var_list, last = (tree) 0;
for (i = 0; i < 2; i++)
{
unexpanded_var_list = malloc (sizeof (struct tree_list));
unexpanded_var_list->list.value = (tree) (long unsigned) (i & 1);
unexpanded_var_list->common.chain = last;
last = unexpanded_var_list;
}
remove_useless_vars (&unexpanded_var_list, 0);
return 0;
}
/* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre" } } */
/* { dg-final { cleanup-tree-dump "pre" } } */

View File

@ -0,0 +1,17 @@
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-pre-stats" } */
/* We can't eliminate the *p load here in any sane way, as eshup8 may
change it. */
void
enormlz (x)
unsigned short x[];
{
register unsigned short *p;
p = &x[2];
while ((*p & 0xff00) == 0)
{
eshup8 (x);
}
}
/* { dg-final { scan-tree-dump-times "Eliminated: 0" 1 "pre"} } */
/* { dg-final { cleanup-tree-dump "pre" } } */

View File

@ -0,0 +1,97 @@
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-pre-stats" } */
typedef union tree_node *tree;
struct tree_common
{
tree chain;
}
VEC_constructor_elt_base;
struct tree_ssa_name
{
tree var;
};
union tree_node
{
struct tree_common common;
struct tree_ssa_name ssa_name;
};
struct edge_def
{
struct basic_block_def *dest;
};
typedef struct edge_def *edge;
typedef struct VEC_edge_base
{
}
VEC_edge_base;
edge
VEC_edge_base_index (const VEC_edge_base * vec_, unsigned ix_)
{
}
typedef struct VEC_edge_gc
{
VEC_edge_base base;
}
VEC_edge_gc;
struct basic_block_def
{
VEC_edge_gc *succs;
};
typedef struct basic_block_def *basic_block;
typedef struct
{
unsigned index;
VEC_edge_gc **container;
}
edge_iterator;
__inline__ VEC_edge_gc *
ei_container (edge_iterator i)
{
return *i.container;
}
__inline__ edge_iterator
ei_start_1 (VEC_edge_gc ** ev)
{
edge_iterator i;
i.container = ev;
return i;
}
ei_next (edge_iterator * i)
{
}
static __inline__ edge
ei_edge (edge_iterator i)
{
return (edge) (VEC_edge_base_index ((((ei_container (i))) ? &((ei_container (i)))->base : 0), (i.index)));
}
static __inline__ unsigned char
ei_cond (edge_iterator ei, edge * p)
{
*p = ei_edge (ei);
}
typedef tree *def_operand_p;
extern tree *get_phi_result_ptr (tree);
static __inline__ tree
get_def_from_ptr (def_operand_p def)
{
}
tree
phi_nodes (basic_block bb)
{
}
/* We can eliminate a load of the SRA'd variable edge_iterator.container */
rewrite_add_phi_arguments (basic_block bb)
{
edge e;
edge_iterator ei;
for ((ei) = ei_start_1 (&((bb->succs))); ei_cond ((ei), &(e));
ei_next (&(ei)))
{
tree phi;
for (phi = phi_nodes (e->dest); phi; phi = (((phi))->common.chain))
get_reaching_def ((get_def_from_ptr (get_phi_result_ptr (phi)))->ssa_name.var);
}
}
/* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre"} } */
/* { dg-final { cleanup-tree-dump "pre" } } */

View File

@ -776,10 +776,14 @@ void print_value_expressions (FILE *, tree);
/* In tree-vn.c */
bool expressions_equal_p (tree, tree);
tree get_value_handle (tree);
hashval_t vn_compute (tree, hashval_t, tree);
hashval_t vn_compute (tree, hashval_t);
void sort_vuses (VEC (tree, gc) *);
tree vn_lookup_or_add (tree, tree);
void vn_add (tree, tree, tree);
tree vn_lookup_or_add_with_vuses (tree, VEC (tree, gc) *);
void vn_add (tree, tree);
void vn_add_with_vuses (tree, tree, VEC (tree, gc) *);
tree vn_lookup (tree, tree);
tree vn_lookup_with_vuses (tree, VEC (tree, gc) *);
void vn_init (void);
void vn_delete (void);

File diff suppressed because it is too large Load Diff

View File

@ -48,8 +48,8 @@ typedef struct val_expr_pair_d
/* Associated expression. */
tree e;
/* for comparing Virtual uses in E. */
tree stmt;
/* For comparing virtual uses in E. */
VEC (tree, gc) *vuses;
/* E's hash value. */
hashval_t hashcode;
@ -77,16 +77,11 @@ make_value_handle (tree type)
any).
VAL can be used to iterate by passing previous value numbers (it is
used by iterative_hash_expr).
STMT is the stmt associated with EXPR for comparing virtual operands. */
used by iterative_hash_expr). */
hashval_t
vn_compute (tree expr, hashval_t val, tree stmt)
vn_compute (tree expr, hashval_t val)
{
ssa_op_iter iter;
tree vuse;
/* EXPR must not be a statement. We are only interested in value
numbering expressions on the RHS of assignments. */
gcc_assert (expr);
@ -94,17 +89,9 @@ vn_compute (tree expr, hashval_t val, tree stmt)
|| expr->common.ann->common.type != STMT_ANN);
val = iterative_hash_expr (expr, val);
/* If the expression has virtual uses, incorporate them into the
hash value computed for EXPR. */
if (stmt)
FOR_EACH_SSA_TREE_OPERAND (vuse, stmt, iter, SSA_OP_VUSE)
val = iterative_hash_expr (vuse, val);
return val;
}
/* Compare two expressions E1 and E2 and return true if they are
equal. */
@ -163,15 +150,26 @@ val_expr_pair_hash (const void *p)
static int
val_expr_pair_expr_eq (const void *p1, const void *p2)
{
bool ret;
int i;
tree vuse1;
const val_expr_pair_t ve1 = (val_expr_pair_t) p1;
const val_expr_pair_t ve2 = (val_expr_pair_t) p2;
if (! expressions_equal_p (ve1->e, ve2->e))
return false;
ret = compare_ssa_operands_equal (ve1->stmt, ve2->stmt, SSA_OP_VUSE);
return ret;
if (ve1->vuses == ve2->vuses)
return true;
if (VEC_length (tree, ve1->vuses) != VEC_length (tree, ve2->vuses))
return false;
for (i = 0; VEC_iterate (tree, ve1->vuses, i, vuse1); i++)
{
if (VEC_index (tree, ve2->vuses, i) != vuse1)
return false;
}
return true;
}
@ -190,13 +188,68 @@ set_value_handle (tree e, tree v)
gcc_assert (is_gimple_min_invariant (e));
}
/* Copy the virtual uses from STMT into a newly allocated VEC(tree),
and return the VEC(tree). */
static VEC (tree, gc) *
copy_vuses_from_stmt (tree stmt)
{
ssa_op_iter iter;
tree vuse;
VEC (tree, gc) *vuses = NULL;
if (!stmt)
return NULL;
FOR_EACH_SSA_TREE_OPERAND (vuse, stmt, iter, SSA_OP_VUSE)
VEC_safe_push (tree, gc, vuses, vuse);
return vuses;
}
/* Place for shared_vuses_from_stmt to shove vuses. */
static VEC (tree, gc) *shared_lookup_vuses;
/* Copy the virtual uses from STMT into SHARED_LOOKUP_VUSES.
This function will overwrite the current SHARED_LOOKUP_VUSES
variable. */
static VEC (tree, gc) *
shared_vuses_from_stmt (tree stmt)
{
ssa_op_iter iter;
tree vuse;
if (!stmt)
return NULL;
VEC_truncate (tree, shared_lookup_vuses, 0);
FOR_EACH_SSA_TREE_OPERAND (vuse, stmt, iter, SSA_OP_VUSE)
VEC_safe_push (tree, gc, shared_lookup_vuses, vuse);
if (VEC_length (tree, shared_lookup_vuses) > 1)
sort_vuses (shared_lookup_vuses);
return shared_lookup_vuses;
}
/* Insert EXPR into VALUE_TABLE with value VAL, and add expression
EXPR to the value set for value VAL. STMT represents the stmt
associated with EXPR. It is used when computing a hash value for EXPR. */
EXPR to the value set for value VAL. */
void
vn_add (tree expr, tree val, tree stmt)
vn_add (tree expr, tree val)
{
vn_add_with_vuses (expr, val, NULL);
}
/* Insert EXPR into VALUE_TABLE with value VAL, and add expression
EXPR to the value set for value VAL. VUSES represents the virtual
use operands associated with EXPR. It is used when computing a
hash value for EXPR. */
void
vn_add_with_vuses (tree expr, tree val, VEC (tree, gc) *vuses)
{
void **slot;
val_expr_pair_t new_pair;
@ -204,8 +257,8 @@ vn_add (tree expr, tree val, tree stmt)
new_pair = XNEW (struct val_expr_pair_d);
new_pair->e = expr;
new_pair->v = val;
new_pair->stmt = stmt;
new_pair->hashcode = vn_compute (expr, 0, stmt);
new_pair->vuses = vuses;
new_pair->hashcode = vn_compute (expr, 0);
slot = htab_find_slot_with_hash (value_table, new_pair, new_pair->hashcode,
INSERT);
if (*slot)
@ -213,7 +266,8 @@ vn_add (tree expr, tree val, tree stmt)
*slot = (void *) new_pair;
set_value_handle (expr, val);
add_to_value (val, expr);
if (TREE_CODE (val) == VALUE_HANDLE)
add_to_value (val, expr);
}
@ -224,6 +278,17 @@ vn_add (tree expr, tree val, tree stmt)
tree
vn_lookup (tree expr, tree stmt)
{
return vn_lookup_with_vuses (expr, shared_vuses_from_stmt (stmt));
}
/* Search in VALUE_TABLE for an existing instance of expression EXPR,
and return its value, or NULL if none has been set. VUSES is the
list of virtual use operands associated with EXPR. It is used when
computing the hash value for EXPR. */
tree
vn_lookup_with_vuses (tree expr, VEC (tree, gc) *vuses)
{
void **slot;
struct val_expr_pair_d vep = {NULL, NULL, NULL, 0};
@ -233,8 +298,8 @@ vn_lookup (tree expr, tree stmt)
return expr;
vep.e = expr;
vep.stmt = stmt;
vep.hashcode = vn_compute (expr, 0, stmt);
vep.vuses = vuses;
vep.hashcode = vn_compute (expr, 0);
slot = htab_find_slot_with_hash (value_table, &vep, vep.hashcode, NO_INSERT);
if (!slot)
return NULL_TREE;
@ -243,10 +308,53 @@ vn_lookup (tree expr, tree stmt)
}
/* A comparison function for use in qsort to compare vuses. Simply
subtracts version numbers. */
static int
vuses_compare (const void *pa, const void *pb)
{
const tree vusea = *((const tree *)pa);
const tree vuseb = *((const tree *)pb);
int sn = SSA_NAME_VERSION (vusea) - SSA_NAME_VERSION (vuseb);
return sn;
}
/* Print out the "Created value <x> for <Y>" statement to the
dump_file.
This is factored because both versions of lookup use it, and it
obscures the real work going on in those functions. */
static void
print_creation_to_file (tree v, tree expr, VEC (tree, gc) *vuses)
{
fprintf (dump_file, "Created value ");
print_generic_expr (dump_file, v, dump_flags);
fprintf (dump_file, " for ");
print_generic_expr (dump_file, expr, dump_flags);
if (vuses && VEC_length (tree, vuses) != 0)
{
size_t i;
tree vuse;
fprintf (dump_file, " vuses: (");
for (i = 0; VEC_iterate (tree, vuses, i, vuse); i++)
{
print_generic_expr (dump_file, vuse, dump_flags);
if (VEC_length (tree, vuses) - 1 != i)
fprintf (dump_file, ",");
}
fprintf (dump_file, ")");
}
fprintf (dump_file, "\n");
}
/* Like vn_lookup, but creates a new value for expression EXPR, if
EXPR doesn't already have a value. Return the existing/created
value for EXPR. STMT represents the stmt associated with EXPR. It is used
when computing the hash value for EXPR. */
value for EXPR. STMT represents the stmt associated with EXPR. It
is used when computing the VUSES for EXPR. */
tree
vn_lookup_or_add (tree expr, tree stmt)
@ -254,18 +362,17 @@ vn_lookup_or_add (tree expr, tree stmt)
tree v = vn_lookup (expr, stmt);
if (v == NULL_TREE)
{
VEC(tree,gc) *vuses;
v = make_value_handle (TREE_TYPE (expr));
vuses = copy_vuses_from_stmt (stmt);
sort_vuses (vuses);
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "Created value ");
print_generic_expr (dump_file, v, dump_flags);
fprintf (dump_file, " for ");
print_generic_expr (dump_file, expr, dump_flags);
fprintf (dump_file, "\n");
}
print_creation_to_file (v, expr, vuses);
vn_add (expr, v, stmt);
VALUE_HANDLE_VUSES (v) = vuses;
vn_add_with_vuses (expr, v, vuses);
}
set_value_handle (expr, v);
@ -273,6 +380,46 @@ vn_lookup_or_add (tree expr, tree stmt)
return v;
}
/* Sort the VUSE array so that we can do equality comparisons
quicker on two vuse vecs. */
void
sort_vuses (VEC (tree,gc) *vuses)
{
if (VEC_length (tree, vuses) > 1)
qsort (VEC_address (tree, vuses),
VEC_length (tree, vuses),
sizeof (tree),
vuses_compare);
}
/* Like vn_lookup, but creates a new value for expression EXPR, if
EXPR doesn't already have a value. Return the existing/created
value for EXPR. STMT represents the stmt associated with EXPR. It is used
when computing the hash value for EXPR. */
tree
vn_lookup_or_add_with_vuses (tree expr, VEC (tree, gc) *vuses)
{
tree v = vn_lookup_with_vuses (expr, vuses);
if (v == NULL_TREE)
{
v = make_value_handle (TREE_TYPE (expr));
sort_vuses (vuses);
if (dump_file && (dump_flags & TDF_DETAILS))
print_creation_to_file (v, expr, vuses);
VALUE_HANDLE_VUSES (v) = vuses;
vn_add_with_vuses (expr, v, vuses);
}
set_value_handle (expr, v);
return v;
}
/* Get the value handle of EXPR. This is the only correct way to get
the value handle for a "thing". If EXPR does not have a value
@ -306,6 +453,7 @@ vn_init (void)
{
value_table = htab_create (511, val_expr_pair_hash,
val_expr_pair_expr_eq, free);
shared_lookup_vuses = NULL;
}
@ -315,5 +463,6 @@ void
vn_delete (void)
{
htab_delete (value_table);
VEC_free (tree, gc, shared_lookup_vuses);
value_table = NULL;
}

View File

@ -2814,6 +2814,9 @@ struct tree_statement_list
#define VALUE_HANDLE_EXPR_SET(NODE) \
(VALUE_HANDLE_CHECK (NODE)->value_handle.expr_set)
#define VALUE_HANDLE_VUSES(NODE) \
(VALUE_HANDLE_CHECK (NODE)->value_handle.vuses)
/* Defined and used in tree-ssa-pre.c. */
struct value_set;
@ -2828,6 +2831,9 @@ struct tree_value_handle GTY(())
conveniently dense form starting at 0, so that we can make
bitmaps of value handles. */
unsigned int id;
/* Set of virtual uses represented by this handle. */
VEC (tree, gc) *vuses;
};
/* Define the overall contents of a tree node.