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

Mehdi Amini via cfe-commits cfe-commits at lists.llvm.org
Mon Feb 22 15:59:01 PST 2016


> On Feb 22, 2016, at 3:47 PM, Peter Collingbourne <peter at pcc.me.uk> wrote:
> 
> 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.

The implementation we have (at least the one I have) generates the most precise information directly from the frontend. You have all the informations at the call site in the clang AST when you access the VTable, there is no cast or anything on the way.

-- 
Mehdi


> 
> 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