On Fri, Aug 21, 2015 at 1:41 PM, Swati Rathi <swatira...@cse.iitb.ac.in> wrote: > On 2015-08-21 16:16, Richard Biener wrote: >> >> On Fri, Aug 21, 2015 at 12:44 PM, Uday P. Khedker <u...@cse.iitb.ac.in> >> wrote: >>> >>> >>> >>> 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). >> >> >> Did you tell GCC this is a complete program? > > > Yes, we did specify the -fwhole-program option with optimization level O3. > Is there any other option we should try?
No, that should be all for single-file testcases. But maybe it no longer works reliably ("may be defined in other units" shouldn't appear with that). Richard. > >> >>> 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. >> >> >> I see. >> >> Richard. >> >>> Uday. >>> >>> >>> >>> >