Skip to content

Commit 7829c33

Browse files
committed
[SCEVExpander] Add helper to clean up instrs inserted while expanding.
SCEVExpander already tracks which instructions have been inserted n InsertedValues/InsertedPostIncValues. This patch adds an additional vector to collect the instructions in insertion order. This can then be used to remove exactly the instructions inserted by the expander. This replaces ExpandedValuesCleaner, which in some cases might remove values not inserted by the expander (e.g. if a value was dead before insertion and is then used during expansion). Reviewed By: lebedev.ri Differential Revision: https://reviews.llvm.org/D84327
1 parent 31fd64a commit 7829c33

File tree

3 files changed

+81
-34
lines changed

3 files changed

+81
-34
lines changed

llvm/include/llvm/Transforms/Utils/ScalarEvolutionExpander.h

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,23 @@ class SCEVExpander : public SCEVVisitor<SCEVExpander, Value *> {
180180
ChainedPhis.clear();
181181
}
182182

183+
/// Return a vector containing all instructions inserted during expansion.
184+
SmallVector<Instruction *, 32> getAllInsertedInstructions() const {
185+
SmallVector<Instruction *, 32> Result;
186+
for (auto &VH : InsertedValues) {
187+
Value *V = VH;
188+
if (auto *Inst = dyn_cast<Instruction>(V))
189+
Result.push_back(Inst);
190+
}
191+
for (auto &VH : InsertedPostIncValues) {
192+
Value *V = VH;
193+
if (auto *Inst = dyn_cast<Instruction>(V))
194+
Result.push_back(Inst);
195+
}
196+
197+
return Result;
198+
}
199+
183200
/// Return true for expressions that can't be evaluated at runtime
184201
/// within given \b Budget.
185202
///
@@ -452,6 +469,27 @@ class SCEVExpander : public SCEVVisitor<SCEVExpander, Value *> {
452469
/// If no PHIs have been created, return the unchanged operand \p OpIdx.
453470
Value *fixupLCSSAFormFor(Instruction *User, unsigned OpIdx);
454471
};
472+
473+
/// Helper to remove instructions inserted during SCEV expansion, unless they
474+
/// are marked as used.
475+
class SCEVExpanderCleaner {
476+
SCEVExpander &Expander;
477+
478+
DominatorTree &DT;
479+
480+
/// Indicates whether the result of the expansion is used. If false, the
481+
/// instructions added during expansion are removed.
482+
bool ResultUsed;
483+
484+
public:
485+
SCEVExpanderCleaner(SCEVExpander &Expander, DominatorTree &DT)
486+
: Expander(Expander), DT(DT), ResultUsed(false) {}
487+
488+
~SCEVExpanderCleaner();
489+
490+
/// Indicate that the result of the expansion is used.
491+
void markResultUsed() { ResultUsed = true; }
492+
};
455493
} // namespace llvm
456494

457495
#endif

llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp

Lines changed: 4 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -295,31 +295,6 @@ static void deleteDeadInstruction(Instruction *I) {
295295
I->eraseFromParent();
296296
}
297297

298-
namespace {
299-
class ExpandedValuesCleaner {
300-
SCEVExpander &Expander;
301-
TargetLibraryInfo *TLI;
302-
SmallVector<Value *, 4> ExpandedValues;
303-
bool Commit = false;
304-
305-
public:
306-
ExpandedValuesCleaner(SCEVExpander &Expander, TargetLibraryInfo *TLI)
307-
: Expander(Expander), TLI(TLI) {}
308-
309-
void add(Value *V) { ExpandedValues.push_back(V); }
310-
311-
void commit() { Commit = true; }
312-
313-
~ExpandedValuesCleaner() {
314-
if (!Commit) {
315-
Expander.clear();
316-
for (auto *V : ExpandedValues)
317-
RecursivelyDeleteTriviallyDeadInstructions(V, TLI);
318-
}
319-
}
320-
};
321-
} // namespace
322-
323298
//===----------------------------------------------------------------------===//
324299
//
325300
// Implementation of LoopIdiomRecognize
@@ -933,7 +908,7 @@ bool LoopIdiomRecognize::processLoopStridedStore(
933908
BasicBlock *Preheader = CurLoop->getLoopPreheader();
934909
IRBuilder<> Builder(Preheader->getTerminator());
935910
SCEVExpander Expander(*SE, *DL, "loop-idiom");
936-
ExpandedValuesCleaner EVC(Expander, TLI);
911+
SCEVExpanderCleaner ExpCleaner(Expander, *DT);
937912

938913
Type *DestInt8PtrTy = Builder.getInt8PtrTy(DestAS);
939914
Type *IntIdxTy = DL->getIndexType(DestPtr->getType());
@@ -956,7 +931,6 @@ bool LoopIdiomRecognize::processLoopStridedStore(
956931
// base pointer and checking the region.
957932
Value *BasePtr =
958933
Expander.expandCodeFor(Start, DestInt8PtrTy, Preheader->getTerminator());
959-
EVC.add(BasePtr);
960934

961935
// From here on out, conservatively report to the pass manager that we've
962936
// changed the IR, even if we later clean up these added instructions. There
@@ -1041,7 +1015,7 @@ bool LoopIdiomRecognize::processLoopStridedStore(
10411015
if (MSSAU && VerifyMemorySSA)
10421016
MSSAU->getMemorySSA()->verifyMemorySSA();
10431017
++NumMemSet;
1044-
EVC.commit();
1018+
ExpCleaner.markResultUsed();
10451019
return true;
10461020
}
10471021

@@ -1075,7 +1049,7 @@ bool LoopIdiomRecognize::processLoopStoreOfLoopLoad(StoreInst *SI,
10751049
IRBuilder<> Builder(Preheader->getTerminator());
10761050
SCEVExpander Expander(*SE, *DL, "loop-idiom");
10771051

1078-
ExpandedValuesCleaner EVC(Expander, TLI);
1052+
SCEVExpanderCleaner ExpCleaner(Expander, *DT);
10791053

10801054
bool Changed = false;
10811055
const SCEV *StrStart = StoreEv->getStart();
@@ -1094,7 +1068,6 @@ bool LoopIdiomRecognize::processLoopStoreOfLoopLoad(StoreInst *SI,
10941068
// checking everything.
10951069
Value *StoreBasePtr = Expander.expandCodeFor(
10961070
StrStart, Builder.getInt8PtrTy(StrAS), Preheader->getTerminator());
1097-
EVC.add(StoreBasePtr);
10981071

10991072
// From here on out, conservatively report to the pass manager that we've
11001073
// changed the IR, even if we later clean up these added instructions. There
@@ -1122,7 +1095,6 @@ bool LoopIdiomRecognize::processLoopStoreOfLoopLoad(StoreInst *SI,
11221095
// mutated by the loop.
11231096
Value *LoadBasePtr = Expander.expandCodeFor(
11241097
LdStart, Builder.getInt8PtrTy(LdAS), Preheader->getTerminator());
1125-
EVC.add(LoadBasePtr);
11261098

11271099
if (mayLoopAccessLocation(LoadBasePtr, ModRefInfo::Mod, CurLoop, BECount,
11281100
StoreSize, *AA, Stores))
@@ -1138,7 +1110,6 @@ bool LoopIdiomRecognize::processLoopStoreOfLoopLoad(StoreInst *SI,
11381110

11391111
Value *NumBytes =
11401112
Expander.expandCodeFor(NumBytesS, IntIdxTy, Preheader->getTerminator());
1141-
EVC.add(NumBytes);
11421113

11431114
CallInst *NewCall = nullptr;
11441115
// Check whether to generate an unordered atomic memcpy:
@@ -1198,7 +1169,7 @@ bool LoopIdiomRecognize::processLoopStoreOfLoopLoad(StoreInst *SI,
11981169
if (MSSAU && VerifyMemorySSA)
11991170
MSSAU->getMemorySSA()->verifyMemorySSA();
12001171
++NumMemCpy;
1201-
EVC.commit();
1172+
ExpCleaner.markResultUsed();
12021173
return true;
12031174
}
12041175

llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1882,10 +1882,12 @@ Value *SCEVExpander::expand(const SCEV *S) {
18821882
// there) so that it is guaranteed to dominate any user inside the loop.
18831883
if (L && SE.hasComputableLoopEvolution(S, L) && !PostIncLoops.count(L))
18841884
InsertPt = &*L->getHeader()->getFirstInsertionPt();
1885+
18851886
while (InsertPt->getIterator() != Builder.GetInsertPoint() &&
18861887
(isInsertedInstruction(InsertPt) ||
1887-
isa<DbgInfoIntrinsic>(InsertPt)))
1888+
isa<DbgInfoIntrinsic>(InsertPt))) {
18881889
InsertPt = &*std::next(InsertPt->getIterator());
1890+
}
18891891
break;
18901892
}
18911893
}
@@ -2630,4 +2632,40 @@ bool isSafeToExpandAt(const SCEV *S, const Instruction *InsertionPoint,
26302632
}
26312633
return false;
26322634
}
2635+
2636+
SCEVExpanderCleaner::~SCEVExpanderCleaner() {
2637+
// Result is used, nothing to remove.
2638+
if (ResultUsed)
2639+
return;
2640+
2641+
auto InsertedInstructions = Expander.getAllInsertedInstructions();
2642+
#ifndef NDEBUG
2643+
SmallPtrSet<Instruction *, 8> InsertedSet(InsertedInstructions.begin(),
2644+
InsertedInstructions.end());
2645+
(void)InsertedSet;
2646+
#endif
2647+
// Remove sets with value handles.
2648+
Expander.clear();
2649+
2650+
// Sort so that earlier instructions do not dominate later instructions.
2651+
stable_sort(InsertedInstructions, [this](Instruction *A, Instruction *B) {
2652+
return DT.dominates(B, A);
2653+
});
2654+
// Remove all inserted instructions.
2655+
for (Instruction *I : InsertedInstructions) {
2656+
2657+
#ifndef NDEBUG
2658+
assert(all_of(I->users(),
2659+
[&InsertedSet](Value *U) {
2660+
return InsertedSet.contains(cast<Instruction>(U));
2661+
}) &&
2662+
"removed instruction should only be used by instructions inserted "
2663+
"during expansion");
2664+
#endif
2665+
assert(!I->getType()->isVoidTy() &&
2666+
"inserted instruction should have non-void types");
2667+
I->replaceAllUsesWith(UndefValue::get(I->getType()));
2668+
I->eraseFromParent();
2669+
}
2670+
}
26332671
}

0 commit comments

Comments
 (0)