[llvm] [EarlyIfConversion] Extend data dependent analysis across multiple blocks (PR #180623)
Nathan Corbyn via llvm-commits
llvm-commits at lists.llvm.org
Wed Aug 5 03:07:00 PDT 2026
================
@@ -925,31 +939,126 @@ 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 a call can be executed between From (where a value is loaded) and
+/// To (the condition). This is done by first scanning the instructions within
+/// From and To MBBs. If no call is found, we then scan all blocks which are
+/// dominated by From (the load) and can reach To (the condition).
+bool EarlyIfConverter::callInRange(const MachineInstr *From,
+ const MachineInstr *To) {
+ if (From == To)
+ return false;
+
+ assert(DomTree->dominates(From, To) && "From is expected to dominate To");
+
+ const MachineBasicBlock *FromBB = From->getParent();
+ const MachineBasicBlock *ToBB = To->getParent();
+
+ unsigned NumScanned = 0;
+ auto UpdateSearchCount = [](unsigned &NumScanned, unsigned N) {
+ NumScanned += N;
+ if (NumScanned <= MaxRegionInstrs)
+ return false;
+ LLVM_DEBUG(dbgs() << " callInRange scanned more than " << MaxRegionInstrs
+ << " instructions\n");
+ return true;
+ };
+ auto IsCallOrHitSearchLimit = [&UpdateSearchCount](const MachineInstr &MI,
+ unsigned &NumScanned) {
+ if (UpdateSearchCount(NumScanned, 1))
+ return true;
+ if (!MI.isCall())
+ return false;
+ LLVM_DEBUG(dbgs() << " found a call before the condition: " << MI);
+ return true;
+ };
+
+ // If From and To are in the same block, just check (From, To).
+ if (FromBB == ToBB) {
+ for (const MachineInstr &MI :
+ make_range(std::next(From->getIterator()), To->getIterator()))
+ if (IsCallOrHitSearchLimit(MI, NumScanned))
+ return true;
+ return false;
+ }
+
+ // Check (From, end of From's block] and [start of To's block, To).
+ for (const MachineInstr &MI :
+ make_range(std::next(From->getIterator()), FromBB->instr_end()))
+ if (IsCallOrHitSearchLimit(MI, NumScanned))
+ return true;
+ for (const MachineInstr &MI :
+ make_range(ToBB->instr_begin(), To->getIterator()))
+ if (IsCallOrHitSearchLimit(MI, NumScanned))
+ return true;
+
+ // Enqueued guards the traversal: the endpoint blocks are traversed through
+ // but their instructions were already handled above.
+ SmallPtrSet<const MachineBasicBlock *, 16> Enqueued = {ToBB};
+ SmallVector<const MachineBasicBlock *, 16> Worklist;
+ auto Enqueue = [&](const MachineBasicBlock *BB) {
+ if (Enqueued.insert(BB).second)
+ Worklist.push_back(BB);
+ };
+
+ for (const MachineBasicBlock *Pred : ToBB->predecessors())
+ Enqueue(Pred);
+
+ while (!Worklist.empty()) {
+ // Count every block we visit towards the limit, even if
+ // this block is not dominated by From. On very wide CFG's this could
+ // potentially cause us to miss cases where the load is very close to the
+ // condition in terms of maximum instructions, but because we walk many
+ // short predecessor basic blocks we will bail out of the scan before
+ // hitting it.
+ if (UpdateSearchCount(NumScanned, 1))
+ return true;
+ const MachineBasicBlock *BB = Worklist.pop_back_val();
+
+ if (BB != FromBB && DomTree->dominates(FromBB, BB)) {
+ auto [CacheIt, Inserted] = NoCallBlocksCache.try_emplace(BB, 0);
+ if (Inserted) {
+ if (UpdateSearchCount(NumScanned, BB->size()) ||
+ any_of(*BB, [](const MachineInstr &MI) { return MI.isCall(); })) {
+ NoCallBlocksCache.erase(BB);
+ return true;
+ }
+ CacheIt->second = BB->size();
+ } else {
+ if (UpdateSearchCount(NumScanned, CacheIt->second))
+ return true;
+ }
+ }
+
+ for (const MachineBasicBlock *Pred : BB->predecessors())
+ Enqueue(Pred);
----------------
cofibrant wrote:
Don't we only want to enqueue the predecessors that `From` dominates?
https://github.com/llvm/llvm-project/pull/180623
More information about the llvm-commits
mailing list