[PATCH] D16821: Add whole-program vtable optimization feature to Clang.

Peter Collingbourne via cfe-commits cfe-commits at lists.llvm.org
Mon Feb 22 15:47:02 PST 2016


On Mon, Feb 22, 2016 at 01:38:27PM -0800, Pete Cooper wrote:
> 
> > On Feb 22, 2016, at 1:30 PM, Peter Collingbourne <peter at pcc.me.uk> wrote:
> > 
> > One thing that I'd like to do (and this would help CFI as well) is to specifically recognize cases like this:
> > 
> > ```
> > struct B {
> >  virtual void vf();
> > };
> > 
> > struct D1 {
> > };
> I assume you meant D1 : B here?

Yes.

> > 
> > struct D2 : B {
> >  virtual void vf();
> > };
> > 
> > void f(D1 *d) {
> >  d->vf();
> > }
> > ```
> > 
> > In this case I'd like to devirtualize the virtual call in `f()` to `B::vf()`. But because the implicit cast to `B` in `f()` removes the information that `d` cannot be of type `D2`, we cannot eliminate `D2::vf()` as a candidate target (see also `test/cfi/sibling.cpp` in the CFI test suite).
> > 
> > Although this could possibly be emitted and pattern matched at the IR level, it seems simpler (and would probably catch enough cases) to have Clang look through the implicit cast when IR gen'ing for the call.
> So my devirtualizer dealt with this by marking each call site with the most specific class we know of in the hierarchy.  
> 
> In this case, then class hierarchy would contain the pairs: (B, B), (D1, B), (D2, B).
> 
> The call site in f() would be tagged with (D1, B) not (B, B).  Then, when we are in the pass, we look at the subclasses from (D1, B), see that there are none (or that none override vf), and devirtualize to B::vf().
> 
> If that isn’t possible in the current solution (I didn’t check), then it should be easy enough to add.  I certainly don’t think any of the current implementation would be hard to adapt to support this use case.

I think it should be possible to do something along those lines. After looking
through the implicit cast we would discover that the most derived type is D1
(I guess this is what your implementation is doing?) and perform the check
against that class's bitset, but only if the implicit cast did not involve
a pointer adjustment.

This won't be as precise as it could be in the presence of multiple inheritance
(which I guess must be why your metadata is also tracking base classes),
but I think that can be a separate metadata enhancement.

Thanks,
-- 
Peter


More information about the cfe-commits mailing list