[llvm-branch-commits] [NFC]Extract the heuristic to find vtable for an indirect call into a helper function (PR #81024)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Wed Feb 7 18:22:14 PST 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-analysis

Author: Mingming Liu (minglotus-6)

<details>
<summary>Changes</summary>

* 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


---
Full diff: https://github.com/llvm/llvm-project/pull/81024.diff


1 Files Affected:

- (modified) llvm/include/llvm/Analysis/IndirectCallVisitor.h (+36-27) 


``````````diff
diff --git a/llvm/include/llvm/Analysis/IndirectCallVisitor.h b/llvm/include/llvm/Analysis/IndirectCallVisitor.h
index c8429e52bee96..5969241a179ea 100644
--- a/llvm/include/llvm/Analysis/IndirectCallVisitor.h
+++ b/llvm/include/llvm/Analysis/IndirectCallVisitor.h
@@ -28,6 +28,38 @@ struct PGOIndirectCallVisitor : public InstVisitor<PGOIndirectCallVisitor> {
   std::vector<Instruction *> ProfiledAddresses;
   PGOIndirectCallVisitor(InstructionType Type) : Type(Type) {}
 
+  // 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());
+
+    if (LI != nullptr) {
+      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.
+      // Since a non-vtable profiled address is not within the address
+      // range of vtable objects, it's stored as zero in indexed profiles.
+      // A pass that looks up symbol with an zero hash will (almost) always
+      // find nullptr and skip the actual transformation (e.g., comparison
+      // of symbols). So the performance overhead from non-vtable profiled
+      // address is negligible if exists at all. Comparing loaded address
+      // with symbol address guarantees correctness.
+      if (VTablePtr != nullptr && isa<Instruction>(VTablePtr)) {
+        return cast<Instruction>(VTablePtr);
+      }
+    }
+    return nullptr;
+  }
+
   void visitCallBase(CallBase &Call) {
     if (Call.isIndirectCall()) {
       IndirectCalls.push_back(&Call);
@@ -35,33 +67,10 @@ struct PGOIndirectCallVisitor : public InstVisitor<PGOIndirectCallVisitor> {
       if (Type != InstructionType::kVTableVal)
         return;
 
-      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.
-        // 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.
-        // Since a non-vtable profiled address is not within the address
-        // range of vtable objects, it's stored as zero in indexed profiles.
-        // A pass that looks up symbol with an zero hash will (almost) always
-        // find nullptr and skip the actual transformation (e.g., comparison
-        // of symbols). So the performance overhead from non-vtable profiled
-        // 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));
-        }
+      Instruction *VPtr =
+          PGOIndirectCallVisitor::tryGetVTableInstruction(&Call);
+      if (VPtr) {
+        ProfiledAddresses.push_back(VPtr);
       }
     }
   }

``````````

</details>


https://github.com/llvm/llvm-project/pull/81024


More information about the llvm-branch-commits mailing list