[llvm] b0d35cf - [SSAUpdater] Avoid scanning basic blocks to find instruction order. (#123803)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Jan 22 08:11:45 PST 2025
Author: Joshua Cranmer
Date: 2025-01-22T11:11:41-05:00
New Revision: b0d35cf22e15be5c62835d689f3c7e301d9f22cd
URL: https://github.com/llvm/llvm-project/commit/b0d35cf22e15be5c62835d689f3c7e301d9f22cd
DIFF: https://github.com/llvm/llvm-project/commit/b0d35cf22e15be5c62835d689f3c7e301d9f22cd.diff
LOG: [SSAUpdater] Avoid scanning basic blocks to find instruction order. (#123803)
This fixes a compile-time regression caused by #116645, where an entry
basic block with a very large number of allocas and other instructions
caused SROA to take ~100× its expected runtime, as every alloca (with ~2
uses) now calls this method to find the order of those few instructions,
rescanning the very large basic block every single time.
Since this code was originally written, Instructions now have ordering
numbers available to determine relative order without unnecessarily
scanning the basic block.
Added:
Modified:
llvm/include/llvm/Transforms/Utils/SSAUpdater.h
llvm/lib/Transforms/Utils/SSAUpdater.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/Transforms/Utils/SSAUpdater.h b/llvm/include/llvm/Transforms/Utils/SSAUpdater.h
index 989cf0b2d0e7b4..4e5da81a7e8851 100644
--- a/llvm/include/llvm/Transforms/Utils/SSAUpdater.h
+++ b/llvm/include/llvm/Transforms/Utils/SSAUpdater.h
@@ -164,13 +164,6 @@ class LoadAndStorePromoter {
/// removed from the code.
void run(const SmallVectorImpl<Instruction *> &Insts);
- /// Return true if the specified instruction is in the Inst list.
- ///
- /// The Insts list is the one passed into the constructor. Clients should
- /// implement this with a more efficient version if possible.
- virtual bool isInstInList(Instruction *I,
- const SmallVectorImpl<Instruction *> &Insts) const;
-
/// This hook is invoked after all the stores are found and inserted as
/// available values.
virtual void doExtraRewritesBeforeFinalDeletion() {}
diff --git a/llvm/lib/Transforms/Utils/SSAUpdater.cpp b/llvm/lib/Transforms/Utils/SSAUpdater.cpp
index 4bf4acd6330f58..229b1d9f07f8c7 100644
--- a/llvm/lib/Transforms/Utils/SSAUpdater.cpp
+++ b/llvm/lib/Transforms/Utils/SSAUpdater.cpp
@@ -432,9 +432,7 @@ void LoadAndStorePromoter::run(const SmallVectorImpl<Instruction *> &Insts) {
}
}
- // If so, we can queue them all as live in loads. We don't have an
- // efficient way to tell which on is first in the block and don't want to
- // scan large blocks, so just add all loads as live ins.
+ // If so, we can queue them all as live in loads.
if (!HasStore) {
for (Instruction *I : BlockUses)
LiveInLoads.push_back(cast<LoadInst>(I));
@@ -442,17 +440,20 @@ void LoadAndStorePromoter::run(const SmallVectorImpl<Instruction *> &Insts) {
continue;
}
+ // Sort all of the interesting instructions in the block so that we don't
+ // have to scan a large block just to find a few instructions.
+ llvm::sort(
+ BlockUses.begin(), BlockUses.end(),
+ [](Instruction *A, Instruction *B) { return A->comesBefore(B); });
+
// Otherwise, we have mixed loads and stores (or just a bunch of stores).
// Since SSAUpdater is purely for cross-block values, we need to determine
// the order of these instructions in the block. If the first use in the
// block is a load, then it uses the live in value. The last store defines
- // the live out value. We handle this by doing a linear scan of the block.
+ // the live out value.
Value *StoredValue = nullptr;
- for (Instruction &I : *BB) {
- if (LoadInst *L = dyn_cast<LoadInst>(&I)) {
- // If this is a load from an unrelated pointer, ignore it.
- if (!isInstInList(L, Insts)) continue;
-
+ for (Instruction *I : BlockUses) {
+ if (LoadInst *L = dyn_cast<LoadInst>(I)) {
// If we haven't seen a store yet, this is a live in use, otherwise
// use the stored value.
if (StoredValue) {
@@ -465,18 +466,14 @@ void LoadAndStorePromoter::run(const SmallVectorImpl<Instruction *> &Insts) {
continue;
}
- if (StoreInst *SI = dyn_cast<StoreInst>(&I)) {
- // If this is a store to an unrelated pointer, ignore it.
- if (!isInstInList(SI, Insts)) continue;
+ if (StoreInst *SI = dyn_cast<StoreInst>(I)) {
updateDebugInfo(SI);
// Remember that this is the active value in the block.
StoredValue = SI->getOperand(0);
- } else if (auto *AI = dyn_cast<AllocaInst>(&I)) {
+ } else if (auto *AI = dyn_cast<AllocaInst>(I)) {
// Check if this an alloca, in which case we treat it as a store of
// getValueToUseForAlloca.
- if (!isInstInList(AI, Insts))
- continue;
StoredValue = getValueToUseForAlloca(AI);
}
}
@@ -533,10 +530,3 @@ void LoadAndStorePromoter::run(const SmallVectorImpl<Instruction *> &Insts) {
User->eraseFromParent();
}
}
-
-bool
-LoadAndStorePromoter::isInstInList(Instruction *I,
- const SmallVectorImpl<Instruction *> &Insts)
- const {
- return is_contained(Insts, I);
-}
More information about the llvm-commits
mailing list