diff options
Diffstat (limited to 'gcc')
-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 |