On 08/19/2015 04:44 PM, Andrew Pinski wrote:
On Wed, Aug 19, 2015 at 7:16 PM, Uday P. Khedker <u...@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 <u...@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.




Reply via email to