aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/gimple.c2
-rw-r--r--gcc/ipa-modref.c20
-rw-r--r--gcc/tree-core.h4
-rw-r--r--gcc/tree-ssa-structalias.c25
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