diff options
author | Jan Hubicka <jh@suse.cz> | 2020-11-25 20:51:26 +0100 |
---|---|---|
committer | Jan Hubicka <jh@suse.cz> | 2020-11-25 20:51:26 +0100 |
commit | bb07490abba850fd5b1d2d09d76d18b8bdc7d817 (patch) | |
tree | 088a7d9ff0a070269412fd9c22a3ce3861066442 | |
parent | 5962efe9186559ada404ac8f9f56006648a5858e (diff) | |
download | gcc-bb07490abba850fd5b1d2d09d76d18b8bdc7d817.zip gcc-bb07490abba850fd5b1d2d09d76d18b8bdc7d817.tar.gz gcc-bb07490abba850fd5b1d2d09d76d18b8bdc7d817.tar.bz2 |
Add EAF_NODIRECTESCAPE flag
Main limitation of modref is the fact that it does not
track anything in memory. This is intentional - I wanted the initial
implementation to be cheap. However it also makes it very limited when it comes
to detecting noescape especially because it is paranoid about what memory
accesses may be used to copy (bits of) pointers.
This patch adds EAF_NODIRECTSCAPE that is weaker vairant of EAF_NOESCAPE where
we only know that the pointer itself does not escape, but memory pointed to
may. This is a lot more reliable to auto-detect that EAF_NOESCAPE and still
enables additional optimization. With patch we get nodirectscape flag for b
that enables in practice similar optimization as EAF_NOESCAPE for arrays of
integers that points nowhere :)
gcc/ChangeLog:
* gimple.c (gimple_call_arg_flags): Also imply EAF_NODIRECTESCAPE.
* tree-core.h (EAF_NODRECTESCAPE): New flag.
* tree-ssa-structalias.c (make_indirect_escape_constraint): New
function.
(handle_rhs_call): Hanlde EAF_NODIRECTESCAPE.
* ipa-modref.c (dump_eaf_flags): Print EAF_NODIRECTESCAPE.
(deref_flags): Dereference is always EAF_NODIRECTESCAPE.
(modref_lattice::init): Also set EAF_NODIRECTESCAPE.
(analyze_ssa_name_flags): Pure functions do not affect
EAF_NODIRECTESCAPE.
(analyze_params): Likewise.
(ipa_merge_modref_summary_after_inlining): Likewise.
(modref_merge_call_site_flags): Likewise.
-rw-r--r-- | gcc/gimple.c | 2 | ||||
-rw-r--r-- | gcc/ipa-modref.c | 20 | ||||
-rw-r--r-- | gcc/tree-core.h | 4 | ||||
-rw-r--r-- | gcc/tree-ssa-structalias.c | 25 |
4 files changed, 40 insertions, 11 deletions
diff --git a/gcc/gimple.c b/gcc/gimple.c index e3e508d..e8246b7 100644 --- a/gcc/gimple.c +++ b/gcc/gimple.c @@ -1543,7 +1543,7 @@ gimple_call_arg_flags (const gcall *stmt, unsigned arg) if (fnspec.arg_direct_p (arg)) flags |= EAF_DIRECT; if (fnspec.arg_noescape_p (arg)) - flags |= EAF_NOESCAPE; + flags |= EAF_NOESCAPE | EAF_NODIRECTESCAPE; if (fnspec.arg_readonly_p (arg)) flags |= EAF_NOCLOBBER; } diff --git a/gcc/ipa-modref.c b/gcc/ipa-modref.c index 0ba1a74..d1d4ba7 100644 --- a/gcc/ipa-modref.c +++ b/gcc/ipa-modref.c @@ -151,6 +151,8 @@ dump_eaf_flags (FILE *out, int flags, bool newline = true) fprintf (out, " noclobber"); if (flags & EAF_NOESCAPE) fprintf (out, " noescape"); + if (flags & EAF_NODIRECTESCAPE) + fprintf (out, " nodirectescape"); if (flags & EAF_UNUSED) fprintf (out, " unused"); if (newline) @@ -1303,7 +1305,7 @@ memory_access_to (tree op, tree ssa_name) static int deref_flags (int flags, bool ignore_stores) { - int ret = 0; + int ret = EAF_NODIRECTESCAPE; if (flags & EAF_UNUSED) ret |= EAF_DIRECT | EAF_NOCLOBBER | EAF_NOESCAPE; else @@ -1361,7 +1363,8 @@ public: void modref_lattice::init () { - flags = EAF_DIRECT | EAF_NOCLOBBER | EAF_NOESCAPE | EAF_UNUSED; + flags = EAF_DIRECT | EAF_NOCLOBBER | EAF_NOESCAPE | EAF_UNUSED + | EAF_NODIRECTESCAPE; open = true; known = false; } @@ -1653,7 +1656,8 @@ analyze_ssa_name_flags (tree name, vec<modref_lattice> &lattice, int depth, { int call_flags = gimple_call_arg_flags (call, i); if (ignore_stores) - call_flags |= EAF_NOCLOBBER | EAF_NOESCAPE; + call_flags |= EAF_NOCLOBBER | EAF_NOESCAPE + | EAF_NODIRECTESCAPE; if (!record_ipa) lattice[index].merge (call_flags); @@ -1829,7 +1833,7 @@ analyze_parms (modref_summary *summary, modref_summary_lto *summary_lto, /* For pure functions we have implicit NOCLOBBER and NOESCAPE. */ if (ecf_flags & ECF_PURE) - flags &= ~(EAF_NOCLOBBER | EAF_NOESCAPE); + flags &= ~(EAF_NOCLOBBER | EAF_NOESCAPE | EAF_NODIRECTESCAPE); if (flags) { @@ -3102,7 +3106,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; + flags |= EAF_NOCLOBBER | EAF_NOESCAPE | EAF_NODIRECTESCAPE; flags |= ee->min_flags; to_info->arg_flags[ee->parm_index] &= flags; if (to_info->arg_flags[ee->parm_index]) @@ -3116,7 +3120,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; + flags |= EAF_NOCLOBBER | EAF_NOESCAPE | EAF_NODIRECTESCAPE; flags |= ee->min_flags; to_info_lto->arg_flags[ee->parm_index] &= flags; if (to_info_lto->arg_flags[ee->parm_index]) @@ -3627,8 +3631,8 @@ modref_merge_call_site_flags (escape_summary *sum, } else if (ignore_stores) { - flags |= EAF_NOESCAPE | EAF_NOCLOBBER; - flags_lto |= EAF_NOESCAPE | EAF_NOCLOBBER; + flags |= EAF_NOESCAPE | EAF_NOCLOBBER | EAF_NODIRECTESCAPE; + flags_lto |= EAF_NOESCAPE | EAF_NOCLOBBER | EAF_NODIRECTESCAPE; } flags |= ee->min_flags; flags_lto |= ee->min_flags; diff --git a/gcc/tree-core.h b/gcc/tree-core.h index 313a6af..e457b91 100644 --- a/gcc/tree-core.h +++ b/gcc/tree-core.h @@ -110,6 +110,10 @@ struct die_struct; /* Nonzero if the argument is not used by the function. */ #define EAF_UNUSED (1 << 3) +/* Nonzero if the argument itself does not escape but memory + referenced by it can escape. */ +#define EAF_NODIRECTESCAPE (1 << 4) + /* Call return flags. */ /* Mask for the argument number that is returned. Lower two bits of the return flags, encodes argument slots zero to three. */ diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c index a4832b7..9f4de96 100644 --- a/gcc/tree-ssa-structalias.c +++ b/gcc/tree-ssa-structalias.c @@ -3851,6 +3851,23 @@ make_escape_constraint (tree op) make_constraint_to (escaped_id, op); } +/* Make constraint necessary to make all indirect references + from VI escape. */ + +static void +make_indirect_escape_constraint (varinfo_t vi) +{ + struct constraint_expr lhs, rhs; + /* escaped = *(VAR + UNKNOWN); */ + lhs.type = SCALAR; + lhs.var = escaped_id; + lhs.offset = 0; + rhs.type = DEREF; + rhs.var = vi->id; + rhs.offset = UNKNOWN_OFFSET; + process_constraint (new_constraint (lhs, rhs)); +} + /* Add constraints to that the solution of VI is transitively closed. */ static void @@ -4026,7 +4043,7 @@ handle_rhs_call (gcall *stmt, vec<ce_s> *results) set. The argument would still get clobbered through the escape solution. */ if ((flags & EAF_NOCLOBBER) - && (flags & EAF_NOESCAPE)) + && (flags & (EAF_NOESCAPE | EAF_NODIRECTESCAPE))) { varinfo_t uses = get_call_use_vi (stmt); varinfo_t tem = new_var_info (NULL_TREE, "callarg", true); @@ -4036,9 +4053,11 @@ handle_rhs_call (gcall *stmt, vec<ce_s> *results) if (!(flags & EAF_DIRECT)) make_transitive_closure_constraints (tem); make_copy_constraint (uses, tem->id); + if (!(flags & (EAF_NOESCAPE | EAF_DIRECT))) + make_indirect_escape_constraint (tem); returns_uses = true; } - else if (flags & EAF_NOESCAPE) + else if (flags & (EAF_NOESCAPE | EAF_NODIRECTESCAPE)) { struct constraint_expr lhs, rhs; varinfo_t uses = get_call_use_vi (stmt); @@ -4061,6 +4080,8 @@ handle_rhs_call (gcall *stmt, vec<ce_s> *results) rhs.var = nonlocal_id; rhs.offset = 0; process_constraint (new_constraint (lhs, rhs)); + if (!(flags & (EAF_NOESCAPE | EAF_DIRECT))) + make_indirect_escape_constraint (tem); returns_uses = true; } else |