From 4c2030661e0a9bce68786f72e4d0da1be5caf3a5 Mon Sep 17 00:00:00 2001 From: Martin Jambor <mjambor@suse.cz> Date: Tue, 2 Nov 2010 16:22:52 +0100 Subject: [PATCH] re PR middle-end/46120 (g++.dg/ipa/ivinline-?.C) 2010-11-02 Martin Jambor <mjambor@suse.cz> PR middle-end/46120 * tree.c (get_binfo_at_offset): Bail out on artificial fields. Identify primary bases according to their offsets. * testsuite/g++.dg/ipa/ivinline-9.C: New test. From-SVN: r166192 --- gcc/ChangeLog | 6 ++ gcc/testsuite/ChangeLog | 5 ++ gcc/testsuite/g++.dg/ipa/ivinline-9.C | 93 +++++++++++++++++++++++++++ gcc/tree.c | 40 ++++++------ 4 files changed, 125 insertions(+), 19 deletions(-) create mode 100644 gcc/testsuite/g++.dg/ipa/ivinline-9.C diff --git a/gcc/ChangeLog b/gcc/ChangeLog index c946683d46e2..a347b05182c7 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2010-11-02 Martin Jambor <mjambor@suse.cz> + + PR middle-end/46120 + * tree.c (get_binfo_at_offset): Bail out on artificial + fields. Identify primary bases according to their offsets. + 2010-11-02 Martin Jambor <mjambor@suse.cz> PR tree-optimization/45875 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index aa80464b054e..471b009da583 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2010-11-02 Martin Jambor <mjambor@suse.cz> + + PR middle-end/46120 + * g++.dg/ipa/ivinline-9.C: New test. + 2010-11-02 Martin Jambor <mjambor@suse.cz> PR tree-optimization/45875 diff --git a/gcc/testsuite/g++.dg/ipa/ivinline-9.C b/gcc/testsuite/g++.dg/ipa/ivinline-9.C new file mode 100644 index 000000000000..429b6f4f00c8 --- /dev/null +++ b/gcc/testsuite/g++.dg/ipa/ivinline-9.C @@ -0,0 +1,93 @@ +/* Verify that simple virtual calls are inlined even without early + inlining, even when a typecast to an ancestor is involved along the + way and that ancestor itself has an ancestor wich is not the + primary base class. */ +/* { dg-do run } */ +/* { dg-options "-O3 -fdump-ipa-inline -fno-early-inlining -fno-ipa-cp" } */ + +extern "C" void abort (void); + +class Distraction +{ +public: + float f; + double d; + Distraction () + { + f = 8.3; + d = 10.2; + } + virtual float bar (float z); +}; + +class A +{ +public: + int data; + virtual int foo (int i); +}; +/* +class D2 +{ +public: + virtual float baz (float z) + { + abort(); + } +}; +*/ +class A2 : public Distraction, public A +{ + int i2; +}; + +class B : public A2 +{ +public: + virtual int foo (int i); +}; + +float Distraction::bar (float z) +{ + f += z; + return f/2; +} + +int A::foo (int i) +{ + return i + 1; +} + +int B::foo (int i) +{ + return i + 2; +} + +int __attribute__ ((noinline,noclone)) get_input(void) +{ + return 1; +} + +static int middleman_1 (class A *obj, int i) +{ + return obj->foo (i); +} + +static int middleman_2 (class B *obj, int i) +{ + return middleman_1 (obj, i); +} + +int main (int argc, char *argv[]) +{ + class B b; + int i; + + for (i = 0; i < get_input (); i++) + if (middleman_2 (&b, get_input ()) != 3) + abort (); + return 0; +} + +/* { dg-final { scan-ipa-dump "B::foo\[^\\n\]*inline copy in int main" "inline" } } */ +/* { dg-final { cleanup-ipa-dump "inline" } } */ diff --git a/gcc/tree.c b/gcc/tree.c index a74603156586..1cc99f07c67a 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -10906,16 +10906,17 @@ lhd_gcc_personality (void) tree get_binfo_at_offset (tree binfo, HOST_WIDE_INT offset, tree expected_type) { - tree type; + tree type = TREE_TYPE (binfo); - type = TREE_TYPE (binfo); - while (offset > 0) + while (true) { - tree base_binfo, found_binfo; HOST_WIDE_INT pos, size; tree fld; int i; + gcc_checking_assert (offset >= 0); + if (type == expected_type) + return binfo; if (TREE_CODE (type) != RECORD_TYPE) return NULL_TREE; @@ -10929,27 +10930,28 @@ get_binfo_at_offset (tree binfo, HOST_WIDE_INT offset, tree expected_type) if (pos <= offset && (pos + size) > offset) break; } - if (!fld) + if (!fld || !DECL_ARTIFICIAL (fld)) return NULL_TREE; - found_binfo = NULL_TREE; - for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++) - if (TREE_TYPE (base_binfo) == TREE_TYPE (fld)) - { - found_binfo = base_binfo; - break; - } - - if (!found_binfo) - return NULL_TREE; + /* Offset 0 indicates the primary base, whose vtable contents are + represented in the binfo for the derived class. */ + if (offset != 0) + { + tree base_binfo, found_binfo = NULL_TREE; + for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++) + if (TREE_TYPE (base_binfo) == TREE_TYPE (fld)) + { + found_binfo = base_binfo; + break; + } + if (!found_binfo) + return NULL_TREE; + binfo = found_binfo; + } type = TREE_TYPE (fld); - binfo = found_binfo; offset -= pos; } - if (type != expected_type) - return NULL_TREE; - return binfo; } /* Returns true if X is a typedef decl. */ -- GitLab