[PATCH] D16795: WholeProgramDevirt: introduce.
Peter Collingbourne via llvm-commits
llvm-commits at lists.llvm.org
Mon Feb 8 15:37:08 PST 2016
pcc added inline comments.
================
Comment at: lib/Transforms/IPO/WholeProgramDevirt.cpp:331-347
@@ +330,19 @@
+ auto OpGlobal = dyn_cast<GlobalVariable>(OpConst);
+ if (!OpGlobal)
+ continue;
+
+ uint64_t Offset =
+ cast<ConstantInt>(
+ cast<ConstantAsMetadata>(Op->getOperand(2))->getValue())
+ ->getZExtValue();
+
+ VTableBits *&BitsPtr = GVToBits[OpGlobal];
+ if (!BitsPtr) {
+ Bits.emplace_back();
+ Bits.back().GV = OpGlobal;
+ Bits.back().ObjectSize = M.getDataLayout().getTypeAllocSize(
+ OpGlobal->getInitializer()->getType());
+ BitsPtr = &Bits.back();
+ }
+ BitSets[BitSetID].insert({BitsPtr, Offset});
+ }
----------------
pete wrote:
> Sorry, don't know how to reply to this point correctly in Phab, but here goes:
>
> So this is the current code to add an entry to BitSets[]. This is where I think we could move the following checks, as that way we know that all elements in BitSets have valid GlobalValue's according to these checks. I don't think thats too bad so long as we can move the checks here. Obviously if for some reason we had to duplicate the checks then your current code is better.
>
> These are the checks I'm thinking of:
>
> if (!BS.Bits->GV->isConstant())
> return false;
>
> auto Init = dyn_cast<ConstantArray>(BS.Bits->GV->getInitializer());
> if (!Init)
> return false;
If an element has an invalid GlobalValue according to those checks, we cannot apply the optimization for that bitset, because it would be an invalid optimization. Consider:
```
@vt1 = global [1 x i8*] [i8* bitcast void()* @vf1 to i8*]
@vt2 = constant [1 x i8*] [i8* bitcast void()* @vf2 to i8*]
void @f(i8* %this) {
%vtable = load %this
llvm.assume(llvm.bitset.test(%vtable, !"bitset"))
; make a virtual call through %vtable
}
!0 = {!"bitset", @vt1, 0}
!1 = {!"bitset", @vt2, 0}
!llvm.bitsets = !{!0, !1}
```
If we do those checks here, the pass would add only `@vt2` to `BitSets["bitset"]`, and it would later apply single-implementation devirtualization to turn the virtual call in `@f` into a direct call to `@vf2`. But that would not be correct, because it could potentially be a call to `@vf1` (or potentially any other function, if some other code overwrites the pointer in `@vt1`).
Because we expect this case to never arise in practice, the simplest thing to do is to handle it in the loop later.
http://reviews.llvm.org/D16795
More information about the llvm-commits
mailing list