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:
parent
11147af397
commit
89fb70a345
|
@ -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
|
||||
|
|
|
@ -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) \
|
||||
|
|
|
@ -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" } } */
|
||||
|
|
|
@ -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" } } */
|
||||
|
|
|
@ -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" } } */
|
||||
|
|
|
@ -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" } } */
|
||||
|
|
|
@ -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" } } */
|
|
@ -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" } } */
|
|
@ -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" } } */
|
|
@ -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" } } */
|
|
@ -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);
|
||||
|
|
|
@ -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
File diff suppressed because it is too large
Load Diff
|
@ -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 */
|
493
gcc/tree-vn.c
493
gcc/tree-vn.c
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue