devirt-42.C: New testcase.
* testsuite/g++.dg/ipa/devirt-42.C: New testcase. * testsuite/g++.dg/ipa/devirt-43.C: New testcase. * testsuite/g++.dg/ipa/devirt-44.C: New testcase. * testsuite/g++.dg/ipa/devirt-45.C: New testcase. * ipa-polymorphic-call.c (ipa_polymorphic_call_context::ipa_polymorphic_call_context): Fix code determining speculative type. (ipa_polymorphic_call_context::combine_with): Fix speculation merge. From-SVN: r215886
This commit is contained in:
parent
dbaba85539
commit
07f4a83d4a
@ -1,3 +1,10 @@
|
||||
2014-10-03 Jan Hubicka <hubicka@ucw.cz>
|
||||
|
||||
* ipa-polymorphic-call.c
|
||||
(ipa_polymorphic_call_context::ipa_polymorphic_call_context): Fix
|
||||
code determining speculative type.
|
||||
(ipa_polymorphic_call_context::combine_with): Fix speculation merge.
|
||||
|
||||
2014-10-03 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
|
||||
|
||||
* altivec.md (altivec_lvsl): New define_expand.
|
||||
|
@ -820,8 +820,7 @@ ipa_polymorphic_call_context::ipa_polymorphic_call_context (tree fndecl,
|
||||
&offset2, &size, &max_size);
|
||||
|
||||
if (max_size != -1 && max_size == size)
|
||||
combine_speculation_with (TYPE_MAIN_VARIANT
|
||||
(TREE_TYPE (TREE_TYPE (base_pointer))),
|
||||
combine_speculation_with (TYPE_MAIN_VARIANT (TREE_TYPE (base)),
|
||||
offset + offset2,
|
||||
true,
|
||||
NULL /* Do not change outer type. */);
|
||||
@ -1970,7 +1969,7 @@ ipa_polymorphic_call_context::combine_with (ipa_polymorphic_call_context ctx,
|
||||
|
||||
updated |= combine_speculation_with (ctx.speculative_outer_type,
|
||||
ctx.speculative_offset,
|
||||
ctx.maybe_in_construction,
|
||||
ctx.speculative_maybe_derived_type,
|
||||
otr_type);
|
||||
|
||||
if (updated && dump_file && (dump_flags & TDF_DETAILS))
|
||||
|
@ -1,3 +1,10 @@
|
||||
2014-10-03 Jan Hubicka <hubicka@ucw.cz>
|
||||
|
||||
* testsuite/g++.dg/ipa/devirt-42.C: New testcase.
|
||||
* testsuite/g++.dg/ipa/devirt-43.C: New testcase.
|
||||
* testsuite/g++.dg/ipa/devirt-44.C: New testcase.
|
||||
* testsuite/g++.dg/ipa/devirt-45.C: New testcase.
|
||||
|
||||
2014-10-03 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
|
||||
|
||||
* gcc.target/powerpc/lvsl-lvsr.c: New test.
|
||||
|
31
gcc/testsuite/g++.dg/ipa/devirt-41.C
Normal file
31
gcc/testsuite/g++.dg/ipa/devirt-41.C
Normal file
@ -0,0 +1,31 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O3 -fdump-ipa-inline-details -fno-early-inlining -fno-ipa-cp" } */
|
||||
struct A {virtual int foo () {return 1;}};
|
||||
struct B:A {virtual int foo () {return 2;}};
|
||||
|
||||
void dostuff(struct A *);
|
||||
|
||||
static void
|
||||
test (struct A *a)
|
||||
{
|
||||
dostuff (a);
|
||||
if (a->foo ()!= 2)
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
main()
|
||||
{
|
||||
struct B a;
|
||||
dostuff (&a);
|
||||
test (&a);
|
||||
}
|
||||
/* Inlining of dostuff into main should combine polymorphic context
|
||||
specifying Outer type:struct B offset 0
|
||||
with Outer type (dynamic):struct A (or a derived type) offset 0
|
||||
and enable devirtualization.
|
||||
|
||||
Because the type is in static storage, we know it won't change type in dostuff
|
||||
and from callstack we can tell that is is not in construction/destruction. */
|
||||
/* { dg-final { scan-ipa-dump-times "First type is base of second" 1 "inline" } } */
|
||||
/* { dg-final { scan-ipa-dump-times "Discovered a virtual call to a known target" 1 "inline" } } */
|
||||
/* { dg-final { cleanup-ipa-dump "inline" } } */
|
42
gcc/testsuite/g++.dg/ipa/devirt-42.C
Normal file
42
gcc/testsuite/g++.dg/ipa/devirt-42.C
Normal file
@ -0,0 +1,42 @@
|
||||
/* { 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;}
|
||||
int bar () {return foo();}
|
||||
int barbar ();
|
||||
};
|
||||
namespace {
|
||||
struct B:A {virtual int foo () {return 2;}
|
||||
int barbar () {return bar();}};
|
||||
}
|
||||
|
||||
int
|
||||
A::barbar()
|
||||
{
|
||||
return static_cast<B*>(this)->barbar();
|
||||
}
|
||||
|
||||
main()
|
||||
{
|
||||
struct B b;
|
||||
struct A *a = &b;
|
||||
return a->barbar ();
|
||||
}
|
||||
|
||||
/* 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" } } */
|
||||
|
||||
/* Verify that speculation is optimized by late optimizers. */
|
||||
/* { dg-final { scan-ipa-dump-times "return 2" 2 "optimized" } } */
|
||||
/* { dg-final { scan-ipa-dump-not "OBJ_TYPE_REF" "optimized" } } */
|
||||
|
||||
/* { dg-final { cleanup-ipa-dump "inline" } } */
|
||||
/* { dg-final { cleanup-ipa-dump "optimized" } } */
|
27
gcc/testsuite/g++.dg/ipa/devirt-43.C
Normal file
27
gcc/testsuite/g++.dg/ipa/devirt-43.C
Normal file
@ -0,0 +1,27 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O3 -fdump-ipa-inline-details -fno-ipa-cp -fno-early-inlining" } */
|
||||
struct A {virtual int foo () {return 1;}};
|
||||
struct B {int i; struct A a;};
|
||||
struct C:A {virtual int foo () {return 2;}};
|
||||
|
||||
void dostuff(struct A *);
|
||||
|
||||
static void
|
||||
test (struct A *a)
|
||||
{
|
||||
dostuff (a);
|
||||
if (a->foo ()!= 2)
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
void
|
||||
t(struct B *b)
|
||||
{
|
||||
test(&b->a);
|
||||
}
|
||||
/* Here b comes externally, but we take speculative hint from type of the pointer that it is
|
||||
of type B. This makes A fully specified and we know C::foo is unlikely.
|
||||
FIXME: We could most probably can devirtualize unconditonally because dereference of b in
|
||||
&b->a makes the type known. GIMPLE does not represent this. */
|
||||
/* { dg-final { scan-ipa-dump-times "Discovered a virtual call to a speculative target" 1 "inline" } } */
|
||||
/* { dg-final { cleanup-ipa-dump "inline" } } */
|
33
gcc/testsuite/g++.dg/ipa/devirt-44.C
Normal file
33
gcc/testsuite/g++.dg/ipa/devirt-44.C
Normal file
@ -0,0 +1,33 @@
|
||||
/* { 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;}
|
||||
int wrapfoo () {foo();}
|
||||
A() {wrapfoo();}
|
||||
};
|
||||
struct B:A {virtual int foo () {return 2;}};
|
||||
|
||||
void dostuff(struct A *);
|
||||
|
||||
static void
|
||||
test (struct A *a)
|
||||
{
|
||||
dostuff (a);
|
||||
if (a->foo ()!= 2)
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
main()
|
||||
{
|
||||
struct B a;
|
||||
dostuff (&a);
|
||||
test (&a);
|
||||
}
|
||||
/* Here one invocation of foo is while type is in construction, while other is not.
|
||||
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" } } */
|
43
gcc/testsuite/g++.dg/ipa/devirt-45.C
Normal file
43
gcc/testsuite/g++.dg/ipa/devirt-45.C
Normal file
@ -0,0 +1,43 @@
|
||||
/* { 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;}
|
||||
int wrapfoo () {foo();}
|
||||
A() {wrapfoo();}
|
||||
};
|
||||
inline void* operator new(__SIZE_TYPE__ s, void* buf) throw() {
|
||||
return buf;
|
||||
}
|
||||
struct B:A {virtual int foo () {return 2;}};
|
||||
|
||||
void dostuff(struct A *);
|
||||
|
||||
static void
|
||||
test2 (struct A *a)
|
||||
{
|
||||
dostuff (a);
|
||||
if (a->foo ()!= 2)
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
static void
|
||||
test (struct A *a)
|
||||
{
|
||||
dostuff (a);
|
||||
static_cast<B*>(a)->~B();
|
||||
new(a) B();
|
||||
test2(a);
|
||||
}
|
||||
|
||||
main()
|
||||
{
|
||||
struct B a;
|
||||
dostuff (&a);
|
||||
test (&a);
|
||||
}
|
||||
|
||||
/* 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" } } */
|
Loading…
Reference in New Issue
Block a user