re PR tree-optimization/55334 (mgrid regression (ipa-cp disables vectorization))

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.
	* gimple-fold.c (maybe_canonicalize_mem_ref_addr): Avoid
	throwing away dependence info.
	* 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.

From-SVN: r218005
This commit is contained in:
Richard Biener 2014-11-24 09:24:50 +00:00
parent f3dccf5091
commit aa09816577
1 changed files with 202 additions and 1 deletions

View File

@ -64,6 +64,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
@ -284,12 +288,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;
@ -381,6 +392,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))
@ -3785,6 +3797,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);
@ -5749,7 +5762,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;
}
@ -5859,6 +5876,7 @@ intra_create_variable_infos (struct function *fn)
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;
@ -6933,6 +6951,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
@ -6964,6 +7162,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 ();