18bcb0991SDimitry Andric//=== ValueProfilePlugins.inc - set of plugins used by ValueProfileCollector =// 28bcb0991SDimitry Andric// 38bcb0991SDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 48bcb0991SDimitry Andric// See https://llvm.org/LICENSE.txt for license information. 58bcb0991SDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 68bcb0991SDimitry Andric// 78bcb0991SDimitry Andric//===----------------------------------------------------------------------===// 88bcb0991SDimitry Andric// 98bcb0991SDimitry Andric// This file contains a set of plugin classes used in ValueProfileCollectorImpl. 108bcb0991SDimitry Andric// Each plugin is responsible for collecting Value Profiling candidates for a 118bcb0991SDimitry Andric// particular optimization. 128bcb0991SDimitry Andric// Each plugin must satisfy the interface described in ValueProfileCollector.cpp 138bcb0991SDimitry Andric// 148bcb0991SDimitry Andric//===----------------------------------------------------------------------===// 158bcb0991SDimitry Andric 168bcb0991SDimitry Andric#include "ValueProfileCollector.h" 178bcb0991SDimitry Andric#include "llvm/Analysis/IndirectCallVisitor.h" 1881ad6265SDimitry Andric#include "llvm/Analysis/TargetLibraryInfo.h" 198bcb0991SDimitry Andric#include "llvm/IR/InstVisitor.h" 208bcb0991SDimitry Andric 218bcb0991SDimitry Andricusing namespace llvm; 228bcb0991SDimitry Andricusing CandidateInfo = ValueProfileCollector::CandidateInfo; 238bcb0991SDimitry Andric 245ffd83dbSDimitry Andricextern cl::opt<bool> MemOPOptMemcmpBcmp; 255ffd83dbSDimitry Andric 268bcb0991SDimitry Andric///--------------------------- MemIntrinsicPlugin ------------------------------ 278bcb0991SDimitry Andricclass MemIntrinsicPlugin : public InstVisitor<MemIntrinsicPlugin> { 288bcb0991SDimitry Andric Function &F; 295ffd83dbSDimitry Andric TargetLibraryInfo &TLI; 308bcb0991SDimitry Andric std::vector<CandidateInfo> *Candidates; 318bcb0991SDimitry Andric 328bcb0991SDimitry Andricpublic: 338bcb0991SDimitry Andric static constexpr InstrProfValueKind Kind = IPVK_MemOPSize; 348bcb0991SDimitry Andric 355ffd83dbSDimitry Andric MemIntrinsicPlugin(Function &Fn, TargetLibraryInfo &TLI) 365ffd83dbSDimitry Andric : F(Fn), TLI(TLI), Candidates(nullptr) {} 378bcb0991SDimitry Andric 388bcb0991SDimitry Andric void run(std::vector<CandidateInfo> &Cs) { 398bcb0991SDimitry Andric Candidates = &Cs; 408bcb0991SDimitry Andric visit(F); 418bcb0991SDimitry Andric Candidates = nullptr; 428bcb0991SDimitry Andric } 438bcb0991SDimitry Andric void visitMemIntrinsic(MemIntrinsic &MI) { 448bcb0991SDimitry Andric Value *Length = MI.getLength(); 458bcb0991SDimitry Andric // Not instrument constant length calls. 46fe6060f1SDimitry Andric if (isa<ConstantInt>(Length)) 478bcb0991SDimitry Andric return; 488bcb0991SDimitry Andric 498bcb0991SDimitry Andric Instruction *InsertPt = &MI; 508bcb0991SDimitry Andric Instruction *AnnotatedInst = &MI; 518bcb0991SDimitry Andric Candidates->emplace_back(CandidateInfo{Length, InsertPt, AnnotatedInst}); 528bcb0991SDimitry Andric } 535ffd83dbSDimitry Andric void visitCallInst(CallInst &CI) { 545ffd83dbSDimitry Andric if (!MemOPOptMemcmpBcmp) 555ffd83dbSDimitry Andric return; 565ffd83dbSDimitry Andric auto *F = CI.getCalledFunction(); 575ffd83dbSDimitry Andric if (!F) 585ffd83dbSDimitry Andric return; 595ffd83dbSDimitry Andric LibFunc Func; 605ffd83dbSDimitry Andric if (TLI.getLibFunc(CI, Func) && 615ffd83dbSDimitry Andric (Func == LibFunc_memcmp || Func == LibFunc_bcmp)) { 625ffd83dbSDimitry Andric Value *Length = CI.getArgOperand(2); 635ffd83dbSDimitry Andric // Not instrument constant length calls. 64fe6060f1SDimitry Andric if (isa<ConstantInt>(Length)) 655ffd83dbSDimitry Andric return; 665ffd83dbSDimitry Andric Instruction *InsertPt = &CI; 675ffd83dbSDimitry Andric Instruction *AnnotatedInst = &CI; 685ffd83dbSDimitry Andric Candidates->emplace_back(CandidateInfo{Length, InsertPt, AnnotatedInst}); 695ffd83dbSDimitry Andric } 705ffd83dbSDimitry Andric } 718bcb0991SDimitry Andric}; 728bcb0991SDimitry Andric 738bcb0991SDimitry Andric///------------------------ IndirectCallPromotionPlugin ------------------------ 748bcb0991SDimitry Andricclass IndirectCallPromotionPlugin { 758bcb0991SDimitry Andric Function &F; 768bcb0991SDimitry Andric 778bcb0991SDimitry Andricpublic: 788bcb0991SDimitry Andric static constexpr InstrProfValueKind Kind = IPVK_IndirectCallTarget; 798bcb0991SDimitry Andric 805ffd83dbSDimitry Andric IndirectCallPromotionPlugin(Function &Fn, TargetLibraryInfo &TLI) : F(Fn) {} 818bcb0991SDimitry Andric 828bcb0991SDimitry Andric void run(std::vector<CandidateInfo> &Candidates) { 835ffd83dbSDimitry Andric std::vector<CallBase *> Result = findIndirectCalls(F); 848bcb0991SDimitry Andric for (Instruction *I : Result) { 855ffd83dbSDimitry Andric Value *Callee = cast<CallBase>(I)->getCalledOperand(); 868bcb0991SDimitry Andric Instruction *InsertPt = I; 878bcb0991SDimitry Andric Instruction *AnnotatedInst = I; 888bcb0991SDimitry Andric Candidates.emplace_back(CandidateInfo{Callee, InsertPt, AnnotatedInst}); 898bcb0991SDimitry Andric } 908bcb0991SDimitry Andric } 918bcb0991SDimitry Andric}; 928bcb0991SDimitry Andric 93*0fca6ea1SDimitry Andric///--------------------- VirtualTableValueProfilingPlugin -------------------- 94*0fca6ea1SDimitry Andricclass VTableProfilingPlugin { 95*0fca6ea1SDimitry Andric Function &F; 96*0fca6ea1SDimitry Andric 97*0fca6ea1SDimitry Andricpublic: 98*0fca6ea1SDimitry Andric static constexpr InstrProfValueKind Kind = IPVK_VTableTarget; 99*0fca6ea1SDimitry Andric 100*0fca6ea1SDimitry Andric VTableProfilingPlugin(Function &Fn, TargetLibraryInfo &TLI) : F(Fn) {} 101*0fca6ea1SDimitry Andric 102*0fca6ea1SDimitry Andric void run(std::vector<CandidateInfo> &Candidates) { 103*0fca6ea1SDimitry Andric std::vector<Instruction *> Result = findVTableAddrs(F); 104*0fca6ea1SDimitry Andric for (Instruction *I : Result) { 105*0fca6ea1SDimitry Andric Instruction *InsertPt = I->getNextNonDebugInstruction(); 106*0fca6ea1SDimitry Andric // When finding an insertion point, keep PHI and EH pad instructions 107*0fca6ea1SDimitry Andric // before vp intrinsics. This is similar to 108*0fca6ea1SDimitry Andric // `BasicBlock::getFirstInsertionPt`. 109*0fca6ea1SDimitry Andric while (InsertPt && (dyn_cast<PHINode>(InsertPt) || InsertPt->isEHPad())) 110*0fca6ea1SDimitry Andric InsertPt = InsertPt->getNextNonDebugInstruction(); 111*0fca6ea1SDimitry Andric // Skip instrumentating the value if InsertPt is the last instruction. 112*0fca6ea1SDimitry Andric // FIXME: Set InsertPt to the end of basic block to instrument the value 113*0fca6ea1SDimitry Andric // if InsertPt is the last instruction. 114*0fca6ea1SDimitry Andric if (InsertPt == nullptr) 115*0fca6ea1SDimitry Andric continue; 116*0fca6ea1SDimitry Andric 117*0fca6ea1SDimitry Andric Instruction *AnnotatedInst = I; 118*0fca6ea1SDimitry Andric Candidates.emplace_back(CandidateInfo{I, InsertPt, AnnotatedInst}); 119*0fca6ea1SDimitry Andric } 120*0fca6ea1SDimitry Andric } 121*0fca6ea1SDimitry Andric}; 122*0fca6ea1SDimitry Andric 1238bcb0991SDimitry Andric///----------------------- Registration of the plugins ------------------------- 1248bcb0991SDimitry Andric/// For now, registering a plugin with the ValueProfileCollector is done by 1258bcb0991SDimitry Andric/// adding the plugin type to the VP_PLUGIN_LIST macro. 1268bcb0991SDimitry Andric#define VP_PLUGIN_LIST \ 127*0fca6ea1SDimitry Andric MemIntrinsicPlugin, IndirectCallPromotionPlugin, VTableProfilingPlugin 128