Commit 33c94679 by Diego Novillo Committed by Diego Novillo

Makefile.in (tree-vn.o): New.


	* Makefile.in (tree-vn.o): New.
	(tree-ssa-pre.o): Don't depend on RTL_H.
	* tree-dfa.c (find_referenced_vars): Don't call init_tree_ssa.
	* tree-flow.h (struct var_ann_d): Remove field expr_set.
	(add_to_value, expressions_equal_p, get_value_handle, vn_compute,
	vn_lookup_or_add, vn_add, vn_lookup, vn_init, vn_delete): Declare.
	* tree-optimize.c (execute_init_datastructures): New local function.
	(pass_init_datastructures): New local variable.
	(init_tree_optimization_passes): Sequence pass_init_datastructures.
	* tree-pretty-print.c (MASK_POINTER): Remove.
	(dump_generic_node): Handle VALUE_HANDLE.
	* tree-ssa-pre.c: Move all value numbering routines to tree-vn.c.
	Update callers to use new function names.
	Use VALUE_HANDLE_ID and VALUE_HANDLE_EXPR_SET instead of
	variable annotations.
	* tree-ssa.c (init_tree_ssa): Call vn_init.
	(delete_tree_ssa): Call vn_delete.
	* tree-vn.c: New file.
	* tree.c (tree_size): Handle VALUE_HANDLE.
	(tree_node_structure): Likewise.
	(iterative_hash_expr): Likewise.
	* tree.def (VALUE_HANDLE): New code.
	* tree.h (struct tree_value_handle): New.
	(VALUE_HANDLE_ID): Define.
	(VALUE_HANDLE_EXPR_SET): Define.
	(enum tree_node_structure_enum): Add TS_VALUE_HANDLE.
	(union tree_node): Add struct tree_value_handle.

From-SVN: r83564
parent 881f20cb
2004-06-23 Diego Novillo <dnovillo@redhat.com>
* Makefile.in (tree-vn.o): New.
(tree-ssa-pre.o): Don't depend on RTL_H.
* tree-dfa.c (find_referenced_vars): Don't call init_tree_ssa.
* tree-flow.h (struct var_ann_d): Remove field expr_set.
(add_to_value, expressions_equal_p, get_value_handle, vn_compute,
vn_lookup_or_add, vn_add, vn_lookup, vn_init, vn_delete): Declare.
* tree-optimize.c (execute_init_datastructures): New local function.
(pass_init_datastructures): New local variable.
(init_tree_optimization_passes): Sequence pass_init_datastructures.
* tree-pretty-print.c (MASK_POINTER): Remove.
(dump_generic_node): Handle VALUE_HANDLE.
* tree-ssa-pre.c: Move all value numbering routines to tree-vn.c.
Update callers to use new function names.
Use VALUE_HANDLE_ID and VALUE_HANDLE_EXPR_SET instead of
variable annotations.
* tree-ssa.c (init_tree_ssa): Call vn_init.
(delete_tree_ssa): Call vn_delete.
* tree-vn.c: New file.
* tree.c (tree_size): Handle VALUE_HANDLE.
(tree_node_structure): Likewise.
(iterative_hash_expr): Likewise.
* tree.def (VALUE_HANDLE): New code.
* tree.h (struct tree_value_handle): New.
(VALUE_HANDLE_ID): Define.
(VALUE_HANDLE_EXPR_SET): Define.
(enum tree_node_structure_enum): Add TS_VALUE_HANDLE.
(union tree_node): Add struct tree_value_handle.
2004-06-23 Andrew Pinski <apinski@apple.com> 2004-06-23 Andrew Pinski <apinski@apple.com>
* c-typeck.c (composite_type): * c-typeck.c (composite_type):
......
...@@ -887,7 +887,7 @@ C_OBJS = c-parse.o c-lang.o stub-objc.o $(C_AND_OBJC_OBJS) ...@@ -887,7 +887,7 @@ C_OBJS = c-parse.o c-lang.o stub-objc.o $(C_AND_OBJC_OBJS)
OBJS-common = \ OBJS-common = \
tree-cfg.o tree-dfa.o tree-eh.o tree-ssa.o tree-optimize.o tree-gimple.o \ tree-cfg.o tree-dfa.o tree-eh.o tree-ssa.o tree-optimize.o tree-gimple.o \
tree-alias-type.o gimplify.o tree-pretty-print.o tree-into-ssa.o \ tree-alias-type.o gimplify.o tree-pretty-print.o tree-into-ssa.o \
tree-outof-ssa.o tree-alias-common.o tree-ssa-ccp.o \ tree-outof-ssa.o tree-alias-common.o tree-ssa-ccp.o tree-vn.o \
@ANDER@ tree-ssa-dce.o tree-ssa-copy.o tree-nrv.o tree-ssa-copyrename.o \ @ANDER@ tree-ssa-dce.o tree-ssa-copy.o tree-nrv.o tree-ssa-copyrename.o \
tree-ssa-pre.o tree-ssa-live.o tree-ssa-operands.o tree-ssa-alias.o \ tree-ssa-pre.o tree-ssa-live.o tree-ssa-operands.o tree-ssa-alias.o \
tree-ssa-phiopt.o tree-ssa-forwprop.o tree-nested.o tree-ssa-dse.o \ tree-ssa-phiopt.o tree-ssa-forwprop.o tree-nested.o tree-ssa-dse.o \
...@@ -1640,9 +1640,12 @@ tree-ssa-copyrename.o : tree-ssa-copyrename.c $(TREE_FLOW_H) $(CONFIG_H) \ ...@@ -1640,9 +1640,12 @@ tree-ssa-copyrename.o : tree-ssa-copyrename.c $(TREE_FLOW_H) $(CONFIG_H) \
diagnostic.h errors.h toplev.h function.h $(TIMEVAR_H) tree-pass.h \ diagnostic.h errors.h toplev.h function.h $(TIMEVAR_H) tree-pass.h \
tree-alias-common.h $(TM_H) coretypes.h $(TREE_DUMP_H) $(TREE_SSA_LIVE_H) tree-alias-common.h $(TM_H) coretypes.h $(TREE_DUMP_H) $(TREE_SSA_LIVE_H)
tree-ssa-pre.o : tree-ssa-pre.c $(TREE_FLOW_H) $(CONFIG_H) \ tree-ssa-pre.o : tree-ssa-pre.c $(TREE_FLOW_H) $(CONFIG_H) \
$(SYSTEM_H) $(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) \ $(SYSTEM_H) $(TREE_H) $(TM_P_H) $(EXPR_H) \
$(GGC_H) output.h diagnostic.h errors.h toplev.h $(TIMEVAR_H) \ $(GGC_H) output.h diagnostic.h errors.h toplev.h $(TIMEVAR_H) \
$(TM_H) coretypes.h $(TREE_DUMP_H) tree-pass.h $(FLAGS_H) $(TM_H) coretypes.h $(TREE_DUMP_H) tree-pass.h $(FLAGS_H)
tree-vn.o : tree-vn.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(GGC_H) \
$(TREE_H) $(TREE_FLOW_H) $(HASHTAB_H) langhooks.h tree-pass.h \
$(TREE_DUMP_H) diagnostic.h
tree-cfg.o : tree-cfg.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \ tree-cfg.o : tree-cfg.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
$(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) $(GGC_H) $(FLAGS_H) output.h \ $(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) $(GGC_H) $(FLAGS_H) output.h \
diagnostic.h errors.h function.h $(TIMEVAR_H) $(TM_H) coretypes.h \ diagnostic.h errors.h function.h $(TIMEVAR_H) $(TM_H) coretypes.h \
...@@ -3068,6 +3071,7 @@ distclean: clean lang.distclean ...@@ -3068,6 +3071,7 @@ distclean: clean lang.distclean
-rm -f fixinc/Makefile -rm -f fixinc/Makefile
# Delete po/*.gmo only if we are not building in the source directory. # Delete po/*.gmo only if we are not building in the source directory.
-if [ ! -f po/exgettext ]; then rm -f po/*.gmo; fi -if [ ! -f po/exgettext ]; then rm -f po/*.gmo; fi
-rmdir ada cp f java objc fixinc intl po testsuite 2>/dev/null
# Get rid of every file that's generated from some other file, except for `configure'. # Get rid of every file that's generated from some other file, except for `configure'.
# Most of these files ARE PRESENT in the GCC distribution. # Most of these files ARE PRESENT in the GCC distribution.
......
...@@ -111,10 +111,6 @@ find_referenced_vars (void) ...@@ -111,10 +111,6 @@ find_referenced_vars (void)
struct walk_state walk_state; struct walk_state walk_state;
tree block; tree block;
/* This is the very first pass in preparation for building the SSA
form of the function, so initialize internal data structures now. */
init_tree_ssa ();
/* Walk the lexical blocks in the function looking for variables that may /* Walk the lexical blocks in the function looking for variables that may
have been used to declare VLAs and for nested functions. Both have been used to declare VLAs and for nested functions. Both
constructs create hidden uses of variables. constructs create hidden uses of variables.
......
...@@ -167,11 +167,6 @@ struct var_ann_d GTY(()) ...@@ -167,11 +167,6 @@ struct var_ann_d GTY(())
live at the same time and this can happen for each call to the live at the same time and this can happen for each call to the
dominator optimizer. */ dominator optimizer. */
tree current_def; tree current_def;
/* The set of expressions represented by this variable if it is a
value handle. This is used by GVN-PRE. */
PTR GTY ((skip)) expr_set;
}; };
...@@ -576,12 +571,23 @@ extern bool tree_can_throw_internal (tree); ...@@ -576,12 +571,23 @@ extern bool tree_can_throw_internal (tree);
extern bool tree_can_throw_external (tree); extern bool tree_can_throw_external (tree);
extern void add_stmt_to_eh_region (tree, int); extern void add_stmt_to_eh_region (tree, int);
/* In tree-ssa-pre.c */ /* In tree-ssa-pre.c */
tree get_value_handle (tree); void add_to_value (tree, tree);
void set_value_handle (tree, tree);
void debug_value_expressions (tree); void debug_value_expressions (tree);
void print_value_expressions (FILE *, tree); void print_value_expressions (FILE *, tree);
/* In tree-vn.c */
bool expressions_equal_p (tree e1, tree e2);
tree get_value_handle (tree);
hashval_t vn_compute (tree, hashval_t);
tree vn_lookup_or_add (tree);
void vn_add (tree, tree);
tree vn_lookup (tree);
void vn_init (void);
void vn_delete (void);
/* In tree-sra.c */ /* In tree-sra.c */
void insert_edge_copies (tree stmt, basic_block bb); void insert_edge_copies (tree stmt, basic_block bb);
......
...@@ -153,6 +153,33 @@ static struct tree_opt_pass pass_free_datastructures = ...@@ -153,6 +153,33 @@ static struct tree_opt_pass pass_free_datastructures =
0 /* todo_flags_finish */ 0 /* todo_flags_finish */
}; };
/* Do the actions required to initialize internal data structures used
in tree-ssa optimization passes. */
static void
execute_init_datastructures (void)
{
/* Allocate hash tables, arrays and other structures. */
init_tree_ssa ();
}
static struct tree_opt_pass pass_init_datastructures =
{
NULL, /* name */
NULL, /* gate */
execute_init_datastructures, /* execute */
NULL, /* sub */
NULL, /* next */
0, /* static_pass_number */
0, /* tv_id */
PROP_cfg, /* properties_required */
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
0 /* todo_flags_finish */
};
/* Iterate over the pass tree allocating dump file numbers. We want /* Iterate over the pass tree allocating dump file numbers. We want
to do this depth first, and independent of whether the pass is to do this depth first, and independent of whether the pass is
enabled or not. */ enabled or not. */
...@@ -253,6 +280,7 @@ init_tree_optimization_passes (void) ...@@ -253,6 +280,7 @@ init_tree_optimization_passes (void)
NEXT_PASS (pass_lower_eh); NEXT_PASS (pass_lower_eh);
NEXT_PASS (pass_build_cfg); NEXT_PASS (pass_build_cfg);
NEXT_PASS (pass_tree_profile); NEXT_PASS (pass_tree_profile);
NEXT_PASS (pass_init_datastructures);
NEXT_PASS (pass_all_optimizations); NEXT_PASS (pass_all_optimizations);
NEXT_PASS (pass_mudflap_2); NEXT_PASS (pass_mudflap_2);
NEXT_PASS (pass_free_datastructures); NEXT_PASS (pass_free_datastructures);
......
...@@ -55,8 +55,6 @@ static void dump_generic_bb_buff (pretty_printer *, basic_block, int, int); ...@@ -55,8 +55,6 @@ static void dump_generic_bb_buff (pretty_printer *, basic_block, int, int);
lang_hooks.decl_printable_name (TREE_OPERAND (NODE, 0), 1) : \ lang_hooks.decl_printable_name (TREE_OPERAND (NODE, 0), 1) : \
lang_hooks.decl_printable_name (NODE, 1)) lang_hooks.decl_printable_name (NODE, 1))
#define MASK_POINTER(P) ((unsigned)((unsigned long)(P) & 0xffff))
static pretty_printer buffer; static pretty_printer buffer;
static int initialized = 0; static int initialized = 0;
static bool dumping_stmts; static bool dumping_stmts;
...@@ -1403,6 +1401,10 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags, ...@@ -1403,6 +1401,10 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
pp_decimal_int (buffer, SSA_NAME_VERSION (node)); pp_decimal_int (buffer, SSA_NAME_VERSION (node));
break; break;
case VALUE_HANDLE:
pp_printf (buffer, "VH.%d", VALUE_HANDLE_ID (node));
break;
default: default:
NIY; NIY;
} }
......
...@@ -19,6 +19,7 @@ You should have received a copy of the GNU General Public License ...@@ -19,6 +19,7 @@ You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to along with GCC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330, the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */ Boston, MA 02111-1307, USA. */
#include "config.h" #include "config.h"
#include "system.h" #include "system.h"
#include "coretypes.h" #include "coretypes.h"
...@@ -26,11 +27,6 @@ Boston, MA 02111-1307, USA. */ ...@@ -26,11 +27,6 @@ Boston, MA 02111-1307, USA. */
#include "errors.h" #include "errors.h"
#include "ggc.h" #include "ggc.h"
#include "tree.h" #include "tree.h"
/* These RTL headers are needed for basic-block.h. */
#include "rtl.h"
#include "tm_p.h"
#include "hard-reg-set.h"
#include "basic-block.h" #include "basic-block.h"
#include "diagnostic.h" #include "diagnostic.h"
#include "tree-inline.h" #include "tree-inline.h"
...@@ -48,6 +44,7 @@ Boston, MA 02111-1307, USA. */ ...@@ -48,6 +44,7 @@ Boston, MA 02111-1307, USA. */
#include "splay-tree.h" #include "splay-tree.h"
#include "bitmap.h" #include "bitmap.h"
#include "langhooks.h" #include "langhooks.h"
/* TODO: /* TODO:
1. Implement load value numbering. 1. Implement load value numbering.
...@@ -279,10 +276,8 @@ static struct ...@@ -279,10 +276,8 @@ static struct
static tree find_leader (value_set_t, tree); static tree find_leader (value_set_t, tree);
static void value_insert_into_set (value_set_t, tree); static void value_insert_into_set (value_set_t, tree);
static void insert_into_set (value_set_t, tree); static void insert_into_set (value_set_t, tree);
static void add_to_value (tree, tree);
static value_set_t set_new (bool); static value_set_t set_new (bool);
static bool is_undefined_value (tree); static bool is_undefined_value (tree);
static bool expressions_equal_p (tree, tree);
static tree create_expression_by_pieces (basic_block, tree, tree); static tree create_expression_by_pieces (basic_block, tree, tree);
/* We can add and remove elements and entries to and from sets /* We can add and remove elements and entries to and from sets
...@@ -293,117 +288,12 @@ static alloc_pool value_set_node_pool; ...@@ -293,117 +288,12 @@ static alloc_pool value_set_node_pool;
static alloc_pool binary_node_pool; static alloc_pool binary_node_pool;
static alloc_pool unary_node_pool; static alloc_pool unary_node_pool;
/* The value table that maps expressions to values. */
static htab_t value_table;
/* The phi_translate_table caches phi translations for a given /* The phi_translate_table caches phi translations for a given
expression and predecessor. */ expression and predecessor. */
static htab_t phi_translate_table; static htab_t phi_translate_table;
/* Compare two expressions E1 and E2 and return true if they are
equal. */
static bool
expressions_equal_p (tree e1, tree e2)
{
tree te1, te2;
if (e1 == e2)
return true;
te1 = TREE_TYPE (e1);
te2 = TREE_TYPE (e2);
if (TREE_CODE (e1) == TREE_CODE (e2)
&& (te1 == te2 || lang_hooks.types_compatible_p (te1, te2))
&& operand_equal_p (e1, e2, 0))
return true;
return false;
}
/* Map expressions to values. These are simple pairs of expressions
and the values they represent. To find the value represented by
an expression, we use a hash table where the elements are {e,v}
pairs, and the expression is the key. */
typedef struct val_expr_pair_d
{
tree v, e;
hashval_t hashcode;
} *val_expr_pair_t;
/* Hash a {v,e} pair that is pointed to by P.
The hashcode is cached in the val_expr_pair, so we just return
that. */
static hashval_t
val_expr_pair_hash (const void *p)
{
const val_expr_pair_t ve = (val_expr_pair_t) p;
return ve->hashcode;
}
/* Given two val_expr_pair_t's, return true if they represent the same
expression, false otherwise.
P1 and P2 should point to the val_expr_pair_t's to be compared. */
static int
val_expr_pair_expr_eq (const void *p1, const void *p2)
{
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 true;
return false;
}
/* Get the value handle of EXPR. This is the only correct way to get
the value handle for a "thing".
Returns NULL if the value handle does not exist. */
tree
get_value_handle (tree expr)
{
/* We should never see these. */
if (DECL_P (expr))
abort ();
else if (TREE_CODE (expr) == SSA_NAME)
{
return SSA_NAME_VALUE (expr);
}
else if (TREE_CODE_CLASS (TREE_CODE (expr)) == 'c')
return expr;
else if (EXPR_P (expr))
{
tree_ann_t ann = tree_ann (expr);
if (ann)
return ann->common.value_handle;
return NULL;
}
abort ();
}
/* Set the value handle for expression E to value V */
void
set_value_handle (tree e, tree v)
{
if (DECL_P (e))
abort ();
else if (TREE_CODE (e) == SSA_NAME)
SSA_NAME_VALUE (e) = v;
else if (EXPR_P (e))
get_tree_ann (e)->common.value_handle = v;
}
/* A three tuple {e, pred, v} used to cache phi translations in the /* A three tuple {e, pred, v} used to cache phi translations in the
phi_translate_table. */ phi_translate_table. */
...@@ -468,7 +358,7 @@ phi_trans_lookup (tree e, basic_block pred) ...@@ -468,7 +358,7 @@ phi_trans_lookup (tree e, basic_block pred)
struct expr_pred_trans_d ept; struct expr_pred_trans_d ept;
ept.e = e; ept.e = e;
ept.pred = pred; ept.pred = pred;
ept.hashcode = iterative_hash_expr (e, (unsigned long) pred); ept.hashcode = vn_compute (e, (unsigned long) pred);
slot = htab_find_slot_with_hash (phi_translate_table, &ept, ept.hashcode, slot = htab_find_slot_with_hash (phi_translate_table, &ept, ept.hashcode,
NO_INSERT); NO_INSERT);
if (!slot) if (!slot)
...@@ -489,7 +379,7 @@ phi_trans_add (tree e, tree v, basic_block pred) ...@@ -489,7 +379,7 @@ phi_trans_add (tree e, tree v, basic_block pred)
new_pair->e = e; new_pair->e = e;
new_pair->pred = pred; new_pair->pred = pred;
new_pair->v = v; new_pair->v = v;
new_pair->hashcode = iterative_hash_expr (e, (unsigned long) pred); new_pair->hashcode = vn_compute (e, (unsigned long) pred);
slot = htab_find_slot_with_hash (phi_translate_table, new_pair, slot = htab_find_slot_with_hash (phi_translate_table, new_pair,
new_pair->hashcode, INSERT); new_pair->hashcode, INSERT);
if (*slot) if (*slot)
...@@ -497,31 +387,11 @@ phi_trans_add (tree e, tree v, basic_block pred) ...@@ -497,31 +387,11 @@ phi_trans_add (tree e, tree v, basic_block pred)
*slot = (void *) new_pair; *slot = (void *) new_pair;
} }
/* Search in TABLE for an existing instance of expression E,
and return its value, or NULL if none has been set. */
static inline tree
lookup (htab_t table, tree e)
{
void **slot;
struct val_expr_pair_d vep = {NULL, NULL, 0};
if (TREE_CODE_CLASS (TREE_CODE (e)) == 'c')
return e;
vep.e = e;
vep.hashcode = iterative_hash_expr (e,0);
slot = htab_find_slot_with_hash (table, &vep, vep.hashcode, NO_INSERT);
if (!slot)
return NULL_TREE;
else
return ((val_expr_pair_t) *slot)->v;
}
/* Add expression E to the expression set of value V. */ /* Add expression E to the expression set of value V. */
static inline void void
add_to_value (tree v, tree e) add_to_value (tree v, tree e)
{ {
var_ann_t va;
/* For values representing non-CST nodes, but still function /* For values representing non-CST nodes, but still function
invariant things we mark TREE_CONSTANT as true and set the tree invariant things we mark TREE_CONSTANT as true and set the tree
chain to the actual constant. This is because unlike values chain to the actual constant. This is because unlike values
...@@ -536,106 +406,40 @@ add_to_value (tree v, tree e) ...@@ -536,106 +406,40 @@ add_to_value (tree v, tree e)
TREE_CHAIN (v) = e; TREE_CHAIN (v) = e;
return; return;
} }
va = var_ann (v);
if (va->expr_set == NULL)
va->expr_set = set_new (false);
insert_into_set (va->expr_set, e);
}
/* Insert E into TABLE with value V, and add expression E to the value
set for value V. */
static inline void
add (htab_t table, tree e, tree v)
{
void **slot;
val_expr_pair_t new_pair = xmalloc (sizeof (struct val_expr_pair_d));
new_pair->e = e;
new_pair->v = v;
new_pair->hashcode = iterative_hash_expr (e, 0);
slot = htab_find_slot_with_hash (table, new_pair, new_pair->hashcode,
INSERT);
if (*slot)
free (*slot);
*slot = (void *) new_pair;
set_value_handle (e, v);
add_to_value (v, e);
}
/* A unique counter that is incremented every time we create a new
value. */
static int pre_uid;
/* Create a new value handle for expression EXPR. */ if (VALUE_HANDLE_EXPR_SET (v) == NULL)
VALUE_HANDLE_EXPR_SET (v) = set_new (false);
static tree
create_new_value (tree expr)
{
tree a = create_tmp_var_raw (TREE_TYPE (expr), "value");
create_var_ann (a);
var_ann (a)->uid = pre_uid++;
if (dump_file && (dump_flags & TDF_DETAILS)) insert_into_set (VALUE_HANDLE_EXPR_SET (v), e);
{
fprintf (dump_file, "Created value ");
print_generic_expr (dump_file, a, dump_flags);
fprintf (dump_file, " for ");
print_generic_expr (dump_file, expr, dump_flags);
fprintf (dump_file, "\n");
}
return a;
} }
/* Like lookup, but creates a new value for expression E if E doesn't
already have a value.
Return the existing/created value for E. */
static inline tree
lookup_or_add (htab_t table, tree e)
{
tree x = lookup (table, e);
if (x == NULL_TREE)
{
tree v;
v = create_new_value (e);
add (table, e, v);
x = v;
}
set_value_handle (e, x);
return x;
}
/* Return true if value V exists in the bitmap for SET. */ /* Return true if value V exists in the bitmap for SET. */
static inline bool static inline bool
value_exists_in_set_bitmap (value_set_t set, tree v) value_exists_in_set_bitmap (value_set_t set, tree v)
{ {
if (TREE_CODE (v) != VAR_DECL)
abort ();
if (!set->values) if (!set->values)
return false; return false;
return bitmap_bit_p (set->values, get_var_ann (v)->uid);
return bitmap_bit_p (set->values, VALUE_HANDLE_ID (v));
} }
/* Remove value V from the bitmap for SET. */ /* Remove value V from the bitmap for SET. */
static void static void
value_remove_from_set_bitmap (value_set_t set, tree v) value_remove_from_set_bitmap (value_set_t set, tree v)
{ {
if (TREE_CODE (v) != VAR_DECL)
abort ();
#ifdef ENABLE_CHECKING #ifdef ENABLE_CHECKING
if (!set->indexed) if (!set->indexed)
abort (); abort ();
#endif #endif
if (!set->values) if (!set->values)
return; return;
bitmap_clear_bit (set->values, get_var_ann (v)->uid);
bitmap_clear_bit (set->values, VALUE_HANDLE_ID (v));
} }
...@@ -645,20 +449,21 @@ value_remove_from_set_bitmap (value_set_t set, tree v) ...@@ -645,20 +449,21 @@ value_remove_from_set_bitmap (value_set_t set, tree v)
static inline void static inline void
value_insert_into_set_bitmap (value_set_t set, tree v) value_insert_into_set_bitmap (value_set_t set, tree v)
{ {
if (TREE_CODE (v) != VAR_DECL)
abort ();
#ifdef ENABLE_CHECKING #ifdef ENABLE_CHECKING
if (!set->indexed) if (!set->indexed)
abort (); abort ();
#endif #endif
if (set->values == NULL) if (set->values == NULL)
{ {
set->values = BITMAP_GGC_ALLOC (); set->values = BITMAP_GGC_ALLOC ();
bitmap_clear (set->values); bitmap_clear (set->values);
} }
bitmap_set_bit (set->values, get_var_ann (v)->uid);
bitmap_set_bit (set->values, VALUE_HANDLE_ID (v));
} }
/* Create a new set. */ /* Create a new set. */
static value_set_t static value_set_t
...@@ -681,8 +486,6 @@ insert_into_set (value_set_t set, tree expr) ...@@ -681,8 +486,6 @@ insert_into_set (value_set_t set, tree expr)
{ {
value_set_node_t newnode = pool_alloc (value_set_node_pool); value_set_node_t newnode = pool_alloc (value_set_node_pool);
tree val = get_value_handle (expr); tree val = get_value_handle (expr);
if (DECL_P (expr))
abort ();
if (val == NULL) if (val == NULL)
abort (); abort ();
...@@ -873,7 +676,6 @@ value_insert_into_set (value_set_t set, tree expr) ...@@ -873,7 +676,6 @@ value_insert_into_set (value_set_t set, tree expr)
{ {
tree val = get_value_handle (expr); tree val = get_value_handle (expr);
/* Constant and invariant values exist everywhere, and thus, /* Constant and invariant values exist everywhere, and thus,
actually keeping them in the sets is pointless. */ actually keeping them in the sets is pointless. */
if (TREE_CONSTANT (val)) if (TREE_CONSTANT (val))
...@@ -913,13 +715,16 @@ print_value_set (FILE *outfile, value_set_t set, ...@@ -913,13 +715,16 @@ print_value_set (FILE *outfile, value_set_t set,
} }
/* Print out the expressions that have VAL to OUTFILE. */ /* Print out the expressions that have VAL to OUTFILE. */
void void
print_value_expressions (FILE *outfile, tree val) print_value_expressions (FILE *outfile, tree val)
{ {
var_ann_t va = var_ann (val); if (VALUE_HANDLE_EXPR_SET (val))
if (va && va->expr_set) {
print_value_set (outfile, va->expr_set, char s[10];
IDENTIFIER_POINTER (DECL_NAME (val)), 0); sprintf (s, "VH.%04d", VALUE_HANDLE_ID (val));
print_value_set (outfile, VALUE_HANDLE_EXPR_SET (val), s, 0);
}
} }
...@@ -983,7 +788,7 @@ phi_translate (tree expr, value_set_t set, basic_block pred, ...@@ -983,7 +788,7 @@ phi_translate (tree expr, value_set_t set, basic_block pred,
create_tree_ann (newexpr); create_tree_ann (newexpr);
TREE_OPERAND (newexpr, 0) = newop1 == oldop1 ? oldop1 : get_value_handle (newop1); TREE_OPERAND (newexpr, 0) = newop1 == oldop1 ? oldop1 : get_value_handle (newop1);
TREE_OPERAND (newexpr, 1) = newop2 == oldop2 ? oldop2 : get_value_handle (newop2); TREE_OPERAND (newexpr, 1) = newop2 == oldop2 ? oldop2 : get_value_handle (newop2);
lookup_or_add (value_table, newexpr); vn_lookup_or_add (newexpr);
expr = newexpr; expr = newexpr;
phi_trans_add (oldexpr, newexpr, pred); phi_trans_add (oldexpr, newexpr, pred);
} }
...@@ -1010,7 +815,7 @@ phi_translate (tree expr, value_set_t set, basic_block pred, ...@@ -1010,7 +815,7 @@ phi_translate (tree expr, value_set_t set, basic_block pred,
memcpy (newexpr, expr, tree_size (expr)); memcpy (newexpr, expr, tree_size (expr));
create_tree_ann (newexpr); create_tree_ann (newexpr);
TREE_OPERAND (newexpr, 0) = get_value_handle (newop1); TREE_OPERAND (newexpr, 0) = get_value_handle (newop1);
lookup_or_add (value_table, newexpr); vn_lookup_or_add (newexpr);
expr = newexpr; expr = newexpr;
phi_trans_add (oldexpr, newexpr, pred); phi_trans_add (oldexpr, newexpr, pred);
} }
...@@ -1035,7 +840,7 @@ phi_translate (tree expr, value_set_t set, basic_block pred, ...@@ -1035,7 +840,7 @@ phi_translate (tree expr, value_set_t set, basic_block pred,
tree val; tree val;
if (is_undefined_value (PHI_ARG_DEF (phi, i))) if (is_undefined_value (PHI_ARG_DEF (phi, i)))
return NULL; return NULL;
val = lookup_or_add (value_table, PHI_ARG_DEF (phi, i)); val = vn_lookup_or_add (PHI_ARG_DEF (phi, i));
return PHI_ARG_DEF (phi, i); return PHI_ARG_DEF (phi, i);
} }
} }
...@@ -1328,15 +1133,6 @@ compute_antic (void) ...@@ -1328,15 +1133,6 @@ compute_antic (void)
fprintf (dump_file, "compute_antic required %d iterations\n", num_iterations); fprintf (dump_file, "compute_antic required %d iterations\n", num_iterations);
} }
/* Get the expressions represented by value VAL. */
static value_set_t
get_expr_set (tree val)
{
var_ann_t va = var_ann (val);
return va->expr_set;
}
/* Find a leader for an expression, or generate one using /* Find a leader for an expression, or generate one using
create_expression_by_pieces if it's ANTIC but create_expression_by_pieces if it's ANTIC but
...@@ -1364,7 +1160,7 @@ find_or_generate_expression (basic_block block, tree expr, tree stmts) ...@@ -1364,7 +1160,7 @@ find_or_generate_expression (basic_block block, tree expr, tree stmts)
not really . */ not really . */
if (genop == NULL) if (genop == NULL)
{ {
genop = get_expr_set (expr)->head->expr; genop = VALUE_HANDLE_EXPR_SET (expr)->head->expr;
if (TREE_CODE_CLASS (TREE_CODE (genop)) != '1' if (TREE_CODE_CLASS (TREE_CODE (genop)) != '1'
&& TREE_CODE_CLASS (TREE_CODE (genop)) != '2') && TREE_CODE_CLASS (TREE_CODE (genop)) != '2')
abort (); abort ();
...@@ -1445,7 +1241,7 @@ create_expression_by_pieces (basic_block block, tree expr, tree stmts) ...@@ -1445,7 +1241,7 @@ create_expression_by_pieces (basic_block block, tree expr, tree stmts)
} }
v = get_value_handle (expr); v = get_value_handle (expr);
add (value_table, name, v); vn_add (name, v);
insert_into_set (NEW_SETS (block), name); insert_into_set (NEW_SETS (block), name);
value_insert_into_set (AVAIL_OUT (block), name); value_insert_into_set (AVAIL_OUT (block), name);
if (dump_file && (dump_flags & TDF_DETAILS)) if (dump_file && (dump_flags & TDF_DETAILS))
...@@ -1610,7 +1406,7 @@ insert_aux (basic_block block) ...@@ -1610,7 +1406,7 @@ insert_aux (basic_block block)
temp = create_tmp_var (type, "prephitmp"); temp = create_tmp_var (type, "prephitmp");
add_referenced_tmp_var (temp); add_referenced_tmp_var (temp);
temp = create_phi_node (temp, block); temp = create_phi_node (temp, block);
add (value_table, PHI_RESULT (temp), val); vn_add (PHI_RESULT (temp), val);
#if 0 #if 0
if (!set_contains_value (AVAIL_OUT (block), val)) if (!set_contains_value (AVAIL_OUT (block), val))
...@@ -1679,17 +1475,19 @@ insert (void) ...@@ -1679,17 +1475,19 @@ insert (void)
fprintf (dump_file, "insert required %d iterations\n", num_iterations); fprintf (dump_file, "insert required %d iterations\n", num_iterations);
} }
/* Return true if EXPR has no defining statement in this procedure, /* Return true if EXPR has no defining statement in this procedure,
*AND* isn't a live-on-entry parameter. */ *AND* isn't a live-on-entry parameter. */
static bool static bool
is_undefined_value (tree expr) is_undefined_value (tree expr)
{ {
#ifdef ENABLE_CHECKING #ifdef ENABLE_CHECKING
/* We should never be handed DECL's */ /* We should never be handed DECL's */
if (DECL_P (expr)) if (DECL_P (expr))
abort (); abort ();
#endif #endif
if (TREE_CODE (expr) == SSA_NAME) if (TREE_CODE (expr) == SSA_NAME)
{ {
/* XXX: Is this the correct test? */ /* XXX: Is this the correct test? */
...@@ -1698,6 +1496,7 @@ is_undefined_value (tree expr) ...@@ -1698,6 +1496,7 @@ is_undefined_value (tree expr)
if (IS_EMPTY_STMT (SSA_NAME_DEF_STMT (expr))) if (IS_EMPTY_STMT (SSA_NAME_DEF_STMT (expr)))
return true; return true;
} }
return false; return false;
} }
...@@ -1731,7 +1530,7 @@ compute_avail (basic_block block) ...@@ -1731,7 +1530,7 @@ compute_avail (basic_block block)
{ {
tree val; tree val;
tree def = default_def (param); tree def = default_def (param);
val = lookup_or_add (value_table, def); val = vn_lookup_or_add (def);
insert_into_set (TMP_GEN (block), def); insert_into_set (TMP_GEN (block), def);
value_insert_into_set (AVAIL_OUT (block), def); value_insert_into_set (AVAIL_OUT (block), def);
} }
...@@ -1746,6 +1545,7 @@ compute_avail (basic_block block) ...@@ -1746,6 +1545,7 @@ compute_avail (basic_block block)
dom = get_immediate_dominator (CDI_DOMINATORS, block); dom = get_immediate_dominator (CDI_DOMINATORS, block);
if (dom) if (dom)
set_copy (AVAIL_OUT (block), AVAIL_OUT (dom)); set_copy (AVAIL_OUT (block), AVAIL_OUT (dom));
for (phi = phi_nodes (block); phi; phi = PHI_CHAIN (phi)) for (phi = phi_nodes (block); phi; phi = PHI_CHAIN (phi))
{ {
/* Ignore virtual PHIs until we can do PRE on expressions /* Ignore virtual PHIs until we can do PRE on expressions
...@@ -1753,7 +1553,7 @@ compute_avail (basic_block block) ...@@ -1753,7 +1553,7 @@ compute_avail (basic_block block)
if (!is_gimple_reg (SSA_NAME_VAR (PHI_RESULT (phi)))) if (!is_gimple_reg (SSA_NAME_VAR (PHI_RESULT (phi))))
continue; continue;
lookup_or_add (value_table, PHI_RESULT (phi)); vn_lookup_or_add (PHI_RESULT (phi));
value_insert_into_set (AVAIL_OUT (block), PHI_RESULT (phi)); value_insert_into_set (AVAIL_OUT (block), PHI_RESULT (phi));
insert_into_set (PHI_GEN (block), PHI_RESULT (phi)); insert_into_set (PHI_GEN (block), PHI_RESULT (phi));
} }
...@@ -1773,7 +1573,7 @@ compute_avail (basic_block block) ...@@ -1773,7 +1573,7 @@ compute_avail (basic_block block)
for (j = 0; j < NUM_DEFS (STMT_DEF_OPS (stmt)); j++) for (j = 0; j < NUM_DEFS (STMT_DEF_OPS (stmt)); j++)
{ {
tree def = DEF_OP (STMT_DEF_OPS (stmt), j); tree def = DEF_OP (STMT_DEF_OPS (stmt), j);
lookup_or_add (value_table, def); vn_lookup_or_add (def);
insert_into_set (TMP_GEN (block), def); insert_into_set (TMP_GEN (block), def);
value_insert_into_set (AVAIL_OUT (block), def); value_insert_into_set (AVAIL_OUT (block), def);
} }
...@@ -1782,7 +1582,7 @@ compute_avail (basic_block block) ...@@ -1782,7 +1582,7 @@ compute_avail (basic_block block)
tree use = USE_OP (STMT_USE_OPS (stmt), j); tree use = USE_OP (STMT_USE_OPS (stmt), j);
if (TREE_CODE (use) == SSA_NAME) if (TREE_CODE (use) == SSA_NAME)
{ {
lookup_or_add (value_table, use); vn_lookup_or_add (use);
insert_into_set (TMP_GEN (block), use); insert_into_set (TMP_GEN (block), use);
value_insert_into_set (AVAIL_OUT (block), use); value_insert_into_set (AVAIL_OUT (block), use);
} }
...@@ -1801,7 +1601,7 @@ compute_avail (basic_block block) ...@@ -1801,7 +1601,7 @@ compute_avail (basic_block block)
STRIP_USELESS_TYPE_CONVERSION (op1); STRIP_USELESS_TYPE_CONVERSION (op1);
if (is_gimple_min_invariant (op1)) if (is_gimple_min_invariant (op1))
{ {
add (value_table, op0, lookup_or_add (value_table, op1)); vn_add (op0, vn_lookup_or_add (op1));
insert_into_set (TMP_GEN (block), op0); insert_into_set (TMP_GEN (block), op0);
value_insert_into_set (AVAIL_OUT (block), op0); value_insert_into_set (AVAIL_OUT (block), op0);
} }
...@@ -1812,15 +1612,15 @@ compute_avail (basic_block block) ...@@ -1812,15 +1612,15 @@ compute_avail (basic_block block)
tree newt; tree newt;
bop1 = TREE_OPERAND (op1, 0); bop1 = TREE_OPERAND (op1, 0);
bop2 = TREE_OPERAND (op1, 1); bop2 = TREE_OPERAND (op1, 1);
val1 = lookup_or_add (value_table, bop1); val1 = vn_lookup_or_add (bop1);
val2 = lookup_or_add (value_table, bop2); val2 = vn_lookup_or_add (bop2);
newt = pool_alloc (binary_node_pool); newt = pool_alloc (binary_node_pool);
memcpy (newt, op1, tree_size (op1)); memcpy (newt, op1, tree_size (op1));
TREE_OPERAND (newt, 0) = val1; TREE_OPERAND (newt, 0) = val1;
TREE_OPERAND (newt, 1) = val2; TREE_OPERAND (newt, 1) = val2;
val = lookup_or_add (value_table, newt); val = vn_lookup_or_add (newt);
add (value_table, op0, val); vn_add (op0, val);
if (!is_undefined_value (bop1)) if (!is_undefined_value (bop1))
value_insert_into_set (EXP_GEN (block), bop1); value_insert_into_set (EXP_GEN (block), bop1);
if (!is_undefined_value (bop2)) if (!is_undefined_value (bop2))
...@@ -1836,12 +1636,12 @@ compute_avail (basic_block block) ...@@ -1836,12 +1636,12 @@ compute_avail (basic_block block)
tree val, val1; tree val, val1;
tree newt; tree newt;
uop = TREE_OPERAND (op1, 0); uop = TREE_OPERAND (op1, 0);
val1 = lookup_or_add (value_table, uop); val1 = vn_lookup_or_add (uop);
newt = pool_alloc (unary_node_pool); newt = pool_alloc (unary_node_pool);
memcpy (newt, op1, tree_size (op1)); memcpy (newt, op1, tree_size (op1));
TREE_OPERAND (newt, 0) = val1; TREE_OPERAND (newt, 0) = val1;
val = lookup_or_add (value_table, newt); val = vn_lookup_or_add (newt);
add (value_table, op0, val); vn_add (op0, val);
if (!is_undefined_value (uop)) if (!is_undefined_value (uop))
value_insert_into_set (EXP_GEN (block), uop); value_insert_into_set (EXP_GEN (block), uop);
value_insert_into_set (EXP_GEN (block), newt); value_insert_into_set (EXP_GEN (block), newt);
...@@ -1850,8 +1650,8 @@ compute_avail (basic_block block) ...@@ -1850,8 +1650,8 @@ compute_avail (basic_block block)
} }
else if (TREE_CODE (op1) == SSA_NAME) else if (TREE_CODE (op1) == SSA_NAME)
{ {
tree val = lookup_or_add (value_table, op1); tree val = vn_lookup_or_add (op1);
add (value_table, op0, val); vn_add (op0, val);
if (!is_undefined_value (op1)) if (!is_undefined_value (op1))
value_insert_into_set (EXP_GEN (block), op1); value_insert_into_set (EXP_GEN (block), op1);
insert_into_set (TMP_GEN (block), op0); insert_into_set (TMP_GEN (block), op0);
...@@ -1863,7 +1663,7 @@ compute_avail (basic_block block) ...@@ -1863,7 +1663,7 @@ compute_avail (basic_block block)
for (j = 0; j < NUM_DEFS (STMT_DEF_OPS (stmt)); j++) for (j = 0; j < NUM_DEFS (STMT_DEF_OPS (stmt)); j++)
{ {
tree def = DEF_OP (STMT_DEF_OPS (stmt), j); tree def = DEF_OP (STMT_DEF_OPS (stmt), j);
lookup_or_add (value_table, def); vn_lookup_or_add (def);
insert_into_set (TMP_GEN (block), def); insert_into_set (TMP_GEN (block), def);
value_insert_into_set (AVAIL_OUT (block), def); value_insert_into_set (AVAIL_OUT (block), def);
if (def != op0) if (def != op0)
...@@ -1874,7 +1674,7 @@ compute_avail (basic_block block) ...@@ -1874,7 +1674,7 @@ compute_avail (basic_block block)
tree use = USE_OP (STMT_USE_OPS (stmt), j); tree use = USE_OP (STMT_USE_OPS (stmt), j);
if (TREE_CODE (use) == SSA_NAME) if (TREE_CODE (use) == SSA_NAME)
{ {
lookup_or_add (value_table, use); vn_lookup_or_add (use);
insert_into_set (TMP_GEN (block), use); insert_into_set (TMP_GEN (block), use);
value_insert_into_set (AVAIL_OUT (block), use); value_insert_into_set (AVAIL_OUT (block), use);
} }
...@@ -1887,7 +1687,7 @@ compute_avail (basic_block block) ...@@ -1887,7 +1687,7 @@ compute_avail (basic_block block)
for (j = 0; j < NUM_DEFS (STMT_DEF_OPS (stmt)); j++) for (j = 0; j < NUM_DEFS (STMT_DEF_OPS (stmt)); j++)
{ {
tree def = DEF_OP (STMT_DEF_OPS (stmt), j); tree def = DEF_OP (STMT_DEF_OPS (stmt), j);
lookup_or_add (value_table, def); vn_lookup_or_add (def);
insert_into_set (TMP_GEN (block), def); insert_into_set (TMP_GEN (block), def);
value_insert_into_set (AVAIL_OUT (block), def); value_insert_into_set (AVAIL_OUT (block), def);
} }
...@@ -1896,7 +1696,7 @@ compute_avail (basic_block block) ...@@ -1896,7 +1696,7 @@ compute_avail (basic_block block)
tree use = USE_OP (STMT_USE_OPS (stmt), j); tree use = USE_OP (STMT_USE_OPS (stmt), j);
if (TREE_CODE (use) == SSA_NAME) if (TREE_CODE (use) == SSA_NAME)
{ {
lookup_or_add (value_table, use); vn_lookup_or_add (use);
insert_into_set (TMP_GEN (block), use); insert_into_set (TMP_GEN (block), use);
value_insert_into_set (AVAIL_OUT (block), use); value_insert_into_set (AVAIL_OUT (block), use);
} }
...@@ -1904,13 +1704,14 @@ compute_avail (basic_block block) ...@@ -1904,13 +1704,14 @@ compute_avail (basic_block block)
} }
} }
} }
for (son = first_dom_son (CDI_DOMINATORS, block); for (son = first_dom_son (CDI_DOMINATORS, block);
son; son;
son = next_dom_son (CDI_DOMINATORS, son)) son = next_dom_son (CDI_DOMINATORS, son))
compute_avail (son); compute_avail (son);
} }
/* Eliminate fully redundant computations. */ /* Eliminate fully redundant computations. */
static void static void
...@@ -1931,6 +1732,7 @@ eliminate (void) ...@@ -1931,6 +1732,7 @@ eliminate (void)
|| NUM_V_MAY_DEFS (STMT_V_MAY_DEF_OPS (stmt)) || NUM_V_MAY_DEFS (STMT_V_MAY_DEF_OPS (stmt))
|| stmt_ann (stmt)->has_volatile_ops) || stmt_ann (stmt)->has_volatile_ops)
continue; continue;
/* Lookup the RHS of the expression, see if we have an /* Lookup the RHS of the expression, see if we have an
available computation for it. If so, replace the RHS with available computation for it. If so, replace the RHS with
the available computation. */ the available computation. */
...@@ -1945,8 +1747,8 @@ eliminate (void) ...@@ -1945,8 +1747,8 @@ eliminate (void)
|| (TREE_CODE_CLASS (TREE_CODE (expr)) != '2' || (TREE_CODE_CLASS (TREE_CODE (expr)) != '2'
&& TREE_CODE_CLASS (TREE_CODE (expr)) != '1')) && TREE_CODE_CLASS (TREE_CODE (expr)) != '1'))
continue; continue;
sprime = find_leader (AVAIL_OUT (b),
lookup (value_table, t)); sprime = find_leader (AVAIL_OUT (b), vn_lookup (t));
if (sprime if (sprime
&& sprime != t && sprime != t
&& may_propagate_copy (sprime, TREE_OPERAND (stmt, 1))) && may_propagate_copy (sprime, TREE_OPERAND (stmt, 1)))
...@@ -1965,11 +1767,11 @@ eliminate (void) ...@@ -1965,11 +1767,11 @@ eliminate (void)
modify_stmt (stmt); modify_stmt (stmt);
} }
} }
} }
} }
} }
/* Main entry point to the SSA-PRE pass. /* Main entry point to the SSA-PRE pass.
PHASE indicates which dump file from the DUMP_FILES array to use when PHASE indicates which dump file from the DUMP_FILES array to use when
...@@ -1980,7 +1782,6 @@ execute_pre (void) ...@@ -1980,7 +1782,6 @@ execute_pre (void)
{ {
size_t tsize; size_t tsize;
basic_block bb; basic_block bb;
pre_uid = num_referenced_vars;
memset (&pre_stats, 0, sizeof (pre_stats)); memset (&pre_stats, 0, sizeof (pre_stats));
FOR_ALL_BB (bb) FOR_ALL_BB (bb)
{ {
...@@ -1989,8 +1790,6 @@ execute_pre (void) ...@@ -1989,8 +1790,6 @@ execute_pre (void)
phi_translate_table = htab_create (511, expr_pred_trans_hash, phi_translate_table = htab_create (511, expr_pred_trans_hash,
expr_pred_trans_eq, expr_pred_trans_eq,
free); free);
value_table = htab_create (511, val_expr_pair_hash,
val_expr_pair_expr_eq, free);
value_set_pool = create_alloc_pool ("Value sets", value_set_pool = create_alloc_pool ("Value sets",
sizeof (struct value_set), 30); sizeof (struct value_set), 30);
value_set_node_pool = create_alloc_pool ("Value set nodes", value_set_node_pool = create_alloc_pool ("Value set nodes",
...@@ -2048,7 +1847,6 @@ execute_pre (void) ...@@ -2048,7 +1847,6 @@ execute_pre (void)
free_alloc_pool (value_set_node_pool); free_alloc_pool (value_set_node_pool);
free_alloc_pool (binary_node_pool); free_alloc_pool (binary_node_pool);
free_alloc_pool (unary_node_pool); free_alloc_pool (unary_node_pool);
htab_delete (value_table);
htab_delete (phi_translate_table); htab_delete (phi_translate_table);
FOR_ALL_BB (bb) FOR_ALL_BB (bb)
......
...@@ -497,6 +497,7 @@ init_tree_ssa (void) ...@@ -497,6 +497,7 @@ init_tree_ssa (void)
init_ssa_operands (); init_ssa_operands ();
init_ssanames (); init_ssanames ();
init_phinodes (); init_phinodes ();
vn_init ();
global_var = NULL_TREE; global_var = NULL_TREE;
aliases_computed_p = false; aliases_computed_p = false;
} }
...@@ -527,6 +528,7 @@ delete_tree_ssa (void) ...@@ -527,6 +528,7 @@ delete_tree_ssa (void)
fini_ssanames (); fini_ssanames ();
fini_phinodes (); fini_phinodes ();
fini_ssa_operands (); fini_ssa_operands ();
vn_delete ();
global_var = NULL_TREE; global_var = NULL_TREE;
BITMAP_XFREE (call_clobbered_vars); BITMAP_XFREE (call_clobbered_vars);
......
/* Value Numbering routines for tree expressions.
Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
Contributed by Daniel Berlin <dan@dberlin.org>, Steven Bosscher
<stevenb@suse.de> and Diego Novillo <dnovillo@redhat.com>
This file is part of GCC.
GCC 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.
GCC 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 GCC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "tm.h"
#include "ggc.h"
#include "tree.h"
#include "tree-flow.h"
#include "hashtab.h"
#include "langhooks.h"
#include "tree-pass.h"
#include "tree-dump.h"
#include "diagnostic.h"
/* The value table that maps expressions to values. */
static htab_t value_table;
/* Map expressions to values. These are simple pairs of expressions
and the values they represent. To find the value represented by
an expression, we use a hash table where the elements are {e,v}
pairs, and the expression is the key. */
typedef struct val_expr_pair_d
{
tree v, e;
hashval_t hashcode;
} *val_expr_pair_t;
static void set_value_handle (tree e, tree v);
/* Create and return a new value handle node of type TYPE. */
static tree
make_value_handle (tree type)
{
static unsigned int id = 0;
tree vh;
vh = build0 (VALUE_HANDLE, type);
VALUE_HANDLE_ID (vh) = id++;
return vh;
}
/* Given an expression or statement P, compute a hash value number using the
code of the expression and its real operands. */
hashval_t
vn_compute (tree expr, hashval_t val)
{
val = iterative_hash_expr (expr, val);
return val;
}
/* Compare two expressions E1 and E2 and return true if they are
equal. */
bool
expressions_equal_p (tree e1, tree e2)
{
tree te1, te2;
if (e1 == e2)
return true;
te1 = TREE_TYPE (e1);
te2 = TREE_TYPE (e2);
if (TREE_CODE (e1) == TREE_CODE (e2)
&& (te1 == te2 || lang_hooks.types_compatible_p (te1, te2))
&& operand_equal_p (e1, e2, 0))
return true;
return false;
}
/* Hash a {v,e} pair that is pointed to by P.
The hashcode is cached in the val_expr_pair, so we just return
that. */
static hashval_t
val_expr_pair_hash (const void *p)
{
const val_expr_pair_t ve = (val_expr_pair_t) p;
return ve->hashcode;
}
/* Given two val_expr_pair_t's, return true if they represent the same
expression, false otherwise.
P1 and P2 should point to the val_expr_pair_t's to be compared. */
static int
val_expr_pair_expr_eq (const void *p1, const void *p2)
{
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 true;
return false;
}
/* Set the value handle for expression E to value V */
static void
set_value_handle (tree e, tree v)
{
if (TREE_CODE (e) == SSA_NAME)
SSA_NAME_VALUE (e) = v;
else if (EXPR_P (e) || DECL_P (e))
get_tree_ann (e)->common.value_handle = v;
else if (TREE_CODE_CLASS (TREE_CODE (e)) == 'c')
/* Do nothing. Constants are their own value handles. */
;
else
abort ();
}
/* Insert E into VALUE_TABLE with value V, and add expression E to the
value set for value V. */
void
vn_add (tree e, tree v)
{
void **slot;
val_expr_pair_t new_pair = xmalloc (sizeof (struct val_expr_pair_d));
new_pair->e = e;
new_pair->v = v;
new_pair->hashcode = vn_compute (e, 0);
slot = htab_find_slot_with_hash (value_table, new_pair, new_pair->hashcode,
INSERT);
if (*slot)
free (*slot);
*slot = (void *) new_pair;
set_value_handle (e, v);
add_to_value (v, e);
}
/* Search in VALUE_TABLE for an existing instance of expression E, and
return its value, or NULL if none has been set. */
tree
vn_lookup (tree e)
{
void **slot;
struct val_expr_pair_d vep = {NULL, NULL, 0};
if (TREE_CODE_CLASS (TREE_CODE (e)) == 'c')
return e;
vep.e = e;
vep.hashcode = vn_compute (e, 0);
slot = htab_find_slot_with_hash (value_table, &vep, vep.hashcode, NO_INSERT);
if (!slot)
return NULL_TREE;
else
return ((val_expr_pair_t) *slot)->v;
}
/* Like vn_lookup, but creates a new value for expression E if E doesn't
already have a value. Return the existing/created value for E. */
tree
vn_lookup_or_add (tree e)
{
tree x = vn_lookup (e);
if (x == NULL_TREE)
{
tree v = make_value_handle (TREE_TYPE (e));
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, e, dump_flags);
fprintf (dump_file, "\n");
}
vn_add (e, v);
x = v;
}
set_value_handle (e, x);
return x;
}
/* 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
handle associated, it generates and returns a new one. */
tree
get_value_handle (tree expr)
{
if (TREE_CODE (expr) == SSA_NAME)
return SSA_NAME_VALUE (expr);
else if (TREE_CODE_CLASS (TREE_CODE (expr)) == 'c')
return expr;
else if (EXPR_P (expr) || DECL_P (expr))
{
tree_ann_t ann = tree_ann (expr);
return ((ann) ? ann->common.value_handle : NULL_TREE);
}
abort ();
}
/* Initialize data structures used in value numbering. */
void
vn_init (void)
{
value_table = htab_create (511, val_expr_pair_hash,
val_expr_pair_expr_eq, free);
}
/* Delete data used for value numbering. */
void
vn_delete (void)
{
htab_delete (value_table);
value_table = NULL;
}
...@@ -196,6 +196,7 @@ tree_size (tree node) ...@@ -196,6 +196,7 @@ tree_size (tree node)
case STATEMENT_LIST: return sizeof (struct tree_statement_list); case STATEMENT_LIST: return sizeof (struct tree_statement_list);
case BLOCK: return sizeof (struct tree_block); case BLOCK: return sizeof (struct tree_block);
case VALUE_HANDLE: return sizeof (struct tree_value_handle);
default: default:
return lang_hooks.tree_size (code); return lang_hooks.tree_size (code);
...@@ -1497,6 +1498,7 @@ tree_node_structure (tree t) ...@@ -1497,6 +1498,7 @@ tree_node_structure (tree t)
case PLACEHOLDER_EXPR: return TS_COMMON; case PLACEHOLDER_EXPR: return TS_COMMON;
case STATEMENT_LIST: return TS_STATEMENT_LIST; case STATEMENT_LIST: return TS_STATEMENT_LIST;
case BLOCK: return TS_BLOCK; case BLOCK: return TS_BLOCK;
case VALUE_HANDLE: return TS_VALUE_HANDLE;
default: default:
abort (); abort ();
...@@ -3851,7 +3853,8 @@ iterative_hash_expr (tree t, hashval_t val) ...@@ -3851,7 +3853,8 @@ iterative_hash_expr (tree t, hashval_t val)
code = TREE_CODE (t); code = TREE_CODE (t);
class = TREE_CODE_CLASS (code); class = TREE_CODE_CLASS (code);
if (class == 'd') if (class == 'd'
|| TREE_CODE (t) == VALUE_HANDLE)
{ {
/* Decls we can just compare by pointer. */ /* Decls we can just compare by pointer. */
val = iterative_hash_object (t, val); val = iterative_hash_object (t, val);
......
...@@ -899,6 +899,12 @@ DEFTREECODE (EH_FILTER_EXPR, "eh_filter_expr", 's', 2) ...@@ -899,6 +899,12 @@ DEFTREECODE (EH_FILTER_EXPR, "eh_filter_expr", 's', 2)
Use the interface in tree-iterator.h to access this node. */ Use the interface in tree-iterator.h to access this node. */
DEFTREECODE (STATEMENT_LIST, "statement_list", 'x', 0) DEFTREECODE (STATEMENT_LIST, "statement_list", 'x', 0)
/* Value handles. Artificial nodes to represent expressions in
partial redundancy elimination (tree-ssa-pre.c). These nodes are
used for expression canonicalization. If two expressions compute
the same value, they will be assigned the same value handle. */
DEFTREECODE (VALUE_HANDLE, "value_handle", 'x', 0)
/* /*
Local variables: Local variables:
mode:c mode:c
......
...@@ -2234,6 +2234,28 @@ struct tree_statement_list ...@@ -2234,6 +2234,28 @@ struct tree_statement_list
struct tree_statement_list_node *head; struct tree_statement_list_node *head;
struct tree_statement_list_node *tail; struct tree_statement_list_node *tail;
}; };
#define VALUE_HANDLE_ID(NODE) \
(VALUE_HANDLE_CHECK (NODE)->value_handle.id)
#define VALUE_HANDLE_EXPR_SET(NODE) \
(VALUE_HANDLE_CHECK (NODE)->value_handle.expr_set)
/* Defined and used in tree-ssa-pre.c. */
struct value_set;
struct tree_value_handle GTY(())
{
struct tree_common common;
/* The set of expressions represented by this handle. */
struct value_set * GTY ((skip)) expr_set;
/* Unique ID for this value handle. IDs are handed out in a
conveniently dense form starting at 0, so that we can make
bitmaps of value handles. */
unsigned int id;
};
enum tree_node_structure_enum { enum tree_node_structure_enum {
TS_COMMON, TS_COMMON,
...@@ -2252,6 +2274,7 @@ enum tree_node_structure_enum { ...@@ -2252,6 +2274,7 @@ enum tree_node_structure_enum {
TS_PHI_NODE, TS_PHI_NODE,
TS_BLOCK, TS_BLOCK,
TS_STATEMENT_LIST, TS_STATEMENT_LIST,
TS_VALUE_HANDLE,
LAST_TS_ENUM LAST_TS_ENUM
}; };
...@@ -2278,6 +2301,7 @@ union tree_node GTY ((ptr_alias (union lang_tree_node), ...@@ -2278,6 +2301,7 @@ union tree_node GTY ((ptr_alias (union lang_tree_node),
struct tree_phi_node GTY ((tag ("TS_PHI_NODE"))) phi; struct tree_phi_node GTY ((tag ("TS_PHI_NODE"))) phi;
struct tree_block GTY ((tag ("TS_BLOCK"))) block; struct tree_block GTY ((tag ("TS_BLOCK"))) block;
struct tree_statement_list GTY ((tag ("TS_STATEMENT_LIST"))) stmt_list; struct tree_statement_list GTY ((tag ("TS_STATEMENT_LIST"))) stmt_list;
struct tree_value_handle GTY ((tag ("TS_VALUE_HANDLE"))) value_handle;
}; };
/* Standard named or nameless data types of the C compiler. */ /* Standard named or nameless data types of the C compiler. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment