//===-- InsertCodePrefetch.cpp ---=========--------------------------------===// // // 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 // //===----------------------------------------------------------------------===// // /// \file /// Code Prefetch Insertion Pass. //===----------------------------------------------------------------------===// /// This pass inserts code prefetch instructions according to the prefetch /// directives in the basic block section profile. The target of a prefetch can /// be the beginning of any dynamic basic block, that is the beginning of a /// machine basic block, or immediately after a callsite. A global symbol is /// emitted at the position of the target so it can be addressed from the /// prefetch instruction from any module. //===----------------------------------------------------------------------===// #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/CodeGen/BasicBlockSectionUtils.h" #include "llvm/CodeGen/BasicBlockSectionsProfileReader.h" #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/Passes.h" #include "llvm/InitializePasses.h" using namespace llvm; #define DEBUG_TYPE "insert-code-prefetch" namespace { class InsertCodePrefetch : public MachineFunctionPass { public: static char ID; InsertCodePrefetch() : MachineFunctionPass(ID) { initializeInsertCodePrefetchPass(*PassRegistry::getPassRegistry()); } StringRef getPassName() const override { return "Code Prefetch Inserter Pass"; } void getAnalysisUsage(AnalysisUsage &AU) const override; // Sets prefetch targets based on the bb section profile. bool runOnMachineFunction(MachineFunction &MF) override; }; } // end anonymous namespace //===----------------------------------------------------------------------===// // Implementation //===----------------------------------------------------------------------===// char InsertCodePrefetch::ID = 0; INITIALIZE_PASS_BEGIN(InsertCodePrefetch, DEBUG_TYPE, "Code prefetch insertion", true, false) INITIALIZE_PASS_DEPENDENCY(BasicBlockSectionsProfileReaderWrapperPass) INITIALIZE_PASS_END(InsertCodePrefetch, DEBUG_TYPE, "Code prefetch insertion", true, false) bool InsertCodePrefetch::runOnMachineFunction(MachineFunction &MF) { assert(MF.getTarget().getBBSectionsType() == BasicBlockSection::List && "BB Sections list not enabled!"); if (hasInstrProfHashMismatch(MF)) return false; // Set each block's prefetch targets so AsmPrinter can emit a special symbol // there. SmallVector PrefetchTargets = getAnalysis() .getPrefetchTargetsForFunction(MF.getName()); DenseMap> PrefetchTargetsByBBID; for (const auto &Target : PrefetchTargets) PrefetchTargetsByBBID[Target.BBID].push_back(Target.CallsiteIndex); // Sort and uniquify the callsite indices for every block. for (auto &[K, V] : PrefetchTargetsByBBID) { llvm::sort(V); V.erase(llvm::unique(V), V.end()); } for (auto &MBB : MF) { auto R = PrefetchTargetsByBBID.find(*MBB.getBBID()); if (R == PrefetchTargetsByBBID.end()) continue; MBB.setPrefetchTargetCallsiteIndexes(R->second); } return false; } void InsertCodePrefetch::getAnalysisUsage(AnalysisUsage &AU) const { AU.setPreservesAll(); AU.addRequired(); MachineFunctionPass::getAnalysisUsage(AU); } MachineFunctionPass *llvm::createInsertCodePrefetchPass() { return new InsertCodePrefetch(); }