Skip to content

Commit 8ac94be

Browse files
committed
[DSE] Fix non-determinism due to address reuse
The malloc->calloc fold creates a new MemoryAccess, which may end of at the same address as a previously deleted access inside SkipStores. To the most part, this is not a problem, because SkipStores is normally only used together with MemDefs. Neither the old malloc access nor the new calloc access will be part of MemDefs, so there is no problem here. However, SkipStores is also used in one more place: In the main DSE loop, ToCheck entries are checked against it. Fix this by not using SkipStores here, and instead using a separate set to track deletions inside this loop. This way it is not affected by the calloc optimization that happens outside it. This is all pretty ugly, but I haven't found another good way to fix it. Suggestions welcome. No test case as I don't have a reliable DSE-only test-case for this. Fixes #84458.
1 parent beba307 commit 8ac94be

File tree

1 file changed

+10
-5
lines changed

1 file changed

+10
-5
lines changed

llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1698,7 +1698,9 @@ struct DSEState {
16981698

16991699
/// Delete dead memory defs and recursively add their operands to ToRemove if
17001700
/// they became dead.
1701-
void deleteDeadInstruction(Instruction *SI) {
1701+
void
1702+
deleteDeadInstruction(Instruction *SI,
1703+
SmallPtrSetImpl<MemoryAccess *> *Deleted = nullptr) {
17021704
MemorySSAUpdater Updater(&MSSA);
17031705
SmallVector<Instruction *, 32> NowDeadInsts;
17041706
NowDeadInsts.push_back(SI);
@@ -1719,6 +1721,8 @@ struct DSEState {
17191721
if (IsMemDef) {
17201722
auto *MD = cast<MemoryDef>(MA);
17211723
SkipStores.insert(MD);
1724+
if (Deleted)
1725+
Deleted->insert(MD);
17221726
if (auto *SI = dyn_cast<StoreInst>(MD->getMemoryInst())) {
17231727
if (SI->getValueOperand()->getType()->isPointerTy()) {
17241728
const Value *UO = getUnderlyingObject(SI->getValueOperand());
@@ -2167,14 +2171,15 @@ static bool eliminateDeadStores(Function &F, AliasAnalysis &AA, MemorySSA &MSSA,
21672171
unsigned PartialLimit = MemorySSAPartialStoreLimit;
21682172
// Worklist of MemoryAccesses that may be killed by KillingDef.
21692173
SmallSetVector<MemoryAccess *, 8> ToCheck;
2174+
SmallPtrSet<MemoryAccess *, 8> Deleted;
21702175
ToCheck.insert(KillingDef->getDefiningAccess());
21712176

21722177
bool Shortend = false;
21732178
bool IsMemTerm = State.isMemTerminatorInst(KillingI);
21742179
// Check if MemoryAccesses in the worklist are killed by KillingDef.
21752180
for (unsigned I = 0; I < ToCheck.size(); I++) {
21762181
MemoryAccess *Current = ToCheck[I];
2177-
if (State.SkipStores.count(Current))
2182+
if (Deleted.contains(Current))
21782183
continue;
21792184

21802185
std::optional<MemoryAccess *> MaybeDeadAccess = State.getDomMemoryDef(
@@ -2221,7 +2226,7 @@ static bool eliminateDeadStores(Function &F, AliasAnalysis &AA, MemorySSA &MSSA,
22212226
continue;
22222227
LLVM_DEBUG(dbgs() << "DSE: Remove Dead Store:\n DEAD: " << *DeadI
22232228
<< "\n KILLER: " << *KillingI << '\n');
2224-
State.deleteDeadInstruction(DeadI);
2229+
State.deleteDeadInstruction(DeadI, &Deleted);
22252230
++NumFastStores;
22262231
MadeChange = true;
22272232
} else {
@@ -2258,7 +2263,7 @@ static bool eliminateDeadStores(Function &F, AliasAnalysis &AA, MemorySSA &MSSA,
22582263
Shortend = true;
22592264
// Remove killing store and remove any outstanding overlap
22602265
// intervals for the updated store.
2261-
State.deleteDeadInstruction(KillingSI);
2266+
State.deleteDeadInstruction(KillingSI, &Deleted);
22622267
auto I = State.IOLs.find(DeadSI->getParent());
22632268
if (I != State.IOLs.end())
22642269
I->second.erase(DeadSI);
@@ -2270,7 +2275,7 @@ static bool eliminateDeadStores(Function &F, AliasAnalysis &AA, MemorySSA &MSSA,
22702275
if (OR == OW_Complete) {
22712276
LLVM_DEBUG(dbgs() << "DSE: Remove Dead Store:\n DEAD: " << *DeadI
22722277
<< "\n KILLER: " << *KillingI << '\n');
2273-
State.deleteDeadInstruction(DeadI);
2278+
State.deleteDeadInstruction(DeadI, &Deleted);
22742279
++NumFastStores;
22752280
MadeChange = true;
22762281
}

0 commit comments

Comments
 (0)