//=== ValueProfilePlugins.inc - set of plugins used by ValueProfileCollector =// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file contains a set of plugin classes used in ValueProfileCollectorImpl. // Each plugin is responsible for collecting Value Profiling candidates for a // particular optimization. // Each plugin must satisfy the interface described in ValueProfileCollector.cpp // //===----------------------------------------------------------------------===// #include "ValueProfileCollector.h" #include "llvm/Analysis/IndirectCallVisitor.h" #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/IR/InstVisitor.h" using namespace llvm; using CandidateInfo = ValueProfileCollector::CandidateInfo; extern cl::opt MemOPOptMemcmpBcmp; ///--------------------------- MemIntrinsicPlugin ------------------------------ class MemIntrinsicPlugin : public InstVisitor { Function &F; TargetLibraryInfo &TLI; std::vector *Candidates; public: static constexpr InstrProfValueKind Kind = IPVK_MemOPSize; MemIntrinsicPlugin(Function &Fn, TargetLibraryInfo &TLI) : F(Fn), TLI(TLI), Candidates(nullptr) {} void run(std::vector &Cs) { Candidates = &Cs; visit(F); Candidates = nullptr; } void visitMemIntrinsic(MemIntrinsic &MI) { Value *Length = MI.getLength(); // Not instrument constant length calls. if (isa(Length)) return; Instruction *InsertPt = &MI; Instruction *AnnotatedInst = &MI; Candidates->emplace_back(CandidateInfo{Length, InsertPt, AnnotatedInst}); } void visitCallInst(CallInst &CI) { if (!MemOPOptMemcmpBcmp) return; auto *F = CI.getCalledFunction(); if (!F) return; LibFunc Func; if (TLI.getLibFunc(CI, Func) && (Func == LibFunc_memcmp || Func == LibFunc_bcmp)) { Value *Length = CI.getArgOperand(2); // Not instrument constant length calls. if (isa(Length)) return; Instruction *InsertPt = &CI; Instruction *AnnotatedInst = &CI; Candidates->emplace_back(CandidateInfo{Length, InsertPt, AnnotatedInst}); } } }; ///------------------------ IndirectCallPromotionPlugin ------------------------ class IndirectCallPromotionPlugin { Function &F; public: static constexpr InstrProfValueKind Kind = IPVK_IndirectCallTarget; IndirectCallPromotionPlugin(Function &Fn, TargetLibraryInfo &TLI) : F(Fn) {} void run(std::vector &Candidates) { std::vector Result = findIndirectCalls(F); for (Instruction *I : Result) { Value *Callee = cast(I)->getCalledOperand(); Instruction *InsertPt = I; Instruction *AnnotatedInst = I; Candidates.emplace_back(CandidateInfo{Callee, InsertPt, AnnotatedInst}); } } }; ///--------------------- VirtualTableValueProfilingPlugin -------------------- class VTableProfilingPlugin { Function &F; public: static constexpr InstrProfValueKind Kind = IPVK_VTableTarget; VTableProfilingPlugin(Function &Fn, TargetLibraryInfo &TLI) : F(Fn) {} void run(std::vector &Candidates) { std::vector Result = findVTableAddrs(F); for (Instruction *I : Result) { Instruction *InsertPt = I->getNextNonDebugInstruction(); // When finding an insertion point, keep PHI and EH pad instructions // before vp intrinsics. This is similar to // `BasicBlock::getFirstInsertionPt`. while (InsertPt && (dyn_cast(InsertPt) || InsertPt->isEHPad())) InsertPt = InsertPt->getNextNonDebugInstruction(); // Skip instrumentating the value if InsertPt is the last instruction. // FIXME: Set InsertPt to the end of basic block to instrument the value // if InsertPt is the last instruction. if (InsertPt == nullptr) continue; Instruction *AnnotatedInst = I; Candidates.emplace_back(CandidateInfo{I, InsertPt, AnnotatedInst}); } } }; ///----------------------- Registration of the plugins ------------------------- /// For now, registering a plugin with the ValueProfileCollector is done by /// adding the plugin type to the VP_PLUGIN_LIST macro. #define VP_PLUGIN_LIST \ MemIntrinsicPlugin, IndirectCallPromotionPlugin, VTableProfilingPlugin