Path: blob/main/contrib/llvm-project/llvm/lib/SandboxIR/Region.cpp
213766 views
//===- Region.cpp ---------------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "llvm/SandboxIR/Region.h"9#include "llvm/SandboxIR/Function.h"1011namespace llvm::sandboxir {1213InstructionCost ScoreBoard::getCost(Instruction *I) const {14auto *LLVMI = cast<llvm::Instruction>(I->Val);15SmallVector<const llvm::Value *> Operands(LLVMI->operands());16return TTI.getInstructionCost(LLVMI, Operands, CostKind);17}1819void ScoreBoard::remove(Instruction *I) {20auto Cost = getCost(I);21if (Rgn.contains(I))22// If `I` is one the newly added ones, then we should adjust `AfterCost`23AfterCost -= Cost;24else25// If `I` is one of the original instructions (outside the region) then it26// is part of the original code, so adjust `BeforeCost`.27BeforeCost += Cost;28}2930#ifndef NDEBUG31void ScoreBoard::dump() const { dump(dbgs()); }32#endif3334Region::Region(Context &Ctx, TargetTransformInfo &TTI)35: Ctx(Ctx), Scoreboard(*this, TTI) {36LLVMContext &LLVMCtx = Ctx.LLVMCtx;37auto *RegionStrMD = MDString::get(LLVMCtx, RegionStr);38RegionMDN = MDNode::getDistinct(LLVMCtx, {RegionStrMD});3940CreateInstCB = Ctx.registerCreateInstrCallback(41[this](Instruction *NewInst) { add(NewInst); });42EraseInstCB = Ctx.registerEraseInstrCallback([this](Instruction *ErasedInst) {43remove(ErasedInst);44removeFromAux(ErasedInst);45});46}4748Region::~Region() {49Ctx.unregisterCreateInstrCallback(CreateInstCB);50Ctx.unregisterEraseInstrCallback(EraseInstCB);51}5253void Region::addImpl(Instruction *I, bool IgnoreCost) {54Insts.insert(I);55// TODO: Consider tagging instructions lazily.56cast<llvm::Instruction>(I->Val)->setMetadata(MDKind, RegionMDN);57if (!IgnoreCost)58// Keep track of the instruction cost.59Scoreboard.add(I);60}6162void Region::setAux(ArrayRef<Instruction *> Aux) {63this->Aux = SmallVector<Instruction *>(Aux);64auto &LLVMCtx = Ctx.LLVMCtx;65for (auto [Idx, I] : enumerate(Aux)) {66llvm::ConstantInt *IdxC =67llvm::ConstantInt::get(llvm::Type::getInt32Ty(LLVMCtx), Idx, false);68assert(cast<llvm::Instruction>(I->Val)->getMetadata(AuxMDKind) == nullptr &&69"Instruction already in Aux!");70cast<llvm::Instruction>(I->Val)->setMetadata(71AuxMDKind, MDNode::get(LLVMCtx, ConstantAsMetadata::get(IdxC)));72// Aux instrs should always be in a region.73addImpl(I, /*DontTrackCost=*/true);74}75}7677void Region::setAux(unsigned Idx, Instruction *I) {78assert((Idx >= Aux.size() || Aux[Idx] == nullptr) &&79"There is already an Instruction at Idx in Aux!");80unsigned ExpectedSz = Idx + 1;81if (Aux.size() < ExpectedSz) {82auto SzBefore = Aux.size();83Aux.resize(ExpectedSz);84// Initialize the gap with nullptr.85for (unsigned Idx = SzBefore; Idx + 1 < ExpectedSz; ++Idx)86Aux[Idx] = nullptr;87}88Aux[Idx] = I;89// Aux instrs should always be in a region.90addImpl(I, /*DontTrackCost=*/true);91}9293void Region::dropAuxMetadata(Instruction *I) {94auto *LLVMI = cast<llvm::Instruction>(I->Val);95LLVMI->setMetadata(AuxMDKind, nullptr);96}9798void Region::removeFromAux(Instruction *I) {99auto It = find(Aux, I);100if (It == Aux.end())101return;102dropAuxMetadata(I);103Aux.erase(It);104}105106void Region::clearAux() {107for (unsigned Idx : seq<unsigned>(0, Aux.size()))108dropAuxMetadata(Aux[Idx]);109Aux.clear();110}111112void Region::remove(Instruction *I) {113// Keep track of the instruction cost. This need to be done *before* we remove114// `I` from the region.115Scoreboard.remove(I);116117Insts.remove(I);118cast<llvm::Instruction>(I->Val)->setMetadata(MDKind, nullptr);119}120121#ifndef NDEBUG122bool Region::operator==(const Region &Other) const {123if (Insts.size() != Other.Insts.size())124return false;125if (!std::is_permutation(Insts.begin(), Insts.end(), Other.Insts.begin()))126return false;127return true;128}129130void Region::dump(raw_ostream &OS) const {131for (auto *I : Insts)132OS << *I << "\n";133if (!Aux.empty()) {134OS << "\nAux:\n";135for (auto *I : Aux) {136if (I == nullptr)137OS << "NULL\n";138else139OS << *I << "\n";140}141}142}143144void Region::dump() const {145dump(dbgs());146dbgs() << "\n";147}148#endif // NDEBUG149150SmallVector<std::unique_ptr<Region>>151Region::createRegionsFromMD(Function &F, TargetTransformInfo &TTI) {152SmallVector<std::unique_ptr<Region>> Regions;153DenseMap<MDNode *, Region *> MDNToRegion;154auto &Ctx = F.getContext();155for (BasicBlock &BB : F) {156for (Instruction &Inst : BB) {157auto *LLVMI = cast<llvm::Instruction>(Inst.Val);158Region *R = nullptr;159if (auto *MDN = LLVMI->getMetadata(MDKind)) {160auto [It, Inserted] = MDNToRegion.try_emplace(MDN);161if (Inserted) {162Regions.push_back(std::make_unique<Region>(Ctx, TTI));163R = Regions.back().get();164It->second = R;165} else {166R = It->second;167}168R->addImpl(&Inst, /*IgnoreCost=*/true);169}170if (auto *AuxMDN = LLVMI->getMetadata(AuxMDKind)) {171llvm::Constant *IdxC =172dyn_cast<ConstantAsMetadata>(AuxMDN->getOperand(0))->getValue();173auto Idx = cast<llvm::ConstantInt>(IdxC)->getSExtValue();174if (R == nullptr) {175errs() << "No region specified for Aux: '" << *LLVMI << "'\n";176exit(1);177}178R->setAux(Idx, &Inst);179}180}181}182#ifndef NDEBUG183// Check that there are no gaps in the Aux vector.184for (auto &RPtr : Regions)185for (auto *I : RPtr->getAux())186assert(I != nullptr && "Gap in Aux!");187#endif188return Regions;189}190191} // namespace llvm::sandboxir192193194