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 if (Remats.count(
N->Node))
77 Remats[
N->Node] = std::move(NUPtr);
78 for (
auto &Def :
N->Node->operands()) {
80 if (!
D || !MaterializableCallback(*
D) ||
84 if (Remats.count(
D)) {
86 N->Operands.push_back(Remats[
D].
get());
91 for (
auto &
I : WorkList) {
94 N->Operands.push_back(
I.get());
100 std::unique_ptr<RematNode> ChildNode = std::make_unique<RematNode>(
D);
101 N->Operands.push_back(ChildNode.get());
102 WorkList.push_back(std::move(ChildNode));
107#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
119 BasicBlock *BB = EntryNode->Node->getParent();
127 dbgs() <<
") : " << *EntryNode->Node <<
"\n";
128 for (
auto &E : Remats) {
129 dbgs() << *(E.first) <<
"\n";
130 for (RematNode *U : E.second->Operands)
131 dbgs() <<
" " << *U->Node <<
"\n";
146 return N->Operands.begin();
172 for (
const auto &E : AllRemats) {
175 RematGraph *RG = E.second.get();
183 auto InsertPoint = &*
Use->getParent()->getFirstInsertionPt();
184 if (isa<AnyCoroSuspendInst>(
Use)) {
186 Use->getParent()->getSinglePredecessor();
187 assert(SuspendPredecessorBlock &&
"malformed coro suspend instruction");
195 for (;
I != RPOT.
end(); ++
I) {
197 CurrentMaterialization =
D->clone();
198 CurrentMaterialization->
setName(
D->getName());
200 InsertPoint = CurrentMaterialization;
204 for (
auto &
I : InstructionsToProcess)
205 I->replaceUsesOfWith(
D, CurrentMaterialization);
210 for (
unsigned i = 0, E =
Use->getNumOperands(); i != E; ++i)
211 if (
Use->getOperand(i) ==
D)
213 {
Use,
D, CurrentMaterialization});
215 InstructionsToProcess.push_back(CurrentMaterialization);
220 for (
auto &R : FinalInstructionsToProcess) {
221 if (
auto *PN = dyn_cast<PHINode>(R.Use)) {
222 assert(PN->getNumIncomingValues() == 1 &&
"unexpected number of incoming "
223 "values in the PHINode");
224 PN->replaceAllUsesWith(R.Remat);
225 PN->eraseFromParent();
228 R.Use->replaceUsesOfWith(R.Def, R.Remat);
236 return (isa<CastInst>(&V) || isa<GetElementPtrInst>(&V) ||
237 isa<BinaryOperator>(&V) || isa<CmpInst>(&V) || isa<SelectInst>(&V));
248 dbgs() <<
"------------- " << Title <<
"--------------\n";
249 for (
const auto &E : RM) {
258 std::function<
bool(
Instruction &)> IsMaterializable) {
268 if (!IsMaterializable(
I))
270 for (
User *U :
I.users())
272 Spills[&
I].push_back(cast<Instruction>(U));
291 for (
auto &E : Spills) {
295 if (AllRemats.
count(U))
300 std::make_unique<RematGraph>(IsMaterializable, U, Checker);
304 for (
auto I = RPOT.begin();
I != RPOT.end();
305 ++
I) { (*I)->Node->dump(); }
dbgs()
308 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.
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.
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)
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.
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.