diff options
author | Jan Hubicka <hubicka@ucw.cz> | 2014-10-04 05:24:42 +0200 |
---|---|---|
committer | Jan Hubicka <hubicka@gcc.gnu.org> | 2014-10-04 03:24:42 +0000 |
commit | 07f4a83d4afba28f8b73a9b9a8aeb48adec9eac3 (patch) | |
tree | 4e12538abcb7a57877879348dae3ea4837723aa8 | |
parent | dbaba85539c4742ccb02f4750c05ccc296cbbb7b (diff) | |
download | gcc-07f4a83d4afba28f8b73a9b9a8aeb48adec9eac3.zip gcc-07f4a83d4afba28f8b73a9b9a8aeb48adec9eac3.tar.gz gcc-07f4a83d4afba28f8b73a9b9a8aeb48adec9eac3.tar.bz2 |
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
-rw-r--r-- | gcc/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/ipa-polymorphic-call.c | 5 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ipa/devirt-41.C | 31 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ipa/devirt-42.C | 42 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ipa/devirt-43.C | 27 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ipa/devirt-44.C | 33 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ipa/devirt-45.C | 43 |
8 files changed, 192 insertions, 3 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f7724f5..9437414 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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. diff --git a/gcc/ipa-polymorphic-call.c b/gcc/ipa-polymorphic-call.c index f352625..a9b037a 100644 --- a/gcc/ipa-polymorphic-call.c +++ b/gcc/ipa-polymorphic-call.c @@ -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)) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 036b171..2293926 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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. diff --git a/gcc/testsuite/g++.dg/ipa/devirt-41.C b/gcc/testsuite/g++.dg/ipa/devirt-41.C new file mode 100644 index 0000000..5ba1158 --- /dev/null +++ b/gcc/testsuite/g++.dg/ipa/devirt-41.C @@ -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" } } */ diff --git a/gcc/testsuite/g++.dg/ipa/devirt-42.C b/gcc/testsuite/g++.dg/ipa/devirt-42.C new file mode 100644 index 0000000..40076dd --- /dev/null +++ b/gcc/testsuite/g++.dg/ipa/devirt-42.C @@ -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" } } */ diff --git a/gcc/testsuite/g++.dg/ipa/devirt-43.C b/gcc/testsuite/g++.dg/ipa/devirt-43.C new file mode 100644 index 0000000..9be49e7 --- /dev/null +++ b/gcc/testsuite/g++.dg/ipa/devirt-43.C @@ -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" } } */ diff --git a/gcc/testsuite/g++.dg/ipa/devirt-44.C b/gcc/testsuite/g++.dg/ipa/devirt-44.C new file mode 100644 index 0000000..4f6ab30 --- /dev/null +++ b/gcc/testsuite/g++.dg/ipa/devirt-44.C @@ -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" } } */ diff --git a/gcc/testsuite/g++.dg/ipa/devirt-45.C b/gcc/testsuite/g++.dg/ipa/devirt-45.C new file mode 100644 index 0000000..2158c7e --- /dev/null +++ b/gcc/testsuite/g++.dg/ipa/devirt-45.C @@ -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" } } */ |