39 SPIRVMergeRegionExitTargets() : FunctionPass(ID) {}
43 std::unordered_set<BasicBlock *> gatherSuccessors(BasicBlock *BB) {
44 std::unordered_set<BasicBlock *> output;
48 output.insert(BI->getSuccessor(0));
49 if (BI->isConditional())
50 output.insert(BI->getSuccessor(1));
55 output.insert(
SI->getDefaultDest());
56 for (
auto &Case :
SI->cases())
57 output.insert(Case.getCaseSuccessor());
69 const DenseMap<BasicBlock *, ConstantInt *> &TargetToValue) {
75 Builder.SetInsertPoint(
T);
81 BI->isConditional() ? BI->getSuccessor(1) :
nullptr;
86 if (
LHS ==
nullptr ||
RHS ==
nullptr)
88 return Builder.CreateSelect(BI->getCondition(),
LHS,
RHS);
97 const SmallPtrSet<BasicBlock *, 4> &ToReplace,
98 BasicBlock *NewTarget) {
104 for (
size_t i = 0; i < BI->getNumSuccessors(); i++) {
105 if (ToReplace.
count(BI->getSuccessor(i)) != 0)
106 BI->setSuccessor(i, NewTarget);
112 for (
size_t i = 0; i <
SI->getNumSuccessors(); i++) {
113 if (ToReplace.
count(
SI->getSuccessor(i)) != 0)
114 SI->setSuccessor(i, NewTarget);
119 assert(
false &&
"Unhandled terminator type.");
122 AllocaInst *CreateVariable(Function &
F,
Type *
Type,
124 const DataLayout &
DL =
F.getDataLayout();
125 return new AllocaInst(
Type,
DL.getAllocaAddrSpace(),
nullptr,
"reg",
131 bool runOnConvergenceRegionNoRecurse(LoopInfo &LI,
132 SPIRV::ConvergenceRegion *CR) {
134 SmallPtrSet<BasicBlock *, 4> ExitTargets;
135 for (BasicBlock *Exit : CR->
Exits) {
136 for (BasicBlock *Target : gatherSuccessors(Exit)) {
138 ExitTargets.
insert(Target);
143 if (ExitTargets.
size() <= 1)
151 AllocaInst *
Variable = CreateVariable(*
F, Builder.getInt32Ty(),
152 F->begin()->getFirstInsertionPt());
157 std::vector<BasicBlock *> SortedExitTargets;
158 std::vector<BasicBlock *> SortedExits;
159 for (BasicBlock &BB : *
F) {
160 if (ExitTargets.
count(&BB) != 0)
161 SortedExitTargets.push_back(&BB);
162 if (CR->
Exits.count(&BB) != 0)
163 SortedExits.push_back(&BB);
168 DenseMap<BasicBlock *, ConstantInt *> TargetToValue;
169 for (BasicBlock *Target : SortedExitTargets)
171 std::make_pair(Target, Builder.getInt32(TargetToValue.
size())));
175 std::vector<std::pair<BasicBlock *, Value *>> ExitToVariable;
176 for (
auto Exit : SortedExits) {
179 B2.SetInsertPoint(
Exit->getFirstInsertionPt());
180 B2.CreateStore(
Value, Variable);
181 ExitToVariable.emplace_back(std::make_pair(Exit,
Value));
184 llvm::Value *
Load = Builder.CreateLoad(Builder.getInt32Ty(), Variable);
187 llvm::SwitchInst *Sw = Builder.CreateSwitch(Load, SortedExitTargets[0],
188 SortedExitTargets.size() - 1);
189 for (
size_t i = 1; i < SortedExitTargets.size(); i++) {
191 Sw->
addCase(TargetToValue[BB], BB);
195 for (
auto Exit : CR->
Exits)
210 bool runOnConvergenceRegion(LoopInfo &LI, SPIRV::ConvergenceRegion *CR) {
212 if (runOnConvergenceRegion(LI, Child))
215 return runOnConvergenceRegionNoRecurse(LI, CR);
221 void validateRegionExits(
const SPIRV::ConvergenceRegion *CR) {
223 validateRegionExits(Child);
225 std::unordered_set<BasicBlock *> ExitTargets;
226 for (
auto *Exit : CR->
Exits) {
227 auto Set = gatherSuccessors(Exit);
228 for (
auto *BB : Set) {
230 ExitTargets.insert(BB);
234 assert(ExitTargets.size() <= 1);
239 LoopInfo &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
240 auto *TopLevelRegion =
241 getAnalysis<SPIRVConvergenceRegionAnalysisWrapperPass>()
243 .getWritableTopLevelRegion();
249 bool modified =
false;
250 while (runOnConvergenceRegion(LI, TopLevelRegion)) {
254#if !defined(NDEBUG) || defined(EXPENSIVE_CHECKS)
255 validateRegionExits(TopLevelRegion);
260 void getAnalysisUsage(AnalysisUsage &AU)
const override {
263 AU.
addRequired<SPIRVConvergenceRegionAnalysisWrapperPass>();
265 AU.
addPreserved<SPIRVConvergenceRegionAnalysisWrapperPass>();
266 FunctionPass::getAnalysisUsage(AU);
271char SPIRVMergeRegionExitTargets::ID = 0;
274 "SPIRV split region exit blocks",
false,
false)
284 return new SPIRVMergeRegionExitTargets();
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file defines the DenseMap class.
static bool runOnFunction(Function &F, bool PostInlining)
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
static void replaceBranchTargets(BasicBlock *BB, BasicBlock *OldTarget, BasicBlock *NewTarget)
This file defines the SmallPtrSet class.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
const Function * getParent() const
Return the enclosing method, or null if none.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
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...
ValueT lookup(const_arg_type_t< KeyT > Val) const
lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Legacy analysis pass which computes a DominatorTree.
FunctionPass class - This class is used to implement most global optimizations.
The legacy pass manager's analysis pass to compute loop information.
SmallVector< ConvergenceRegion * > Children
SmallPtrSet< BasicBlock *, 2 > Exits
ConvergenceRegion * Parent
SmallPtrSet< BasicBlock *, 8 > Blocks
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
LLVM_ABI void addCase(ConstantInt *OnVal, BasicBlock *Dest)
Add an entry to the switch instruction.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ BasicBlock
Various leaf nodes.
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
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...
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
FunctionPass * createSPIRVMergeRegionExitTargetsPass()