Teresa Johnson via llvm-dev
2019-May-06 23:05 UTC
[llvm-dev] Regarding devirtualization in clang
Hi Kamlesh, Cc'ing llvm-dev as well as some specific parties interested in devirtualization in clang for thoughts. Some comments below. *From: *kamlesh kumar <kamleshbhalui at gmail.com> *Date: *Mon, May 6, 2019 at 7:48 AM *To: * <tejohnson at google.com> Hi Teresa,> I am going through devirtualization in clang/llvm. > And found a testcase which suitable for devirtualzation but clang is > unable to do so. > Consider below test case link of Godbolt. > https://gcc.godbolt.org/z/j4uhZT > > Even though B::value() is marked as final, > clang is unable to devirtualize it. > can you please shed some light here? > or am i missing something? >In general, devirtualization in cases like this where inlining is required is pretty limited in clang. Note that clang can devirtualize if you changed foo_test to define the variable (rather than take it as a parameter). E.g.: void foo_test() { B b; test(&b); <- b->value() gets devirtualized after inlining test() (looks like it is devirtualized during inlining, presumably via some constant propagation after inlining test(), because we then inline B::value()). } It also works if inlining isn't required, e.g. if I manually inline test(): void foo_test2(B*b) { b->value() + 11; <--- b->value() gets devirtualized early by clang that sees the final specifier } So I think there is a phase ordering issue between the type of devirt supported by clang, and the inlining that happens later and exposes the opportunity in the original test case. I've been focusing so far on whole program devirtualization (which Peter implemented for LTO as well as hybrid ThinLTO/LTO, but I am porting to ThinLTO only). But devirtualization opportunities exposed by inlining is one of the limitations that I'd like to figure out how to address. In this case it doesn't require whole program analysis since B::value is explicitly marked final. Piotr - not sure if your -fstrict-vtable-pointers devirtualization can help at all in this case - I tried it but it didn't seem to. Teresa> > Thanks > ./Kamlesh > >-- Teresa Johnson | Software Engineer | tejohnson at google.com | -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20190506/a95cf5d0/attachment.html>
Xinliang David Li via llvm-dev
2019-May-06 23:13 UTC
[llvm-dev] Regarding devirtualization in clang
Looks like the type information for the indirect callsite in 'test' needs to be updated after inline transformations so that devirtualization can kick in. This sounds like a bug (I remember similar situation was discussed before somewhere). David On Mon, May 6, 2019 at 4:05 PM Teresa Johnson <tejohnson at google.com> wrote:> Hi Kamlesh, > > Cc'ing llvm-dev as well as some specific parties interested in > devirtualization in clang for thoughts. Some comments below. > > *From: *kamlesh kumar <kamleshbhalui at gmail.com> > *Date: *Mon, May 6, 2019 at 7:48 AM > *To: * <tejohnson at google.com> > > Hi Teresa, >> I am going through devirtualization in clang/llvm. >> And found a testcase which suitable for devirtualzation but clang is >> unable to do so. >> Consider below test case link of Godbolt. >> https://gcc.godbolt.org/z/j4uhZT >> >> Even though B::value() is marked as final, >> clang is unable to devirtualize it. >> can you please shed some light here? >> or am i missing something? >> > > In general, devirtualization in cases like this where inlining is required > is pretty limited in clang. > > Note that clang can devirtualize if you changed foo_test to define the > variable (rather than take it as a parameter). E.g.: > > void foo_test() > { > B b; > test(&b); <- b->value() gets devirtualized after inlining test() > (looks like it is devirtualized during inlining, presumably via some > constant propagation after inlining test(), because we then inline > B::value()). > } > > It also works if inlining isn't required, e.g. if I manually inline test(): > > void foo_test2(B*b) > { > b->value() + 11; <--- b->value() gets devirtualized early by clang > that sees the final specifier > } > > So I think there is a phase ordering issue between the type of devirt > supported by clang, and the inlining that happens later and exposes the > opportunity in the original test case. > > I've been focusing so far on whole program devirtualization (which Peter > implemented for LTO as well as hybrid ThinLTO/LTO, but I am porting to > ThinLTO only). But devirtualization opportunities exposed by inlining is > one of the limitations that I'd like to figure out how to address. In this > case it doesn't require whole program analysis since B::value is explicitly > marked final. > > Piotr - not sure if your -fstrict-vtable-pointers devirtualization can > help at all in this case - I tried it but it didn't seem to. > > Teresa > > >> >> Thanks >> ./Kamlesh >> >> > > -- > Teresa Johnson | Software Engineer | tejohnson at google.com | >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20190506/da457b93/attachment.html>