xref: /llvm-project/llvm/lib/SandboxIR/Region.cpp (revision 4b209c5d87c8b8eb4bbf2750ea9daa5927a13699)
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