Introduce EAF_NOREAD and cleanup EAF_UNUSED + ipa-modref
this patch add EAF_NOREAD (as disucssed on IRC already) and fixes meaning of EAF_UNUSED to be really unused and not "does not escape, is not clobbered, read or returned" since we have separate flags for each of the properties now. Since number of flags has grown I refactored the code a bit to avoid repeated uses of complex flag combinations and also simplified the logic of merging. Merging is bit tricky since we have flags that implies other flags (like NOESCAPE implies NODIRECTESCAPE) but code that sets only NOESCAPE. Perhaps it would make sense to update fnspecs to always set flag along with all the implications, but for now I am handlingit in merge. I made only trivial update to tree-ssa-structalias to handle EAF_NORETURN in normal function handling, but not in pure functions. The problem is that the way constraints are generated for pure functions makes this difficult. I think logical step is to track whether function reads/stores global memory and rewrite the constraint generation so we can handle normal, pure and const in unified manner. Bootstrapped/regtested x86_64-linux, plan to commit it after furhter testing. The patch improves alias oracle stats for cc1plus somewhat. From: Alias oracle query stats: refs_may_alias_p: 72380497 disambiguations, 82649832 queries ref_maybe_used_by_call_p: 495184 disambiguations, 73366950 queries call_may_clobber_ref_p: 259312 disambiguations, 263253 queries nonoverlapping_component_refs_p: 0 disambiguations, 38006 queries nonoverlapping_refs_since_match_p: 21157 disambiguations, 65698 must overlaps, 87756 queries aliasing_component_refs_p: 63141 disambiguations, 2164695 queries TBAA oracle: 25975753 disambiguations 61449632 queries 12138220 are in alias set 0 11316663 queries asked about the same object 144 queries asked about the same alias set 0 access volatile 10472885 are dependent in the DAG 1545967 are aritificially in conflict with void * Modref stats: modref use: 23857 disambiguations, 754515 queries modref clobber: 1392162 disambiguations, 17753512 queries 3450241 tbaa queries (0.194341 per modref query) 534816 base compares (0.030125 per modref query) PTA query stats: pt_solution_includes: 12394915 disambiguations, 20235925 queries pt_solutions_intersect: 1365299 disambiguations, 14638068 queries To: Alias oracle query stats: refs_may_alias_p: 72629640 disambiguations, 82903333 queries ref_maybe_used_by_call_p: 502474 disambiguations, 73612186 queries call_may_clobber_ref_p: 261806 disambiguations, 265659 queries nonoverlapping_component_refs_p: 0 disambiguations, 38007 queries nonoverlapping_refs_since_match_p: 21139 disambiguations, 65772 must overlaps, 87816 queries aliasing_component_refs_p: 63144 disambiguations, 2164330 queries TBAA oracle: 26059018 disambiguations 61571714 queries 12158033 are in alias set 0 11326115 queries asked about the same object 144 queries asked about the same alias set 0 access volatile 10484493 are dependent in the DAG 1543911 are aritificially in conflict with void * Modref stats: modref use: 24008 disambiguations, 712712 queries modref clobber: 1395917 disambiguations, 17163694 queries 3465657 tbaa queries (0.201918 per modref query) 537591 base compares (0.031321 per modref query) PTA query stats: pt_solution_includes: 12468934 disambiguations, 20295402 queries pt_solutions_intersect: 1391917 disambiguations, 14665265 queries I think it is mostly due to better heandling of EAF_NODIRECTESCAPE. Honza gcc/ChangeLog: 2021-08-12 Jan Hubicka <hubicka@ucw.cz> * ipa-modref.c (dump_eaf_flags): Dump EAF_NOREAD. (implicit_const_eaf_flags, implicit_pure_eaf_flags, ignore_stores_eaf_flags): New constants. (remove_useless_eaf_flags): New function. (eaf_flags_useful_p): Use it. (deref_flags): Add EAF_NOT_RETURNED if flag is unused; handle EAF_NOREAD. (modref_lattice::init): Add EAF_NOREAD. (modref_lattice::add_escape_point): Do not reacord escape point if result is unused. (modref_lattice::merge): EAF_NOESCAPE implies EAF_NODIRECTESCAPE; use remove_useless_eaf_flags. (modref_lattice::merge_deref): Use ignore_stores_eaf_flags. (modref_lattice::merge_direct_load): Add EAF_NOREAD (analyze_ssa_name_flags): Fix handling EAF_NOT_RETURNED (analyze_parms): Use remove_useless_eaf_flags. (ipa_merge_modref_summary_after_inlining): Use ignore_stores_eaf_flags. (modref_merge_call_site_flags): Add caller and ecf_flags parameter; use remove_useless_eaf_flags. (modref_propagate_flags_in_scc): Update. * ipa-modref.h: Turn eaf_flags_t back to char. * tree-core.h (EAF_NOT_RETURNED): Fix. (EAF_NOREAD): New constant * tree-ssa-alias.c: (ref_maybe_used_by_call_p_1): Check for EAF_NOREAD. * tree-ssa-structalias.c (handle_rhs_call): Handle new flags. (handle_pure_call): Likewise. gcc/testsuite/ChangeLog: 2021-08-12 Jan Hubicka <hubicka@ucw.cz> * gcc.dg/tree-ssa/modref-6.c: Update.
This commit is contained in:
parent
e37ddb91a8
commit
4341b1b165
169
gcc/ipa-modref.c
169
gcc/ipa-modref.c
@ -158,6 +158,8 @@ dump_eaf_flags (FILE *out, int flags, bool newline = true)
|
||||
fprintf (out, " unused");
|
||||
if (flags & EAF_NOT_RETURNED)
|
||||
fprintf (out, " not_returned");
|
||||
if (flags & EAF_NOREAD)
|
||||
fprintf (out, " noread");
|
||||
if (newline)
|
||||
fprintf (out, "\n");
|
||||
}
|
||||
@ -278,27 +280,46 @@ modref_summary::~modref_summary ()
|
||||
ggc_delete (stores);
|
||||
}
|
||||
|
||||
/* All flags that are implied by the ECF_CONST functions. */
|
||||
const int implicit_const_eaf_flags = EAF_DIRECT | EAF_NOCLOBBER | EAF_NOESCAPE
|
||||
| EAF_NODIRECTESCAPE | EAF_NOREAD;
|
||||
/* All flags that are implied by the ECF_PURE function. */
|
||||
const int implicit_pure_eaf_flags = EAF_NOCLOBBER | EAF_NOESCAPE
|
||||
| EAF_NODIRECTESCAPE;
|
||||
/* All flags implied when we know we can ignore stores (i.e. when handling
|
||||
call to noreturn). */
|
||||
const int ignore_stores_eaf_flags = EAF_DIRECT | EAF_NOCLOBBER | EAF_NOESCAPE
|
||||
| EAF_NODIRECTESCAPE;
|
||||
|
||||
/* Remove all flags from EAF_FLAGS that are implied by ECF_FLAGS and not
|
||||
useful to track. If returns_void is true moreover clear
|
||||
EAF_NOT_RETURNED. */
|
||||
static int
|
||||
remove_useless_eaf_flags (int eaf_flags, int ecf_flags, bool returns_void)
|
||||
{
|
||||
if (ecf_flags & ECF_NOVOPS)
|
||||
return 0;
|
||||
if (ecf_flags & ECF_CONST)
|
||||
eaf_flags &= ~implicit_const_eaf_flags;
|
||||
else if (ecf_flags & ECF_PURE)
|
||||
eaf_flags &= ~implicit_pure_eaf_flags;
|
||||
else if ((ecf_flags & ECF_NORETURN) || returns_void)
|
||||
eaf_flags &= ~EAF_NOT_RETURNED;
|
||||
/* Only NOCLOBBER or DIRECT flags alone are not useful (see comments
|
||||
in tree-ssa-alias.c). Give up earlier. */
|
||||
if ((eaf_flags & ~(EAF_DIRECT | EAF_NOCLOBBER)) == 0)
|
||||
return 0;
|
||||
return eaf_flags;
|
||||
}
|
||||
|
||||
/* Return true if FLAGS holds some useful information. */
|
||||
|
||||
static bool
|
||||
eaf_flags_useful_p (vec <eaf_flags_t> &flags, int ecf_flags)
|
||||
{
|
||||
for (unsigned i = 0; i < flags.length (); i++)
|
||||
if (ecf_flags & ECF_CONST)
|
||||
{
|
||||
if (flags[i] & (EAF_UNUSED | EAF_NOT_RETURNED))
|
||||
return true;
|
||||
}
|
||||
else if (ecf_flags & ECF_PURE)
|
||||
{
|
||||
if (flags[i] & (EAF_UNUSED | EAF_DIRECT | EAF_NOT_RETURNED))
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (flags[i])
|
||||
return true;
|
||||
}
|
||||
if (remove_useless_eaf_flags (flags[i], ecf_flags, false))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1320,17 +1341,35 @@ static int
|
||||
deref_flags (int flags, bool ignore_stores)
|
||||
{
|
||||
int ret = EAF_NODIRECTESCAPE;
|
||||
/* If argument is unused just account for
|
||||
the read involved in dereference. */
|
||||
if (flags & EAF_UNUSED)
|
||||
ret |= EAF_DIRECT | EAF_NOCLOBBER | EAF_NOESCAPE;
|
||||
ret |= EAF_DIRECT | EAF_NOCLOBBER | EAF_NOESCAPE | EAF_NOT_RETURNED;
|
||||
else
|
||||
{
|
||||
if ((flags & EAF_NOCLOBBER) || ignore_stores)
|
||||
ret |= EAF_NOCLOBBER;
|
||||
if ((flags & EAF_NOESCAPE) || ignore_stores)
|
||||
ret |= EAF_NOESCAPE;
|
||||
/* If the value dereferenced is not used for another load or store
|
||||
we can still consider ARG as used only directly.
|
||||
|
||||
Consider
|
||||
|
||||
int
|
||||
test (int *a)
|
||||
{
|
||||
return *a!=0;
|
||||
}
|
||||
|
||||
*/
|
||||
if ((flags & (EAF_NOREAD | EAF_NOT_RETURNED | EAF_NOESCAPE | EAF_DIRECT))
|
||||
== (EAF_NOREAD | EAF_NOT_RETURNED | EAF_NOESCAPE | EAF_DIRECT)
|
||||
&& ((flags & EAF_NOCLOBBER) || ignore_stores))
|
||||
ret |= EAF_DIRECT;
|
||||
if (flags & EAF_NOT_RETURNED)
|
||||
ret |= EAF_NOT_RETURNED;
|
||||
}
|
||||
if (flags & EAF_NOT_RETURNED)
|
||||
ret |= EAF_NOT_RETURNED;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -1355,7 +1394,7 @@ class modref_lattice
|
||||
{
|
||||
public:
|
||||
/* EAF flags of the SSA name. */
|
||||
int flags;
|
||||
eaf_flags_t flags;
|
||||
/* DFS bookkkeeping: we don't do real dataflow yet. */
|
||||
bool known;
|
||||
bool open;
|
||||
@ -1379,8 +1418,12 @@ public:
|
||||
void
|
||||
modref_lattice::init ()
|
||||
{
|
||||
flags = EAF_DIRECT | EAF_NOCLOBBER | EAF_NOESCAPE | EAF_UNUSED
|
||||
| EAF_NODIRECTESCAPE | EAF_NOT_RETURNED;
|
||||
/* All flags we track. */
|
||||
int f = EAF_DIRECT | EAF_NOCLOBBER | EAF_NOESCAPE | EAF_UNUSED
|
||||
| EAF_NODIRECTESCAPE | EAF_NOT_RETURNED | EAF_NOREAD;
|
||||
flags = f;
|
||||
/* Check that eaf_flags_t is wide enough to hold all flags. */
|
||||
gcc_checking_assert (f == flags);
|
||||
open = true;
|
||||
known = false;
|
||||
}
|
||||
@ -1424,8 +1467,8 @@ modref_lattice::add_escape_point (gcall *call, int arg, int min_flags,
|
||||
unsigned int i;
|
||||
|
||||
/* If we already determined flags to be bad enough,
|
||||
* we do not need to record. */
|
||||
if ((flags & min_flags) == flags)
|
||||
we do not need to record. */
|
||||
if ((flags & min_flags) == flags || (min_flags & EAF_UNUSED))
|
||||
return false;
|
||||
|
||||
FOR_EACH_VEC_ELT (escape_points, i, ep)
|
||||
@ -1455,13 +1498,18 @@ modref_lattice::merge (int f)
|
||||
{
|
||||
if (f & EAF_UNUSED)
|
||||
return false;
|
||||
/* Noescape implies that value also does not escape directly.
|
||||
Fnspec machinery does set both so compensate for this. */
|
||||
if (f & EAF_NOESCAPE)
|
||||
f |= EAF_NODIRECTESCAPE;
|
||||
if ((flags & f) != flags)
|
||||
{
|
||||
flags &= f;
|
||||
/* Only NOCLOBBER or DIRECT flags alone are not useful (see comments
|
||||
in tree-ssa-alias.c). Give up earlier. */
|
||||
if ((flags & ~(EAF_DIRECT | EAF_NOCLOBBER)) == 0)
|
||||
flags = 0;
|
||||
/* Prune obvoiusly useless flags;
|
||||
We do not have ECF_FLAGS handy which is not big problem since
|
||||
we will do final flags cleanup before producing summary.
|
||||
Merging should be fast so it can work well with dataflow. */
|
||||
flags = remove_useless_eaf_flags (flags, 0, false);
|
||||
if (!flags)
|
||||
escape_points.release ();
|
||||
return true;
|
||||
@ -1509,7 +1557,7 @@ modref_lattice::merge_deref (const modref_lattice &with, bool ignore_stores)
|
||||
if (with.escape_points[i].direct)
|
||||
min_flags = deref_flags (min_flags, ignore_stores);
|
||||
else if (ignore_stores)
|
||||
min_flags |= EAF_NOCLOBBER | EAF_NOESCAPE | EAF_NODIRECTESCAPE;
|
||||
min_flags |= ignore_stores_eaf_flags;
|
||||
changed |= add_escape_point (with.escape_points[i].call,
|
||||
with.escape_points[i].arg,
|
||||
min_flags,
|
||||
@ -1523,7 +1571,7 @@ modref_lattice::merge_deref (const modref_lattice &with, bool ignore_stores)
|
||||
bool
|
||||
modref_lattice::merge_direct_load ()
|
||||
{
|
||||
return merge (~EAF_UNUSED);
|
||||
return merge (~(EAF_UNUSED | EAF_NOREAD));
|
||||
}
|
||||
|
||||
/* Merge in flags for direct store. */
|
||||
@ -1632,6 +1680,9 @@ analyze_ssa_name_flags (tree name, vec<modref_lattice> &lattice, int depth,
|
||||
fprintf (dump_file, "%*s Analyzing stmt: ", depth * 4, "");
|
||||
print_gimple_stmt (dump_file, use_stmt, 0);
|
||||
}
|
||||
/* If we see a direct non-debug use, clear unused bit.
|
||||
All dereferneces should be accounted below using deref_flags. */
|
||||
lattice[index].merge (~EAF_UNUSED);
|
||||
|
||||
/* Gimple return may load the return value.
|
||||
Returning name counts as an use by tree-ssa-structalias.c */
|
||||
@ -1642,7 +1693,7 @@ analyze_ssa_name_flags (tree name, vec<modref_lattice> &lattice, int depth,
|
||||
else if (memory_access_to (gimple_return_retval (ret), name))
|
||||
{
|
||||
lattice[index].merge_direct_load ();
|
||||
lattice[index].merge (~EAF_NOT_RETURNED);
|
||||
lattice[index].merge (~(EAF_UNUSED | EAF_NOT_RETURNED));
|
||||
}
|
||||
}
|
||||
/* Account for LHS store, arg loads and flags from callee function. */
|
||||
@ -1697,8 +1748,7 @@ analyze_ssa_name_flags (tree name, vec<modref_lattice> &lattice, int depth,
|
||||
int call_flags = gimple_call_arg_flags (call, i)
|
||||
| EAF_NOT_RETURNED;
|
||||
if (ignore_stores)
|
||||
call_flags |= EAF_NOCLOBBER | EAF_NOESCAPE
|
||||
| EAF_NODIRECTESCAPE;
|
||||
call_flags |= ignore_stores_eaf_flags;
|
||||
|
||||
if (!record_ipa)
|
||||
lattice[index].merge (call_flags);
|
||||
@ -1890,14 +1940,12 @@ analyze_parms (modref_summary *summary, modref_summary_lto *summary_lto,
|
||||
analyze_ssa_name_flags (name, lattice, 0, ipa);
|
||||
int flags = lattice[SSA_NAME_VERSION (name)].flags;
|
||||
|
||||
/* For pure functions we have implicit NOCLOBBER
|
||||
and NOESCAPE. */
|
||||
if (ecf_flags & ECF_PURE)
|
||||
flags &= (EAF_UNUSED | EAF_DIRECT | EAF_NOT_RETURNED);
|
||||
/* Only useful flags for const function are EAF_NOT_RETURNED and
|
||||
EAF_UNUSED. */
|
||||
if (ecf_flags & ECF_CONST)
|
||||
flags &= (EAF_UNUSED | EAF_NOT_RETURNED);
|
||||
/* Eliminate useless flags so we do not end up storing unnecessary
|
||||
summaries. */
|
||||
|
||||
flags = remove_useless_eaf_flags
|
||||
(flags, ecf_flags,
|
||||
VOID_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl))));
|
||||
|
||||
if (flags)
|
||||
{
|
||||
@ -3176,7 +3224,7 @@ ipa_merge_modref_summary_after_inlining (cgraph_edge *edge)
|
||||
if (!ee->direct)
|
||||
flags = deref_flags (flags, ignore_stores);
|
||||
else if (ignore_stores)
|
||||
flags |= EAF_NOCLOBBER | EAF_NOESCAPE | EAF_NODIRECTESCAPE;
|
||||
flags |= ignore_stores_eaf_flags;
|
||||
flags |= ee->min_flags;
|
||||
to_info->arg_flags[ee->parm_index] &= flags;
|
||||
if (to_info->arg_flags[ee->parm_index])
|
||||
@ -3190,7 +3238,7 @@ ipa_merge_modref_summary_after_inlining (cgraph_edge *edge)
|
||||
if (!ee->direct)
|
||||
flags = deref_flags (flags, ignore_stores);
|
||||
else if (ignore_stores)
|
||||
flags |= EAF_NOCLOBBER | EAF_NOESCAPE | EAF_NODIRECTESCAPE;
|
||||
flags |= ignore_stores_eaf_flags;
|
||||
flags |= ee->min_flags;
|
||||
to_info_lto->arg_flags[ee->parm_index] &= flags;
|
||||
if (to_info_lto->arg_flags[ee->parm_index])
|
||||
@ -3673,11 +3721,13 @@ modref_merge_call_site_flags (escape_summary *sum,
|
||||
modref_summary_lto *cur_summary_lto,
|
||||
modref_summary *summary,
|
||||
modref_summary_lto *summary_lto,
|
||||
bool ignore_stores)
|
||||
tree caller,
|
||||
int ecf_flags)
|
||||
{
|
||||
escape_entry *ee;
|
||||
unsigned int i;
|
||||
bool changed = false;
|
||||
bool ignore_stores = ignore_stores_p (caller, ecf_flags);
|
||||
|
||||
/* If we have no useful info to propagate. */
|
||||
if ((!cur_summary || !cur_summary->arg_flags.length ())
|
||||
@ -3701,21 +3751,27 @@ modref_merge_call_site_flags (escape_summary *sum,
|
||||
}
|
||||
else if (ignore_stores)
|
||||
{
|
||||
flags |= EAF_NOESCAPE | EAF_NOCLOBBER | EAF_NODIRECTESCAPE;
|
||||
flags_lto |= EAF_NOESCAPE | EAF_NOCLOBBER | EAF_NODIRECTESCAPE;
|
||||
flags |= ignore_stores_eaf_flags;
|
||||
flags_lto |= ignore_stores_eaf_flags;
|
||||
}
|
||||
/* Returning the value is already accounted to at local propagation. */
|
||||
flags |= ee->min_flags | EAF_NOT_RETURNED;
|
||||
flags_lto |= ee->min_flags | EAF_NOT_RETURNED;
|
||||
/* Noescape implies that value also does not escape directly.
|
||||
Fnspec machinery does set both so compensate for this. */
|
||||
if (flags & EAF_NOESCAPE)
|
||||
flags |= EAF_NODIRECTESCAPE;
|
||||
if (flags_lto & EAF_NOESCAPE)
|
||||
flags_lto |= EAF_NODIRECTESCAPE;
|
||||
if (!(flags & EAF_UNUSED)
|
||||
&& cur_summary && ee->parm_index < cur_summary->arg_flags.length ())
|
||||
{
|
||||
int f = cur_summary->arg_flags[ee->parm_index];
|
||||
if ((f & flags) != f)
|
||||
{
|
||||
f = f & flags;
|
||||
if ((f & ~(EAF_DIRECT | EAF_NOCLOBBER)) == 0)
|
||||
f = 0;
|
||||
f = remove_useless_eaf_flags
|
||||
(f & flags, ecf_flags,
|
||||
VOID_TYPE_P (TREE_TYPE (TREE_TYPE (caller))));
|
||||
cur_summary->arg_flags[ee->parm_index] = f;
|
||||
changed = true;
|
||||
}
|
||||
@ -3727,9 +3783,9 @@ modref_merge_call_site_flags (escape_summary *sum,
|
||||
int f = cur_summary_lto->arg_flags[ee->parm_index];
|
||||
if ((f & flags_lto) != f)
|
||||
{
|
||||
f = f & flags;
|
||||
if ((f & ~(EAF_DIRECT | EAF_NOCLOBBER)) == 0)
|
||||
f = 0;
|
||||
f = remove_useless_eaf_flags
|
||||
(f & flags_lto, ecf_flags,
|
||||
VOID_TYPE_P (TREE_TYPE (TREE_TYPE (caller))));
|
||||
cur_summary_lto->arg_flags[ee->parm_index] = f;
|
||||
changed = true;
|
||||
}
|
||||
@ -3780,8 +3836,8 @@ modref_propagate_flags_in_scc (cgraph_node *component_node)
|
||||
|
||||
changed |= modref_merge_call_site_flags
|
||||
(sum, cur_summary, cur_summary_lto,
|
||||
NULL, NULL, ignore_stores_p (node->decl,
|
||||
e->indirect_info->ecf_flags));
|
||||
NULL, NULL,
|
||||
node->decl, e->indirect_info->ecf_flags);
|
||||
}
|
||||
|
||||
if (!cur_summary && !cur_summary_lto)
|
||||
@ -3790,12 +3846,13 @@ modref_propagate_flags_in_scc (cgraph_node *component_node)
|
||||
for (cgraph_edge *callee_edge = cur->callees; callee_edge;
|
||||
callee_edge = callee_edge->next_callee)
|
||||
{
|
||||
int flags = flags_from_decl_or_type (callee_edge->callee->decl);
|
||||
int ecf_flags = flags_from_decl_or_type
|
||||
(callee_edge->callee->decl);
|
||||
modref_summary *callee_summary = NULL;
|
||||
modref_summary_lto *callee_summary_lto = NULL;
|
||||
struct cgraph_node *callee;
|
||||
|
||||
if (flags & (ECF_CONST | ECF_NOVOPS)
|
||||
if (ecf_flags & (ECF_CONST | ECF_NOVOPS)
|
||||
|| !callee_edge->inline_failed)
|
||||
continue;
|
||||
/* Get the callee and its summary. */
|
||||
@ -3832,7 +3889,7 @@ modref_propagate_flags_in_scc (cgraph_node *component_node)
|
||||
changed |= modref_merge_call_site_flags
|
||||
(sum, cur_summary, cur_summary_lto,
|
||||
callee_summary, callee_summary_lto,
|
||||
ignore_stores_p (node->decl, flags));
|
||||
node->decl, ecf_flags);
|
||||
if (dump_file && changed)
|
||||
{
|
||||
if (cur_summary)
|
||||
|
@ -21,7 +21,7 @@ along with GCC; see the file COPYING3. If not see
|
||||
#define IPA_MODREF_H
|
||||
|
||||
typedef modref_tree <alias_set_type> modref_records;
|
||||
typedef unsigned short eaf_flags_t;
|
||||
typedef unsigned char eaf_flags_t;
|
||||
|
||||
/* Single function summary. */
|
||||
|
||||
|
@ -32,6 +32,6 @@ int test2()
|
||||
/* Flags for pure call. */
|
||||
/* { dg-final { scan-tree-dump "parm 0 flags: direct not_returned" "modref1" } } */
|
||||
/* Flags for const call. */
|
||||
/* { dg-final { scan-tree-dump "parm 0 flags: unused not_returned" "modref1" } } */
|
||||
/* { dg-final { scan-tree-dump "parm 0 flags: not_returned" "modref1" } } */
|
||||
/* Overall we want to make "int a" non escaping. */
|
||||
/* { dg-final { scan-tree-dump "return 42" "optimized" } } */
|
||||
|
@ -115,7 +115,10 @@ struct die_struct;
|
||||
#define EAF_NODIRECTESCAPE (1 << 4)
|
||||
|
||||
/* Nonzero if the argument does not escape to return value. */
|
||||
#define EAF_NOT_RETURNED (1 << 8)
|
||||
#define EAF_NOT_RETURNED (1 << 5)
|
||||
|
||||
/* Nonzero if the argument is not read. */
|
||||
#define EAF_NOREAD (1 << 6)
|
||||
|
||||
/* Call return flags. */
|
||||
/* Mask for the argument number that is returned. Lower two bits of
|
||||
|
@ -2870,7 +2870,7 @@ process_args:
|
||||
tree op = gimple_call_arg (call, i);
|
||||
int flags = gimple_call_arg_flags (call, i);
|
||||
|
||||
if (flags & EAF_UNUSED)
|
||||
if (flags & (EAF_UNUSED | EAF_NOREAD))
|
||||
continue;
|
||||
|
||||
if (TREE_CODE (op) == WITH_SIZE_EXPR)
|
||||
|
@ -4063,8 +4063,14 @@ handle_rhs_call (gcall *stmt, vec<ce_s> *results)
|
||||
tree arg = gimple_call_arg (stmt, i);
|
||||
int flags = gimple_call_arg_flags (stmt, i);
|
||||
|
||||
/* If the argument is not used we can ignore it. */
|
||||
if (flags & EAF_UNUSED)
|
||||
/* If the argument is not used we can ignore it.
|
||||
Similarly argument is invisile for us if it not clobbered, does not
|
||||
escape, is not read and can not be returned. */
|
||||
if ((flags & EAF_UNUSED)
|
||||
|| ((flags & (EAF_NOCLOBBER | EAF_NOESCAPE | EAF_NOREAD
|
||||
| EAF_NOT_RETURNED))
|
||||
== (EAF_NOCLOBBER | EAF_NOESCAPE | EAF_NOREAD
|
||||
| EAF_NOT_RETURNED)))
|
||||
continue;
|
||||
|
||||
/* As we compute ESCAPED context-insensitive we do not gain
|
||||
@ -4316,7 +4322,9 @@ handle_pure_call (gcall *stmt, vec<ce_s> *results)
|
||||
int flags = gimple_call_arg_flags (stmt, i);
|
||||
|
||||
/* If the argument is not used we can ignore it. */
|
||||
if (flags & EAF_UNUSED)
|
||||
if ((flags & EAF_UNUSED)
|
||||
|| (flags & (EAF_NOT_RETURNED | EAF_NOREAD))
|
||||
== (EAF_NOT_RETURNED | EAF_NOREAD))
|
||||
continue;
|
||||
if (!uses)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user