This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH][alias-improvements] Re-implement the SCCVN reference walker / alias oracle
- From: Richard Guenther <rguenther at suse dot de>
- To: gcc-patches at gcc dot gnu dot org
- Date: Wed, 10 Dec 2008 17:23:56 +0100 (CET)
- Subject: [PATCH][alias-improvements] Re-implement the SCCVN reference walker / alias oracle
This re-implements the SCCVN oracle by properly walking all
value-equivalent VUSEs for a given memory reference and doing hashtable
lookups for them. On the trunk we only do this for the final aliasing
def - which means we catch store-forwarding reliably but not really
doing CSE of loads properly. This is more visible on the
alias-improvements branch but it also fixes for example PR38207 which
is seen on the trunk.
Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to the
branch.
This fixes a bunch of testsuite failures and exposes some which
I have reduced to a PRE issue (that is not easy to fix, I have
added tree-ssa/ssa-pre-24.c for that which fails now) but which
is fixable with a copyprop patch as well (PR38458).
I will install the copyprop patch as a separate revision though.
Additional fails are
+FAIL: gcc.dg/vect/pr25413a.c scan-tree-dump-times vect "vectorized 1
loops" 1
+FAIL: gcc.dg/vect/vect-64.c scan-tree-dump-times vect "vectorized 3
loops" 1
+FAIL: gcc.dg/vect/vect-align-2.c scan-tree-dump-times vect "Alignment of
access
forced using versioning" 1
+FAIL: gcc.dg/vect/vect-align-2.c scan-tree-dump-times vect "vectorized 1
loops"
1
+FAIL: gcc.dg/vect/no-section-anchors-vect-64.c scan-tree-dump-times vect
"vecto
rized 3 loops" 1
+FAIL: gcc.dg/vect/no-section-anchors-vect-64.c scan-tree-dump-times vect
"Align
ment of access forced using peeling" 2
we also accumulated one more XPASS on the branch,
+XPASS: gcc.dg/tree-ssa/20070302-1.c (test for excess errors)
Richard.
2008-12-09 Richard Guenther <rguenther@suse.de>
PR tree-optimization/38207
* tree-flow.h: Include tree-ssa-alias.h.
(get_single_def_stmt, get_single_def_stmt_from_phi,
get_single_def_stmt_with_phi): Remove.
(refs_may_alias_p): Move ...
* tree-ssa-alias.h: ... here. New file.
* tree-dfa.c (refs_may_alias_p): Handle non-aliased locals.
(get_single_def_stmt, get_single_def_stmt_from_phi,
get_single_def_stmt_with_phi): Remove.
* tree-ssa-alias.c: Include tree-ssa-alias.h.
(call_may_clobber_ref_p): New function.
(stmt_may_clobber_ref_p): Likewise.
(get_single_incoming_phi_arg_for_maybe_loop_invariant_ref): Likewise.
(walk_non_aliased_vuses): Likewise.
* Makefile.in (TREE_FLOW_H): Add tree-ssa-alias.h.
* tree-ssa-sccvn.c (SSA_VAL): Revert handling NULL arguments.
(get_def_ref_stmt_vuse): Remove.
(vn_reference_lookup_2): New function.
(vn_reference_lookup_pieces): Use walk_non_aliased_vuses for
walking equivalent vuses.
(vn_reference_lookup): Likewise.
* gcc.dg/tree-ssa/ssa-fre-18.c: New testcase.
* gcc.dg/tree-ssa/ssa-fre-19.c: Likewise.
* gcc.dg/tree-ssa/ssa-lim-3.c: Run at -O to disable PRE.
* gcc.dg/tree-ssa/ssa-pre-23.c: New testcase.
* gcc.dg/tree-ssa/ssa-pre-24.c: Likewise.
Index: gcc/tree-ssa-alias.h
===================================================================
*** /dev/null 1970-01-01 00:00:00.000000000 +0000
--- gcc/tree-ssa-alias.h 2008-12-10 16:06:54.000000000 +0100
***************
*** 0 ****
--- 1,33 ----
+ /* Tree based alias analysis and alias oracle.
+ Copyright (C) 2008 Free Software Foundation, Inc.
+ Contributed by Richard Guenther <rguenther@suse.de>
+
+ 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 3 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; see the file COPYING3. If not see
+ <http://www.gnu.org/licenses/>. */
+
+ #ifndef TREE_SSA_ALIAS_H
+ #define TREE_SSA_ALIAS_H
+
+ #include "coretypes.h"
+
+ /* In tree-ssa-alias.c */
+ void *walk_non_aliased_vuses (tree, tree,
+ void *(*)(tree, tree, void *), void *);
+
+ /* In tree-dfa.c */
+ extern bool refs_may_alias_p (tree, tree);
+
+ #endif /* TREE_SSA_ALIAS_H */
Index: gcc/tree-flow.h
===================================================================
*** gcc/tree-flow.h.orig 2008-12-10 16:00:59.000000000 +0100
--- gcc/tree-flow.h 2008-12-10 16:06:54.000000000 +0100
*************** along with GCC; see the file COPYING3.
*** 30,35 ****
--- 30,36 ----
#include "tree-ssa-operands.h"
#include "cgraph.h"
#include "ipa-reference.h"
+ #include "tree-ssa-alias.h"
/* Forward declare structures for the garbage collector GTY markers. */
#ifndef GCC_BASIC_BLOCK_H
*************** extern tree make_rename_temp (tree, cons
*** 669,678 ****
extern void set_default_def (tree, tree);
extern tree gimple_default_def (struct function *, tree);
extern bool stmt_references_abnormal_ssa_name (gimple);
- extern bool refs_may_alias_p (tree, tree);
- extern gimple get_single_def_stmt (gimple);
- extern gimple get_single_def_stmt_from_phi (tree, gimple);
- extern gimple get_single_def_stmt_with_phi (tree, gimple);
/* In tree-phinodes.c */
extern void reserve_phi_args_for_new_edge (basic_block);
--- 670,675 ----
Index: gcc/tree-dfa.c
===================================================================
*** gcc/tree-dfa.c.orig 2008-12-10 16:01:51.000000000 +0100
--- gcc/tree-dfa.c 2008-12-10 16:07:37.000000000 +0100
*************** refs_may_alias_p (tree ref1, tree ref2)
*** 975,980 ****
--- 975,992 ----
return ranges_overlap_p (offset1, max_size1, offset2, max_size2);
}
+ /* If one reference is based on a pointer and one is based on a local
+ variable that does not have its address taken, they cannot alias. */
+ if ((SSA_VAR_P (base1)
+ && !TREE_ADDRESSABLE (base1)
+ && !is_global_var (base1)
+ && INDIRECT_REF_P (base2))
+ || (SSA_VAR_P (base2)
+ && !TREE_ADDRESSABLE (base2)
+ && !is_global_var (base2)
+ && INDIRECT_REF_P (base1)))
+ return false;
+
/* If one base is a ref-all pointer or a TARGET_MEM_REF weird things
are allowed. */
strict_aliasing_applies = (flag_strict_aliasing
*************** refs_may_alias_p (tree ref1, tree ref2)
*** 1062,1138 ****
return true;
}
- /* Given a stmt STMT that references memory, return the single stmt
- that is reached by following the VUSE -> VDEF link.
- Note that this may return a PHI node as well.
- Note that if the VUSE is a default definition this function will
- return an empty statement. */
-
- gimple
- get_single_def_stmt (gimple stmt)
- {
- return SSA_NAME_DEF_STMT (gimple_vuse (stmt));
- }
-
- /* Given a PHI node of virtual operands, tries to eliminate cyclic
- reached definitions if they do not alias REF and returns the
- defining statement of the single virtual operand that flows in
- from a non-backedge. Returns NULL_TREE if such statement within
- the above conditions cannot be found. */
-
- gimple
- get_single_def_stmt_from_phi (tree ref, gimple phi)
- {
- tree def_arg = NULL_TREE;
- unsigned i;
-
- /* Find the single PHI argument that is not flowing in from a
- back edge and verify that the loop-carried definitions do
- not alias the reference we look for. */
- for (i = 0; i < gimple_phi_num_args (phi); ++i)
- {
- tree arg = PHI_ARG_DEF (phi, i);
- gimple def_stmt;
-
- if (!(gimple_phi_arg_edge (phi, i)->flags & EDGE_DFS_BACK))
- {
- /* Multiple non-back edges? Do not try to handle this. */
- if (def_arg)
- return NULL;
- def_arg = arg;
- continue;
- }
-
- /* Follow the definitions back to the original PHI node. Bail
- out once a definition is found that may alias REF. */
- def_stmt = SSA_NAME_DEF_STMT (arg);
- do
- {
- if (!is_gimple_assign (def_stmt)
- || refs_may_alias_p (ref, gimple_assign_lhs (def_stmt)))
- return NULL;
- def_stmt = get_single_def_stmt (def_stmt);
- if (!def_stmt)
- return NULL;
- }
- while (def_stmt != phi);
- }
-
- return SSA_NAME_DEF_STMT (def_arg);
- }
-
- /* Return the single reference statement defining all virtual uses
- on STMT or NULL_TREE, if there are multiple defining statements.
- Take into account only definitions that alias REF if following
- back-edges when looking through a loop PHI node. */
-
- gimple
- get_single_def_stmt_with_phi (tree ref, gimple stmt)
- {
- gimple def_stmt = SSA_NAME_DEF_STMT (gimple_vuse (stmt));
-
- if (gimple_code (def_stmt) == GIMPLE_PHI)
- return get_single_def_stmt_from_phi (ref, def_stmt);
-
- return def_stmt;
- }
--- 1074,1076 ----
Index: gcc/tree-ssa-alias.c
===================================================================
*** gcc/tree-ssa-alias.c.orig 2008-12-10 16:00:59.000000000 +0100
--- gcc/tree-ssa-alias.c 2008-12-10 16:08:00.000000000 +0100
*************** along with GCC; see the file COPYING3.
*** 48,53 ****
--- 48,54 ----
#include "vecprim.h"
#include "pointer-set.h"
#include "alloc-pool.h"
+ #include "tree-ssa-alias.h"
/* Broad overview of how aliasing works:
*************** struct gimple_opt_pass pass_build_alias
*** 1107,1109 ****
--- 1108,1239 ----
TODO_rebuild_alias | TODO_dump_func /* todo_flags_finish */
}
};
+
+
+
+ /* If the call in statement CALL may clobber the memory reference REF
+ return true, otherwise return false. */
+
+ static bool
+ call_may_clobber_ref_p (gimple call, tree ref)
+ {
+ tree base;
+
+ /* If the call is pure or const it cannot clobber anything. */
+ if (gimple_call_flags (call)
+ & (ECF_PURE|ECF_CONST|ECF_LOOPING_CONST_OR_PURE|ECF_NOVOPS))
+ return false;
+
+ base = get_base_address (ref);
+ if (SSA_VAR_P (base))
+ return is_call_clobbered (base);
+
+ return true;
+ }
+
+ /* If the statement STMT may clobber the memory reference REF return true,
+ otherwise return false. */
+
+ static bool
+ stmt_may_clobber_ref_p (gimple stmt, tree ref)
+ {
+ if (is_gimple_call (stmt))
+ {
+ tree lhs = gimple_call_lhs (stmt);
+ if (lhs
+ && !is_gimple_reg (lhs)
+ && refs_may_alias_p (ref, lhs))
+ return true;
+
+ return call_may_clobber_ref_p (stmt, ref);
+ }
+ else if (is_gimple_assign (stmt))
+ return refs_may_alias_p (ref, gimple_assign_lhs (stmt));
+ else if (gimple_code (stmt) == GIMPLE_ASM)
+ return true;
+
+ return false;
+ }
+
+ /* For a phi-node PHI for the virtual operand get the argument that
+ represents the single incoming edge into a loop if REF is invariant
+ in that loop. */
+
+ static tree
+ get_single_incoming_phi_arg_for_maybe_loop_invariant_ref (gimple phi, tree ref)
+ {
+ tree def_arg = NULL_TREE;
+ unsigned i;
+
+ for (i = 0; i < gimple_phi_num_args (phi); ++i)
+ {
+ tree arg = PHI_ARG_DEF (phi, i);
+ gimple def_stmt;
+
+ if (!(gimple_phi_arg_edge (phi, i)->flags & EDGE_DFS_BACK))
+ {
+ /* Multiple non-back edges? Do not try to handle this. */
+ if (def_arg)
+ return NULL_TREE;
+ def_arg = arg;
+ continue;
+ }
+
+ /* Follow the definitions back to the original PHI node. Bail
+ out once a definition is found that may clobber REF. */
+ def_stmt = SSA_NAME_DEF_STMT (arg);
+ do
+ {
+ if (gimple_code (def_stmt) == GIMPLE_PHI
+ || gimple_nop_p (def_stmt)
+ || stmt_may_clobber_ref_p (def_stmt, ref))
+ return NULL;
+ def_stmt = SSA_NAME_DEF_STMT (gimple_vuse (def_stmt));
+ }
+ while (def_stmt != phi);
+ }
+
+ return def_arg;
+ }
+
+ /* Based on the memory reference REF and its virtual use VUSE call
+ WALKER for each virtual use that is equivalent to VUSE, including VUSE
+ itself. That is, for each virtual use for which its defining statement
+ does not clobber REF.
+
+ WALKER is called with REF, the current virtual use and DATA. If
+ WALKER returns non-NULL the walk stops and its result is returned.
+ At the end of a non-successful walk NULL is returned.
+
+ TODO: Cache the vector of equivalent vuses per ref, vuse pair. */
+
+ void *
+ walk_non_aliased_vuses (tree ref, tree vuse,
+ void *(*walker)(tree, tree, void *), void *data)
+ {
+ do
+ {
+ gimple def_stmt;
+ void *res;
+
+ res = (*walker) (ref, vuse, data);
+ if (res)
+ return res;
+
+ def_stmt = SSA_NAME_DEF_STMT (vuse);
+ if (gimple_nop_p (def_stmt))
+ return NULL;
+ else if (gimple_code (def_stmt) == GIMPLE_PHI)
+ vuse = get_single_incoming_phi_arg_for_maybe_loop_invariant_ref
+ (def_stmt, ref);
+ else
+ {
+ if (stmt_may_clobber_ref_p (def_stmt, ref))
+ return NULL;
+ vuse = gimple_vuse (def_stmt);
+ }
+ }
+ while (vuse);
+
+ return NULL;
+ }
Index: gcc/Makefile.in
===================================================================
*** gcc/Makefile.in.orig 2008-12-10 16:00:59.000000000 +0100
--- gcc/Makefile.in 2008-12-10 16:06:54.000000000 +0100
*************** CPP_INTERNAL_H = $(srcdir)/../libcpp/int
*** 870,876 ****
TREE_DUMP_H = tree-dump.h $(SPLAY_TREE_H) tree-pass.h
TREE_FLOW_H = tree-flow.h tree-flow-inline.h tree-ssa-operands.h \
$(BITMAP_H) $(BASIC_BLOCK_H) hard-reg-set.h $(GIMPLE_H) \
! $(HASHTAB_H) $(CGRAPH_H) $(IPA_REFERENCE_H)
TREE_SSA_LIVE_H = tree-ssa-live.h $(PARTITION_H) vecprim.h
PRETTY_PRINT_H = pretty-print.h $(INPUT_H) $(OBSTACK_H)
DIAGNOSTIC_H = diagnostic.h diagnostic.def $(PRETTY_PRINT_H) options.h
--- 870,877 ----
TREE_DUMP_H = tree-dump.h $(SPLAY_TREE_H) tree-pass.h
TREE_FLOW_H = tree-flow.h tree-flow-inline.h tree-ssa-operands.h \
$(BITMAP_H) $(BASIC_BLOCK_H) hard-reg-set.h $(GIMPLE_H) \
! $(HASHTAB_H) $(CGRAPH_H) $(IPA_REFERENCE_H) \
! tree-ssa-alias.h
TREE_SSA_LIVE_H = tree-ssa-live.h $(PARTITION_H) vecprim.h
PRETTY_PRINT_H = pretty-print.h $(INPUT_H) $(OBSTACK_H)
DIAGNOSTIC_H = diagnostic.h diagnostic.def $(PRETTY_PRINT_H) options.h
Index: gcc/tree-ssa-sccvn.c
===================================================================
*** gcc/tree-ssa-sccvn.c.orig 2008-12-10 16:00:59.000000000 +0100
--- gcc/tree-ssa-sccvn.c 2008-12-10 16:06:54.000000000 +0100
*************** static vn_tables_t current_info;
*** 140,146 ****
static int *rpo_numbers;
! #define SSA_VAL(x) (x ? VN_INFO ((x))->valnum : NULL_TREE)
/* This represents the top of the VN lattice, which is the universal
value. */
--- 140,146 ----
static int *rpo_numbers;
! #define SSA_VAL(x) (VN_INFO ((x))->valnum)
/* This represents the top of the VN lattice, which is the universal
value. */
*************** valueize_refs (VEC (vn_reference_op_s, h
*** 793,823 ****
return orig;
}
- /* Return the single reference statement defining all virtual uses
- in VUSES or NULL_TREE, if there are multiple defining statements.
- Take into account only definitions that alias REF if following
- back-edges. */
-
- static gimple
- get_def_ref_stmt_vuse (tree ref, tree vuse)
- {
- gimple def_stmt;
-
- gcc_assert (vuse != NULL_TREE);
-
- def_stmt = SSA_NAME_DEF_STMT (vuse);
- if (gimple_code (def_stmt) == GIMPLE_PHI)
- def_stmt = get_single_def_stmt_from_phi (ref, def_stmt);
-
- /* Now see if the definition aliases ref, and loop until it does. */
- while (def_stmt
- && is_gimple_assign (def_stmt)
- && !refs_may_alias_p (ref, gimple_get_lhs (def_stmt)))
- def_stmt = get_single_def_stmt_with_phi (ref, def_stmt);
-
- return def_stmt;
- }
-
/* Lookup a SCCVN reference operation VR in the current hash table.
Returns the resulting value number if it exists in the hash table,
NULL_TREE otherwise. VNRESULT will be filled in with the actual
--- 793,798 ----
*************** vn_reference_lookup_1 (vn_reference_t vr
*** 845,850 ****
--- 820,851 ----
return NULL_TREE;
}
+ /* Callback for walk_non_aliased_vuses. Adjusts the vn_reference_t VR_
+ with the current VUSE and performs the expression lookup. */
+
+ static void *
+ vn_reference_lookup_2 (tree op ATTRIBUTE_UNUSED, tree vuse, void *vr_)
+ {
+ vn_reference_t vr = (vn_reference_t)vr_;
+ void **slot;
+ hashval_t hash;
+
+ /* Fixup vuse and hash. */
+ vr->hashcode = vr->hashcode - iterative_hash_expr (vr->vuse, 0);
+ vr->vuse = SSA_VAL (vuse);
+ vr->hashcode = vr->hashcode + iterative_hash_expr (vr->vuse, 0);
+
+ hash = vr->hashcode;
+ slot = htab_find_slot_with_hash (current_info->references, vr,
+ hash, NO_INSERT);
+ if (!slot && current_info == optimistic_info)
+ slot = htab_find_slot_with_hash (valid_info->references, vr,
+ hash, NO_INSERT);
+ if (slot)
+ return *slot;
+
+ return NULL;
+ }
/* Lookup a reference operation by it's parts, in the current hash table.
Returns the resulting value number if it exists in the hash table,
*************** vn_reference_lookup_pieces (tree vuse,
*** 858,889 ****
{
struct vn_reference_s vr1;
tree result;
if (vnresult)
*vnresult = NULL;
! vr1.vuse = SSA_VAL (vuse);
vr1.operands = valueize_refs (operands);
vr1.hashcode = vn_reference_compute_hash (&vr1);
result = vn_reference_lookup_1 (&vr1, vnresult);
- /* If there is a single defining statement for all virtual uses, we can
- use that, following virtual use-def chains. */
if (!result
&& maywalk
&& vr1.vuse)
{
tree ref = get_ref_from_reference_ops (operands);
! gimple def_stmt;
! if (ref
! && (def_stmt = get_def_ref_stmt_vuse (ref, vr1.vuse))
! && is_gimple_assign (def_stmt))
! {
! /* We are now at an aliasing definition for the vuse we want to
! look up. Re-do the lookup with the vdef for this stmt. */
! vr1.vuse = SSA_VAL (gimple_vdef (def_stmt));
! vr1.hashcode = vn_reference_compute_hash (&vr1);
! result = vn_reference_lookup_1 (&vr1, vnresult);
}
}
return result;
--- 859,892 ----
{
struct vn_reference_s vr1;
tree result;
+
if (vnresult)
*vnresult = NULL;
! vr1.vuse = vuse ? SSA_VAL (vuse) : NULL_TREE;
vr1.operands = valueize_refs (operands);
vr1.hashcode = vn_reference_compute_hash (&vr1);
result = vn_reference_lookup_1 (&vr1, vnresult);
if (!result
&& maywalk
&& vr1.vuse)
{
+ vn_reference_t wvnresult;
tree ref = get_ref_from_reference_ops (operands);
! if (!ref)
! return NULL_TREE;
! wvnresult =
! (vn_reference_t)walk_non_aliased_vuses (ref, vr1.vuse,
! vn_reference_lookup_2, &vr1);
! if (wvnresult)
! {
! if (vnresult)
! *vnresult = wvnresult;
! return wvnresult->result;
}
+
+ return NULL_TREE;
}
return result;
*************** vn_reference_lookup (tree op, tree vuse,
*** 900,931 ****
vn_reference_t *vnresult)
{
struct vn_reference_s vr1;
! tree result;
! gimple def_stmt;
if (vnresult)
*vnresult = NULL;
! vr1.vuse = SSA_VAL (vuse);
vr1.operands = valueize_refs (shared_reference_ops_from_ref (op));
vr1.hashcode = vn_reference_compute_hash (&vr1);
- result = vn_reference_lookup_1 (&vr1, vnresult);
! /* If there is a single defining statement for all virtual uses, we can
! use that, following virtual use-def chains. */
! if (!result
! && maywalk
! && vr1.vuse
! && (def_stmt = get_def_ref_stmt_vuse (op, vr1.vuse))
! && is_gimple_assign (def_stmt))
! {
! /* We are now at an aliasing definition for the vuse we want to
! look up. Re-do the lookup with the vdef for this stmt. */
! vr1.vuse = SSA_VAL (gimple_vdef (def_stmt));
! vr1.hashcode = vn_reference_compute_hash (&vr1);
! result = vn_reference_lookup_1 (&vr1, vnresult);
}
! return result;
}
--- 903,934 ----
vn_reference_t *vnresult)
{
struct vn_reference_s vr1;
!
if (vnresult)
*vnresult = NULL;
! vr1.vuse = vuse ? SSA_VAL (vuse) : NULL_TREE;
vr1.operands = valueize_refs (shared_reference_ops_from_ref (op));
vr1.hashcode = vn_reference_compute_hash (&vr1);
! if (maywalk
! && vr1.vuse)
! {
! vn_reference_t wvnresult;
! wvnresult =
! (vn_reference_t)walk_non_aliased_vuses (op, vr1.vuse,
! vn_reference_lookup_2, &vr1);
! if (wvnresult)
! {
! if (vnresult)
! *vnresult = wvnresult;
! return wvnresult->result;
! }
!
! return NULL_TREE;
}
! return vn_reference_lookup_1 (&vr1, vnresult);
}
*************** vn_reference_insert (tree op, tree resul
*** 943,949 ****
vr1->value_id = VN_INFO (result)->value_id;
else
vr1->value_id = get_or_alloc_constant_value_id (result);
! vr1->vuse = SSA_VAL (vuse);
vr1->operands = valueize_refs (create_reference_ops_from_ref (op));
vr1->hashcode = vn_reference_compute_hash (vr1);
vr1->result = TREE_CODE (result) == SSA_NAME ? SSA_VAL (result) : result;
--- 946,952 ----
vr1->value_id = VN_INFO (result)->value_id;
else
vr1->value_id = get_or_alloc_constant_value_id (result);
! vr1->vuse = vuse ? SSA_VAL (vuse) : NULL_TREE;
vr1->operands = valueize_refs (create_reference_ops_from_ref (op));
vr1->hashcode = vn_reference_compute_hash (vr1);
vr1->result = TREE_CODE (result) == SSA_NAME ? SSA_VAL (result) : result;
*************** vn_reference_insert_pieces (tree vuse,
*** 981,988 ****
vn_reference_t vr1;
vr1 = (vn_reference_t) pool_alloc (current_info->references_pool);
! vr1->value_id = value_id;
! vr1->vuse = SSA_VAL (vuse);
vr1->operands = valueize_refs (operands);
vr1->hashcode = vn_reference_compute_hash (vr1);
if (result && TREE_CODE (result) == SSA_NAME)
--- 984,991 ----
vn_reference_t vr1;
vr1 = (vn_reference_t) pool_alloc (current_info->references_pool);
! vr1->value_id = value_id;
! vr1->vuse = vuse ? SSA_VAL (vuse) : NULL_TREE;
vr1->operands = valueize_refs (operands);
vr1->hashcode = vn_reference_compute_hash (vr1);
if (result && TREE_CODE (result) == SSA_NAME)
*************** visit_reference_op_call (tree lhs, gimpl
*** 1575,1582 ****
bool changed = false;
struct vn_reference_s vr1;
tree result;
! vr1.vuse = SSA_VAL (gimple_vuse (stmt));
vr1.operands = valueize_refs (shared_reference_ops_from_call (stmt));
vr1.hashcode = vn_reference_compute_hash (&vr1);
result = vn_reference_lookup_1 (&vr1, NULL);
--- 1578,1586 ----
bool changed = false;
struct vn_reference_s vr1;
tree result;
+ tree vuse = gimple_vuse (stmt);
! vr1.vuse = vuse ? SSA_VAL (vuse) : NULL_TREE;
vr1.operands = valueize_refs (shared_reference_ops_from_call (stmt));
vr1.hashcode = vn_reference_compute_hash (&vr1);
result = vn_reference_lookup_1 (&vr1, NULL);
*************** visit_reference_op_call (tree lhs, gimpl
*** 1593,1599 ****
vn_reference_t vr2;
changed = set_ssa_val_to (lhs, lhs);
vr2 = (vn_reference_t) pool_alloc (current_info->references_pool);
! vr2->vuse = SSA_VAL (gimple_vuse (stmt));
vr2->operands = valueize_refs (create_reference_ops_from_call (stmt));
vr2->hashcode = vr1.hashcode;
vr2->result = lhs;
--- 1597,1603 ----
vn_reference_t vr2;
changed = set_ssa_val_to (lhs, lhs);
vr2 = (vn_reference_t) pool_alloc (current_info->references_pool);
! vr2->vuse = vr1.vuse;
vr2->operands = valueize_refs (create_reference_ops_from_call (stmt));
vr2->hashcode = vr1.hashcode;
vr2->result = lhs;
Index: gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-18.c
===================================================================
*** /dev/null 1970-01-01 00:00:00.000000000 +0000
--- gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-18.c 2008-12-10 16:06:54.000000000 +0100
***************
*** 0 ****
--- 1,28 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O -fdump-tree-fre" } */
+
+ struct a
+ {
+ union
+ {
+ int a;
+ int b;
+ };
+ union
+ {
+ int c;
+ int d;
+ };
+ };
+
+ int f(struct a *c)
+ {
+ int d = c->a;
+ c->c = 1;
+ return c->a + d;
+ }
+
+ /* We should have CSEd the load from c->a. */
+
+ /* { dg-final { scan-tree-dump-times "c_.*\\\.a" 1 "fre" } } */
+ /* { dg-final { cleanup-tree-dump "fre" } } */
Index: gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-19.c
===================================================================
*** /dev/null 1970-01-01 00:00:00.000000000 +0000
--- gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-19.c 2008-12-10 16:06:54.000000000 +0100
***************
*** 0 ****
--- 1,31 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O -fdump-tree-fre" } */
+
+ struct a
+ {
+ union
+ {
+ int a;
+ int b;
+ };
+ union
+ {
+ int c;
+ int d;
+ };
+ int e;
+ };
+
+ int f(struct a *c)
+ {
+ int d;
+ c->e = 2;
+ d = c->a;
+ c->c = 1;
+ return c->a + d;
+ }
+
+ /* We should have CSEd the load from c->a. */
+
+ /* { dg-final { scan-tree-dump-times "c_.*\\\.a" 1 "fre" } } */
+ /* { dg-final { cleanup-tree-dump "fre" } } */
Index: gcc/testsuite/gcc.dg/tree-ssa/ssa-lim-3.c
===================================================================
*** gcc/testsuite/gcc.dg/tree-ssa/ssa-lim-3.c.orig 2008-12-10 16:00:59.000000000 +0100
--- gcc/testsuite/gcc.dg/tree-ssa/ssa-lim-3.c 2008-12-10 16:06:54.000000000 +0100
***************
*** 1,5 ****
/* { dg-do compile } */
! /* { dg-options "-O2 -fdump-tree-lim-details" } */
struct { int x; int y; } global;
void foo(int n)
--- 1,5 ----
/* { dg-do compile } */
! /* { dg-options "-O -fdump-tree-lim-details" } */
struct { int x; int y; } global;
void foo(int n)
Index: gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-23.c
===================================================================
*** /dev/null 1970-01-01 00:00:00.000000000 +0000
--- gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-23.c 2008-12-10 16:06:54.000000000 +0100
***************
*** 0 ****
--- 1,13 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -fdump-tree-pre-stats" } */
+
+ struct { int x; int y; } global;
+ void foo(int n)
+ {
+ int i;
+ for ( i=0; i<n; i++)
+ global.y += global.x*global.x;
+ }
+
+ /* { dg-final { scan-tree-dump "Eliminated: 2" "pre" } } */
+ /* { dg-final { cleanup-tree-dump "pre" } } */
Index: gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-24.c
===================================================================
*** /dev/null 1970-01-01 00:00:00.000000000 +0000
--- gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-24.c 2008-12-10 16:06:54.000000000 +0100
***************
*** 0 ****
--- 1,15 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -fdump-tree-pre" } */
+
+ void foo(int *p, double *x, int n)
+ {
+ int i;
+ for (i = 0; i < n; ++i)
+ *(x + *p * i) = 0.0;
+ }
+
+ /* We should remove the unnecessary insertion of a phi-node and
+ _not_ end up using the phi result for replacement *p. */
+
+ /* { dg-final { scan-tree-dump-not "prephitmp" "pre" } } */
+ /* { dg-final { cleanup-tree-dump "pre" } } */