Introduce EAF_NOREAD and cleanup EAF_UNUSED + ipa-modref
Jan Hubicka
hubicka@ucw.cz
Thu Aug 12 19:02:02 GMT 2021
Hi,
this patch add EAF_NOREAD (as disucssed on IRC earlier) 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.
Number of flags has grown and I thus 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 and
not NODIRECTESCAPE and therefore simple and does not right thing. I
added code that deals with the implications. 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 and will send changes
needed for EAF_NOREAD incrementally, so it can be discussed. 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.
diff --git a/gcc/ipa-modref.c b/gcc/ipa-modref.c
index c65b2f65372..fafd804d4ba 100644
--- a/gcc/ipa-modref.c
+++ b/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)
diff --git a/gcc/ipa-modref.h b/gcc/ipa-modref.h
index 498cc2414ac..540fdea8efa 100644
--- a/gcc/ipa-modref.h
+++ b/gcc/ipa-modref.h
@@ -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. */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/modref-6.c b/gcc/testsuite/gcc.dg/tree-ssa/modref-6.c
index 8db9a1d619c..2d97a4903ff 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/modref-6.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/modref-6.c
@@ -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" } } */
diff --git a/gcc/tree-core.h b/gcc/tree-core.h
index bfab988ecdd..45ffcb84446 100644
--- a/gcc/tree-core.h
+++ b/gcc/tree-core.h
@@ -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
diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c
index cbd51ac4d7c..ce667ff32b9 100644
--- a/gcc/tree-ssa-alias.c
+++ b/gcc/tree-ssa-alias.c
@@ -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)
diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c
index c6949268881..ad31cc4333c 100644
--- a/gcc/tree-ssa-structalias.c
+++ b/gcc/tree-ssa-structalias.c
@@ -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 +4329,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)
{
More information about the Gcc-patches
mailing list