File indexing completed on 2026-05-10 08:44:38
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #ifndef LLVM_TRANSFORMS_COROUTINES_SUSPENDCROSSINGINFO_H
0016 #define LLVM_TRANSFORMS_COROUTINES_SUSPENDCROSSINGINFO_H
0017
0018 #include "llvm/ADT/BitVector.h"
0019 #include "llvm/ADT/PostOrderIterator.h"
0020 #include "llvm/ADT/SmallVector.h"
0021 #include "llvm/IR/BasicBlock.h"
0022 #include "llvm/IR/Function.h"
0023 #include "llvm/IR/Instruction.h"
0024 #include "llvm/Transforms/Coroutines/CoroInstr.h"
0025
0026 namespace llvm {
0027
0028 class ModuleSlotTracker;
0029
0030
0031 class BlockToIndexMapping {
0032 SmallVector<BasicBlock *, 32> V;
0033
0034 public:
0035 size_t size() const { return V.size(); }
0036
0037 BlockToIndexMapping(Function &F) {
0038 for (BasicBlock &BB : F)
0039 V.push_back(&BB);
0040 llvm::sort(V);
0041 }
0042
0043 size_t blockToIndex(BasicBlock const *BB) const {
0044 auto *I = llvm::lower_bound(V, BB);
0045 assert(I != V.end() && *I == BB && "BasicBlockNumberng: Unknown block");
0046 return I - V.begin();
0047 }
0048
0049 BasicBlock *indexToBlock(unsigned Index) const { return V[Index]; }
0050 };
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067 class SuspendCrossingInfo {
0068 BlockToIndexMapping Mapping;
0069
0070 struct BlockData {
0071 BitVector Consumes;
0072 BitVector Kills;
0073 bool Suspend = false;
0074 bool End = false;
0075 bool KillLoop = false;
0076 bool Changed = false;
0077 };
0078 SmallVector<BlockData, 32> Block;
0079
0080 iterator_range<pred_iterator> predecessors(BlockData const &BD) const {
0081 BasicBlock *BB = Mapping.indexToBlock(&BD - &Block[0]);
0082 return llvm::predecessors(BB);
0083 }
0084
0085 BlockData &getBlockData(BasicBlock *BB) {
0086 return Block[Mapping.blockToIndex(BB)];
0087 }
0088
0089
0090
0091
0092
0093 template <bool Initialize = false>
0094 bool computeBlockData(const ReversePostOrderTraversal<Function *> &RPOT);
0095
0096 public:
0097 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
0098
0099 void dump() const;
0100 void dump(StringRef Label, BitVector const &BV,
0101 const ReversePostOrderTraversal<Function *> &RPOT,
0102 ModuleSlotTracker &MST) const;
0103 #endif
0104
0105 SuspendCrossingInfo(Function &F,
0106 const SmallVectorImpl<AnyCoroSuspendInst *> &CoroSuspends,
0107 const SmallVectorImpl<AnyCoroEndInst *> &CoroEnds);
0108
0109
0110
0111 bool hasPathCrossingSuspendPoint(BasicBlock *From, BasicBlock *To) const;
0112
0113
0114
0115
0116 bool hasPathOrLoopCrossingSuspendPoint(BasicBlock *From,
0117 BasicBlock *To) const;
0118
0119 bool isDefinitionAcrossSuspend(BasicBlock *DefBB, User *U) const {
0120 auto *I = cast<Instruction>(U);
0121
0122
0123
0124 if (auto *PN = dyn_cast<PHINode>(I))
0125 if (PN->getNumIncomingValues() > 1)
0126 return false;
0127
0128 BasicBlock *UseBB = I->getParent();
0129
0130
0131
0132
0133 if (isa<CoroSuspendRetconInst>(I) || isa<CoroSuspendAsyncInst>(I)) {
0134 UseBB = UseBB->getSinglePredecessor();
0135 assert(UseBB && "should have split coro.suspend into its own block");
0136 }
0137
0138 return hasPathCrossingSuspendPoint(DefBB, UseBB);
0139 }
0140
0141 bool isDefinitionAcrossSuspend(Argument &A, User *U) const {
0142 return isDefinitionAcrossSuspend(&A.getParent()->getEntryBlock(), U);
0143 }
0144
0145 bool isDefinitionAcrossSuspend(Instruction &I, User *U) const {
0146 auto *DefBB = I.getParent();
0147
0148
0149
0150
0151 if (isa<AnyCoroSuspendInst>(I)) {
0152 DefBB = DefBB->getSingleSuccessor();
0153 assert(DefBB && "should have split coro.suspend into its own block");
0154 }
0155
0156 return isDefinitionAcrossSuspend(DefBB, U);
0157 }
0158
0159 bool isDefinitionAcrossSuspend(Value &V, User *U) const {
0160 if (auto *Arg = dyn_cast<Argument>(&V))
0161 return isDefinitionAcrossSuspend(*Arg, U);
0162 if (auto *Inst = dyn_cast<Instruction>(&V))
0163 return isDefinitionAcrossSuspend(*Inst, U);
0164
0165 llvm_unreachable(
0166 "Coroutine could only collect Argument and Instruction now.");
0167 }
0168
0169 bool isDefinitionAcrossSuspend(Value &V) const {
0170 if (auto *Arg = dyn_cast<Argument>(&V)) {
0171 for (User *U : Arg->users())
0172 if (isDefinitionAcrossSuspend(*Arg, U))
0173 return true;
0174 } else if (auto *Inst = dyn_cast<Instruction>(&V)) {
0175 for (User *U : Inst->users())
0176 if (isDefinitionAcrossSuspend(*Inst, U))
0177 return true;
0178 }
0179
0180 llvm_unreachable(
0181 "Coroutine could only collect Argument and Instruction now.");
0182 }
0183 };
0184
0185 }
0186
0187 #endif