LLVM 19.0.0git
IndirectCallVisitor.h
Go to the documentation of this file.
1//===-- IndirectCallVisitor.h - indirect call visitor ---------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements defines a visitor class and a helper function that find
10// all indirect call-sites in a function.
11
12#ifndef LLVM_ANALYSIS_INDIRECTCALLVISITOR_H
13#define LLVM_ANALYSIS_INDIRECTCALLVISITOR_H
14
15#include "llvm/IR/InstVisitor.h"
16#include <vector>
17
18namespace llvm {
19// Visitor class that finds indirect calls or instructions that gives vtable
20// value, depending on Type.
21struct PGOIndirectCallVisitor : public InstVisitor<PGOIndirectCallVisitor> {
22 enum class InstructionType {
23 kIndirectCall = 0,
24 kVTableVal = 1,
25 };
26 std::vector<CallBase *> IndirectCalls;
27 std::vector<Instruction *> ProfiledAddresses;
29
30 void visitCallBase(CallBase &Call) {
31 if (!Call.isIndirectCall())
32 return;
33
35 IndirectCalls.push_back(&Call);
36 return;
37 }
38
39 assert(Type == InstructionType::kVTableVal && "Control flow guaranteed");
40
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 if (LI != nullptr) {
53 Value *VTablePtr = Ptr->stripInBoundsConstantOffsets();
54 // This is a heuristic to find address feeding instructions.
55 // FIXME: Add support in the frontend so LLVM type intrinsics are
56 // emitted without LTO. This way, added intrinsics could filter
57 // non-vtable instructions and reduce instrumentation overhead.
58 // Since a non-vtable profiled address is not within the address
59 // range of vtable objects, it's stored as zero in indexed profiles.
60 // A pass that looks up symbol with an zero hash will (almost) always
61 // find nullptr and skip the actual transformation (e.g., comparison
62 // of symbols). So the performance overhead from non-vtable profiled
63 // address is negligible if exists at all. Comparing loaded address
64 // with symbol address guarantees correctness.
65 if (VTablePtr != nullptr && isa<Instruction>(VTablePtr))
66 ProfiledAddresses.push_back(cast<Instruction>(VTablePtr));
67 }
68 }
69
70private:
72};
73
74inline std::vector<CallBase *> findIndirectCalls(Function &F) {
77 ICV.visit(F);
78 return ICV.IndirectCalls;
79}
80
81inline std::vector<Instruction *> findVTableAddrs(Function &F) {
84 ICV.visit(F);
85 return ICV.ProfiledAddresses;
86}
87
88} // namespace llvm
89
90#endif
#define F(x, y, z)
Definition: MD5.cpp:55
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
Definition: InstrTypes.h:1494
Base class for instruction visitors.
Definition: InstVisitor.h:78
void visit(Iterator Start, Iterator End)
Definition: InstVisitor.h:87
An instruction for reading from memory.
Definition: Instructions.h:184
Value * getPointerOperand()
Definition: Instructions.h:280
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
LLVM Value Representation.
Definition: Value.h:74
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
std::vector< CallBase * > findIndirectCalls(Function &F)
std::vector< Instruction * > findVTableAddrs(Function &F)
std::vector< CallBase * > IndirectCalls
PGOIndirectCallVisitor(InstructionType Type)
std::vector< Instruction * > ProfiledAddresses
void visitCallBase(CallBase &Call)