[llvm] [EarlyIfConversion] Extend data dependent analysis across multiple blocks (PR #180623)

Jonathan Cohen via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 4 12:53:50 PDT 2026


================
@@ -923,15 +932,62 @@ static bool isConstantPoolLoad(const MachineInstr *MI) {
          });
 }
 
-/// Check if there are any calls in the range (From, To].
-static bool callInRange(const MachineInstr *From, const MachineInstr *To) {
-  constexpr int MaxInstructionsToCheck = 64;
-  int Count = 0;
-  auto InstrRange =
-      make_range(std::next(From->getIterator()), To->getIterator());
-  return any_of(InstrRange, [&](const MachineInstr &MI) {
-    return ++Count > MaxInstructionsToCheck || MI.isCall();
-  });
+/// Check if there are any calls in the path from From to To, potentially
+/// spanning multiple basic blocks. The IntermediateBlocks set contains
+/// blocks that are between From's block and To's block in the control flow.
+///
+/// Checks:
+/// - If same block: (From, To)
+/// - If different blocks:
+///   - (From, end of From's block]
+///   - All instructions in IntermediateBlocks
+///   - [start of To's block, To)
+///
+/// Returns true if a call is found or if the path exceeds MaxInstructions.
+/// Uses NoCallBlocksCache to skip blocks already verified to have no calls.
+bool EarlyIfConverter::callInPath(
+    const MachineInstr *From, const MachineInstr *To,
+    const SmallPtrSetImpl<const MachineBasicBlock *> &IntermediateBlocks,
+    unsigned MaxInstructions /* = 64 */) {
+  if (From == To)
+    return false;
+
+  unsigned Count = 0;
+  const MachineBasicBlock *FromBB = From->getParent();
+  const MachineBasicBlock *ToBB = To->getParent();
+
+  // Helper to check if instruction limit exceeded or call found.
+  auto CheckInstrIsCall = [&](const MachineInstr &MI) {
+    return ++Count > MaxInstructions || MI.isCall();
+  };
+
+  // If From and To are in the same block, just check (From, To).
+  if (FromBB == ToBB)
+    return llvm::any_of(
+        llvm::make_range(std::next(From->getIterator()), To->getIterator()),
+        CheckInstrIsCall);
+
+  // Check (From, end of From's block].
+  if (any_of(
+          llvm::make_range(std::next(From->getIterator()), FromBB->instr_end()),
+          CheckInstrIsCall))
+    return true;
+
+  // Check all intermediate blocks entirely.
+  // Use cache to skip blocks already verified to have no calls.
+  for (const MachineBasicBlock *BB : IntermediateBlocks) {
+    if (BB == FromBB || BB == ToBB)
+      continue;
+    if (NoCallBlocksCache.contains(BB))
+      continue;
+    if (any_of(*BB, CheckInstrIsCall))
+      return true;
+    NoCallBlocksCache.insert(BB);
----------------
jcohen-apple wrote:

Fixed, thanks

https://github.com/llvm/llvm-project/pull/180623


More information about the llvm-commits mailing list