This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Compilation of object creation in C++




On 08/19/2015 04:44 PM, Andrew Pinski wrote:
On Wed, Aug 19, 2015 at 7:16 PM, Uday P. Khedker <uday@cse.iitb.ac.in> wrote:

Why is this different? Why is __comp_ctor not invoked in each case?
This looks like the function has been inlined as it is short.



Thanks, this is a useful lead. Setting -fno-inline seems to do the trick and now the behaviour is same. C intermediate language


On 08/19/2015 06:00 PM, Richard Biener wrote:
On Wed, Aug 19, 2015 at 2:10 PM, Uday P. Khedker <uday@cse.iitb.ac.in> wrote:
Andrew Pinski wrote on Wednesday 19 August 2015 04:44 PM:

Most of this is already in GCC 5 and above.  Including the IPA pass.
Have you looked into that pass yet?
 From what I have read, it involves flow insensitive analysis whereas we are
looking at flow sensitive analysis.
It also performs flow-sensitive analysis, exactly like you suggest by looking
for constructor calls or patterns that involve setting the vtable pointer
exposed through inlining.


When I said flow sensitive, I have interprocedural version in mind. When I looked up ipa-devirt.c,
there seems to be a traversal  using FOR_EACH_DEFINED_FUNCTION (n), but nothing in it
indicates, an interprocedural transfer of information. I also looked up Jan Hubicka's blogs
(http://hubicka.blogspot.ca/2014/01/devirtualization-in-c-part-2-low-level.html)
and if I have understood it correctly, the analysis done by constant propagation and global
value numbering is at the intraprocedural level (haven't looked up these passes though).

Here's a rather trivial example where gcc-5.1 misses devirtualization

class A
{
       public:
               virtual void f() {cout << "\tA:f" << endl;}
};

class B : public A
{     public:
              void f() {cout << "\tB:f" << endl;}
};

class C : public B
{
     public:
              void f() {cout<< "\tC:f" << endl;}
};

void fun1 (A *a, int i)
{
    cout << "\nhi in fun1" << i << endl ;
    a->f();
}

int main()
{
        A  *a1;
    a1 = new A;
    fun1 (a1, 10);

    A *a2;
    a2 = new A;
    fun1 (a2, 5);
}

Assuming that there is no other translation unit and this is the complete program, the call a->f() is always for class
A but the dump in .058i.devirt says

Procesing function void fun1(A*, int)/232
  Targets of polymorphic call of type 28:struct A token 0
    Outer type (dynamic):struct A (or a derived type) offset 0
    This is partial list; extra targets may be defined in other units. (derived types included)
       virtual void A::f()/229 virtual void B::f()/230 virtual void C::f()/231

suggesting that A, B, and C are possible classes.

Even a simple field and context insensitive interprocedural analysis would figure out that only one call is
possible (assuming this is the complete program).

The situation we are looking at involves interprocedural propagation with complex calls such as a->f->g->h(). We
plan to use a demand driven flow, context, and field sensitive sensitive points-to analysis which involves just about enough
computation required to resolves such calls.

Uday.





Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]