[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