@@ -27,31 +27,21 @@ struct PGOIndirectCallVisitor : public InstVisitor<PGOIndirectCallVisitor> {
27
27
std::vector<Instruction *> ProfiledAddresses;
28
28
PGOIndirectCallVisitor (InstructionType Type) : Type(Type) {}
29
29
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 ());
40
41
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.
51
42
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 ();
55
45
// FIXME: Add support in the frontend so LLVM type intrinsics are
56
46
// emitted without LTO. This way, added intrinsics could filter
57
47
// non-vtable instructions and reduce instrumentation overhead.
@@ -63,7 +53,22 @@ struct PGOIndirectCallVisitor : public InstVisitor<PGOIndirectCallVisitor> {
63
53
// address is negligible if exists at all. Comparing loaded address
64
54
// with symbol address guarantees correctness.
65
55
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);
67
72
}
68
73
}
69
74
0 commit comments