Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/SandboxIR/Tracker.cpp
35260 views
1
//===- Tracker.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/Tracker.h"
10
#include "llvm/ADT/STLExtras.h"
11
#include "llvm/IR/BasicBlock.h"
12
#include "llvm/IR/Instruction.h"
13
#include "llvm/SandboxIR/SandboxIR.h"
14
#include <sstream>
15
16
using namespace llvm::sandboxir;
17
18
IRChangeBase::IRChangeBase(Tracker &Parent) : Parent(Parent) {
19
#ifndef NDEBUG
20
assert(!Parent.InMiddleOfCreatingChange &&
21
"We are in the middle of creating another change!");
22
if (Parent.isTracking())
23
Parent.InMiddleOfCreatingChange = true;
24
#endif // NDEBUG
25
}
26
27
#ifndef NDEBUG
28
unsigned IRChangeBase::getIdx() const {
29
auto It =
30
find_if(Parent.Changes, [this](auto &Ptr) { return Ptr.get() == this; });
31
return It - Parent.Changes.begin();
32
}
33
34
void UseSet::dump() const {
35
dump(dbgs());
36
dbgs() << "\n";
37
}
38
#endif // NDEBUG
39
40
Tracker::~Tracker() {
41
assert(Changes.empty() && "You must accept or revert changes!");
42
}
43
44
EraseFromParent::EraseFromParent(std::unique_ptr<sandboxir::Value> &&ErasedIPtr,
45
Tracker &Tracker)
46
: IRChangeBase(Tracker), ErasedIPtr(std::move(ErasedIPtr)) {
47
auto *I = cast<Instruction>(this->ErasedIPtr.get());
48
auto LLVMInstrs = I->getLLVMInstrs();
49
// Iterate in reverse program order.
50
for (auto *LLVMI : reverse(LLVMInstrs)) {
51
SmallVector<llvm::Value *> Operands;
52
Operands.reserve(LLVMI->getNumOperands());
53
for (auto [OpNum, Use] : enumerate(LLVMI->operands()))
54
Operands.push_back(Use.get());
55
InstrData.push_back({Operands, LLVMI});
56
}
57
assert(is_sorted(InstrData,
58
[](const auto &D0, const auto &D1) {
59
return D0.LLVMI->comesBefore(D1.LLVMI);
60
}) &&
61
"Expected reverse program order!");
62
auto *BotLLVMI = cast<llvm::Instruction>(I->Val);
63
if (BotLLVMI->getNextNode() != nullptr)
64
NextLLVMIOrBB = BotLLVMI->getNextNode();
65
else
66
NextLLVMIOrBB = BotLLVMI->getParent();
67
}
68
69
void EraseFromParent::accept() {
70
for (const auto &IData : InstrData)
71
IData.LLVMI->deleteValue();
72
}
73
74
void EraseFromParent::revert() {
75
// Place the bottom-most instruction first.
76
auto [Operands, BotLLVMI] = InstrData[0];
77
if (auto *NextLLVMI = NextLLVMIOrBB.dyn_cast<llvm::Instruction *>()) {
78
BotLLVMI->insertBefore(NextLLVMI);
79
} else {
80
auto *LLVMBB = NextLLVMIOrBB.get<llvm::BasicBlock *>();
81
BotLLVMI->insertInto(LLVMBB, LLVMBB->end());
82
}
83
for (auto [OpNum, Op] : enumerate(Operands))
84
BotLLVMI->setOperand(OpNum, Op);
85
86
// Go over the rest of the instructions and stack them on top.
87
for (auto [Operands, LLVMI] : drop_begin(InstrData)) {
88
LLVMI->insertBefore(BotLLVMI);
89
for (auto [OpNum, Op] : enumerate(Operands))
90
LLVMI->setOperand(OpNum, Op);
91
BotLLVMI = LLVMI;
92
}
93
Parent.getContext().registerValue(std::move(ErasedIPtr));
94
}
95
96
#ifndef NDEBUG
97
void EraseFromParent::dump() const {
98
dump(dbgs());
99
dbgs() << "\n";
100
}
101
#endif // NDEBUG
102
103
RemoveFromParent::RemoveFromParent(Instruction *RemovedI, Tracker &Tracker)
104
: IRChangeBase(Tracker), RemovedI(RemovedI) {
105
if (auto *NextI = RemovedI->getNextNode())
106
NextInstrOrBB = NextI;
107
else
108
NextInstrOrBB = RemovedI->getParent();
109
}
110
111
void RemoveFromParent::revert() {
112
if (auto *NextI = NextInstrOrBB.dyn_cast<Instruction *>()) {
113
RemovedI->insertBefore(NextI);
114
} else {
115
auto *BB = NextInstrOrBB.get<BasicBlock *>();
116
RemovedI->insertInto(BB, BB->end());
117
}
118
}
119
120
#ifndef NDEBUG
121
void RemoveFromParent::dump() const {
122
dump(dbgs());
123
dbgs() << "\n";
124
}
125
#endif
126
127
MoveInstr::MoveInstr(Instruction *MovedI, Tracker &Tracker)
128
: IRChangeBase(Tracker), MovedI(MovedI) {
129
if (auto *NextI = MovedI->getNextNode())
130
NextInstrOrBB = NextI;
131
else
132
NextInstrOrBB = MovedI->getParent();
133
}
134
135
void MoveInstr::revert() {
136
if (auto *NextI = NextInstrOrBB.dyn_cast<Instruction *>()) {
137
MovedI->moveBefore(NextI);
138
} else {
139
auto *BB = NextInstrOrBB.get<BasicBlock *>();
140
MovedI->moveBefore(*BB, BB->end());
141
}
142
}
143
144
#ifndef NDEBUG
145
void MoveInstr::dump() const {
146
dump(dbgs());
147
dbgs() << "\n";
148
}
149
#endif
150
151
void Tracker::track(std::unique_ptr<IRChangeBase> &&Change) {
152
assert(State == TrackerState::Record && "The tracker should be tracking!");
153
Changes.push_back(std::move(Change));
154
155
#ifndef NDEBUG
156
InMiddleOfCreatingChange = false;
157
#endif
158
}
159
160
void Tracker::save() { State = TrackerState::Record; }
161
162
void Tracker::revert() {
163
assert(State == TrackerState::Record && "Forgot to save()!");
164
State = TrackerState::Disabled;
165
for (auto &Change : reverse(Changes))
166
Change->revert();
167
Changes.clear();
168
}
169
170
void Tracker::accept() {
171
assert(State == TrackerState::Record && "Forgot to save()!");
172
State = TrackerState::Disabled;
173
for (auto &Change : Changes)
174
Change->accept();
175
Changes.clear();
176
}
177
178
#ifndef NDEBUG
179
void Tracker::dump(raw_ostream &OS) const {
180
for (const auto &ChangePtr : Changes) {
181
ChangePtr->dump(OS);
182
OS << "\n";
183
}
184
}
185
void Tracker::dump() const {
186
dump(dbgs());
187
dbgs() << "\n";
188
}
189
#endif // NDEBUG
190
191