Skip to content

Commit 879245e

Browse files
[NFC]Extract the heuristic to find vtable for an indirect call into a helper function (#81024)
* This way the helper function could be re-used by indirect-call-promotion pass to find out the vtable for an indirect call and extract the value profiles if any. * The parent patch is #80762
1 parent 02ce822 commit 879245e

File tree

1 file changed

+29
-24
lines changed

1 file changed

+29
-24
lines changed

llvm/include/llvm/Analysis/IndirectCallVisitor.h

Lines changed: 29 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -27,31 +27,21 @@ struct PGOIndirectCallVisitor : public InstVisitor<PGOIndirectCallVisitor> {
2727
std::vector<Instruction *> ProfiledAddresses;
2828
PGOIndirectCallVisitor(InstructionType Type) : Type(Type) {}
2929

30-
void visitCallBase(CallBase &Call) {
31-
if (!Call.isIndirectCall())
32-
return;
33-
34-
if (Type == InstructionType::kIndirectCall) {
35-
IndirectCalls.push_back(&Call);
36-
return;
37-
}
38-
39-
assert(Type == InstructionType::kVTableVal && "Control flow guaranteed");
30+
// Given an indirect call instruction, try to find the the following pattern
31+
//
32+
// %vtable = load ptr, ptr %obj
33+
// %vfn = getelementptr inbounds ptr, ptr %vtable, i64 1
34+
// %2 = load ptr, ptr %vfn
35+
// $call = tail call i32 %2
36+
//
37+
// A heuristic is used to find the address feeding instructions.
38+
static Instruction *tryGetVTableInstruction(CallBase *CB) {
39+
assert(CB != nullptr && "Caller guaranteed");
40+
LoadInst *LI = dyn_cast<LoadInst>(CB->getCalledOperand());
4041

41-
LoadInst *LI = dyn_cast<LoadInst>(Call.getCalledOperand());
42-
// The code pattern to look for
43-
//
44-
// %vtable = load ptr, ptr %b
45-
// %vfn = getelementptr inbounds ptr, ptr %vtable, i64 1
46-
// %2 = load ptr, ptr %vfn
47-
// %call = tail call i32 %2(ptr %b)
48-
//
49-
// %vtable is the vtable address value to profile, and
50-
// %2 is the indirect call target address to profile.
5142
if (LI != nullptr) {
52-
Value *Ptr = LI->getPointerOperand();
53-
Value *VTablePtr = Ptr->stripInBoundsConstantOffsets();
54-
// This is a heuristic to find address feeding instructions.
43+
Value *FuncPtr = LI->getPointerOperand(); // GEP (or bitcast)
44+
Value *VTablePtr = FuncPtr->stripInBoundsConstantOffsets();
5545
// FIXME: Add support in the frontend so LLVM type intrinsics are
5646
// emitted without LTO. This way, added intrinsics could filter
5747
// non-vtable instructions and reduce instrumentation overhead.
@@ -63,7 +53,22 @@ struct PGOIndirectCallVisitor : public InstVisitor<PGOIndirectCallVisitor> {
6353
// address is negligible if exists at all. Comparing loaded address
6454
// with symbol address guarantees correctness.
6555
if (VTablePtr != nullptr && isa<Instruction>(VTablePtr))
66-
ProfiledAddresses.push_back(cast<Instruction>(VTablePtr));
56+
return cast<Instruction>(VTablePtr);
57+
}
58+
return nullptr;
59+
}
60+
61+
void visitCallBase(CallBase &Call) {
62+
if (Call.isIndirectCall()) {
63+
IndirectCalls.push_back(&Call);
64+
65+
if (Type != InstructionType::kVTableVal)
66+
return;
67+
68+
Instruction *VPtr =
69+
PGOIndirectCallVisitor::tryGetVTableInstruction(&Call);
70+
if (VPtr)
71+
ProfiledAddresses.push_back(VPtr);
6772
}
6873
}
6974

0 commit comments

Comments
 (0)