[llvm] [SimplifyCFG] Speculatively execute empty BBs with multiple predecessors (PR #120905)
Antonio Frighetto via llvm-commits
llvm-commits at lists.llvm.org
Mon Dec 23 06:41:12 PST 2024
================
@@ -3506,6 +3506,96 @@ bool SimplifyCFGOpt::speculativelyExecuteBB(BranchInst *BI,
return true;
}
+/// Speculate a conditional basic block flattening the CFG.
+/// Compared to speculativelyExecuteBB, it allows \p ThenBB to have multiple
+/// predecessors other than the current BB. An illustration of this transform is
+/// turning this IR:
+/// \code
+/// BB:
+/// %cmp = icmp ult %x, %y
+/// br i1 %cmp, label %EndBB, label %ThenBB
+/// ThenBB:
+/// br label BB2
+/// EndBB:
+/// %phi = phi i1 [ true, %ThenBB ], [ false, %BB ], [ false, %OtherBB ]
+/// ...
+/// \endcode
+///
+/// Into this IR:
+/// \code
+/// BB:
+/// %cmp = icmp ult %x, %y
+/// %sel = select i1 %cmp, i1 true, i1 false
+/// br label %EndBB
+/// ThenBB:
+/// br label BB2
+/// EndBB:
+/// %phi = phi i1 [ %sel, %ThenBB ], [ false, %BB ], [ false, %OtherBB ]
+/// ...
+/// \endcode
+/// \returns true if the branch edge is removed.
+static bool speculativelyExecuteEmptyBB(BranchInst *BI, bool Invert,
+ DomTreeUpdater *DTU,
+ const TargetTransformInfo &TTI) {
+ BasicBlock *BB = BI->getParent();
+ BasicBlock *ThenBB = BI->getSuccessor(Invert);
+ BasicBlock *EndBB = BI->getSuccessor(!Invert);
+
+ BranchInst *SuccBI = dyn_cast<BranchInst>(ThenBB->getTerminator());
+ if (!SuccBI || !SuccBI->isUnconditional() || SuccBI->getSuccessor(0) != EndBB)
+ return false;
+ if (&ThenBB->front() != SuccBI)
+ return false;
+ if (!isProfitableToSpeculate(BI, Invert, TTI))
+ return false;
+
+ InstructionCost Budget =
+ PHINodeFoldingThreshold * TargetTransformInfo::TCC_Basic;
+ InstructionCost Cost = 0;
+ unsigned SpeculatedInstructions = 0;
+ if (!validateAndCostRequiredSelects(BB, ThenBB, EndBB, SpeculatedInstructions,
+ Cost, TTI) ||
+ Cost > Budget)
+ return false;
+
+ LLVM_DEBUG(dbgs() << "SPECULATIVELY EXECUTING BB" << *ThenBB << "\n";);
+
+ // Insert selects and rewrite the PHI operands.
+ Value *BrCond = BI->getCondition();
+ IRBuilder<NoFolder> Builder(BI);
+ for (PHINode &PN : EndBB->phis()) {
+ unsigned OrigI = PN.getBasicBlockIndex(BB);
+ unsigned ThenI = PN.getBasicBlockIndex(ThenBB);
+ Value *OrigV = PN.getIncomingValue(OrigI);
+ Value *ThenV = PN.getIncomingValue(ThenI);
+
+ // Skip PHIs which are trivial.
+ if (OrigV == ThenV)
+ continue;
+
+ // Create a select whose true value is the speculatively executed value and
+ // false value is the pre-existing value. Swap them if the branch
+ // destinations were inverted.
+ Value *TrueV = ThenV, *FalseV = OrigV;
+ if (Invert)
+ std::swap(TrueV, FalseV);
+ Value *V = Builder.CreateSelect(BrCond, TrueV, FalseV, "spec.select", BI);
+ PN.setIncomingValue(OrigI, V);
----------------
antoniofrighetto wrote:
`ThenI` not set to the select on purpose?
https://github.com/llvm/llvm-project/pull/120905
More information about the llvm-commits
mailing list