22#define DEBUG_TYPE "control-flow-hub"
38 "Only support branch terminator.");
40 auto *Condition = Branch->isConditional() ? Branch->getCondition() :
nullptr;
44 if (Branch->isUnconditional()) {
45 assert(Succ0 == Branch->getSuccessor(0));
47 Branch->setSuccessor(0, FirstGuardBlock);
49 assert(!Succ1 || Succ1 == Branch->getSuccessor(1));
50 if (Succ0 && !Succ1) {
51 Branch->setSuccessor(0, FirstGuardBlock);
52 }
else if (Succ1 && !Succ0) {
53 Branch->setSuccessor(1, FirstGuardBlock);
55 Branch->eraseFromParent();
74 for (
int E = GuardBlocks.
size() - 1;
I != E; ++
I) {
97 for (
auto [BB, Succ0, Succ1] : Branches) {
99 Value *IncomingId =
nullptr;
100 if (Succ0 && Succ1) {
101 auto Succ0Iter =
find(Outgoing, Succ0);
102 auto Succ1Iter =
find(Outgoing, Succ1);
104 ConstantInt::get(Int32Ty, std::distance(Outgoing.
begin(), Succ0Iter));
106 ConstantInt::get(Int32Ty, std::distance(Outgoing.
begin(), Succ1Iter));
108 BB->getTerminator()->getIterator());
111 auto SuccIter = Succ0 ?
find(Outgoing, Succ0) :
find(Outgoing, Succ1);
113 ConstantInt::get(Int32Ty, std::distance(Outgoing.
begin(), SuccIter));
115 Phi->addIncoming(IncomingId, BB);
118 for (
int I = 0, E = Outgoing.
size() - 1;
I != E; ++
I) {
122 auto *Cmp = ICmpInst::Create(Instruction::ICmp, ICmpInst::ICMP_EQ, Phi,
123 ConstantInt::get(Int32Ty,
I),
124 Out->
getName() +
".predicate", GuardBlocks[
I]);
125 GuardPredicates[Out] = Cmp;
142 for (
int I = 0, E = Outgoing.
size() - 1;
I != E; ++
I) {
150 GuardPredicates[Out] = Phi;
153 for (
auto [BB, Succ0, Succ1] : Branches) {
163 bool OneSuccessorDone =
false;
164 for (
int I = 0, E = Outgoing.
size() - 1;
I != E; ++
I) {
166 PHINode *Phi = cast<PHINode>(GuardPredicates[Out]);
167 if (Out != Succ0 && Out != Succ1) {
168 Phi->addIncoming(BoolFalse, BB);
169 }
else if (!Succ0 || !Succ1 || OneSuccessorDone) {
172 Phi->addIncoming(BoolTrue, BB);
176 Phi->addIncoming(Condition, BB);
180 Phi->addIncoming(Inverted, BB);
182 OneSuccessorDone =
true;
206 std::optional<unsigned> MaxControlFlowBooleans) {
210 for (
int I = 0, E = Outgoing.
size() - 1;
I != E; ++
I)
219 if (!MaxControlFlowBooleans || Outgoing.
size() <= *MaxControlFlowBooleans)
241 while (
I != Out->
end() && isa<PHINode>(
I)) {
242 auto *Phi = cast<PHINode>(
I);
245 Phi->getName() +
".moved", FirstGuardBlock->
begin());
246 bool AllUndef =
true;
247 for (
auto [BB, Succ0, Succ1] :
Incoming) {
251 }
else if (Phi->getBasicBlockIndex(BB) != -1) {
252 V = Phi->removeIncomingValue(BB,
false);
253 AllUndef &= isa<UndefValue>(V);
255 NewPhi->addIncoming(V, BB);
258 Value *NewV = NewPhi;
260 NewPhi->eraseFromParent();
263 if (Phi->getNumOperands() == 0) {
264 Phi->replaceAllUsesWith(NewV);
265 I = Phi->eraseFromParent();
268 Phi->addIncoming(NewV, GuardBlock);
275 const StringRef Prefix, std::optional<unsigned> MaxControlFlowBooleans) {
281 for (
auto [BB, Succ0, Succ1] :
Branches) {
283 assert(
Incoming.insert(BB).second &&
"Duplicate entry for incoming block.");
291 if (Outgoing.
size() < 2)
292 return Outgoing.
front();
296 for (
auto [BB, Succ0, Succ1] :
Branches) {
306 DeletionCandidates, Prefix, MaxControlFlowBooleans);
310 for (
int I = 0, E = GuardBlocks.
size();
I != E; ++
I)
316 int NumGuards = GuardBlocks.
size();
318 for (
auto [BB, Succ0, Succ1] :
Branches)
321 for (
int I = 0;
I != NumGuards - 1; ++
I) {
329 Outgoing[NumGuards - 1]});
331 Outgoing[NumGuards]});
335 for (
auto I : DeletionCandidates) {
337 if (
auto *Inst = dyn_cast_or_null<Instruction>(
I))
338 Inst->eraseFromParent();
341 return FirstGuardBlock;
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static void calcPredicateUsingBooleans(ArrayRef< EdgeDescriptor > Branches, ArrayRef< BasicBlock * > Outgoing, SmallVectorImpl< BasicBlock * > &GuardBlocks, BBPredicates &GuardPredicates, SmallVectorImpl< WeakVH > &DeletionCandidates)
static void setupBranchForGuard(ArrayRef< BasicBlock * > GuardBlocks, ArrayRef< BasicBlock * > Outgoing, BBPredicates &GuardPredicates)
static void reconnectPhis(BasicBlock *Out, BasicBlock *GuardBlock, ArrayRef< EdgeDescriptor > Incoming, BasicBlock *FirstGuardBlock)
static void calcPredicateUsingInteger(ArrayRef< EdgeDescriptor > Branches, ArrayRef< BasicBlock * > Outgoing, ArrayRef< BasicBlock * > GuardBlocks, BBPredicates &GuardPredicates)
static Value * redirectToHub(BasicBlock *BB, BasicBlock *Succ0, BasicBlock *Succ1, BasicBlock *FirstGuardBlock)
static void convertToGuardPredicates(ArrayRef< EdgeDescriptor > Branches, ArrayRef< BasicBlock * > Outgoing, SmallVectorImpl< BasicBlock * > &GuardBlocks, SmallVectorImpl< WeakVH > &DeletionCandidates, const StringRef Prefix, std::optional< unsigned > MaxControlFlowBooleans)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file implements a set that has insertion order iteration characteristics.
This file defines the SmallSet class.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
const T & front() const
front - Get the first element.
size_t size() const
size - Get the array size.
LLVM Basic Block Representation.
iterator begin()
Instruction iterator methods.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
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...
static BranchInst * Create(BasicBlock *IfTrue, InsertPosition InsertBefore=nullptr)
static ConstantInt * getTrue(LLVMContext &Context)
static ConstantInt * getFalse(LLVMContext &Context)
static constexpr UpdateKind Delete
static constexpr UpdateKind Insert
void applyUpdates(ArrayRef< UpdateT > Updates)
Submit updates to all available trees.
This is an important class for using LLVM in a threaded context.
static PHINode * Create(Type *Ty, unsigned NumReservedValues, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
Constructors - NumReservedValues is a hint for the number of incoming edges that this phi node will h...
static PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
static SelectInst * Create(Value *C, Value *S1, Value *S2, const Twine &NameStr="", InsertPosition InsertBefore=nullptr, Instruction *MDFrom=nullptr)
A vector that has set insertion semantics.
ArrayRef< value_type > getArrayRef() const
size_type size() const
Determine the number of elements in the SetVector.
const value_type & front() const
Return the first element of the SetVector.
const value_type & back() const
Return the last element of the SetVector.
bool insert(const value_type &X)
Insert a new element into the SetVector.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
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.
The instances of the Type class are immutable: once they are created, they are never changed.
static IntegerType * getInt1Ty(LLVMContext &C)
static IntegerType * getInt32Ty(LLVMContext &C)
LLVM Value Representation.
StringRef getName() const
Return a constant reference to the value's name.
This is an optimization pass for GlobalISel generic memory operations.
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Value * invertCondition(Value *Condition)
Invert the given true/false value, possibly reusing an existing copy.
BasicBlock * finalize(DomTreeUpdater *DTU, SmallVectorImpl< BasicBlock * > &GuardBlocks, const StringRef Prefix, std::optional< unsigned > MaxControlFlowBooleans=std::nullopt)
SmallVector< BranchDescriptor > Branches
Incoming for lane maks phi as machine instruction, incoming register Reg and incoming block Block are...