LLVM 20.0.0git
Tracker.cpp
Go to the documentation of this file.
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
10#include "llvm/ADT/STLExtras.h"
11#include "llvm/IR/BasicBlock.h"
12#include "llvm/IR/Instruction.h"
14#include <sstream>
15
16using namespace llvm::sandboxir;
17
18#ifndef NDEBUG
19void UseSet::dump() const {
20 dump(dbgs());
21 dbgs() << "\n";
22}
23
24void UseSwap::dump() const {
25 dump(dbgs());
26 dbgs() << "\n";
27}
28#endif // NDEBUG
29
31 : PHI(PHI), Idx(Idx) {
32 switch (What) {
33 case What::Value:
34 OrigValueOrBB = PHI->getIncomingValue(Idx);
35 break;
36 case What::Block:
37 OrigValueOrBB = PHI->getIncomingBlock(Idx);
38 break;
39 }
40}
41
43 if (auto *V = OrigValueOrBB.dyn_cast<Value *>())
44 PHI->setIncomingValue(Idx, V);
45 else
46 PHI->setIncomingBlock(Idx, OrigValueOrBB.get<BasicBlock *>());
47}
48
49#ifndef NDEBUG
51 dump(dbgs());
52 dbgs() << "\n";
53}
54#endif // NDEBUG
55
57 : PHI(PHI), RemovedIdx(RemovedIdx) {
58 RemovedV = PHI->getIncomingValue(RemovedIdx);
59 RemovedBB = PHI->getIncomingBlock(RemovedIdx);
60}
61
63 // Special case: if the PHI is now empty, as we don't need to care about the
64 // order of the incoming values.
65 unsigned NumIncoming = PHI->getNumIncomingValues();
66 if (NumIncoming == 0) {
67 PHI->addIncoming(RemovedV, RemovedBB);
68 return;
69 }
70 // Shift all incoming values by one starting from the end until `Idx`.
71 // Start by adding a copy of the last incoming values.
72 unsigned LastIdx = NumIncoming - 1;
73 PHI->addIncoming(PHI->getIncomingValue(LastIdx),
74 PHI->getIncomingBlock(LastIdx));
75 for (unsigned Idx = LastIdx; Idx > RemovedIdx; --Idx) {
76 auto *PrevV = PHI->getIncomingValue(Idx - 1);
77 auto *PrevBB = PHI->getIncomingBlock(Idx - 1);
78 PHI->setIncomingValue(Idx, PrevV);
79 PHI->setIncomingBlock(Idx, PrevBB);
80 }
81 PHI->setIncomingValue(RemovedIdx, RemovedV);
82 PHI->setIncomingBlock(RemovedIdx, RemovedBB);
83}
84
85#ifndef NDEBUG
87 dump(dbgs());
88 dbgs() << "\n";
89}
90#endif // NDEBUG
91
93 : PHI(PHI), Idx(PHI->getNumIncomingValues()) {}
94
96
97#ifndef NDEBUG
99 dump(dbgs());
100 dbgs() << "\n";
101}
102#endif // NDEBUG
103
105 assert(Changes.empty() && "You must accept or revert changes!");
106}
107
108EraseFromParent::EraseFromParent(std::unique_ptr<sandboxir::Value> &&ErasedIPtr)
109 : ErasedIPtr(std::move(ErasedIPtr)) {
110 auto *I = cast<Instruction>(this->ErasedIPtr.get());
111 auto LLVMInstrs = I->getLLVMInstrs();
112 // Iterate in reverse program order.
113 for (auto *LLVMI : reverse(LLVMInstrs)) {
115 Operands.reserve(LLVMI->getNumOperands());
116 for (auto [OpNum, Use] : enumerate(LLVMI->operands()))
117 Operands.push_back(Use.get());
118 InstrData.push_back({Operands, LLVMI});
119 }
120 assert(is_sorted(InstrData,
121 [](const auto &D0, const auto &D1) {
122 return D0.LLVMI->comesBefore(D1.LLVMI);
123 }) &&
124 "Expected reverse program order!");
125 auto *BotLLVMI = cast<llvm::Instruction>(I->Val);
126 if (BotLLVMI->getNextNode() != nullptr)
127 NextLLVMIOrBB = BotLLVMI->getNextNode();
128 else
129 NextLLVMIOrBB = BotLLVMI->getParent();
130}
131
133 for (const auto &IData : InstrData)
134 IData.LLVMI->deleteValue();
135}
136
138 // Place the bottom-most instruction first.
139 auto [Operands, BotLLVMI] = InstrData[0];
140 if (auto *NextLLVMI = NextLLVMIOrBB.dyn_cast<llvm::Instruction *>()) {
141 BotLLVMI->insertBefore(NextLLVMI);
142 } else {
143 auto *LLVMBB = NextLLVMIOrBB.get<llvm::BasicBlock *>();
144 BotLLVMI->insertInto(LLVMBB, LLVMBB->end());
145 }
146 for (auto [OpNum, Op] : enumerate(Operands))
147 BotLLVMI->setOperand(OpNum, Op);
148
149 // Go over the rest of the instructions and stack them on top.
150 for (auto [Operands, LLVMI] : drop_begin(InstrData)) {
151 LLVMI->insertBefore(BotLLVMI);
152 for (auto [OpNum, Op] : enumerate(Operands))
153 LLVMI->setOperand(OpNum, Op);
154 BotLLVMI = LLVMI;
155 }
156 Tracker.getContext().registerValue(std::move(ErasedIPtr));
157}
158
159#ifndef NDEBUG
161 dump(dbgs());
162 dbgs() << "\n";
163}
164#endif // NDEBUG
165
166RemoveFromParent::RemoveFromParent(Instruction *RemovedI) : RemovedI(RemovedI) {
167 if (auto *NextI = RemovedI->getNextNode())
168 NextInstrOrBB = NextI;
169 else
170 NextInstrOrBB = RemovedI->getParent();
171}
172
174 if (auto *NextI = NextInstrOrBB.dyn_cast<Instruction *>()) {
175 RemovedI->insertBefore(NextI);
176 } else {
177 auto *BB = NextInstrOrBB.get<BasicBlock *>();
178 RemovedI->insertInto(BB, BB->end());
179 }
180}
181
182#ifndef NDEBUG
184 dump(dbgs());
185 dbgs() << "\n";
186}
187#endif
188
190 unsigned Idx)
191 : CallBr(CallBr), Idx(Idx) {
192 OrigIndirectDest = CallBr->getIndirectDest(Idx);
193}
195 CallBr->setIndirectDest(Idx, OrigIndirectDest);
196}
197#ifndef NDEBUG
199 dump(dbgs());
200 dbgs() << "\n";
201}
202#endif
203
204MoveInstr::MoveInstr(Instruction *MovedI) : MovedI(MovedI) {
205 if (auto *NextI = MovedI->getNextNode())
206 NextInstrOrBB = NextI;
207 else
208 NextInstrOrBB = MovedI->getParent();
209}
210
212 if (auto *NextI = NextInstrOrBB.dyn_cast<Instruction *>()) {
213 MovedI->moveBefore(NextI);
214 } else {
215 auto *BB = NextInstrOrBB.get<BasicBlock *>();
216 MovedI->moveBefore(*BB, BB->end());
217 }
218}
219
220#ifndef NDEBUG
221void MoveInstr::dump() const {
222 dump(dbgs());
223 dbgs() << "\n";
224}
225#endif
226
228
229InsertIntoBB::InsertIntoBB(Instruction *InsertedI) : InsertedI(InsertedI) {}
230
231#ifndef NDEBUG
232void InsertIntoBB::dump() const {
233 dump(dbgs());
234 dbgs() << "\n";
235}
236#endif
237
239
240#ifndef NDEBUG
242 dump(dbgs());
243 dbgs() << "\n";
244}
245#endif
246
248
250 assert(State == TrackerState::Record && "Forgot to save()!");
252 for (auto &Change : reverse(Changes))
253 Change->revert(*this);
254 Changes.clear();
255}
256
258 assert(State == TrackerState::Record && "Forgot to save()!");
260 for (auto &Change : Changes)
261 Change->accept();
262 Changes.clear();
263}
264
265#ifndef NDEBUG
267 for (auto [Idx, ChangePtr] : enumerate(Changes)) {
268 OS << Idx << ". ";
269 ChangePtr->dump(OS);
270 OS << "\n";
271 }
272}
273void Tracker::dump() const {
274 dump(dbgs());
275 dbgs() << "\n";
276}
277#endif // NDEBUG
Rewrite undef for PHI
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
#define I(x, y, z)
Definition: MD5.cpp:58
mir Rename Register Operands
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file contains some templates that are useful if you are working with the STL at all.
raw_pwrite_stream & OS
LLVM Basic Block Representation.
Definition: BasicBlock.h:61
void insertInto(Function *Parent, BasicBlock *InsertBefore=nullptr)
Insert unlinked basic block into a function.
Definition: BasicBlock.cpp:198
This class represents an Operation in the Expression.
T get() const
Returns the value of the specified pointer type.
Definition: PointerUnion.h:155
T dyn_cast() const
Returns the current pointer if it is of the specified pointer type, otherwise returns null.
Definition: PointerUnion.h:162
void push_back(const T &Elt)
Definition: SmallVector.h:427
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1210
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
Contains a list of sandboxir::Instruction's.
Definition: SandboxIR.h:558
void revert(Tracker &Tracker) final
This runs when changes get reverted.
Definition: Tracker.cpp:194
CallBrInstSetIndirectDest(CallBrInst *CallBr, unsigned Idx)
Definition: Tracker.cpp:189
LLVM_DUMP_METHOD void dump() const final
Definition: Tracker.cpp:198
BasicBlock * getIndirectDest(unsigned Idx) const
Definition: SandboxIR.cpp:1016
void setIndirectDest(unsigned Idx, BasicBlock *BB)
Definition: SandboxIR.cpp:1033
Value * registerValue(std::unique_ptr< Value > &&VPtr)
Take ownership of VPtr and store it in LLVMValueToValueMap.
Definition: SandboxIR.cpp:1626
LLVM_DUMP_METHOD void dump() const final
Definition: Tracker.cpp:241
void revert(Tracker &Tracker) final
This runs when changes get reverted.
Definition: Tracker.cpp:238
void accept() final
This runs when changes get accepted.
Definition: Tracker.cpp:132
LLVM_DUMP_METHOD void dump() const final
Definition: Tracker.cpp:160
void revert(Tracker &Tracker) final
This runs when changes get reverted.
Definition: Tracker.cpp:137
EraseFromParent(std::unique_ptr< sandboxir::Value > &&IPtr)
Definition: Tracker.cpp:108
LLVM_DUMP_METHOD void dump() const final
Definition: Tracker.cpp:232
InsertIntoBB(Instruction *InsertedI)
Definition: Tracker.cpp:229
void revert(Tracker &Tracker) final
This runs when changes get reverted.
Definition: Tracker.cpp:227
A sandboxir::User with operands, opcode and linked with previous/next instructions in an instruction ...
Definition: SandboxIR.h:605
void removeFromParent()
Detach this from its parent BasicBlock without deleting it.
Definition: SandboxIR.cpp:359
void insertInto(BasicBlock *BB, const BBIterator &WhereIt)
Insert this detached instruction into BB at WhereIt.
Definition: SandboxIR.cpp:433
void eraseFromParent()
Detach this Value from its parent and delete it.
Definition: SandboxIR.cpp:367
Instruction * getNextNode() const
\Returns the next sandboxir::Instruction in the block, or nullptr if at the end of the block.
Definition: SandboxIR.cpp:336
void moveBefore(BasicBlock &BB, const BBIterator &WhereIt)
Move this instruction to WhereIt.
Definition: SandboxIR.cpp:391
void insertBefore(Instruction *BeforeI)
Insert this detached instruction before BeforeI.
Definition: SandboxIR.cpp:415
BasicBlock * getParent() const
\Returns the BasicBlock containing this Instruction, or null if it is detached.
Definition: SandboxIR.cpp:455
LLVM_DUMP_METHOD void dump() const final
Definition: Tracker.cpp:221
MoveInstr(sandboxir::Instruction *I)
Definition: Tracker.cpp:204
void revert(Tracker &Tracker) final
This runs when changes get reverted.
Definition: Tracker.cpp:211
void revert(Tracker &Tracker) final
This runs when changes get reverted.
Definition: Tracker.cpp:95
LLVM_DUMP_METHOD void dump() const final
Definition: Tracker.cpp:98
void setIncomingBlock(unsigned Idx, BasicBlock *BB)
Definition: SandboxIR.cpp:1120
void setIncomingValue(unsigned Idx, Value *V)
Definition: SandboxIR.cpp:1104
unsigned getNumIncomingValues() const
Definition: SandboxIR.h:1838
void addIncoming(Value *V, BasicBlock *BB)
Definition: SandboxIR.cpp:1127
Value * removeIncomingValue(unsigned Idx)
Definition: SandboxIR.cpp:1134
BasicBlock * getIncomingBlock(unsigned Idx) const
Definition: SandboxIR.cpp:1111
Value * getIncomingValue(unsigned Idx) const
Definition: SandboxIR.cpp:1101
LLVM_DUMP_METHOD void dump() const final
Definition: Tracker.cpp:86
PHIRemoveIncoming(PHINode *PHI, unsigned RemovedIdx)
Definition: Tracker.cpp:56
void revert(Tracker &Tracker) final
This runs when changes get reverted.
Definition: Tracker.cpp:62
PHISetIncoming(PHINode *PHI, unsigned Idx, What What)
Definition: Tracker.cpp:30
void revert(Tracker &Tracker) final
This runs when changes get reverted.
Definition: Tracker.cpp:42
LLVM_DUMP_METHOD void dump() const final
Definition: Tracker.cpp:50
void revert(Tracker &Tracker) final
This runs when changes get reverted.
Definition: Tracker.cpp:173
RemoveFromParent(Instruction *RemovedI)
Definition: Tracker.cpp:166
LLVM_DUMP_METHOD void dump() const final
Definition: Tracker.cpp:183
The tracker collects all the change objects and implements the main API for saving / reverting / acce...
Definition: Tracker.h:313
@ Record
ā€¨Tracking is disabled
void revert()
Stops tracking and reverts to saved state.
Definition: Tracker.cpp:249
void save()
Turns on IR tracking.
Definition: Tracker.cpp:247
Context & getContext() const
Definition: Tracker.h:336
void accept()
Stops tracking and accept changes.
Definition: Tracker.cpp:257
LLVM_DUMP_METHOD void dump() const
Definition: Tracker.cpp:273
LLVM_DUMP_METHOD void dump() const final
Definition: Tracker.cpp:19
LLVM_DUMP_METHOD void dump() const final
Definition: Tracker.cpp:24
Represents a Def-use/Use-def edge in SandboxIR.
Definition: Use.h:32
Value * get() const
Definition: SandboxIR.cpp:18
A SandboxIR Value has users. This is the base class.
Definition: SandboxIR.h:200
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
Definition: STLExtras.h:329
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
Definition: STLExtras.h:2406
auto reverse(ContainerTy &&C)
Definition: STLExtras.h:419
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
bool is_sorted(R &&Range, Compare C)
Wrapper function around std::is_sorted to check if elements in a range R are sorted with respect to a...
Definition: STLExtras.h:1902
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1849
Implement std::hash so that hash_code can be used in STL containers.
Definition: BitVector.h:858