Discussion:
Track dynamic type changes
Jan Hubicka
2014-10-05 16:34:49 UTC
Permalink
Hi,
this patch makes ipa_polymorphic_call_context::get_dynamic_type to
track if vptr has changed in between function entry and polymorphic
call.

The patch also add logic skipping if (a==0) checks in multiple
inheritance so I can construct testcase more easily.

I got my SVN tree into an inconsistent state yesterday by stopping in
middle of commit. The patch went in in two parts, so i am attaching
both changes. Quite few of devirt-4*.C was broken overnight, I apologize
for that.

Honza

* ipa-polymorphic-call.c (walk_ssa_copies): Recognize
NULL pointer checks.
(ipa_polymorphic_call_context::get_dynamic_type): Return true
if type doesn't change.
* cgraph.h (cgraph_indirect_call_info): New flag.
* cgraph.c (cgraph_node::create_indirect_edge): Initialize it.
(cgraph_node::dump): Dump it.
* ipa-prop.c (ipa_analyze_call_uses): Ignore return valud
of context.get_dynamic_type.
(ipa_make_edge_direct_to_target): Do not speculate
edge that is already speuclative.
(try_make_edge_direct_virtual_call): Use VPTR_CHANGED; Do not
speculate to __builtin_unreachable
(ipa_write_indirect_edge_info, ipa_read_indirect_edge_info): Stream
vptr_changed.
* ipa-cp.c (ipa_get_indirect_edge_target_1): Use vptr_changed.
* g++.dg/ipa/devirt-47.C: New testcase.

* ipa-polymorphic-call.c (possible_placement_new): Fix condition
on size.
(ipa_polymorphic_call_context::restrict_to_inner_type): Do not walk
into vptr pointer.
(ipa_polymorphic_call_context::dump): Fix formating.
* ipa-prop.c (ipa_analyze_call_uses): Compute vptr_changed.

* g++.dg/ipa/devirt-42.C: Update template.
* g++.dg/ipa/devirt-44.C: Update template.
* g++.dg/ipa/devirt-45.C: Update template.
* g++.dg/ipa/devirt-46.C: Update template.
* g++.dg/ipa/devirt-47.C: Update template.
* g++.dg/ipa/devirt-48.C: New testcase.
Index: ipa-polymorphic-call.c
===================================================================
--- ipa-polymorphic-call.c (revision 215890)
+++ ipa-polymorphic-call.c (working copy)
@@ -760,11 +760,37 @@ walk_ssa_copies (tree op)
while (TREE_CODE (op) == SSA_NAME&& !SSA_NAME_IS_DEFAULT_DEF (op)
&& SSA_NAME_DEF_STMT (op)
- && gimple_assign_single_p (SSA_NAME_DEF_STMT (op)))
+ && (gimple_assign_single_p (SSA_NAME_DEF_STMT (op))
+ || gimple_code (SSA_NAME_DEF_STMT (op)) == GIMPLE_PHI))
{
- if (gimple_assign_load_p (SSA_NAME_DEF_STMT (op)))
- return op;
- op = gimple_assign_rhs1 (SSA_NAME_DEF_STMT (op));
+ /* Special case
+ if (ptr == 0)
+ ptr = 0;
+ else
+ ptr = ptr.foo;
+ This pattern is implicitly produced for casts to non-primary
+ bases. When doing context analysis, we do not really care
+ about the case pointer is NULL, becuase the call will be
+ undefined anyway. */
+ if (gimple_code (SSA_NAME_DEF_STMT (op)) == GIMPLE_PHI)
+ {
+ gimple phi = SSA_NAME_DEF_STMT (op);
+
+ if (gimple_phi_num_args (phi) != 2)
+ return op;
+ if (integer_zerop (gimple_phi_arg_def (phi, 0)))
+ op = gimple_phi_arg_def (phi, 1);
+ else if (integer_zerop (gimple_phi_arg_def (phi, 1)))
+ op = gimple_phi_arg_def (phi, 0);
+ else
+ return op;
+ }
+ else
+ {
+ if (gimple_assign_load_p (SSA_NAME_DEF_STMT (op)))
+ return op;
+ op = gimple_assign_rhs1 (SSA_NAME_DEF_STMT (op));
+ }
STRIP_NOPS (op);
}
return op;
@@ -1371,6 +1397,8 @@ check_stmt_for_type_change (ao_ref *ao A
is set), try to walk memory writes and find the actual construction of the
instance.

+ Return true if memory is unchanged from function entry.
+
We do not include this analysis in the context analysis itself, because
it needs memory SSA to be fully built and the walk may be expensive.
So it is not suitable for use withing fold_stmt and similar uses. */
@@ -1615,7 +1643,7 @@ ipa_polymorphic_call_context::get_dynami
function_entry_reached ? " (multiple types encountered)" : "");
}

- return true;
+ return false;
}

/* See if speculation given by SPEC_OUTER_TYPE, SPEC_OFFSET and SPEC_MAYBE_DERIVED_TYPE
Index: cgraph.h
===================================================================
--- cgraph.h (revision 215890)
+++ cgraph.h (working copy)
@@ -1393,6 +1393,9 @@ struct GTY(()) cgraph_indirect_call_info
/* When the previous bit is set, this one determines whether the destination
is loaded from a parameter passed by reference. */
unsigned by_ref : 1;
+ /* For polymorphic calls this specify whether the virtual table pointer
+ may have changed in between function entry and the call. */
+ unsigned vptr_changed : 1;
};

struct GTY((chain_next ("%h.next_caller"), chain_prev ("%h.prev_caller"))) cgraph_edge {
Index: cgraph.c
===================================================================
--- cgraph.c (revision 215890)
+++ cgraph.c (working copy)
@@ -883,6 +883,7 @@ cgraph_node::create_indirect_edge (gimpl

edge->indirect_info = cgraph_allocate_init_indirect_info ();
edge->indirect_info->ecf_flags = ecf_flags;
+ edge->indirect_info->vptr_changed = true;

/* Record polymorphic call info. */
if (compute_indirect_info
@@ -1988,6 +1989,8 @@ cgraph_node::dump (FILE *f)
edge->indirect_info->member_ptr ? "member ptr" : "aggregate",
edge->indirect_info->by_ref ? "passed by reference":"",
(int)edge->indirect_info->offset);
+ if (edge->indirect_info->vptr_changed)
+ fprintf (f, " (vptr maybe changed)");
}
fprintf (f, "\n");
if (edge->indirect_info->polymorphic)
Index: ipa-prop.c
===================================================================
--- ipa-prop.c (revision 215890)
+++ ipa-prop.c (working copy)
@@ -2371,10 +2371,10 @@ ipa_analyze_call_uses (struct func_body_
gcc_checking_assert (cs->indirect_info->otr_token
== tree_to_shwi (OBJ_TYPE_REF_TOKEN (target)));

- if (context.get_dynamic_type (instance,
- OBJ_TYPE_REF_OBJECT (target),
- obj_type_ref_class (target), call))
- cs->indirect_info->context = context;
+ context.get_dynamic_type (instance,
+ OBJ_TYPE_REF_OBJECT (target),
+ obj_type_ref_class (target), call);
+ cs->indirect_info->context = context;
}

if (TREE_CODE (target) == SSA_NAME)
@@ -2878,6 +2878,38 @@ ipa_make_edge_direct_to_target (struct c
callee = cgraph_node::get_create (target);
}

+ /* If the edge is already speculated. */
+ if (speculative && ie->speculative)
+ {
+ struct cgraph_edge *e2;
+ struct ipa_ref *ref;
+ ie->speculative_call_info (e2, ie, ref);
+ if (e2->callee->ultimate_alias_target ()
+ != callee->ultimate_alias_target ())
+ {
+ if (dump_file)
+ fprintf (dump_file, "ipa-prop: Discovered call to a speculative target "
+ "(%s/%i -> %s/%i) but the call is already speculated to %s/%i. Giving up.\n",
+ xstrdup (ie->caller->name ()),
+ ie->caller->order,
+ xstrdup (callee->name ()),
+ callee->order,
+ xstrdup (e2->callee->name ()),
+ e2->callee->order);
+ }
+ else
+ {
+ if (dump_file)
+ fprintf (dump_file, "ipa-prop: Discovered call to a speculative target "
+ "(%s/%i -> %s/%i) this agree with previous speculation.\n",
+ xstrdup (ie->caller->name ()),
+ ie->caller->order,
+ xstrdup (callee->name ()),
+ callee->order);
+ }
+ return NULL;
+ }
+
if (!dbg_cnt (devirt))
return NULL;

@@ -3127,17 +3159,17 @@ try_make_edge_direct_virtual_call (struc

ctx.offset_by (ie->indirect_info->offset);

- /* TODO: We want to record if type change happens.
- Old code did not do that that seems like a bug. */
- ctx.possible_dynamic_type_change (ie->in_polymorphic_cdtor,
- ie->indirect_info->otr_type);
+ if (ie->indirect_info->vptr_changed)
+ ctx.possible_dynamic_type_change (ie->in_polymorphic_cdtor,
+ ie->indirect_info->otr_type);

updated = ie->indirect_info->context.combine_with
(ctx, ie->indirect_info->otr_type);
}

/* Try to do lookup via known virtual table pointer value. */
- if (!ie->indirect_info->by_ref)
+ if (!ie->indirect_info->by_ref
+ && (!ie->indirect_info->vptr_changed || flag_devirtualize_speculatively))
{
tree vtable;
unsigned HOST_WIDE_INT offset;
@@ -3146,16 +3178,24 @@ try_make_edge_direct_virtual_call (struc
true);
if (t && vtable_pointer_value_to_vtable (t, &vtable, &offset))
{
- target = gimple_get_virt_method_for_vtable (ie->indirect_info->otr_token,
+ t = gimple_get_virt_method_for_vtable (ie->indirect_info->otr_token,
vtable, offset);
- if (target)
+ if (t)
{
- if ((TREE_CODE (TREE_TYPE (target)) == FUNCTION_TYPE
- && DECL_FUNCTION_CODE (target) == BUILT_IN_UNREACHABLE)
+ if ((TREE_CODE (TREE_TYPE (t)) == FUNCTION_TYPE
+ && DECL_FUNCTION_CODE (t) == BUILT_IN_UNREACHABLE)
|| !possible_polymorphic_call_target_p
- (ie, cgraph_node::get (target)))
- target = ipa_impossible_devirt_target (ie, target);
- return ipa_make_edge_direct_to_target (ie, target);
+ (ie, cgraph_node::get (t)))
+ {
+ /* Do not speculate builtin_unreachable, it is stpid! */
+ if (!ie->indirect_info->vptr_changed)
+ target = ipa_impossible_devirt_target (ie, target);
+ }
+ else
+ {
+ target = t;
+ speculative = ie->indirect_info->vptr_changed;
+ }
}
}
}
@@ -3188,7 +3228,7 @@ try_make_edge_direct_virtual_call (struc
else
target = ipa_impossible_devirt_target (ie, NULL_TREE);
}
- else if (flag_devirtualize_speculatively
+ else if (!target && flag_devirtualize_speculatively
&& !ie->speculative && ie->maybe_hot_p ())
{
cgraph_node *n = try_speculative_devirtualization (ie->indirect_info->otr_type,
@@ -3222,7 +3264,11 @@ try_make_edge_direct_virtual_call (struc
if (target)
{
if (!possible_polymorphic_call_target_p (ie, cgraph_node::get_create (target)))
- target = ipa_impossible_devirt_target (ie, target);
+ {
+ if (!speculative)
+ return NULL;
+ target = ipa_impossible_devirt_target (ie, target);
+ }
return ipa_make_edge_direct_to_target (ie, target, speculative);
}
else
@@ -4801,6 +4847,7 @@ ipa_write_indirect_edge_info (struct out
bp_pack_value (&bp, ii->agg_contents, 1);
bp_pack_value (&bp, ii->member_ptr, 1);
bp_pack_value (&bp, ii->by_ref, 1);
+ bp_pack_value (&bp, ii->vptr_changed, 1);
streamer_write_bitpack (&bp);
if (ii->agg_contents || ii->polymorphic)
streamer_write_hwi (ob, ii->offset);
@@ -4832,6 +4879,7 @@ ipa_read_indirect_edge_info (struct lto_
ii->agg_contents = bp_unpack_value (&bp, 1);
ii->member_ptr = bp_unpack_value (&bp, 1);
ii->by_ref = bp_unpack_value (&bp, 1);
+ ii->vptr_changed = bp_unpack_value (&bp, 1);
if (ii->agg_contents || ii->polymorphic)
ii->offset = (HOST_WIDE_INT) streamer_read_hwi (ib);
else
Index: ipa-cp.c
===================================================================
--- ipa-cp.c (revision 215890)
+++ ipa-cp.c (working copy)
@@ -1560,7 +1560,8 @@ ipa_get_indirect_edge_target_1 (struct c
t = NULL;

/* Try to work out value of virtual table pointer value in replacemnets. */
- if (!t && agg_reps && !ie->indirect_info->by_ref)
+ if (!t && agg_reps && !ie->indirect_info->by_ref
+ && !ie->indirect_info->vptr_changed)
{
while (agg_reps)
{
@@ -1578,7 +1579,8 @@ ipa_get_indirect_edge_target_1 (struct c
/* Try to work out value of virtual table pointer value in known
aggregate values. */
if (!t && known_aggs.length () > (unsigned int) param_index
- && !ie->indirect_info->by_ref)
+ && !ie->indirect_info->by_ref
+ && !ie->indirect_info->vptr_changed)
{
struct ipa_agg_jump_function *agg;
agg = known_aggs[param_index];
Index: testsuite/g++.dg/ipa/devirt-47.C
===================================================================
--- testsuite/g++.dg/ipa/devirt-47.C (revision 0)
+++ testsuite/g++.dg/ipa/devirt-47.C (revision 0)
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fno-ipa-cp -fdump-ipa-inline-details -fno-early-inlining -fdump-tree-optimized" } */
+struct A {
+ virtual int foo(){return 1;}
+};
+struct B {
+ virtual int bar(){return 4;}
+};
+struct C:B,A {
+ virtual int foo(){return 2;}
+};
+static void
+test (struct A *a)
+{
+ if (a->foo() != 2)
+ __builtin_abort ();
+}
+int
+m()
+{
+ struct A *a = new C;
+ test (a);
+ return 0;
+}
+
+/* { dg-final { scan-ipa-dump-times "Discovered a virtual call to a speculative target\[^\\n\]*C::_ZTh" 1 "inline" } } */
+/* { dg-final { scan-ipa-dump-not "OBJ_TYPE_REF" "optimized" } } */
+/* FIXME: We ought to inline thunk. */
+/* { dg-final { scan-ipa-dump "C::_ZThn" "optimized" } } */
+/* { dg-final { cleanup-ipa-dump "inline" } } */
+/* { dg-final { cleanup-ipa-dump "optimized" } } */


Index: ipa-polymorphic-call.c
===================================================================
--- ipa-polymorphic-call.c (revision 215901)
+++ ipa-polymorphic-call.c (working copy)
@@ -97,7 +97,7 @@ possible_placement_new (tree type, tree
|| !tree_fits_shwi_p (TYPE_SIZE (type))
|| (cur_offset
+ (expected_type ? tree_to_uhwi (TYPE_SIZE (expected_type))
- : 1)
+ : GET_MODE_BITSIZE (Pmode))
<= tree_to_uhwi (TYPE_SIZE (type)))));
}

@@ -278,6 +278,14 @@ ipa_polymorphic_call_context::restrict_t
pos = int_bit_position (fld);
if (pos > (unsigned HOST_WIDE_INT)cur_offset)
continue;
+
+ /* Do not consider vptr itself. Not even for placement new. */
+ if (!pos && DECL_ARTIFICIAL (fld)
+ && POINTER_TYPE_P (TREE_TYPE (fld))
+ && TYPE_BINFO (type)
+ && polymorphic_type_binfo_p (TYPE_BINFO (type)))
+ continue;
+
if (!DECL_SIZE (fld) || !tree_fits_uhwi_p (DECL_SIZE (fld)))
goto no_useful_type_info;
size = tree_to_uhwi (DECL_SIZE (fld));
@@ -583,7 +591,7 @@ ipa_polymorphic_call_context::dump (FILE
{
fprintf (f, " ");
if (invalid)
- fprintf (f, "Call is known to be undefined\n");
+ fprintf (f, "Call is known to be undefined");
else
{
if (useless_p ())
Index: testsuite/g++.dg/ipa/devirt-42.C
===================================================================
--- testsuite/g++.dg/ipa/devirt-42.C (revision 215901)
+++ testsuite/g++.dg/ipa/devirt-42.C (working copy)
@@ -26,13 +26,9 @@ main()
/* Inlining everything into main makes type clear from type of variable b.
However devirtualization is also possible for offline copy of A::barbar. Invoking
B's barbar makes it clear the type is at least B and B is an anonymous
- namespace type and therefore we know it has no derivations.
- FIXME: Currently we devirtualize speculatively only because we do not track
- dynamic type changes well. */
-/* { dg-final { scan-ipa-dump-times "First type is base of second" 1 "inline" } } */
-/* { dg-final { scan-ipa-dump-times "Outer types match, merging flags" 2 "inline" } } */
-/* { dg-final { scan-ipa-dump-times "Discovered a virtual call to a known target" 1 "inline" } } */
-/* { dg-final { scan-ipa-dump-times "Discovered a virtual call to a speculative target" 1 "inline" } } */
+ namespace type and therefore we know it has no derivations. */
+/* { dg-final { scan-ipa-dump-times "First type is base of second" 3 "inline" } } */
+/* { dg-final { scan-ipa-dump-times "Discovered a virtual call to a known target" 2 "inline" } } */

/* Verify that speculation is optimized by late optimizers. */
/* { dg-final { scan-ipa-dump-times "return 2" 2 "optimized" } } */
Index: testsuite/g++.dg/ipa/devirt-44.C
===================================================================
--- testsuite/g++.dg/ipa/devirt-44.C (revision 215901)
+++ testsuite/g++.dg/ipa/devirt-44.C (working copy)
@@ -27,7 +27,6 @@ main()
Check that we handle that. */

/* { dg-final { scan-ipa-dump-times "First type is base of second" 1 "inline" } } */
-/* { dg-final { scan-ipa-dump "(maybe in construction)" "inline" } } */
/* { dg-final { scan-ipa-dump-times "Discovered a virtual call to a known target\[^\\n\]*A::foo" 1 "inline" } } */
/* { dg-final { scan-ipa-dump-times "Discovered a virtual call to a known target\[^\\n\]*B::foo" 1 "inline" } } */
/* { dg-final { cleanup-ipa-dump "inline" } } */
Index: testsuite/g++.dg/ipa/devirt-46.C
===================================================================
--- testsuite/g++.dg/ipa/devirt-46.C (revision 215901)
+++ testsuite/g++.dg/ipa/devirt-46.C (working copy)
@@ -20,7 +20,7 @@ m()
return 0;
}

-/* { dg-final { scan-ipa-dump-times "Discovered a virtual call to a speculative target\[^\\n\]*B::foo" 1 "inline" } } */
+/* { dg-final { scan-ipa-dump-times "Discovered a virtual call to a known target\[^\\n\]*B::foo" 1 "inline" } } */
/* { dg-final { scan-ipa-dump-not "OBJ_TYPE_REF" "optimized" } } */
/* { dg-final { scan-ipa-dump-not "abort" "optimized" } } */
/* { dg-final { cleanup-ipa-dump "inline" } } */
Index: testsuite/g++.dg/ipa/devirt-48.C
===================================================================
--- testsuite/g++.dg/ipa/devirt-48.C (revision 0)
+++ testsuite/g++.dg/ipa/devirt-48.C (revision 0)
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fno-ipa-cp -fdump-ipa-inline-details -fno-early-inlining" } */
+struct A {
+ virtual int foo(){return 1;}
+};
+struct B:A {
+ virtual int foo(){return 2;}
+ int callfoo(){foo();}
+};
+struct C:A {
+ virtual int foo(){return 3;}
+};
+struct D:B {
+ virtual int foo(){return 4;}
+ int callfoo(){foo();}
+};
+static void
+test (struct A *a)
+{
+ if (a->foo() != 2)
+ __builtin_abort ();
+}
+int
+m()
+{
+ struct A *a = new C;
+ static_cast<B*>(a)->callfoo();
+ return 0;
+}
+
+/* { dg-final { scan-ipa-dump-times "Discovered a virtual call to a known target\[^\\n\]*__builtin_unreachable" 1 "inline" } } */
+/* { dg-final { cleanup-ipa-dump "inline" } } */
Index: testsuite/g++.dg/ipa/devirt-45.C
===================================================================
--- testsuite/g++.dg/ipa/devirt-45.C (revision 215901)
+++ testsuite/g++.dg/ipa/devirt-45.C (working copy)
@@ -37,7 +37,6 @@ main()
}

/* One invocation is A::foo () other is B::foo () even though the type is destroyed and rebuilt in test() */
-/* { dg-final { scan-ipa-dump "(maybe in construction)" "inline" } } */
/* { dg-final { scan-ipa-dump-times "Discovered a virtual call to a known target\[^\\n\]*A::foo" 1 "inline" } } */
/* { dg-final { scan-ipa-dump-times "Discovered a virtual call to a known target\[^\\n\]*B::foo" 1 "inline" } } */
/* { dg-final { cleanup-ipa-dump "inline" } } */
Index: testsuite/g++.dg/ipa/devirt-47.C
===================================================================
--- testsuite/g++.dg/ipa/devirt-47.C (revision 215901)
+++ testsuite/g++.dg/ipa/devirt-47.C (working copy)
@@ -23,7 +23,7 @@ m()
return 0;
}

-/* { dg-final { scan-ipa-dump-times "Discovered a virtual call to a speculative target\[^\\n\]*C::_ZTh" 1 "inline" } } */
+/* { dg-final { scan-ipa-dump-times "Discovered a virtual call to a known target\[^\\n\]*C::_ZTh" 1 "inline" } } */
/* { dg-final { scan-ipa-dump-not "OBJ_TYPE_REF" "optimized" } } */
/* FIXME: We ought to inline thunk. */
/* { dg-final { scan-ipa-dump "C::_ZThn" "optimized" } } */
Index: ipa-prop.c
===================================================================
--- ipa-prop.c (revision 215901)
+++ ipa-prop.c (working copy)
@@ -2371,9 +2371,10 @@ ipa_analyze_call_uses (struct func_body_
gcc_checking_assert (cs->indirect_info->otr_token
== tree_to_shwi (OBJ_TYPE_REF_TOKEN (target)));

- context.get_dynamic_type (instance,
- OBJ_TYPE_REF_OBJECT (target),
- obj_type_ref_class (target), call);
+ cs->indirect_info->vptr_changed
+ = !context.get_dynamic_type (instance,
+ OBJ_TYPE_REF_OBJECT (target),
+ obj_type_ref_class (target), call);
cs->indirect_info->context = context;
}
Rainer Orth
2014-10-08 09:10:32 UTC
Permalink
Hi Jan,
Post by Jan Hubicka
this patch makes ipa_polymorphic_call_context::get_dynamic_type to
track if vptr has changed in between function entry and polymorphic
call.
The patch also add logic skipping if (a==0) checks in multiple
inheritance so I can construct testcase more easily.
I got my SVN tree into an inconsistent state yesterday by stopping in
middle of commit. The patch went in in two parts, so i am attaching
both changes. Quite few of devirt-4*.C was broken overnight, I apologize
for that.
as of yesterday (r215969), many of the devirt-4*.C tests come up
UNRESOLVED on both Solaris/x86 and Solaris/SPARC:

UNRESOLVED: g++.dg/ipa/devirt-42.C -std=gnu++11 scan-ipa-dump-not optimized "OBJ_TYPE_REF"
UNRESOLVED: g++.dg/ipa/devirt-42.C -std=gnu++11 scan-ipa-dump-times optimized "return 2" 2
UNRESOLVED: g++.dg/ipa/devirt-42.C -std=gnu++1y scan-ipa-dump-not optimized "OBJ_TYPE_REF"
UNRESOLVED: g++.dg/ipa/devirt-42.C -std=gnu++1y scan-ipa-dump-times optimized "return 2" 2
UNRESOLVED: g++.dg/ipa/devirt-42.C -std=gnu++98 scan-ipa-dump-not optimized "OBJ_TYPE_REF"
UNRESOLVED: g++.dg/ipa/devirt-42.C -std=gnu++98 scan-ipa-dump-times optimized "return 2" 2
UNRESOLVED: g++.dg/ipa/devirt-46.C -std=gnu++11 scan-ipa-dump-not optimized "OBJ_TYPE_REF"
UNRESOLVED: g++.dg/ipa/devirt-46.C -std=gnu++11 scan-ipa-dump-not optimized "abort"
UNRESOLVED: g++.dg/ipa/devirt-46.C -std=gnu++1y scan-ipa-dump-not optimized "OBJ_TYPE_REF"
UNRESOLVED: g++.dg/ipa/devirt-46.C -std=gnu++1y scan-ipa-dump-not optimized "abort"
UNRESOLVED: g++.dg/ipa/devirt-46.C -std=gnu++98 scan-ipa-dump-not optimized "OBJ_TYPE_REF"
UNRESOLVED: g++.dg/ipa/devirt-46.C -std=gnu++98 scan-ipa-dump-not optimized "abort"
UNRESOLVED: g++.dg/ipa/devirt-47.C -std=gnu++11 scan-ipa-dump optimized "C::_ZThn"
UNRESOLVED: g++.dg/ipa/devirt-47.C -std=gnu++11 scan-ipa-dump-not optimized "OBJ_TYPE_REF"
UNRESOLVED: g++.dg/ipa/devirt-47.C -std=gnu++1y scan-ipa-dump optimized "C::_ZThn"
UNRESOLVED: g++.dg/ipa/devirt-47.C -std=gnu++1y scan-ipa-dump-not optimized "OBJ_TYPE_REF"
UNRESOLVED: g++.dg/ipa/devirt-47.C -std=gnu++98 scan-ipa-dump optimized "C::_ZThn"
UNRESOLVED: g++.dg/ipa/devirt-47.C -std=gnu++98 scan-ipa-dump-not optimized "OBJ_TYPE_REF"

both 32 and 64-bit.

In all cases, g++.log shows

g++.dg/ipa/devirt-42.C -std=gnu++98 : dump file does not exist
UNRESOLVED: g++.dg/ipa/devirt-42.C -std=gnu++98 scan-ipa-dump-times optimized "return 2" 2
g++.dg/ipa/devirt-42.C -std=gnu++98 : dump file does not exist
UNRESOLVED: g++.dg/ipa/devirt-42.C -std=gnu++98 scan-ipa-dump-not optimized "OBJ_TYPE_REF"

Rainer
--
-----------------------------------------------------------------------------
Rainer Orth, Center for Biotechnology, Bielefeld University
Loading...