LLVM 20.0.0git
Tracker.h
Go to the documentation of this file.
1//===- Tracker.h ------------------------------------------------*- C++ -*-===//
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// This file is the component of SandboxIR that tracks all changes made to its
10// state, such that we can revert the state when needed.
11//
12// Tracking changes
13// ----------------
14// The user needs to call `Tracker::save()` to enable tracking changes
15// made to SandboxIR. From that point on, any change made to SandboxIR, will
16// automatically create a change tracking object and register it with the
17// tracker. IR-change objects are subclasses of `IRChangeBase` and get
18// registered with the `Tracker::track()` function. The change objects
19// are saved in the order they are registered with the tracker and are stored in
20// the `Tracker::Changes` vector. All of this is done transparently to
21// the user.
22//
23// Reverting changes
24// -----------------
25// Calling `Tracker::revert()` will restore the state saved when
26// `Tracker::save()` was called. Internally this goes through the
27// change objects in `Tracker::Changes` in reverse order, calling their
28// `IRChangeBase::revert()` function one by one.
29//
30// Accepting changes
31// -----------------
32// The user needs to either revert or accept changes before the tracker object
33// is destroyed. This is enforced in the tracker's destructor.
34// This is the job of `Tracker::accept()`. Internally this will go
35// through the change objects in `Tracker::Changes` in order, calling
36// `IRChangeBase::accept()`.
37//
38//===----------------------------------------------------------------------===//
39
40#ifndef LLVM_SANDBOXIR_TRACKER_H
41#define LLVM_SANDBOXIR_TRACKER_H
42
45#include "llvm/IR/IRBuilder.h"
46#include "llvm/IR/Instruction.h"
47#include "llvm/IR/Module.h"
48#include "llvm/SandboxIR/Use.h"
49#include "llvm/Support/Debug.h"
50#include <memory>
51#include <regex>
52
53namespace llvm::sandboxir {
54
55class BasicBlock;
56class CallBrInst;
57class LoadInst;
58class StoreInst;
59class Instruction;
60class Tracker;
61class AllocaInst;
62
63/// The base class for IR Change classes.
65protected:
66 friend class Tracker; // For Parent.
67
68public:
69 /// This runs when changes get reverted.
70 virtual void revert(Tracker &Tracker) = 0;
71 /// This runs when changes get accepted.
72 virtual void accept() = 0;
73 virtual ~IRChangeBase() = default;
74#ifndef NDEBUG
75 virtual void dump(raw_ostream &OS) const = 0;
76 LLVM_DUMP_METHOD virtual void dump() const = 0;
78 C.dump(OS);
79 return OS;
80 }
81#endif
82};
83
84/// Tracks the change of the source Value of a sandboxir::Use.
85class UseSet : public IRChangeBase {
86 Use U;
87 Value *OrigV = nullptr;
88
89public:
90 UseSet(const Use &U) : U(U), OrigV(U.get()) {}
91 void revert(Tracker &Tracker) final { U.set(OrigV); }
92 void accept() final {}
93#ifndef NDEBUG
94 void dump(raw_ostream &OS) const final { OS << "UseSet"; }
95 LLVM_DUMP_METHOD void dump() const final;
96#endif
97};
98
100 PHINode *PHI;
101 unsigned Idx;
103
104public:
105 enum class What {
106 Value,
107 Block,
108 };
109 PHISetIncoming(PHINode *PHI, unsigned Idx, What What);
110 void revert(Tracker &Tracker) final;
111 void accept() final {}
112#ifndef NDEBUG
113 void dump(raw_ostream &OS) const final { OS << "PHISetIncoming"; }
114 LLVM_DUMP_METHOD void dump() const final;
115#endif
116};
117
119 PHINode *PHI;
120 unsigned RemovedIdx;
121 Value *RemovedV;
122 BasicBlock *RemovedBB;
123
124public:
125 PHIRemoveIncoming(PHINode *PHI, unsigned RemovedIdx);
126 void revert(Tracker &Tracker) final;
127 void accept() final {}
128#ifndef NDEBUG
129 void dump(raw_ostream &OS) const final { OS << "PHISetIncoming"; }
130 LLVM_DUMP_METHOD void dump() const final;
131#endif
132};
133
135 PHINode *PHI;
136 unsigned Idx;
137
138public:
140 void revert(Tracker &Tracker) final;
141 void accept() final {}
142#ifndef NDEBUG
143 void dump(raw_ostream &OS) const final { OS << "PHISetIncoming"; }
144 LLVM_DUMP_METHOD void dump() const final;
145#endif
146};
147
148/// Tracks swapping a Use with another Use.
149class UseSwap : public IRChangeBase {
150 Use ThisUse;
151 Use OtherUse;
152
153public:
154 UseSwap(const Use &ThisUse, const Use &OtherUse)
155 : ThisUse(ThisUse), OtherUse(OtherUse) {
156 assert(ThisUse.getUser() == OtherUse.getUser() && "Expected same user!");
157 }
158 void revert(Tracker &Tracker) final { ThisUse.swap(OtherUse); }
159 void accept() final {}
160#ifndef NDEBUG
161 void dump(raw_ostream &OS) const final { OS << "UseSwap"; }
162 LLVM_DUMP_METHOD void dump() const final;
163#endif
164};
165
167 /// Contains all the data we need to restore an "erased" (i.e., detached)
168 /// instruction: the instruction itself and its operands in order.
169 struct InstrAndOperands {
170 /// The operands that got dropped.
172 /// The instruction that got "erased".
173 llvm::Instruction *LLVMI;
174 };
175 /// The instruction data is in reverse program order, which helps create the
176 /// original program order during revert().
178 /// This is either the next Instruction in the stream, or the parent
179 /// BasicBlock if at the end of the BB.
181 /// We take ownership of the "erased" instruction.
182 std::unique_ptr<sandboxir::Value> ErasedIPtr;
183
184public:
185 EraseFromParent(std::unique_ptr<sandboxir::Value> &&IPtr);
186 void revert(Tracker &Tracker) final;
187 void accept() final;
188#ifndef NDEBUG
189 void dump(raw_ostream &OS) const final { OS << "EraseFromParent"; }
190 LLVM_DUMP_METHOD void dump() const final;
192 C.dump(OS);
193 return OS;
194 }
195#endif
196};
197
199 /// The instruction that is about to get removed.
200 Instruction *RemovedI = nullptr;
201 /// This is either the next instr, or the parent BB if at the end of the BB.
203
204public:
205 RemoveFromParent(Instruction *RemovedI);
206 void revert(Tracker &Tracker) final;
207 void accept() final {};
208 Instruction *getInstruction() const { return RemovedI; }
209#ifndef NDEBUG
210 void dump(raw_ostream &OS) const final { OS << "RemoveFromParent"; }
211 LLVM_DUMP_METHOD void dump() const final;
212#endif // NDEBUG
213};
214
215/// This class can be used for tracking most instruction setters.
216/// The two template arguments are:
217/// - GetterFn: The getter member function pointer (e.g., `&Foo::get`)
218/// - SetterFn: The setter member function pointer (e.g., `&Foo::set`)
219/// Upon construction, it saves a copy of the original value by calling the
220/// getter function. Revert sets the value back to the one saved, using the
221/// setter function provided.
222///
223/// Example:
224/// Tracker.track(std::make_unique<
225/// GenericSetter<&FooInst::get, &FooInst::set>>(I, Tracker));
226///
227template <auto GetterFn, auto SetterFn>
228class GenericSetter final : public IRChangeBase {
229 /// Traits for getting the class type from GetterFn type.
230 template <typename> struct GetClassTypeFromGetter;
231 template <typename RetT, typename ClassT>
232 struct GetClassTypeFromGetter<RetT (ClassT::*)() const> {
233 using ClassType = ClassT;
234 };
235 using InstrT = typename GetClassTypeFromGetter<decltype(GetterFn)>::ClassType;
236 using SavedValT = std::invoke_result_t<decltype(GetterFn), InstrT>;
237 InstrT *I;
238 SavedValT OrigVal;
239
240public:
241 GenericSetter(InstrT *I) : I(I), OrigVal((I->*GetterFn)()) {}
242 void revert(Tracker &Tracker) final { (I->*SetterFn)(OrigVal); }
243 void accept() final {}
244#ifndef NDEBUG
245 void dump(raw_ostream &OS) const final { OS << "GenericSetter"; }
247 dump(dbgs());
248 dbgs() << "\n";
249 }
250#endif
251};
252
254 CallBrInst *CallBr;
255 unsigned Idx;
256 BasicBlock *OrigIndirectDest;
257
258public:
259 CallBrInstSetIndirectDest(CallBrInst *CallBr, unsigned Idx);
260 void revert(Tracker &Tracker) final;
261 void accept() final {}
262#ifndef NDEBUG
263 void dump(raw_ostream &OS) const final { OS << "CallBrInstSetIndirectDest"; }
264 LLVM_DUMP_METHOD void dump() const final;
265#endif
266};
267
268class MoveInstr : public IRChangeBase {
269 /// The instruction that moved.
270 Instruction *MovedI;
271 /// This is either the next instruction in the block, or the parent BB if at
272 /// the end of the BB.
274
275public:
277 void revert(Tracker &Tracker) final;
278 void accept() final {}
279#ifndef NDEBUG
280 void dump(raw_ostream &OS) const final { OS << "MoveInstr"; }
281 LLVM_DUMP_METHOD void dump() const final;
282#endif // NDEBUG
283};
284
285class InsertIntoBB final : public IRChangeBase {
286 Instruction *InsertedI = nullptr;
287
288public:
289 InsertIntoBB(Instruction *InsertedI);
290 void revert(Tracker &Tracker) final;
291 void accept() final {}
292#ifndef NDEBUG
293 void dump(raw_ostream &OS) const final { OS << "InsertIntoBB"; }
294 LLVM_DUMP_METHOD void dump() const final;
295#endif // NDEBUG
296};
297
298class CreateAndInsertInst final : public IRChangeBase {
299 Instruction *NewI = nullptr;
300
301public:
302 CreateAndInsertInst(Instruction *NewI) : NewI(NewI) {}
303 void revert(Tracker &Tracker) final;
304 void accept() final {}
305#ifndef NDEBUG
306 void dump(raw_ostream &OS) const final { OS << "CreateAndInsertInst"; }
307 LLVM_DUMP_METHOD void dump() const final;
308#endif
309};
310
311/// The tracker collects all the change objects and implements the main API for
312/// saving / reverting / accepting.
313class Tracker {
314public:
315 enum class TrackerState {
316 Disabled, ///> Tracking is disabled
317 Record, ///> Tracking changes
318 };
319
320private:
321 /// The list of changes that are being tracked.
323 /// The current state of the tracker.
325 Context &Ctx;
326
327public:
328#ifndef NDEBUG
329 /// Helps catch bugs where we are creating new change objects while in the
330 /// middle of creating other change objects.
332#endif // NDEBUG
333
334 explicit Tracker(Context &Ctx) : Ctx(Ctx) {}
335 ~Tracker();
336 Context &getContext() const { return Ctx; }
337 /// Record \p Change and take ownership. This is the main function used to
338 /// track Sandbox IR changes.
339 void track(std::unique_ptr<IRChangeBase> &&Change) {
340 assert(State == TrackerState::Record && "The tracker should be tracking!");
341#ifndef NDEBUG
343 "We are in the middle of creating another change!");
344 if (isTracking())
346#endif // NDEBUG
347 Changes.push_back(std::move(Change));
348
349#ifndef NDEBUG
351#endif
352 }
353 /// A convenience wrapper for `track()` that constructs and tracks the Change
354 /// object if tracking is enabled. \Returns true if tracking is enabled.
355 template <typename ChangeT, typename... ArgsT>
356 bool emplaceIfTracking(ArgsT... Args) {
357 if (!isTracking())
358 return false;
359 track(std::make_unique<ChangeT>(Args...));
360 return true;
361 }
362 /// \Returns true if the tracker is recording changes.
363 bool isTracking() const { return State == TrackerState::Record; }
364 /// \Returns the current state of the tracker.
365 TrackerState getState() const { return State; }
366 /// Turns on IR tracking.
367 void save();
368 /// Stops tracking and accept changes.
369 void accept();
370 /// Stops tracking and reverts to saved state.
371 void revert();
372
373#ifndef NDEBUG
374 void dump(raw_ostream &OS) const;
375 LLVM_DUMP_METHOD void dump() const;
377 Tracker.dump(OS);
378 return OS;
379 }
380#endif // NDEBUG
381};
382
383} // namespace llvm::sandboxir
384
385#endif // LLVM_SANDBOXIR_TRACKER_H
aarch64 promote const
Rewrite undef for PHI
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
Definition: Compiler.h:537
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
Module.h This file contains the declarations for the Module class.
This file defines the PointerUnion class, which is a discriminated union of pointer types.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
raw_pwrite_stream & OS
This file defines the SmallVector class.
A discriminated union of two or more pointer types, with the discriminator in the low bit of the poin...
Definition: PointerUnion.h:118
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:556
void accept() final
This runs when changes get accepted.
Definition: Tracker.h:261
void dump(raw_ostream &OS) const final
Definition: Tracker.h:263
void revert(Tracker &Tracker) final
This runs when changes get reverted.
Definition: Tracker.cpp:194
LLVM_DUMP_METHOD void dump() const final
Definition: Tracker.cpp:198
LLVM_DUMP_METHOD void dump() const final
Definition: Tracker.cpp:241
void accept() final
This runs when changes get accepted.
Definition: Tracker.h:304
CreateAndInsertInst(Instruction *NewI)
Definition: Tracker.h:302
void dump(raw_ostream &OS) const final
Definition: Tracker.h:306
void revert(Tracker &Tracker) final
This runs when changes get reverted.
Definition: Tracker.cpp:238
void dump(raw_ostream &OS) const final
Definition: Tracker.h:189
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
This class can be used for tracking most instruction setters.
Definition: Tracker.h:228
void dump(raw_ostream &OS) const final
Definition: Tracker.h:245
void accept() final
This runs when changes get accepted.
Definition: Tracker.h:243
void revert(Tracker &Tracker) final
This runs when changes get reverted.
Definition: Tracker.h:242
LLVM_DUMP_METHOD void dump() const final
Definition: Tracker.h:246
The base class for IR Change classes.
Definition: Tracker.h:64
virtual LLVM_DUMP_METHOD void dump() const =0
virtual void revert(Tracker &Tracker)=0
This runs when changes get reverted.
friend raw_ostream & operator<<(raw_ostream &OS, const IRChangeBase &C)
Definition: Tracker.h:77
virtual ~IRChangeBase()=default
virtual void accept()=0
This runs when changes get accepted.
virtual void dump(raw_ostream &OS) const =0
void dump(raw_ostream &OS) const final
Definition: Tracker.h:293
LLVM_DUMP_METHOD void dump() const final
Definition: Tracker.cpp:232
void accept() final
This runs when changes get accepted.
Definition: Tracker.h:291
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:603
LLVM_DUMP_METHOD void dump() const final
Definition: Tracker.cpp:221
void revert(Tracker &Tracker) final
This runs when changes get reverted.
Definition: Tracker.cpp:211
void accept() final
This runs when changes get accepted.
Definition: Tracker.h:278
void dump(raw_ostream &OS) const final
Definition: Tracker.h:280
void dump(raw_ostream &OS) const final
Definition: Tracker.h:143
void revert(Tracker &Tracker) final
This runs when changes get reverted.
Definition: Tracker.cpp:95
void accept() final
This runs when changes get accepted.
Definition: Tracker.h:141
LLVM_DUMP_METHOD void dump() const final
Definition: Tracker.cpp:98
void accept() final
This runs when changes get accepted.
Definition: Tracker.h:127
LLVM_DUMP_METHOD void dump() const final
Definition: Tracker.cpp:86
void dump(raw_ostream &OS) const final
Definition: Tracker.h:129
void revert(Tracker &Tracker) final
This runs when changes get reverted.
Definition: Tracker.cpp:62
void dump(raw_ostream &OS) const final
Definition: Tracker.h:113
void revert(Tracker &Tracker) final
This runs when changes get reverted.
Definition: Tracker.cpp:42
void accept() final
This runs when changes get accepted.
Definition: Tracker.h:111
LLVM_DUMP_METHOD void dump() const final
Definition: Tracker.cpp:50
void dump(raw_ostream &OS) const final
Definition: Tracker.h:210
Instruction * getInstruction() const
Definition: Tracker.h:208
void revert(Tracker &Tracker) final
This runs when changes get reverted.
Definition: Tracker.cpp:173
void accept() final
This runs when changes get accepted.
Definition: Tracker.h:207
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
TrackerState getState() const
\Returns the current state of the tracker.
Definition: Tracker.h:365
friend raw_ostream & operator<<(raw_ostream &OS, const Tracker &Tracker)
Definition: Tracker.h:376
void dump(raw_ostream &OS) const
Definition: Tracker.cpp:266
bool isTracking() const
\Returns true if the tracker is recording changes.
Definition: Tracker.h:363
void save()
Turns on IR tracking.
Definition: Tracker.cpp:247
Tracker(Context &Ctx)
Definition: Tracker.h:334
void track(std::unique_ptr< IRChangeBase > &&Change)
Record Change and take ownership.
Definition: Tracker.h:339
bool InMiddleOfCreatingChange
Helps catch bugs where we are creating new change objects while in the middle of creating other chang...
Definition: Tracker.h:331
Context & getContext() const
Definition: Tracker.h:336
bool emplaceIfTracking(ArgsT... Args)
A convenience wrapper for track() that constructs and tracks the Change object if tracking is enabled...
Definition: Tracker.h:356
void accept()
Stops tracking and accept changes.
Definition: Tracker.cpp:257
LLVM_DUMP_METHOD void dump() const
Definition: Tracker.cpp:273
Tracks the change of the source Value of a sandboxir::Use.
Definition: Tracker.h:85
UseSet(const Use &U)
Definition: Tracker.h:90
void revert(Tracker &Tracker) final
This runs when changes get reverted.
Definition: Tracker.h:91
void dump(raw_ostream &OS) const final
Definition: Tracker.h:94
void accept() final
This runs when changes get accepted.
Definition: Tracker.h:92
LLVM_DUMP_METHOD void dump() const final
Definition: Tracker.cpp:19
Tracks swapping a Use with another Use.
Definition: Tracker.h:149
void revert(Tracker &Tracker) final
This runs when changes get reverted.
Definition: Tracker.h:158
LLVM_DUMP_METHOD void dump() const final
Definition: Tracker.cpp:24
void accept() final
This runs when changes get accepted.
Definition: Tracker.h:159
void dump(raw_ostream &OS) const final
Definition: Tracker.h:161
UseSwap(const Use &ThisUse, const Use &OtherUse)
Definition: Tracker.h:154
Represents a Def-use/Use-def edge in SandboxIR.
Definition: Use.h:32
void swap(Use &OtherUse)
Definition: SandboxIR.cpp:27
class User * getUser() const
Definition: Use.h:54
A SandboxIR Value has users. This is the base class.
Definition: SandboxIR.h:199
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
@ BasicBlock
Various leaf nodes.
Definition: ISDOpcodes.h:71
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163