aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.9/gcc/tree-ssa-structalias.c
diff options
context:
space:
mode:
authorAndrew Senkevich <andrew.senkevich@intel.com>2015-02-27 20:35:05 +0300
committerAndrew Senkevich <andrew.senkevich@intel.com>2015-02-27 20:35:05 +0300
commit6278c3db6b4eb6f38ccd27c1227452ad9915db28 (patch)
tree7382c5f9da59cc3cdb935167b977ea13cf1acbd1 /gcc-4.9/gcc/tree-ssa-structalias.c
parentf8623c7fd5ebd974202059297c57c705b34eab7a (diff)
downloadtoolchain_gcc-6278c3db6b4eb6f38ccd27c1227452ad9915db28.zip
toolchain_gcc-6278c3db6b4eb6f38ccd27c1227452ad9915db28.tar.gz
toolchain_gcc-6278c3db6b4eb6f38ccd27c1227452ad9915db28.tar.bz2
[4.9] Additional SLM tuning. Backport from trunk.
2014-11-24 Richard Biener <rguenther@suse.de> PR tree-optimization/55334 * function.h (struct function): Add last_clique member. * tree-inline.c (remap_dependence_clique): New function. (remap_gimple_op_r): Remap dependence cliques in MEM_REFs. (copy_tree_body_r): Likewise. (copy_cfg_body): Free dependence map. (copy_gimple_seq_and_replace_locals): Likewise. * tree-pretty-print.c (dump_generic_node): Dump dependence info. * tree-ssa-alias.c (refs_may_alias_p_1): Use dependence info to answer alias query. * tree-ssa-structalias.c: Include tree-phinodes.h, ssa-iterators.h, tree-pretty-print.h and gimple-walk.h. (struct variable_info): Add is_restrict_var flag and ruid member. (new_var_info): Initialize is_restrict_var. (make_constraint_from_restrict): Likewise. (create_variable_info_for): Exclude restricts from global vars from new handling. (intra_create_variable_infos): But not those from parameters. (visit_loadstore): New function. (maybe_set_dependence_info): Likewise. (compute_dependence_clique): Likewise. (compute_may_aliases): Call compute_dependence_clique. * tree-data-ref.c (dr_analyze_indices): Copy dependence info to fake MEM_REF. (dr_may_alias_p): Use recorded dependence info to answer alias query. * tree-core.h (struct tree_base): Add clique, base struct in union. * tree.h (MR_DEPENDENCE_CLIQUE): New macro. (MR_DEPENDENCE_BASE): Likewise. * tree-inline.h (dependence_hasher): New hash-map kind. (struct copy_body_data): Add dependence_map pointer. * tree-streamer-in.c (unpack_value_fields): Stream dependence info. * tree-streamer-out.c (streamer_pack_tree_bitfields): Likewise. * gcc.dg/tree-ssa/restrict-5.c: New testcase. Change-Id: I45c8d5eac758aea881a884c131f627cc916cbaf3 Signed-off-by: Andrew Senkevich <andrew.senkevich@intel.com>
Diffstat (limited to 'gcc-4.9/gcc/tree-ssa-structalias.c')
-rw-r--r--gcc-4.9/gcc/tree-ssa-structalias.c203
1 files changed, 202 insertions, 1 deletions
diff --git a/gcc-4.9/gcc/tree-ssa-structalias.c b/gcc-4.9/gcc/tree-ssa-structalias.c
index abc99ba..f44667b 100644
--- a/gcc-4.9/gcc/tree-ssa-structalias.c
+++ b/gcc-4.9/gcc/tree-ssa-structalias.c
@@ -53,6 +53,10 @@
#include "splay-tree.h"
#include "params.h"
#include "alias.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-pretty-print.h"
+#include "gimple-walk.h"
/* The idea behind this analyzer is to generate set constraints from the
program, then solve the resulting constraints in order to generate the
@@ -273,12 +277,19 @@ struct variable_info
/* True if this field has only restrict qualified pointers. */
unsigned int only_restrict_pointers : 1;
+ /* True if this represents a heap var created for a restrict qualified
+ pointer. */
+ unsigned int is_restrict_var : 1;
+
/* True if this represents a global variable. */
unsigned int is_global_var : 1;
/* True if this represents a IPA function info. */
unsigned int is_fn_info : 1;
+ /* ??? Store somewhere better. */
+ unsigned short ruid;
+
/* The ID of the variable for the next field in this structure
or zero for the last field in this structure. */
unsigned next;
@@ -370,6 +381,7 @@ new_var_info (tree t, const char *name)
ret->is_heap_var = false;
ret->may_have_pointers = true;
ret->only_restrict_pointers = false;
+ ret->is_restrict_var = false;
ret->is_global_var = (t == NULL_TREE);
ret->is_fn_info = false;
if (t && DECL_P (t))
@@ -3782,6 +3794,7 @@ static varinfo_t
make_constraint_from_restrict (varinfo_t lhs, const char *name)
{
varinfo_t vi = make_heapvar (name);
+ vi->is_restrict_var = 1;
vi->is_global_var = 1;
vi->may_have_pointers = 1;
make_constraint_from (lhs, vi->id);
@@ -5760,7 +5773,11 @@ create_variable_info_for (tree decl, const char *name)
&& TYPE_RESTRICT (TREE_TYPE (decl)))
|| vi->only_restrict_pointers)
{
- make_constraint_from_global_restrict (vi, "GLOBAL_RESTRICT");
+ varinfo_t rvi
+ = make_constraint_from_global_restrict (vi, "GLOBAL_RESTRICT");
+ /* ??? For now exclude reads from globals as restrict sources
+ if those are not (indirectly) from incoming parameters. */
+ rvi->is_restrict_var = false;
continue;
}
@@ -5870,6 +5887,7 @@ intra_create_variable_infos (void)
tree heapvar = build_fake_var_decl (TREE_TYPE (TREE_TYPE (t)));
DECL_EXTERNAL (heapvar) = 1;
vi = create_variable_info_for_1 (heapvar, "PARM_NOALIAS");
+ vi->is_restrict_var = 1;
insert_vi_for_tree (heapvar, vi);
lhsc.var = p->id;
lhsc.type = SCALAR;
@@ -6953,6 +6971,186 @@ delete_points_to_sets (void)
obstack_free (&final_solutions_obstack, NULL);
}
+/* Mark "other" loads and stores as belonging to CLIQUE and with
+ base zero. */
+
+static bool
+visit_loadstore (gimple, tree base, tree ref, void *clique_)
+{
+ unsigned short clique = (uintptr_t)clique_;
+ if (TREE_CODE (base) == MEM_REF
+ || TREE_CODE (base) == TARGET_MEM_REF)
+ {
+ tree ptr = TREE_OPERAND (base, 0);
+ if (TREE_CODE (ptr) == SSA_NAME)
+ {
+ /* ??? We need to make sure 'ptr' doesn't include any of
+ the restrict tags in its points-to set. */
+ return false;
+ }
+
+ /* For now let decls through. */
+
+ /* Do not overwrite existing cliques (that includes clique, base
+ pairs we just set). */
+ if (MR_DEPENDENCE_CLIQUE (base) == 0)
+ {
+ MR_DEPENDENCE_CLIQUE (base) = clique;
+ MR_DEPENDENCE_BASE (base) = 0;
+ }
+ }
+
+ /* For plain decl accesses see whether they are accesses to globals
+ and rewrite them to MEM_REFs with { clique, 0 }. */
+ if (TREE_CODE (base) == VAR_DECL
+ && is_global_var (base)
+ /* ??? We can't rewrite a plain decl with the walk_stmt_load_store
+ ops callback. */
+ && base != ref)
+ {
+ tree *basep = &ref;
+ while (handled_component_p (*basep))
+ basep = &TREE_OPERAND (*basep, 0);
+ gcc_assert (TREE_CODE (*basep) == VAR_DECL);
+ tree ptr = build_fold_addr_expr (*basep);
+ tree zero = build_int_cst (TREE_TYPE (ptr), 0);
+ *basep = build2 (MEM_REF, TREE_TYPE (*basep), ptr, zero);
+ MR_DEPENDENCE_CLIQUE (*basep) = clique;
+ MR_DEPENDENCE_BASE (*basep) = 0;
+ }
+
+ return false;
+}
+
+/* If REF is a MEM_REF then assign a clique, base pair to it, updating
+ CLIQUE, *RESTRICT_VAR and LAST_RUID. Return whether dependence info
+ was assigned to REF. */
+
+static bool
+maybe_set_dependence_info (tree ref, tree ptr,
+ unsigned short &clique, varinfo_t restrict_var,
+ unsigned short &last_ruid)
+{
+ while (handled_component_p (ref))
+ ref = TREE_OPERAND (ref, 0);
+ if ((TREE_CODE (ref) == MEM_REF
+ || TREE_CODE (ref) == TARGET_MEM_REF)
+ && TREE_OPERAND (ref, 0) == ptr)
+ {
+ /* Do not overwrite existing cliques. This avoids overwriting dependence
+ info inlined from a function with restrict parameters inlined
+ into a function with restrict parameters. This usually means we
+ prefer to be precise in innermost loops. */
+ if (MR_DEPENDENCE_CLIQUE (ref) == 0)
+ {
+ if (clique == 0)
+ clique = ++cfun->last_clique;
+ if (restrict_var->ruid == 0)
+ restrict_var->ruid = ++last_ruid;
+ MR_DEPENDENCE_CLIQUE (ref) = clique;
+ MR_DEPENDENCE_BASE (ref) = restrict_var->ruid;
+ return true;
+ }
+ }
+ return false;
+}
+
+/* Compute the set of independend memory references based on restrict
+ tags and their conservative propagation to the points-to sets. */
+
+static void
+compute_dependence_clique (void)
+{
+ unsigned short clique = 0;
+ unsigned short last_ruid = 0;
+ for (unsigned i = 0; i < num_ssa_names; ++i)
+ {
+ tree ptr = ssa_name (i);
+ if (!ptr || !POINTER_TYPE_P (TREE_TYPE (ptr)))
+ continue;
+
+ /* Avoid all this when ptr is not dereferenced? */
+ tree p = ptr;
+ if (SSA_NAME_IS_DEFAULT_DEF (ptr)
+ && (TREE_CODE (SSA_NAME_VAR (ptr)) == PARM_DECL
+ || TREE_CODE (SSA_NAME_VAR (ptr)) == RESULT_DECL))
+ p = SSA_NAME_VAR (ptr);
+ varinfo_t vi = lookup_vi_for_tree (p);
+ if (!vi)
+ continue;
+ vi = get_varinfo (find (vi->id));
+ bitmap_iterator bi;
+ unsigned j;
+ varinfo_t restrict_var = NULL;
+ EXECUTE_IF_SET_IN_BITMAP (vi->solution, 0, j, bi)
+ {
+ varinfo_t oi = get_varinfo (j);
+ if (oi->is_restrict_var)
+ {
+ if (restrict_var)
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "found restrict pointed-to "
+ "for ");
+ print_generic_expr (dump_file, ptr, 0);
+ fprintf (dump_file, " but not exclusively\n");
+ }
+ restrict_var = NULL;
+ break;
+ }
+ restrict_var = oi;
+ }
+ /* NULL is the only other valid points-to entry. */
+ else if (oi->id != nothing_id)
+ {
+ restrict_var = NULL;
+ break;
+ }
+ }
+ /* Ok, found that ptr must(!) point to a single(!) restrict
+ variable. */
+ /* ??? PTA isn't really a proper propagation engine to compute
+ this property.
+ ??? We could handle merging of two restricts by unifying them. */
+ if (restrict_var)
+ {
+ /* Now look at possible dereferences of ptr. */
+ imm_use_iterator ui;
+ gimple use_stmt;
+ FOR_EACH_IMM_USE_STMT (use_stmt, ui, ptr)
+ {
+ /* ??? Calls and asms. */
+ if (!gimple_assign_single_p (use_stmt))
+ continue;
+ maybe_set_dependence_info (gimple_assign_lhs (use_stmt), ptr,
+ clique, restrict_var, last_ruid);
+ maybe_set_dependence_info (gimple_assign_rhs1 (use_stmt), ptr,
+ clique, restrict_var, last_ruid);
+ }
+ }
+ }
+
+ if (clique == 0)
+ return;
+
+ /* Assign the BASE id zero to all accesses not based on a restrict
+ pointer. That way they get disabiguated against restrict
+ accesses but not against each other. */
+ /* ??? For restricts derived from globals (thus not incoming
+ parameters) we can't restrict scoping properly thus the following
+ is too aggressive there. For now we have excluded those globals from
+ getting into the MR_DEPENDENCE machinery. */
+ basic_block bb;
+ FOR_EACH_BB_FN (bb, cfun)
+ for (gimple_stmt_iterator gsi = gsi_start_bb (bb);
+ !gsi_end_p (gsi); gsi_next (&gsi))
+ {
+ gimple stmt = gsi_stmt (gsi);
+ walk_stmt_load_store_ops (stmt, (void *)(uintptr_t)clique,
+ visit_loadstore, visit_loadstore);
+ }
+}
/* Compute points-to information for every SSA_NAME pointer in the
current function and compute the transitive closure of escaped
@@ -6984,6 +7182,9 @@ compute_may_aliases (void)
if (dump_file)
dump_alias_info (dump_file);
+ /* Compute restrict-based memory disambiguations. */
+ compute_dependence_clique ();
+
/* Deallocate memory used by aliasing data structures and the internal
points-to solution. */
delete_points_to_sets ();