43 std::unordered_set<BasicBlock *> gatherSuccessors(
BasicBlock *BB) {
44 std::unordered_set<BasicBlock *> output;
47 if (
auto *BI = dyn_cast<BranchInst>(
T)) {
48 output.insert(BI->getSuccessor(0));
49 if (BI->isConditional())
50 output.insert(BI->getSuccessor(1));
54 if (
auto *SI = dyn_cast<SwitchInst>(
T)) {
55 output.insert(
SI->getDefaultDest());
56 for (
auto &Case :
SI->cases())
57 output.insert(Case.getCaseSuccessor());
61 assert(isa<ReturnInst>(
T) &&
"Unhandled terminator type.");
71 if (isa<ReturnInst>(
T))
75 Builder.SetInsertPoint(
T);
77 if (
auto *BI = dyn_cast<BranchInst>(
T)) {
81 BI->isConditional() ? BI->getSuccessor(1) :
nullptr;
86 if (LHS ==
nullptr || RHS ==
nullptr)
88 return Builder.CreateSelect(BI->getCondition(), LHS, RHS);
100 if (isa<ReturnInst>(
T))
103 if (
auto *BI = dyn_cast<BranchInst>(
T)) {
104 for (
size_t i = 0; i < BI->getNumSuccessors(); i++) {
105 if (ToReplace.
count(BI->getSuccessor(i)) != 0)
111 if (
auto *SI = dyn_cast<SwitchInst>(
T)) {
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.");
131 bool runOnConvergenceRegionNoRecurse(
LoopInfo &LI,
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;
160 if (ExitTargets.
count(&BB) != 0)
161 SortedExitTargets.push_back(&BB);
162 if (CR->
Exits.count(&BB) != 0)
163 SortedExits.push_back(&BB);
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);
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)
200 CR->
Blocks.insert(NewExitTarget);
212 if (runOnConvergenceRegion(LI, Child))
215 return runOnConvergenceRegionNoRecurse(LI, 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) {
229 if (CR->
Blocks.count(BB) == 0)
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);
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.
#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.
an instruction to allocate memory on the stack
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
LLVM Basic Block Representation.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
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...
A parsed version of the target data layout string in and methods for querying it.
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.
virtual bool runOnFunction(Function &F)=0
runOnFunction - Virtual method overriden by subclasses to do the per-function processing of the pass.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
LLVM_ABI void setSuccessor(unsigned Idx, BasicBlock *BB)
Update the specified successor to point at the provided block.
The legacy pass manager's analysis pass to compute loop information.
virtual void getAnalysisUsage(AnalysisUsage &) const
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
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.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
LLVM_ABI void addCase(ConstantInt *OnVal, BasicBlock *Dest)
Add an entry to the switch instruction.
Target - Wrapper for Target specific information.
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM Value Representation.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
This is an optimization pass for GlobalISel generic memory operations.
FunctionPass * createSPIRVMergeRegionExitTargetsPass()