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
18IRChangeBase::IRChangeBase(Tracker &Parent) : Parent(Parent) {
19#ifndef NDEBUG
21 "We are in the middle of creating another change!");
22 if (Parent.isTracking())
24#endif // NDEBUG
25}
26
27#ifndef NDEBUG
28unsigned 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
34void UseSet::dump() const {
35 dump(dbgs());
36 dbgs() << "\n";
37}
38
39void UseSwap::dump() const {
40 dump(dbgs());
41 dbgs() << "\n";
42}
43#endif // NDEBUG
44
46 assert(Changes.empty() && "You must accept or revert changes!");
47}
48
49EraseFromParent::EraseFromParent(std::unique_ptr<sandboxir::Value> &&ErasedIPtr,
51 : IRChangeBase(Tracker), ErasedIPtr(std::move(ErasedIPtr)) {
52 auto *I = cast<Instruction>(this->ErasedIPtr.get());
53 auto LLVMInstrs = I->getLLVMInstrs();
54 // Iterate in reverse program order.
55 for (auto *LLVMI : reverse(LLVMInstrs)) {
57 Operands.reserve(LLVMI->getNumOperands());
58 for (auto [OpNum, Use] : enumerate(LLVMI->operands()))
59 Operands.push_back(Use.get());
60 InstrData.push_back({Operands, LLVMI});
61 }
62 assert(is_sorted(InstrData,
63 [](const auto &D0, const auto &D1) {
64 return D0.LLVMI->comesBefore(D1.LLVMI);
65 }) &&
66 "Expected reverse program order!");
67 auto *BotLLVMI = cast<llvm::Instruction>(I->Val);
68 if (BotLLVMI->getNextNode() != nullptr)
69 NextLLVMIOrBB = BotLLVMI->getNextNode();
70 else
71 NextLLVMIOrBB = BotLLVMI->getParent();
72}
73
75 for (const auto &IData : InstrData)
76 IData.LLVMI->deleteValue();
77}
78
80 // Place the bottom-most instruction first.
81 auto [Operands, BotLLVMI] = InstrData[0];
82 if (auto *NextLLVMI = NextLLVMIOrBB.dyn_cast<llvm::Instruction *>()) {
83 BotLLVMI->insertBefore(NextLLVMI);
84 } else {
85 auto *LLVMBB = NextLLVMIOrBB.get<llvm::BasicBlock *>();
86 BotLLVMI->insertInto(LLVMBB, LLVMBB->end());
87 }
88 for (auto [OpNum, Op] : enumerate(Operands))
89 BotLLVMI->setOperand(OpNum, Op);
90
91 // Go over the rest of the instructions and stack them on top.
92 for (auto [Operands, LLVMI] : drop_begin(InstrData)) {
93 LLVMI->insertBefore(BotLLVMI);
94 for (auto [OpNum, Op] : enumerate(Operands))
95 LLVMI->setOperand(OpNum, Op);
96 BotLLVMI = LLVMI;
97 }
98 Parent.getContext().registerValue(std::move(ErasedIPtr));
99}
100
101#ifndef NDEBUG
103 dump(dbgs());
104 dbgs() << "\n";
105}
106#endif // NDEBUG
107
109 : IRChangeBase(Tracker), RemovedI(RemovedI) {
110 if (auto *NextI = RemovedI->getNextNode())
111 NextInstrOrBB = NextI;
112 else
113 NextInstrOrBB = RemovedI->getParent();
114}
115
117 if (auto *NextI = NextInstrOrBB.dyn_cast<Instruction *>()) {
118 RemovedI->insertBefore(NextI);
119 } else {
120 auto *BB = NextInstrOrBB.get<BasicBlock *>();
121 RemovedI->insertInto(BB, BB->end());
122 }
123}
124
125#ifndef NDEBUG
127 dump(dbgs());
128 dbgs() << "\n";
129}
130#endif
131
133 : IRChangeBase(Tracker), MovedI(MovedI) {
134 if (auto *NextI = MovedI->getNextNode())
135 NextInstrOrBB = NextI;
136 else
137 NextInstrOrBB = MovedI->getParent();
138}
139
141 if (auto *NextI = NextInstrOrBB.dyn_cast<Instruction *>()) {
142 MovedI->moveBefore(NextI);
143 } else {
144 auto *BB = NextInstrOrBB.get<BasicBlock *>();
145 MovedI->moveBefore(*BB, BB->end());
146 }
147}
148
149#ifndef NDEBUG
150void MoveInstr::dump() const {
151 dump(dbgs());
152 dbgs() << "\n";
153}
154#endif
155
156void Tracker::track(std::unique_ptr<IRChangeBase> &&Change) {
157 assert(State == TrackerState::Record && "The tracker should be tracking!");
158 Changes.push_back(std::move(Change));
159
160#ifndef NDEBUG
162#endif
163}
164
166
168 assert(State == TrackerState::Record && "Forgot to save()!");
170 for (auto &Change : reverse(Changes))
171 Change->revert();
172 Changes.clear();
173}
174
176 assert(State == TrackerState::Record && "Forgot to save()!");
178 for (auto &Change : Changes)
179 Change->accept();
180 Changes.clear();
181}
182
183#ifndef NDEBUG
185 for (const auto &ChangePtr : Changes) {
186 ChangePtr->dump(OS);
187 OS << "\n";
188 }
189}
190void Tracker::dump() const {
191 dump(dbgs());
192 dbgs() << "\n";
193}
194#endif // NDEBUG
#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:426
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1209
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:876
Value * registerValue(std::unique_ptr< Value > &&VPtr)
Take ownership of VPtr and store it in LLVMValueToValueMap.
Definition: SandboxIR.cpp:805
EraseFromParent(std::unique_ptr< sandboxir::Value > &&IPtr, Tracker &Tracker)
Definition: Tracker.cpp:49
void accept() final
This runs when changes get accepted.
Definition: Tracker.cpp:74
LLVM_DUMP_METHOD void dump() const final
Definition: Tracker.cpp:102
void revert() final
This runs when changes get reverted.
Definition: Tracker.cpp:79
The base class for IR Change classes.
Definition: Tracker.h:60
IRChangeBase(Tracker &Parent)
Definition: Tracker.cpp:18
unsigned getIdx() const
\Returns the index of this change by iterating over all changes in the tracker.
Definition: Tracker.cpp:28
A sandboxir::User with operands, opcode and linked with previous/next instructions in an instruction ...
Definition: SandboxIR.h:496
void insertInto(BasicBlock *BB, const BBIterator &WhereIt)
Insert this detached instruction into BB at WhereIt.
Definition: SandboxIR.cpp:418
Instruction * getNextNode() const
\Returns the next sandboxir::Instruction in the block, or nullptr if at the end of the block.
Definition: SandboxIR.cpp:319
void moveBefore(BasicBlock &BB, const BBIterator &WhereIt)
Move this instruction to WhereIt.
Definition: SandboxIR.cpp:377
void insertBefore(Instruction *BeforeI)
Insert this detached instruction before BeforeI.
Definition: SandboxIR.cpp:403
BasicBlock * getParent() const
\Returns the BasicBlock containing this Instruction, or null if it is detached.
Definition: SandboxIR.cpp:435
LLVM_DUMP_METHOD void dump() const final
Definition: Tracker.cpp:150
void revert() final
This runs when changes get reverted.
Definition: Tracker.cpp:140
MoveInstr(sandboxir::Instruction *I, Tracker &Tracker)
Definition: Tracker.cpp:132
void revert() final
This runs when changes get reverted.
Definition: Tracker.cpp:116
RemoveFromParent(Instruction *RemovedI, Tracker &Tracker)
Definition: Tracker.cpp:108
LLVM_DUMP_METHOD void dump() const final
Definition: Tracker.cpp:126
The tracker collects all the change objects and implements the main API for saving / reverting / acce...
Definition: Tracker.h:202
@ Record
ā€¨Tracking is disabled
void revert()
Stops tracking and reverts to saved state.
Definition: Tracker.cpp:167
bool isTracking() const
\Returns true if the tracker is recording changes.
Definition: Tracker.h:233
void save()
Turns on IR tracking.
Definition: Tracker.cpp:165
bool InMiddleOfCreatingChange
Helps catch bugs where we are creating new change objects while in the middle of creating other chang...
Definition: Tracker.h:223
Context & getContext() const
Definition: Tracker.h:228
void track(std::unique_ptr< IRChangeBase > &&Change)
Record Change and take ownership.
Definition: Tracker.cpp:156
void accept()
Stops tracking and accept changes.
Definition: Tracker.cpp:175
LLVM_DUMP_METHOD void dump() const
Definition: Tracker.cpp:190
LLVM_DUMP_METHOD void dump() const final
Definition: Tracker.cpp:34
LLVM_DUMP_METHOD void dump() const final
Definition: Tracker.cpp:39
Represents a Def-use/Use-def edge in SandboxIR.
Definition: Use.h:29
Value * get() const
Definition: SandboxIR.cpp:17
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 are tuples (A,...
Definition: STLExtras.h:2400
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
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1749
Implement std::hash so that hash_code can be used in STL containers.
Definition: BitVector.h:858