Fix PR tree-optimization/32540 Fix PR tree-optimization/31651

2007-06-30  Daniel Berlin  <dberlin@dberlin.org>
	
	Fix PR tree-optimization/32540
	Fix PR tree-optimization/31651

	* tree-ssa-sccvn.c: New file.

	* tree-ssa-sccvn.h: Ditto.
	
	* tree-vn.c: Include tree-ssa-sccvn.h
	(val_expr_paid_d): Removed.
	(value_table): Ditto.
	(vn_compute): Ditto.
	(val_expr_pair_hash): Ditto.
	(val_expr_pair_expr_eq): Ditto.
	(copy_vuses_from_stmt): Ditto.
	(vn_delete): Ditto.
	(vn_init): Ditto.
	(shared_vuses_from_stmt): Ditto.
	(print_creation_to_file): Moved up.
	(sort_vuses): Ditto.
	(sort_vuses_heap): Ditto.
	(set_value_handle): Make non-static.
	(make_value_handle): Ditto.
	(vn_add): Rewritten to use sccvn lookups.
	(vn_add_with_vuses): Ditto.
	(vn_lookup): Ditto (and second argument removed).
	(vn_lookup_with_vuses): Ditto.
	(vn_lookup_or_add): Ditto (and second argument removed);
	(vn_lookup_or_add_with_vuses): Ditto.
	(vn_lookup_with_stmt): New.
	(vn_lookup_or_add_with_stmt): Ditto.
	(create_value_handle_for_expr): Ditto.

	* tree-ssa-pre.c: Include tree-ssa-sccvn.h.
	(seen_during_translate): New function.
	(phi_trans_lookup): Use iterative_hash_expr, not vn_compute.
	(phi_trans_add): Ditto.
	(constant_expr_p): FIELD_DECL is always constant.
	(phi_translate_1): Renamed from phi_translate, add seen bitmap.
	Use constant_expr_p.
	Avoid infinite recursion on mutually valued expressions.
	Change callers of vn_lookup_or_add.
	(phi_translate): New function.
	(compute_antic_safe): Allow phi nodes.
	(create_component_ref_by_pieces): Update for FIELD_DECL change.
	(find_or_generate_expression): Rewrite slightly.
	(create_expression_by_pieces): Updated for vn_lookup_or_add
	change.
	Update VN_INFO for new names.
	(insert_into_preds_of_block): Update for new names.
	(add_to_exp_gen): New function.
	(add_to_sets): Use vn_lookup_or_add_with_stmt.
	(find_existing_value_expr): Rewrite to changed vn_lookup.
	(create_value_expr_from): Ditto, and use add_to_exp_gen.
	(try_look_through_load): Removed.
	(try_combine_conversion): Ditto.
	(get_sccvn_value): New function.
	(make_values_for_phi): Ditto.
	(make_values_for_stmt): Ditto.
	(compute_avail): Rewritten for vn_lookup_or_add changes and to use
	SCCVN.
	(init_pre): Update for SCCVN changes.
	(fini_pre): Ditto.
	(execute_pre): Ditto.

	* tree-flow.h (make_value_handle): Declare.
	(set_value_handle): Ditto.
	(sort_vuses_heap): Ditto.
	(vn_lookup_or_add_with_stmt): Ditto.
	(vn_lookup_with_stmt): Ditto.
	(vn_compute): Remove.
	(vn_init): Ditto.
	(vn_delete): Ditto.
	(vn_lookup): Update arguments.

	* Makefile.in (tree-ssa-pre.o): Add tree-ssa-sccvn.h
	(tree-vn.o): Ditto.
	(tree-ssa-sccvn.o): New.
	(OBJS-common): Add tree-ssa-sccvn.o

From-SVN: r126149
This commit is contained in:
Daniel Berlin 2007-06-30 14:15:26 +00:00 committed by Daniel Berlin
parent 11147af397
commit 89fb70a345
16 changed files with 2904 additions and 548 deletions

View File

@ -1,3 +1,84 @@
2007-06-30 Daniel Berlin <dberlin@dberlin.org>
Fix PR tree-optimization/32540
Fix PR tree-optimization/31651
* tree-ssa-sccvn.c: New file.
* tree-ssa-sccvn.h: Ditto.
* tree-vn.c: Include tree-ssa-sccvn.h
(val_expr_paid_d): Removed.
(value_table): Ditto.
(vn_compute): Ditto.
(val_expr_pair_hash): Ditto.
(val_expr_pair_expr_eq): Ditto.
(copy_vuses_from_stmt): Ditto.
(vn_delete): Ditto.
(vn_init): Ditto.
(shared_vuses_from_stmt): Ditto.
(print_creation_to_file): Moved up.
(sort_vuses): Ditto.
(sort_vuses_heap): Ditto.
(set_value_handle): Make non-static.
(make_value_handle): Ditto.
(vn_add): Rewritten to use sccvn lookups.
(vn_add_with_vuses): Ditto.
(vn_lookup): Ditto (and second argument removed).
(vn_lookup_with_vuses): Ditto.
(vn_lookup_or_add): Ditto (and second argument removed);
(vn_lookup_or_add_with_vuses): Ditto.
(vn_lookup_with_stmt): New.
(vn_lookup_or_add_with_stmt): Ditto.
(create_value_handle_for_expr): Ditto.
* tree-ssa-pre.c: Include tree-ssa-sccvn.h.
(seen_during_translate): New function.
(phi_trans_lookup): Use iterative_hash_expr, not vn_compute.
(phi_trans_add): Ditto.
(constant_expr_p): FIELD_DECL is always constant.
(phi_translate_1): Renamed from phi_translate, add seen bitmap.
Use constant_expr_p.
Avoid infinite recursion on mutually valued expressions.
Change callers of vn_lookup_or_add.
(phi_translate): New function.
(compute_antic_safe): Allow phi nodes.
(create_component_ref_by_pieces): Update for FIELD_DECL change.
(find_or_generate_expression): Rewrite slightly.
(create_expression_by_pieces): Updated for vn_lookup_or_add
change.
Update VN_INFO for new names.
(insert_into_preds_of_block): Update for new names.
(add_to_exp_gen): New function.
(add_to_sets): Use vn_lookup_or_add_with_stmt.
(find_existing_value_expr): Rewrite to changed vn_lookup.
(create_value_expr_from): Ditto, and use add_to_exp_gen.
(try_look_through_load): Removed.
(try_combine_conversion): Ditto.
(get_sccvn_value): New function.
(make_values_for_phi): Ditto.
(make_values_for_stmt): Ditto.
(compute_avail): Rewritten for vn_lookup_or_add changes and to use
SCCVN.
(init_pre): Update for SCCVN changes.
(fini_pre): Ditto.
(execute_pre): Ditto.
* tree-flow.h (make_value_handle): Declare.
(set_value_handle): Ditto.
(sort_vuses_heap): Ditto.
(vn_lookup_or_add_with_stmt): Ditto.
(vn_lookup_with_stmt): Ditto.
(vn_compute): Remove.
(vn_init): Ditto.
(vn_delete): Ditto.
(vn_lookup): Update arguments.
* Makefile.in (tree-ssa-pre.o): Add tree-ssa-sccvn.h
(tree-vn.o): Ditto.
(tree-ssa-sccvn.o): New.
(OBJS-common): Add tree-ssa-sccvn.o
2007-06-30 Manuel Lopez-Ibanez <manu@gcc.gnu.org>
PR c/4076

View File

@ -1137,6 +1137,7 @@ OBJS-common = \
tree-ssa-pre.o \
tree-ssa-propagate.o \
tree-ssa-reassoc.o \
tree-ssa-sccvn.o \
tree-ssa-sink.o \
tree-ssa-structalias.o \
tree-ssa-ter.o \
@ -2006,10 +2007,15 @@ tree-ssa-pre.o : tree-ssa-pre.c $(TREE_FLOW_H) $(CONFIG_H) \
$(SYSTEM_H) $(TREE_H) $(GGC_H) $(DIAGNOSTIC_H) $(TIMEVAR_H) \
$(TM_H) coretypes.h $(TREE_DUMP_H) tree-pass.h $(FLAGS_H) $(CFGLOOP_H) \
alloc-pool.h $(BASIC_BLOCK_H) bitmap.h $(HASHTAB_H) $(TREE_GIMPLE_H) \
$(TREE_INLINE_H) tree-iterator.h
$(TREE_INLINE_H) tree-iterator.h tree-ssa-sccvn.h
tree-ssa-sccvn.o : tree-ssa-sccvn.c $(TREE_FLOW_H) $(CONFIG_H) \
$(SYSTEM_H) $(TREE_H) $(GGC_H) $(DIAGNOSTIC_H) $(TIMEVAR_H) \
$(TM_H) coretypes.h $(TREE_DUMP_H) tree-pass.h $(FLAGS_H) $(CFGLOOP_H) \
alloc-pool.h $(BASIC_BLOCK_H) bitmap.h $(HASHTAB_H) $(TREE_GIMPLE_H) \
$(TREE_INLINE_H) tree-iterator.h tree-ssa-sccvn.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_DUMP_H) $(DIAGNOSTIC_H) tree-ssa-sccvn.h
tree-vrp.o : tree-vrp.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
$(TREE_FLOW_H) tree-pass.h $(TREE_DUMP_H) $(DIAGNOSTIC_H) $(GGC_H) \
$(BASIC_BLOCK_H) tree-ssa-propagate.h $(FLAGS_H) $(TREE_DUMP_H) \

View File

@ -11,6 +11,6 @@ int f(int *a)
return *c + t;
}
/* { dg-final { scan-tree-dump "Replaced \\\(int \\\*\\\) b_.*with a_" "fre" } } */
/* { dg-final { scan-tree-dump "Replaced \\\*c_.*with t_" "fre" } } */
/* { dg-final { scan-tree-dump "Replaced \\\(int \\\*\\\) b_.*with a_" "fre" { xfail *-*-* } } } */
/* { dg-final { scan-tree-dump "Replaced \\\*c_.*with t_" "fre" { xfail *-*-* } } } */
/* { dg-final { cleanup-tree-dump "fre" } } */

View File

@ -11,5 +11,5 @@ foo (int a, int b)
return aa + bb;
}
/* { dg-final { scan-tree-dump "Replaced \\\(int\\\) aa_.*with a_" "fre" } } */
/* { dg-final { scan-tree-dump "Replaced \\\(int\\\) aa_.*with a_" "fre" { xfail *-*-* } } } */
/* { dg-final { cleanup-tree-dump "fre" } } */

View File

@ -9,6 +9,6 @@ char bar(char f)
return wrap(f);
}
/* { dg-final { scan-tree-dump "Replaced \\\(char\\\) .*with " "fre" } } */
/* { dg-final { scan-tree-dump "Replaced \\\(int\\\) .*with " "fre" } } */
/* { dg-final { scan-tree-dump "Replaced \\\(char\\\) .*with " "fre" { xfail *-*-* } } } */
/* { dg-final { scan-tree-dump "Replaced \\\(int\\\) .*with " "fre" { xfail *-*-* } } } */
/* { dg-final { cleanup-tree-dump "fre" } } */

View File

@ -10,5 +10,5 @@ bar (unsigned int t)
return a == t;
}
/* { dg-final { scan-tree-dump "Replaced \\\(unsigned int\\\) a_.*with t_" "fre" } } */
/* { dg-final { scan-tree-dump "Replaced \\\(unsigned int\\\) a_.*with t_" "fre" { xfail *-*-* } } } */
/* { dg-final { cleanup-tree-dump "fre" } } */

View File

@ -0,0 +1,21 @@
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-fre-stats" } */
void vnum_test8(int *data)
{
int i;
int stop = data[3];
int m = data[4];
int n = m;
for (i=0; i<stop; i++) {
int k = data[2];
data[k] = 2;
data[0] = m - n;
k = data[1];
m = m + k;
n = n + k;
}
}
/* We should eliminate m - n, and set n = n + k into n = m. */
/* { dg-final { scan-tree-dump-times "Eliminated: 2" 1 "fre"} } */
/* { dg-final { cleanup-tree-dump "fre" } } */

View File

@ -0,0 +1,25 @@
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-fre-stats" } */
int vnum_test8(int *data)
{
int i;
int stop = data[3];
int m = data[4];
int n = m;
int p;
for (i=0; i<stop; i++) {
int k = data[2];
data[k] = 2;
data[0] = m - n;
k = data[1];
m = m + k;
n = n + k;
p = data[0];
}
return p;
}
/* We should eliminate m - n, and set n = n + k into n = m, and
set p to 0 */
/* { dg-final { scan-tree-dump-times "Eliminated: 3" 1 "fre"} } */
/* { dg-final { cleanup-tree-dump "fre" } } */

View File

@ -0,0 +1,15 @@
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-fre-stats" } */
int main(int argc, char **argv)
{
int *p;
int result;
*p = 2;
if (argc)
*p = 2;
result = *p;
return result;
}
/* We should eliminate result = *p by saying it has the value 2. */
/* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "fre"} } */
/* { dg-final { cleanup-tree-dump "fre" } } */

View File

@ -0,0 +1,27 @@
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-fre-stats" } */
int vnum_test8(int *data)
{
int i;
int stop = data[3];
int m = data[4];
int n = m;
int p = 0;
for (i=0; i<stop; i++) {
int k = data[2];
data[5] = 0;
if (i < 30)
data[5] = m - n;
p = data[5];
k = data[1];
m = m + k;
n = n + k;
}
return p;
}
/* We should eliminate m - n, n + k, set data[5] = 0, eliminate the
address arithmetic for data[5], and set p = 0.
/* { dg-final { scan-tree-dump-times "Eliminated: 5" 1 "fre"} } */
/* { dg-final { cleanup-tree-dump "fre" } } */

View File

@ -1083,18 +1083,20 @@ void print_value_expressions (FILE *, tree);
/* In tree-vn.c */
tree make_value_handle (tree);
void set_value_handle (tree, tree);
bool expressions_equal_p (tree, tree);
static inline tree get_value_handle (tree);
hashval_t vn_compute (tree, hashval_t);
void sort_vuses (VEC (tree, gc) *);
tree vn_lookup_or_add (tree, tree);
void sort_vuses_heap (VEC (tree, heap) *);
tree vn_lookup_or_add (tree);
tree vn_lookup_or_add_with_stmt (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_stmt (tree, tree);
tree vn_lookup (tree);
tree vn_lookup_with_vuses (tree, VEC (tree, gc) *);
void vn_init (void);
void vn_delete (void);
/* In tree-ssa-sink.c */
bool is_hidden_global_store (tree);

View File

@ -299,12 +299,12 @@ typedef struct ssa_operand_iterator_d
DEFVAR = op_iter_next_def (&(ITER)))
/* This macro executes a loop over the VDEF operands of STMT. The def
and use for each VDEF is returned in DEFVAR and USEVAR.
and use vector for each VDEF is returned in DEFVAR and USEVECT.
ITER is an ssa_op_iter structure used to control the loop. */
#define FOR_EACH_SSA_VDEF_OPERAND(DEFVAR, USEVAR, STMT, ITER) \
for (op_iter_init_vdef (&(ITER), STMT, &(USEVAR), &(DEFVAR)); \
#define FOR_EACH_SSA_VDEF_OPERAND(DEFVAR, USEVECT, STMT, ITER) \
for (op_iter_init_vdef (&(ITER), STMT, &(USEVECT), &(DEFVAR)); \
!op_iter_done (&(ITER)); \
op_iter_next_vdef (&(USEVAR), &(DEFVAR), &(ITER)))
op_iter_next_vdef (&(USEVECT), &(DEFVAR), &(ITER)))
/* This macro will execute a loop over all the arguments of a PHI which
match FLAGS. A use_operand_p is always returned via USEVAR. FLAGS

File diff suppressed because it is too large Load Diff

2043
gcc/tree-ssa-sccvn.c Normal file

File diff suppressed because it is too large Load Diff

65
gcc/tree-ssa-sccvn.h Normal file
View File

@ -0,0 +1,65 @@
/* Tree SCC value numbering
Copyright (C) 2007 Free Software Foundation, Inc.
Contributed by Daniel Berlin <dberlin@dberlin.org>
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, 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; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef TREE_SSA_SCCVN_H
#define TREE_SSA_SCCVN_H
/* TOP of the VN lattice. */
extern tree VN_TOP;
typedef struct vn_ssa_aux
{
/* SCC information. */
unsigned int dfsnum;
bool visited;
unsigned int low;
bool on_sccstack;
/* Value number. This may be an SSA name or a constant. */
tree valnum;
/* Representative expression, if not a direct constant. */
tree expr;
/* Whether the representative expression contains constants. */
bool has_constants;
/* Whether the SSA_NAME has been value numbered already. This is
only saying whether visit_use has been called on it at least
once. It cannot be used to avoid visitation for SSA_NAME's
involved in non-singleton SCC's. */
bool use_processed;
} *vn_ssa_aux_t;
/* Return the value numbering info for an SSA_NAME. */
extern vn_ssa_aux_t VN_INFO (tree);
extern vn_ssa_aux_t VN_INFO_GET (tree);
void run_scc_vn (void);
void free_scc_vn (void);
void switch_to_PRE_table (void);
tree vn_binary_op_lookup (tree);
void vn_binary_op_insert (tree, tree);
tree vn_unary_op_lookup (tree);
void vn_unary_op_insert (tree, tree);
tree vn_reference_lookup (tree, VEC (tree, gc) *);
void vn_reference_insert (tree, tree, VEC (tree, gc) *);
VEC (tree, gc) *shared_vuses_from_stmt (tree);
VEC (tree, gc) *copy_vuses_from_stmt (tree);
#endif /* TREE_SSA_SCCVN_H */

View File

@ -32,35 +32,15 @@ Boston, MA 02110-1301, USA. */
#include "tree-pass.h"
#include "tree-dump.h"
#include "diagnostic.h"
#include "tree-ssa-sccvn.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
{
/* Value handle. */
tree v;
/* Associated expression. */
tree e;
/* For comparing virtual uses in E. */
VEC (tree, gc) *vuses;
/* E's hash value. */
hashval_t hashcode;
} *val_expr_pair_t;
static void set_value_handle (tree e, tree v);
/* Most of this is PRE specific. The real grunt work is done in
tree-ssa-sccvn.c. This is where the lookup and insertion
functions, etc, can be found */
/* Create and return a new value handle node of type TYPE. */
static tree
tree
make_value_handle (tree type)
{
static unsigned int id = 0;
@ -72,25 +52,6 @@ make_value_handle (tree type)
}
/* Given an expression EXPR, compute a hash value number using the
code of the expression, its real operands and virtual operands (if
any).
VAL can be used to iterate by passing previous value numbers (it is
used by iterative_hash_expr). */
hashval_t
vn_compute (tree expr, hashval_t val)
{
/* EXPR must not be a statement. We are only interested in value
numbering expressions on the RHS of assignments. */
gcc_assert (expr);
gcc_assert (!expr->base.ann
|| expr->base.ann->common.type != STMT_ANN);
val = iterative_hash_expr (expr, val);
return val;
}
/* Compare two expressions E1 and E2 and return true if they are
equal. */
@ -130,52 +91,9 @@ expressions_equal_p (tree e1, tree e2)
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)
{
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;
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;
}
/* Set the value handle for expression E to value V. */
static void
void
set_value_handle (tree e, tree v)
{
if (TREE_CODE (e) == SSA_NAME)
@ -189,124 +107,7 @@ 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. */
void
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;
new_pair = XNEW (struct val_expr_pair_d);
new_pair->e = expr;
new_pair->v = val;
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)
free (*slot);
*slot = (void *) new_pair;
set_value_handle (expr, val);
if (TREE_CODE (val) == VALUE_HANDLE)
add_to_value (val, expr);
}
/* Search in VALUE_TABLE for an existing instance of expression EXPR,
and return its value, or NULL if none has been set. STMT
represents the stmt associated with EXPR. It is used when computing the
hash value for EXPR. */
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};
/* Constants are their own value. */
if (is_gimple_min_invariant (expr))
return expr;
vep.e = expr;
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;
else
return ((val_expr_pair_t) *slot)->v;
}
/* A comparison function for use in qsort to compare vuses. Simply
@ -352,34 +153,6 @@ print_creation_to_file (tree v, tree expr, VEC (tree, gc) *vuses)
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 VUSES for EXPR. */
tree
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))
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;
}
/* Sort the VUSE array so that we can do equality comparisons
quicker on two vuse vecs. */
@ -394,6 +167,222 @@ sort_vuses (VEC (tree,gc) *vuses)
vuses_compare);
}
/* Sort the VUSE array so that we can do equality comparisons
quicker on two vuse vecs. */
void
sort_vuses_heap (VEC (tree,heap) *vuses)
{
if (VEC_length (tree, vuses) > 1)
qsort (VEC_address (tree, vuses),
VEC_length (tree, vuses),
sizeof (tree),
vuses_compare);
}
/* Insert EXPR into VALUE_TABLE with value VAL, and add expression
EXPR to the value set for value VAL. */
void
vn_add (tree expr, tree val)
{
switch (TREE_CODE_CLASS (TREE_CODE (expr)))
{
case tcc_comparison:
case tcc_binary:
vn_binary_op_insert (expr, val);
break;
case tcc_unary:
vn_unary_op_insert (expr, val);
break;
/* In the case of array-refs of constants, for example, we can
end up with no vuses. */
case tcc_reference:
vn_reference_insert (expr, val, NULL);
break;
/* The *only* time CALL_EXPR should appear here is
when it has no vuses. */
case tcc_vl_exp:
case tcc_exceptional:
case tcc_expression:
case tcc_declaration:
if (TREE_CODE (expr) == CALL_EXPR || DECL_P (expr))
{
vn_reference_insert (expr, val, NULL);
break;
}
else if (TREE_CODE (expr) == SSA_NAME)
{
SSA_NAME_VALUE (expr) = val;
break;
}
else if (TREE_CODE (expr) == ADDR_EXPR)
{
vn_unary_op_insert (expr, val);
break;
}
/* FALLTHROUGH */
default:
gcc_unreachable ();
}
set_value_handle (expr, val);
if (TREE_CODE (val) == VALUE_HANDLE)
add_to_value (val, expr);
}
/* Insert EXPR into the value numbering tables. 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)
{
if (!vuses)
{
vn_add (expr, val);
return;
}
vn_reference_insert (expr, val, vuses);
set_value_handle (expr, val);
if (TREE_CODE (val) == VALUE_HANDLE)
add_to_value (val, expr);
}
/* Lookup EXPR in the value numbering tables and return the result, if
we have one. */
tree
vn_lookup (tree expr)
{
/* Constants are their own value. */
if (is_gimple_min_invariant (expr) || TREE_CODE (expr) == FIELD_DECL)
return expr;
switch (TREE_CODE_CLASS (TREE_CODE (expr)))
{
case tcc_comparison:
case tcc_binary:
return vn_binary_op_lookup (expr);
case tcc_unary:
return vn_unary_op_lookup (expr);
break;
/* In the case of array-refs of constants, for example, we can
end up with no vuses. */
case tcc_reference:
return vn_reference_lookup (expr, NULL);
break;
/* It is possible to have CALL_EXPR with no vuses for things
like "cos", and these will fall into vn_lookup. */
case tcc_vl_exp:
case tcc_exceptional:
case tcc_expression:
case tcc_declaration:
if (TREE_CODE (expr) == CALL_EXPR || DECL_P (expr))
return vn_reference_lookup (expr, NULL);
else if (TREE_CODE (expr) == SSA_NAME)
return SSA_NAME_VALUE (expr);
else if (TREE_CODE (expr) == ADDR_EXPR)
return vn_unary_op_lookup (expr);
/* FALLTHROUGH */
default:
gcc_unreachable ();
}
return NULL;
}
/* Search in the value numbering tables for an existing instance of
expression EXPR, and return its value, or NULL if none has been set. STMT
represents the stmt associated with EXPR. It is used when computing the
hash value for EXPR for reference operations. */
tree
vn_lookup_with_stmt (tree expr, tree stmt)
{
if (stmt == NULL)
return vn_lookup (expr);
/* Constants are their own value. */
if (is_gimple_min_invariant (expr) || TREE_CODE (expr) == FIELD_DECL)
return expr;
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)
{
if (!vuses || !VEC_length (tree, vuses))
return vn_lookup (expr);
if (is_gimple_min_invariant (expr) || TREE_CODE (expr) == FIELD_DECL)
return expr;
return vn_reference_lookup (expr, vuses);
}
static tree
create_value_handle_for_expr (tree expr, VEC (tree, gc) *vuses)
{
tree v;
v = make_value_handle (TREE_TYPE (expr));
if (dump_file && (dump_flags & TDF_DETAILS))
print_creation_to_file (v, expr, vuses);
if (vuses)
VALUE_HANDLE_VUSES (v) = vuses;
return v;
}
/* Like vn_lookup, but creates a new value for the operation if one
does not exist. */
tree
vn_lookup_or_add (tree expr)
{
tree v = vn_lookup (expr);
if (v == NULL_TREE)
{
v = create_value_handle_for_expr (expr, NULL);
vn_add (expr, v);
}
else
set_value_handle (expr, v);
return v;
}
/* Like vn_lookup, but handles reference operations as well by using
STMT to get the set of vuses. */
tree
vn_lookup_or_add_with_stmt (tree expr, tree stmt)
{
tree v;
if (!stmt)
return vn_lookup_or_add (expr);
v = vn_lookup_with_stmt (expr, stmt);
if (v == NULL_TREE)
{
VEC (tree, gc) *vuses = copy_vuses_from_stmt (stmt);
v = create_value_handle_for_expr (expr, vuses);
vn_add_with_vuses (expr, v, vuses);
}
else
set_value_handle (expr, v);
return v;
}
/* 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
@ -402,40 +391,20 @@ sort_vuses (VEC (tree,gc) *vuses)
tree
vn_lookup_or_add_with_vuses (tree expr, VEC (tree, gc) *vuses)
{
tree v = vn_lookup_with_vuses (expr, vuses);
tree v;
if (!vuses || VEC_length (tree, vuses) == 0)
return vn_lookup_or_add (expr);
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;
v = create_value_handle_for_expr (expr, vuses);
vn_add_with_vuses (expr, v, vuses);
}
set_value_handle (expr, v);
else
set_value_handle (expr, v);
return v;
}
/* 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);
shared_lookup_vuses = NULL;
}
/* Delete data used for value numbering. */
void
vn_delete (void)
{
htab_delete (value_table);
VEC_free (tree, gc, shared_lookup_vuses);
value_table = NULL;
}