1 //===- Region.cpp ---------------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "llvm/SandboxIR/Region.h" 10 #include "llvm/SandboxIR/Function.h" 11 12 namespace llvm::sandboxir { 13 14 InstructionCost ScoreBoard::getCost(Instruction *I) const { 15 auto *LLVMI = cast<llvm::Instruction>(I->Val); 16 SmallVector<const llvm::Value *> Operands(LLVMI->operands()); 17 return TTI.getInstructionCost(LLVMI, Operands, CostKind); 18 } 19 20 void ScoreBoard::remove(Instruction *I) { 21 auto Cost = getCost(I); 22 if (Rgn.contains(I)) 23 // If `I` is one the newly added ones, then we should adjust `AfterCost` 24 AfterCost -= Cost; 25 else 26 // If `I` is one of the original instructions (outside the region) then it 27 // is part of the original code, so adjust `BeforeCost`. 28 BeforeCost += Cost; 29 } 30 31 #ifndef NDEBUG 32 void ScoreBoard::dump() const { dump(dbgs()); } 33 #endif 34 35 Region::Region(Context &Ctx, TargetTransformInfo &TTI) 36 : Ctx(Ctx), Scoreboard(*this, TTI) { 37 LLVMContext &LLVMCtx = Ctx.LLVMCtx; 38 auto *RegionStrMD = MDString::get(LLVMCtx, RegionStr); 39 RegionMDN = MDNode::getDistinct(LLVMCtx, {RegionStrMD}); 40 41 CreateInstCB = Ctx.registerCreateInstrCallback( 42 [this](Instruction *NewInst) { add(NewInst); }); 43 EraseInstCB = Ctx.registerEraseInstrCallback( 44 [this](Instruction *ErasedInst) { remove(ErasedInst); }); 45 } 46 47 Region::~Region() { 48 Ctx.unregisterCreateInstrCallback(CreateInstCB); 49 Ctx.unregisterEraseInstrCallback(EraseInstCB); 50 } 51 52 void Region::add(Instruction *I) { 53 Insts.insert(I); 54 // TODO: Consider tagging instructions lazily. 55 cast<llvm::Instruction>(I->Val)->setMetadata(MDKind, RegionMDN); 56 // Keep track of the instruction cost. 57 Scoreboard.add(I); 58 } 59 60 void Region::remove(Instruction *I) { 61 // Keep track of the instruction cost. This need to be done *before* we remove 62 // `I` from the region. 63 Scoreboard.remove(I); 64 65 Insts.remove(I); 66 cast<llvm::Instruction>(I->Val)->setMetadata(MDKind, nullptr); 67 } 68 69 #ifndef NDEBUG 70 bool Region::operator==(const Region &Other) const { 71 if (Insts.size() != Other.Insts.size()) 72 return false; 73 if (!std::is_permutation(Insts.begin(), Insts.end(), Other.Insts.begin())) 74 return false; 75 return true; 76 } 77 78 void Region::dump(raw_ostream &OS) const { 79 for (auto *I : Insts) 80 OS << *I << "\n"; 81 } 82 83 void Region::dump() const { 84 dump(dbgs()); 85 dbgs() << "\n"; 86 } 87 #endif // NDEBUG 88 89 SmallVector<std::unique_ptr<Region>> 90 Region::createRegionsFromMD(Function &F, TargetTransformInfo &TTI) { 91 SmallVector<std::unique_ptr<Region>> Regions; 92 DenseMap<MDNode *, Region *> MDNToRegion; 93 auto &Ctx = F.getContext(); 94 for (BasicBlock &BB : F) { 95 for (Instruction &Inst : BB) { 96 if (auto *MDN = cast<llvm::Instruction>(Inst.Val)->getMetadata(MDKind)) { 97 Region *R = nullptr; 98 auto It = MDNToRegion.find(MDN); 99 if (It == MDNToRegion.end()) { 100 Regions.push_back(std::make_unique<Region>(Ctx, TTI)); 101 R = Regions.back().get(); 102 MDNToRegion[MDN] = R; 103 } else { 104 R = It->second; 105 } 106 R->add(&Inst); 107 } 108 } 109 } 110 return Regions; 111 } 112 113 } // namespace llvm::sandboxir 114