28#define DEBUG_TYPE "coro-suspend-crossing"
44 RematNode() =
default;
55 RematGraph(
const std::function<
bool(
Instruction &)> &MaterializableCallback,
57 : MaterializableCallback(MaterializableCallback), Checker(Checker) {
58 std::unique_ptr<RematNode> FirstNode = std::make_unique<RematNode>(
I);
59 EntryNode = FirstNode.get();
60 std::deque<std::unique_ptr<RematNode>> WorkList;
61 addNode(std::move(FirstNode), WorkList, cast<User>(
I));
62 while (WorkList.size()) {
63 std::unique_ptr<RematNode>
N = std::move(WorkList.front());
65 addNode(std::move(
N), WorkList, cast<User>(
I));
69 void addNode(std::unique_ptr<RematNode> NUPtr,
70 std::deque<std::unique_ptr<RematNode>> &WorkList,
72 RematNode *
N = NUPtr.get();
73 auto [It, Inserted] = Remats.try_emplace(
N->Node);
78 It->second = std::move(NUPtr);
79 for (
auto &Def :
N->Node->operands()) {
81 if (!
D || !MaterializableCallback(*
D) ||
85 if (
auto It = Remats.find(
D); It != Remats.end()) {
87 N->Operands.push_back(It->second.get());
92 for (
auto &
I : WorkList) {
95 N->Operands.push_back(
I.get());
101 std::unique_ptr<RematNode> ChildNode = std::make_unique<RematNode>(
D);
102 N->Operands.push_back(ChildNode.get());
103 WorkList.push_back(std::move(ChildNode));
108#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
120 BasicBlock *BB = EntryNode->Node->getParent();
128 dbgs() <<
") : " << *EntryNode->Node <<
"\n";
129 for (
auto &E : Remats) {
130 dbgs() << *(E.first) <<
"\n";
131 for (RematNode *U : E.second->Operands)
132 dbgs() <<
" " << *U->Node <<
"\n";
147 return N->Operands.begin();
173 for (
const auto &E : AllRemats) {
176 RematGraph *RG = E.second.get();
185 if (isa<AnyCoroSuspendInst>(
Use)) {
187 Use->getParent()->getSinglePredecessor();
188 assert(SuspendPredecessorBlock &&
"malformed coro suspend instruction");
196 for (;
I != RPOT.
end(); ++
I) {
198 CurrentMaterialization =
D->clone();
199 CurrentMaterialization->
setName(
D->getName());
201 InsertPoint = CurrentMaterialization->
getIterator();
205 for (
auto &
I : InstructionsToProcess)
206 I->replaceUsesOfWith(
D, CurrentMaterialization);
211 for (
unsigned i = 0, E =
Use->getNumOperands(); i != E; ++i)
212 if (
Use->getOperand(i) ==
D)
214 {
Use,
D, CurrentMaterialization});
216 InstructionsToProcess.push_back(CurrentMaterialization);
221 for (
auto &R : FinalInstructionsToProcess) {
222 if (
auto *PN = dyn_cast<PHINode>(R.Use)) {
223 assert(PN->getNumIncomingValues() == 1 &&
"unexpected number of incoming "
224 "values in the PHINode");
225 PN->replaceAllUsesWith(R.Remat);
226 PN->eraseFromParent();
229 R.Use->replaceUsesOfWith(R.Def, R.Remat);
237 return (isa<CastInst>(&V) || isa<GetElementPtrInst>(&V) ||
238 isa<BinaryOperator>(&V) || isa<CmpInst>(&V) || isa<SelectInst>(&V));
249 dbgs() <<
"------------- " << Title <<
"--------------\n";
250 for (
const auto &E : RM) {
259 std::function<
bool(
Instruction &)> IsMaterializable) {
269 if (!IsMaterializable(
I))
271 for (
User *U :
I.users())
273 Spills[&
I].push_back(cast<Instruction>(U));
292 for (
auto &E : Spills) {
296 if (AllRemats.
count(U))
301 std::make_unique<RematGraph>(IsMaterializable, U, Checker);
305 for (
auto I = RPOT.begin();
I != RPOT.end();
306 ++
I) { (*I)->Node->dump(); }
dbgs()
309 AllRemats[U] = std::move(RematUPtr);
Expand Atomic instructions
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
mir Rename Register Operands
static void rewriteMaterializableInstructions(const SmallMapVector< Instruction *, std::unique_ptr< RematGraph >, 8 > &AllRemats)
static void dumpRemats(StringRef Title, const SmallMapVector< Instruction *, std::unique_ptr< RematGraph >, 8 > &RM)
This file builds on the ADT/GraphTraits.h file to build a generic graph post order iterator.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
LLVM Basic Block Representation.
const Function * getParent() const
Return the enclosing method, or null if none.
InstListType::iterator iterator
Instruction iterators...
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
void insertBefore(Instruction *InsertPos)
Insert an unlinked instruction into a basic block immediately before the specified instruction.
size_type count(const KeyT &Key) const
Manage lifetime of a slot tracker for printing IR.
int getLocalSlot(const Value *V)
Return the slot number of the specified local value.
void incorporateFunction(const Function &F)
Incorporate the given function.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
bool isDefinitionAcrossSuspend(BasicBlock *DefBB, User *U) const
A Use represents the edge between a Value definition and its users.
void setName(const Twine &Name)
Change the name of the value.
StringRef getName() const
Return a constant reference to the value's name.
self_iterator getIterator()
bool defaultMaterializable(Instruction &V)
Default materializable callback.
bool isTriviallyMaterializable(Instruction &I)
void doRematerializations(Function &F, SuspendCrossingInfo &Checker, std::function< bool(Instruction &)> IsMaterializable)
This is an optimization pass for GlobalISel generic memory operations.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
static void dumpBasicBlockLabel(const BasicBlock *BB, ModuleSlotTracker &MST)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
RematGraph::RematNode * NodeRef
static ChildIteratorType child_end(NodeRef N)
RematGraph::RematNode ** ChildIteratorType
static NodeRef getEntryNode(RematGraph *G)
static ChildIteratorType child_begin(NodeRef N)
A MapVector that performs no allocations if smaller than a certain size.