xref: /freebsd/contrib/llvm-project/llvm/lib/Transforms/Instrumentation/ValueProfilePlugins.inc (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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