Avoid recomputing PHI results after failure (PR104203).
Resolves: PR tree-optimization/104203 - huge compile-time regression in pointer_query gcc/ChangeLog: PR tree-optimization/104203 * gimple-ssa-warn-access.cc (pass_data pass_data_waccess): Use TV_WARN_ACCESS. * pointer-query.cc (access_ref::merge_ref): Change return type. Convert failure to a conservative success. (access_ref::get_ref): Adjust to the change above. Short-circuit PHI evaluation after first failure turned into conservative success. * pointer-query.h (access_ref::merge_ref): Change return type. * timevar.def (TV_WARN_ACCESS): New timer variable.
This commit is contained in:
parent
5c1f274e3e
commit
58ec0964b1
@ -2053,7 +2053,7 @@ const pass_data pass_data_waccess = {
|
|||||||
GIMPLE_PASS,
|
GIMPLE_PASS,
|
||||||
"waccess",
|
"waccess",
|
||||||
OPTGROUP_NONE,
|
OPTGROUP_NONE,
|
||||||
TV_NONE,
|
TV_WARN_ACCESS, /* timer variable */
|
||||||
PROP_cfg, /* properties_required */
|
PROP_cfg, /* properties_required */
|
||||||
0, /* properties_provided */
|
0, /* properties_provided */
|
||||||
0, /* properties_destroyed */
|
0, /* properties_destroyed */
|
||||||
|
@ -629,7 +629,7 @@ access_ref::phi () const
|
|||||||
ARG refers to the null pointer. Return true on success and false
|
ARG refers to the null pointer. Return true on success and false
|
||||||
on failure. */
|
on failure. */
|
||||||
|
|
||||||
bool
|
void
|
||||||
access_ref::merge_ref (vec<access_ref> *all_refs, tree arg, gimple *stmt,
|
access_ref::merge_ref (vec<access_ref> *all_refs, tree arg, gimple *stmt,
|
||||||
int ostype, bool skip_null,
|
int ostype, bool skip_null,
|
||||||
ssa_name_limit_t &snlim, pointer_query &qry)
|
ssa_name_limit_t &snlim, pointer_query &qry)
|
||||||
@ -637,8 +637,16 @@ access_ref::merge_ref (vec<access_ref> *all_refs, tree arg, gimple *stmt,
|
|||||||
access_ref aref;
|
access_ref aref;
|
||||||
if (!compute_objsize_r (arg, stmt, false, ostype, &aref, snlim, &qry)
|
if (!compute_objsize_r (arg, stmt, false, ostype, &aref, snlim, &qry)
|
||||||
|| aref.sizrng[0] < 0)
|
|| aref.sizrng[0] < 0)
|
||||||
/* This may be a PHI with all null pointer arguments. */
|
{
|
||||||
return false;
|
/* This may be a PHI with all null pointer arguments. Handle it
|
||||||
|
conservatively by setting all properties to the most permissive
|
||||||
|
values. */
|
||||||
|
base0 = false;
|
||||||
|
offrng[0] = offrng[1] = 0;
|
||||||
|
add_max_offset ();
|
||||||
|
set_max_size_range ();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (all_refs)
|
if (all_refs)
|
||||||
{
|
{
|
||||||
@ -675,13 +683,13 @@ access_ref::merge_ref (vec<access_ref> *all_refs, tree arg, gimple *stmt,
|
|||||||
if (arg_known_size)
|
if (arg_known_size)
|
||||||
sizrng[0] = aref.sizrng[0];
|
sizrng[0] = aref.sizrng[0];
|
||||||
|
|
||||||
return true;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Disregard null pointers in PHIs with two or more arguments.
|
/* Disregard null pointers in PHIs with two or more arguments.
|
||||||
TODO: Handle this better! */
|
TODO: Handle this better! */
|
||||||
if (nullp)
|
if (nullp)
|
||||||
return true;
|
return;
|
||||||
|
|
||||||
const bool known_size = (sizrng[0] != 0 || sizrng[1] != maxobjsize);
|
const bool known_size = (sizrng[0] != 0 || sizrng[1] != maxobjsize);
|
||||||
|
|
||||||
@ -717,7 +725,7 @@ access_ref::merge_ref (vec<access_ref> *all_refs, tree arg, gimple *stmt,
|
|||||||
sizrng[0] = minsize;
|
sizrng[0] = minsize;
|
||||||
parmarray = merged_parmarray;
|
parmarray = merged_parmarray;
|
||||||
|
|
||||||
return true;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Determine and return the largest object to which *THIS refers. If
|
/* Determine and return the largest object to which *THIS refers. If
|
||||||
@ -755,14 +763,12 @@ access_ref::get_ref (vec<access_ref> *all_refs,
|
|||||||
|
|
||||||
access_ref aref;
|
access_ref aref;
|
||||||
tree arg1 = gimple_assign_rhs1 (def_stmt);
|
tree arg1 = gimple_assign_rhs1 (def_stmt);
|
||||||
if (!aref.merge_ref (all_refs, arg1, def_stmt, ostype, false,
|
aref.merge_ref (all_refs, arg1, def_stmt, ostype, false,
|
||||||
*psnlim, *qry))
|
*psnlim, *qry);
|
||||||
return NULL_TREE;
|
|
||||||
|
|
||||||
tree arg2 = gimple_assign_rhs2 (def_stmt);
|
tree arg2 = gimple_assign_rhs2 (def_stmt);
|
||||||
if (!aref.merge_ref (all_refs, arg2, def_stmt, ostype, false,
|
aref.merge_ref (all_refs, arg2, def_stmt, ostype, false,
|
||||||
*psnlim, *qry))
|
*psnlim, *qry);
|
||||||
return NULL_TREE;
|
|
||||||
|
|
||||||
if (pref && pref != this)
|
if (pref && pref != this)
|
||||||
{
|
{
|
||||||
@ -801,15 +807,23 @@ access_ref::get_ref (vec<access_ref> *all_refs,
|
|||||||
phi_ref = *pref;
|
phi_ref = *pref;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const offset_int maxobjsize = wi::to_offset (max_object_size ());
|
||||||
const unsigned nargs = gimple_phi_num_args (phi_stmt);
|
const unsigned nargs = gimple_phi_num_args (phi_stmt);
|
||||||
for (unsigned i = 0; i < nargs; ++i)
|
for (unsigned i = 0; i < nargs; ++i)
|
||||||
{
|
{
|
||||||
access_ref phi_arg_ref;
|
access_ref phi_arg_ref;
|
||||||
bool skip_null = i || i + 1 < nargs;
|
bool skip_null = i || i + 1 < nargs;
|
||||||
tree arg = gimple_phi_arg_def (phi_stmt, i);
|
tree arg = gimple_phi_arg_def (phi_stmt, i);
|
||||||
if (!phi_ref.merge_ref (all_refs, arg, phi_stmt, ostype, skip_null,
|
phi_ref.merge_ref (all_refs, arg, phi_stmt, ostype, skip_null,
|
||||||
*psnlim, *qry))
|
*psnlim, *qry);
|
||||||
return NULL_TREE;
|
|
||||||
|
if (!phi_ref.base0
|
||||||
|
&& phi_ref.sizrng[0] == 0
|
||||||
|
&& phi_ref.sizrng[1] >= maxobjsize)
|
||||||
|
/* When an argument results in the most permissive result,
|
||||||
|
the remaining arguments cannot constrain it. Short-circuit
|
||||||
|
the evaluation. */
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (phi_ref.sizrng[0] < 0)
|
if (phi_ref.sizrng[0] < 0)
|
||||||
|
@ -67,7 +67,7 @@ struct access_ref
|
|||||||
gphi *phi () const;
|
gphi *phi () const;
|
||||||
|
|
||||||
/* Merge the result for a pointer with *THIS. */
|
/* Merge the result for a pointer with *THIS. */
|
||||||
bool merge_ref (vec<access_ref> *all_refs, tree, gimple *, int, bool,
|
void merge_ref (vec<access_ref> *all_refs, tree, gimple *, int, bool,
|
||||||
ssa_name_limit_t &, pointer_query &);
|
ssa_name_limit_t &, pointer_query &);
|
||||||
|
|
||||||
/* Return the object to which REF refers. */
|
/* Return the object to which REF refers. */
|
||||||
|
@ -307,6 +307,7 @@ DEFTIMEVAR (TV_TREE_UBSAN , "tree ubsan")
|
|||||||
DEFTIMEVAR (TV_INITIALIZE_RTL , "initialize rtl")
|
DEFTIMEVAR (TV_INITIALIZE_RTL , "initialize rtl")
|
||||||
DEFTIMEVAR (TV_GIMPLE_LADDRESS , "address lowering")
|
DEFTIMEVAR (TV_GIMPLE_LADDRESS , "address lowering")
|
||||||
DEFTIMEVAR (TV_TREE_LOOP_IFCVT , "tree loop if-conversion")
|
DEFTIMEVAR (TV_TREE_LOOP_IFCVT , "tree loop if-conversion")
|
||||||
|
DEFTIMEVAR (TV_WARN_ACCESS , "access analysis")
|
||||||
|
|
||||||
/* Everything else in rest_of_compilation not included above. */
|
/* Everything else in rest_of_compilation not included above. */
|
||||||
DEFTIMEVAR (TV_EARLY_LOCAL , "early local passes")
|
DEFTIMEVAR (TV_EARLY_LOCAL , "early local passes")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user