29#define DEBUG_TYPE "coro-suspend-crossing"
45 RematNode() =
default;
56 RematGraph(
const std::function<
bool(
Instruction &)> &MaterializableCallback,
58 : MaterializableCallback(MaterializableCallback), Checker(Checker) {
59 std::unique_ptr<RematNode> FirstNode = std::make_unique<RematNode>(
I);
60 EntryNode = FirstNode.get();
61 std::deque<std::unique_ptr<RematNode>> WorkList;
62 addNode(std::move(FirstNode), WorkList,
cast<User>(
I));
63 while (WorkList.size()) {
64 std::unique_ptr<RematNode>
N = std::move(WorkList.front());
70 void addNode(std::unique_ptr<RematNode> NUPtr,
71 std::deque<std::unique_ptr<RematNode>> &WorkList,
73 RematNode *
N = NUPtr.get();
74 auto [It, Inserted] = Remats.try_emplace(
N->Node);
79 It->second = std::move(NUPtr);
80 for (
auto &Def :
N->Node->operands()) {
82 if (!
D || !MaterializableCallback(*
D) ||
86 if (
auto It = Remats.find(
D); It != Remats.end()) {
88 N->Operands.push_back(It->second.get());
93 for (
auto &
I : WorkList) {
96 N->Operands.push_back(
I.get());
102 std::unique_ptr<RematNode> ChildNode = std::make_unique<RematNode>(
D);
103 N->Operands.push_back(ChildNode.get());
104 WorkList.push_back(std::move(ChildNode));
109#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
121 BasicBlock *BB = EntryNode->Node->getParent();
129 dbgs() <<
") : " << *EntryNode->Node <<
"\n";
130 for (
auto &
E : Remats) {
131 dbgs() << *(
E.first) <<
"\n";
132 for (RematNode *U :
E.second->Operands)
133 dbgs() <<
" " << *U->Node <<
"\n";
147 return N->Operands.begin();
171 for (
const auto &
E : AllRemats) {
174 RematGraph *RG =
E.second.get();
185 Use->getParent()->getSinglePredecessor();
186 assert(SuspendPredecessorBlock &&
"malformed coro suspend instruction");
194 for (;
I != RPOT.
end(); ++
I) {
196 CurrentMaterialization =
D->clone();
197 CurrentMaterialization->
setName(
D->getName());
203 for (
auto &
I : InstructionsToProcess)
204 I->replaceUsesOfWith(
D, CurrentMaterialization);
209 for (
unsigned i = 0,
E =
Use->getNumOperands(); i !=
E; ++i)
210 if (
Use->getOperand(i) ==
D)
212 {
Use,
D, CurrentMaterialization});
214 InstructionsToProcess.push_back(CurrentMaterialization);
219 for (
auto &R : FinalInstructionsToProcess) {
221 assert(PN->getNumIncomingValues() == 1 &&
"unexpected number of incoming "
222 "values in the PHINode");
223 PN->replaceAllUsesWith(R.Remat);
224 PN->eraseFromParent();
227 R.Use->replaceUsesOfWith(R.Def, R.Remat);
241 switch (
II->getIntrinsicID()) {
243 case Intrinsic::fabs:
244 case Intrinsic::sqrt:
247 case Intrinsic::exp2:
248 case Intrinsic::log2:
250 case Intrinsic::minnum:
251 case Intrinsic::maxnum:
252 case Intrinsic::minimum:
253 case Intrinsic::maximum:
254 case Intrinsic::copysign:
255 case Intrinsic::ldexp:
257 case Intrinsic::fptoui_sat:
258 case Intrinsic::fptosi_sat:
259 case Intrinsic::is_fpclass:
261 case Intrinsic::floor:
262 case Intrinsic::ceil:
263 case Intrinsic::trunc:
264 case Intrinsic::rint:
265 case Intrinsic::nearbyint:
266 case Intrinsic::round:
267 case Intrinsic::roundeven:
269 case Intrinsic::ctpop:
270 case Intrinsic::ctlz:
271 case Intrinsic::cttz:
272 case Intrinsic::bitreverse:
274 case Intrinsic::sadd_sat:
275 case Intrinsic::uadd_sat:
276 case Intrinsic::ssub_sat:
277 case Intrinsic::usub_sat:
279 case Intrinsic::smax:
280 case Intrinsic::smin:
281 case Intrinsic::umax:
282 case Intrinsic::umin:
300 dbgs() <<
"------------- " << Title <<
"--------------\n";
301 for (
const auto &
E : RM) {
310 std::function<
bool(
Instruction &)> IsMaterializable) {
320 if (!IsMaterializable(
I))
322 for (
User *U :
I.users())
343 for (
auto &E : Spills) {
353 std::make_unique<RematGraph>(IsMaterializable, U, Checker);
357 for (
auto I = RPOT.begin();
I != RPOT.end();
358 ++
I) { (*I)->Node->dump(); }
dbgs()
361 It->second = std::move(RematUPtr);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Expand Atomic instructions
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
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)
uint64_t IntrinsicInst * II
This file builds on the ADT/GraphTraits.h file to build a generic graph post order iterator.
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; assumes that the block is well-formed.
LLVM_ABI void insertBefore(InstListType::iterator InsertPos)
Insert an unlinked instruction into a basic block immediately before the specified position.
std::pair< iterator, bool > try_emplace(const KeyT &Key, Ts &&...Args)
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.
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.
LLVM_ABI void setName(const Twine &Name)
Change the name of the value.
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
self_iterator getIterator()
SmallMapVector< Value *, SmallVector< Instruction *, 2 >, 8 > SpillInfo
bool defaultMaterializable(Instruction &V)
Default materializable callback.
LLVM_ABI bool isTriviallyMaterializable(Instruction &I)
LLVM_ABI 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)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
static void dumpBasicBlockLabel(const BasicBlock *BB, ModuleSlotTracker &MST)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
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.