fprintf (out, "%*s Arg %i (%s) min flags", indent, "",
escape_points[i].arg,
escape_points[i].direct ? "direct" : "indirect");
- dump_eaf_flags (out, flags, false);
+ dump_eaf_flags (out, escape_points[i].min_flags, false);
fprintf (out, " in call ");
print_gimple_stmt (out, escape_points[i].call, 0);
}
if (!flags)
return changed;
for (unsigned int i = 0; i < with.escape_points.length (); i++)
- changed |= add_escape_point (with.escape_points[i].call,
- with.escape_points[i].arg,
- with.escape_points[i].min_flags,
- false);
+ {
+ int min_flags = with.escape_points[i].min_flags;
+
+ 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;
+ changed |= add_escape_point (with.escape_points[i].call,
+ with.escape_points[i].arg,
+ min_flags,
+ false);
+ }
return changed;
}
static void
update_escape_summary_1 (cgraph_edge *e,
- vec <vec <escape_map>> &map)
+ vec <vec <escape_map>> &map,
+ bool ignore_stores)
{
escape_summary *sum = escape_summaries->get (e);
if (!sum)
continue;
FOR_EACH_VEC_ELT (map[ee->parm_index], j, em)
{
+ int min_flags = ee->min_flags;
+ if (ee->direct && !em->direct)
+ min_flags = deref_flags (min_flags, ignore_stores);
struct escape_entry entry = {em->parm_index, ee->arg,
ee->min_flags,
ee->direct & em->direct};
static void
update_escape_summary (cgraph_node *node,
- vec <vec <escape_map>> &map)
+ vec <vec <escape_map>> &map,
+ bool ignore_stores)
{
if (!escape_summaries)
return;
for (cgraph_edge *e = node->indirect_calls; e; e = e->next_callee)
- update_escape_summary_1 (e, map);
+ update_escape_summary_1 (e, map, ignore_stores);
for (cgraph_edge *e = node->callees; e; e = e->next_callee)
{
if (!e->inline_failed)
- update_escape_summary (e->callee, map);
+ update_escape_summary (e->callee, map, ignore_stores);
else
- update_escape_summary_1 (e, map);
+ update_escape_summary_1 (e, map, ignore_stores);
}
}
if (needed)
emap[ee->arg].safe_push (entry);
}
- update_escape_summary (edge->callee, emap);
+ update_escape_summary (edge->callee, emap, ignore_stores);
for (i = 0; (int)i < max_escape + 1; i++)
emap[i].release ();
if (sum)
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-dse2-details" } */
+/* { dg-final { scan-tree-dump-not "Deleted dead store" "dse2" } } */
+
+struct foo { unsigned long bar; };
+
+unsigned y;
+
+static int __attribute__ ((__noinline__, __noclone__))
+wrapped (struct foo *p, int i);
+
+static int wrapper (struct foo *p);
+
+static int __attribute__ ((__noclone__))
+wrapper (struct foo *p) {
+ return wrapped (p, 1);
+}
+
+static int __attribute__ ((__noinline__, __noclone__))
+dind (struct foo **pp);
+
+int __attribute__ ((__noclone__, __no_reorder__))
+xfn () {
+ struct foo x = { 0xBADC0FFE };
+ struct foo *p = &x;
+ return dind (&p);
+}
+
+static int __attribute__ ((__noinline__, __no_reorder__))
+wrapped (struct foo *p, int i) {
+ return p->bar + i == y++;
+}
+
+static int __attribute__ ((__noinline__, __noclone__, __no_reorder__))
+dind (struct foo **pp) {
+ wrapper (*pp);
+ return 0;
+}