[llvm] 879245e - [NFC]Extract the heuristic to find vtable for an indirect call into a helper function (#81024)
via llvm-commits
llvm-commits at lists.llvm.org
Mon May 6 21:39:18 PDT 2024
Author: Mingming Liu
Date: 2024-05-06T21:39:13-07:00
New Revision: 879245e2b5d48b629e8b085afacf69cc1fd6a6ec
URL: https://github.com/llvm/llvm-project/commit/879245e2b5d48b629e8b085afacf69cc1fd6a6ec
DIFF: https://github.com/llvm/llvm-project/commit/879245e2b5d48b629e8b085afacf69cc1fd6a6ec.diff
LOG: [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 https://github.com/llvm/llvm-project/pull/80762
Added:
Modified:
llvm/include/llvm/Analysis/IndirectCallVisitor.h
Removed:
################################################################################
diff --git a/llvm/include/llvm/Analysis/IndirectCallVisitor.h b/llvm/include/llvm/Analysis/IndirectCallVisitor.h
index 50815f4e3e8398..66c972572b06c8 100644
--- a/llvm/include/llvm/Analysis/IndirectCallVisitor.h
+++ b/llvm/include/llvm/Analysis/IndirectCallVisitor.h
@@ -27,31 +27,21 @@ struct PGOIndirectCallVisitor : public InstVisitor<PGOIndirectCallVisitor> {
std::vector<Instruction *> ProfiledAddresses;
PGOIndirectCallVisitor(InstructionType Type) : Type(Type) {}
- void visitCallBase(CallBase &Call) {
- if (!Call.isIndirectCall())
- return;
-
- if (Type == InstructionType::kIndirectCall) {
- IndirectCalls.push_back(&Call);
- return;
- }
-
- assert(Type == InstructionType::kVTableVal && "Control flow guaranteed");
+ // Given an indirect call instruction, try to find the the following pattern
+ //
+ // %vtable = load ptr, ptr %obj
+ // %vfn = getelementptr inbounds ptr, ptr %vtable, i64 1
+ // %2 = load ptr, ptr %vfn
+ // $call = tail call i32 %2
+ //
+ // A heuristic is used to find the address feeding instructions.
+ static Instruction *tryGetVTableInstruction(CallBase *CB) {
+ assert(CB != nullptr && "Caller guaranteed");
+ LoadInst *LI = dyn_cast<LoadInst>(CB->getCalledOperand());
- LoadInst *LI = dyn_cast<LoadInst>(Call.getCalledOperand());
- // The code pattern to look for
- //
- // %vtable = load ptr, ptr %b
- // %vfn = getelementptr inbounds ptr, ptr %vtable, i64 1
- // %2 = load ptr, ptr %vfn
- // %call = tail call i32 %2(ptr %b)
- //
- // %vtable is the vtable address value to profile, and
- // %2 is the indirect call target address to profile.
if (LI != nullptr) {
- Value *Ptr = LI->getPointerOperand();
- Value *VTablePtr = Ptr->stripInBoundsConstantOffsets();
- // This is a heuristic to find address feeding instructions.
+ Value *FuncPtr = LI->getPointerOperand(); // GEP (or bitcast)
+ Value *VTablePtr = FuncPtr->stripInBoundsConstantOffsets();
// FIXME: Add support in the frontend so LLVM type intrinsics are
// emitted without LTO. This way, added intrinsics could filter
// non-vtable instructions and reduce instrumentation overhead.
@@ -63,7 +53,22 @@ struct PGOIndirectCallVisitor : public InstVisitor<PGOIndirectCallVisitor> {
// address is negligible if exists at all. Comparing loaded address
// with symbol address guarantees correctness.
if (VTablePtr != nullptr && isa<Instruction>(VTablePtr))
- ProfiledAddresses.push_back(cast<Instruction>(VTablePtr));
+ return cast<Instruction>(VTablePtr);
+ }
+ return nullptr;
+ }
+
+ void visitCallBase(CallBase &Call) {
+ if (Call.isIndirectCall()) {
+ IndirectCalls.push_back(&Call);
+
+ if (Type != InstructionType::kVTableVal)
+ return;
+
+ Instruction *VPtr =
+ PGOIndirectCallVisitor::tryGetVTableInstruction(&Call);
+ if (VPtr)
+ ProfiledAddresses.push_back(VPtr);
}
}
More information about the llvm-commits
mailing list