23#define DEBUG_TYPE "control-flow-hub"
39 assert(Succ0 == Branch->getSuccessor(0));
41 Branch->setSuccessor(FirstGuardBlock);
46 auto *Condition = Branch->getCondition();
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();
75 for (
int E = GuardBlocks.
size() - 1;
I !=
E; ++
I) {
100 for (
auto [BB, Succ0, Succ1] : Branches) {
102 Value *IncomingId =
nullptr;
103 if (Succ0 && Succ1 && Succ0 != Succ1) {
104 auto Succ0Iter =
find(Outgoing, Succ0);
105 auto Succ1Iter =
find(Outgoing, Succ1);
107 ConstantInt::get(Int32Ty, std::distance(Outgoing.
begin(), Succ0Iter));
109 ConstantInt::get(Int32Ty, std::distance(Outgoing.
begin(), Succ1Iter));
111 BB->getTerminator()->getIterator());
115 auto SuccIter = Succ0 ?
find(Outgoing, Succ0) :
find(Outgoing, Succ1);
117 ConstantInt::get(Int32Ty, std::distance(Outgoing.
begin(), SuccIter));
119 Phi->addIncoming(IncomingId, BB);
122 for (
int I = 0,
E = Outgoing.
size() - 1;
I !=
E; ++
I) {
124 LLVM_DEBUG(
dbgs() <<
"Creating integer guard for " << Out->getName()
127 ConstantInt::get(Int32Ty,
I),
128 Out->getName() +
".predicate", GuardBlocks[
I]);
129 GuardPredicates[Out] = Cmp;
146 for (
int I = 0,
E = Outgoing.
size() - 1;
I !=
E; ++
I) {
148 LLVM_DEBUG(
dbgs() <<
"Creating boolean guard for " << Out->getName()
153 StringRef(
"Guard.") + Out->getName(), FirstGuardBlock);
154 GuardPredicates[Out] = Phi;
157 for (
auto [BB, Succ0, Succ1] : Branches) {
167 bool OneSuccessorDone =
false;
168 for (
int I = 0,
E = Outgoing.
size() - 1;
I !=
E; ++
I) {
171 if (Out != Succ0 && Out != Succ1) {
172 Phi->addIncoming(BoolFalse, BB);
173 }
else if (!Succ0 || !Succ1 || Succ0 == Succ1 || OneSuccessorDone) {
177 Phi->addIncoming(BoolTrue, BB);
181 Phi->addIncoming(Condition, BB);
185 Phi->addIncoming(Inverted, BB);
187 OneSuccessorDone =
true;
211 std::optional<unsigned> MaxControlFlowBooleans) {
215 for (
int I = 0,
E = Outgoing.
size() - 1;
I !=
E; ++
I)
224 if (!MaxControlFlowBooleans || Outgoing.
size() <= *MaxControlFlowBooleans)
247 auto I = Out->begin();
252 Phi->getName() +
".moved", FirstGuardBlock->
begin());
253 bool AllUndef =
true;
254 bool AllPoison =
true;
255 for (
auto [BB, Succ0, Succ1] : Incoming) {
259 if ((Succ0 == Out || Succ1 == Out) && Phi->getBasicBlockIndex(BB) != -1) {
260 V = Phi->removeIncomingValue(BB,
false);
263 if (Succ0 && Succ1 && Succ0 == Succ1 &&
264 Phi->getBasicBlockIndex(BB) != -1)
265 Phi->removeIncomingValue(BB,
false);
270 NewPhi->addIncoming(
V, BB);
272 assert(NewPhi->getNumIncomingValues() == Incoming.size());
273 Value *NewV = NewPhi;
278 NewPhi->eraseFromParent();
282 if (Phi->getNumOperands() == 0) {
283 Phi->replaceAllUsesWith(NewV);
284 I = Phi->eraseFromParent();
287 Phi->addIncoming(NewV, GuardBlock);
294 const StringRef Prefix, std::optional<unsigned> MaxControlFlowBooleans) {
300 for (
auto [BB, Succ0, Succ1] :
Branches) {
304 "Duplicate entry for incoming block.");
312 assert(Outgoing.
size() &&
"No outgoing edges");
314 if (Outgoing.
size() < 2)
315 return {Outgoing.
front(),
false};
319 for (
auto [BB, Succ0, Succ1] :
Branches) {
323 if (Succ1 && Succ1 != Succ0)
330 DeletionCandidates, Prefix, MaxControlFlowBooleans);
334 for (
int I = 0, E = GuardBlocks.
size();
I != E; ++
I)
340 int NumGuards = GuardBlocks.
size();
342 for (
auto [BB, Succ0, Succ1] :
Branches)
345 for (
int I = 0;
I != NumGuards - 1; ++
I) {
353 Outgoing[NumGuards - 1]});
355 Outgoing[NumGuards]});
359 for (
auto &
I : DeletionCandidates) {
361 if (Inst->use_empty())
362 Inst->eraseFromParent();
366 return {FirstGuardBlock,
true};
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
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)
DenseMap< BasicBlock *, Instruction * > BBPredicates
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)
ControlFlowHub::BranchDescriptor EdgeDescriptor
This file contains the declarations for profiling metadata utility functions.
This file implements a set that has insertion order iteration characteristics.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
const T & front() const
Get the first element.
size_t size() const
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; assumes that the block is well-formed.
static LLVM_ABI CmpInst * Create(OtherOps Op, Predicate Pred, Value *S1, Value *S2, const Twine &Name="", InsertPosition InsertBefore=nullptr)
Construct a compare instruction, given the opcode, the predicate and the two operands.
static CondBrInst * Create(Value *Cond, BasicBlock *IfTrue, BasicBlock *IfFalse, InsertPosition InsertBefore=nullptr)
static LLVM_ABI ConstantInt * getTrue(LLVMContext &Context)
static LLVM_ABI 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 LLVM_ABI 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, const 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.
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.
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.
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 LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
static LLVM_ABI IntegerType * getInt1Ty(LLVMContext &C)
static UncondBrInst * Create(BasicBlock *Target, InsertPosition InsertBefore=nullptr)
static LLVM_ABI UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
LLVM Value Representation.
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.
LLVM_ABI void setExplicitlyUnknownBranchWeightsIfProfiled(Instruction &I, StringRef PassName, const Function *F=nullptr)
Like setExplicitlyUnknownBranchWeights(...), but only sets unknown branch weights in the new instruct...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
auto dyn_cast_if_present(const Y &Val)
dyn_cast_if_present<X> - Functionally identical to dyn_cast, except that a null (or none in the case ...
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.
LLVM_ABI Value * invertCondition(Value *Condition)
Invert the given true/false value, possibly reusing an existing copy.
LLVM_ABI std::pair< BasicBlock *, bool > finalize(DomTreeUpdater *DTU, SmallVectorImpl< BasicBlock * > &GuardBlocks, const StringRef Prefix, std::optional< unsigned > MaxControlFlowBooleans=std::nullopt)
Return the unified loop exit block and a flag indicating if the CFG was changed at all.
SmallVector< BranchDescriptor > Branches