@@ -902,6 +902,16 @@ struct DSEState {
902
902
});
903
903
}
904
904
905
+ static void pushMemUses (MemoryAccess *Acc,
906
+ SmallVectorImpl<MemoryAccess *> &WorkList,
907
+ SmallPtrSetImpl<MemoryAccess *> &Visited) {
908
+ for (Use &U : Acc->uses ()) {
909
+ auto *MA = cast<MemoryAccess>(U.getUser ());
910
+ if (Visited.insert (MA).second )
911
+ WorkList.push_back (MA);
912
+ }
913
+ };
914
+
905
915
LocationSize strengthenLocationSize (const Instruction *I,
906
916
LocationSize Size) const {
907
917
if (auto *CB = dyn_cast<CallBase>(I)) {
@@ -1157,26 +1167,14 @@ struct DSEState {
1157
1167
}
1158
1168
1159
1169
// / Returns true if \p Def is not read before returning from the function.
1160
- bool isWriteAtEndOfFunction (MemoryDef *Def) {
1170
+ bool isWriteAtEndOfFunction (MemoryDef *Def, const MemoryLocation &DefLoc ) {
1161
1171
LLVM_DEBUG (dbgs () << " Check if def " << *Def << " ("
1162
1172
<< *Def->getMemoryInst ()
1163
1173
<< " ) is at the end the function \n " );
1164
-
1165
- auto MaybeLoc = getLocForWrite (Def->getMemoryInst ());
1166
- if (!MaybeLoc) {
1167
- LLVM_DEBUG (dbgs () << " ... could not get location for write.\n " );
1168
- return false ;
1169
- }
1170
-
1171
1174
SmallVector<MemoryAccess *, 4 > WorkList;
1172
1175
SmallPtrSet<MemoryAccess *, 8 > Visited;
1173
- auto PushMemUses = [&WorkList, &Visited](MemoryAccess *Acc) {
1174
- if (!Visited.insert (Acc).second )
1175
- return ;
1176
- for (Use &U : Acc->uses ())
1177
- WorkList.push_back (cast<MemoryAccess>(U.getUser ()));
1178
- };
1179
- PushMemUses (Def);
1176
+
1177
+ pushMemUses (Def, WorkList, Visited);
1180
1178
for (unsigned I = 0 ; I < WorkList.size (); I++) {
1181
1179
if (WorkList.size () >= MemorySSAScanLimit) {
1182
1180
LLVM_DEBUG (dbgs () << " ... hit exploration limit.\n " );
@@ -1188,22 +1186,22 @@ struct DSEState {
1188
1186
// AliasAnalysis does not account for loops. Limit elimination to
1189
1187
// candidates for which we can guarantee they always store to the same
1190
1188
// memory location.
1191
- if (!isGuaranteedLoopInvariant (MaybeLoc-> Ptr ))
1189
+ if (!isGuaranteedLoopInvariant (DefLoc. Ptr ))
1192
1190
return false ;
1193
1191
1194
- PushMemUses (cast<MemoryPhi>(UseAccess));
1192
+ pushMemUses (cast<MemoryPhi>(UseAccess), WorkList, Visited );
1195
1193
continue ;
1196
1194
}
1197
1195
// TODO: Checking for aliasing is expensive. Consider reducing the amount
1198
1196
// of times this is called and/or caching it.
1199
1197
Instruction *UseInst = cast<MemoryUseOrDef>(UseAccess)->getMemoryInst ();
1200
- if (isReadClobber (*MaybeLoc , UseInst)) {
1198
+ if (isReadClobber (DefLoc , UseInst)) {
1201
1199
LLVM_DEBUG (dbgs () << " ... hit read clobber " << *UseInst << " .\n " );
1202
1200
return false ;
1203
1201
}
1204
1202
1205
1203
if (MemoryDef *UseDef = dyn_cast<MemoryDef>(UseAccess))
1206
- PushMemUses (UseDef);
1204
+ pushMemUses (UseDef, WorkList, Visited );
1207
1205
}
1208
1206
return true ;
1209
1207
}
@@ -1505,12 +1503,9 @@ struct DSEState {
1505
1503
LLVM_DEBUG (dbgs () << " Checking for reads of " << *MaybeDeadAccess << " ("
1506
1504
<< *MaybeDeadI << " )\n " );
1507
1505
1508
- SmallSetVector<MemoryAccess *, 32 > WorkList;
1509
- auto PushMemUses = [&WorkList](MemoryAccess *Acc) {
1510
- for (Use &U : Acc->uses ())
1511
- WorkList.insert (cast<MemoryAccess>(U.getUser ()));
1512
- };
1513
- PushMemUses (MaybeDeadAccess);
1506
+ SmallVector<MemoryAccess *, 32 > WorkList;
1507
+ SmallPtrSet<MemoryAccess *, 32 > Visited;
1508
+ pushMemUses (MaybeDeadAccess, WorkList, Visited);
1514
1509
1515
1510
// Check if DeadDef may be read.
1516
1511
for (unsigned I = 0 ; I < WorkList.size (); I++) {
@@ -1534,7 +1529,7 @@ struct DSEState {
1534
1529
continue ;
1535
1530
}
1536
1531
LLVM_DEBUG (dbgs () << " \n ... adding PHI uses\n " );
1537
- PushMemUses (UseAccess);
1532
+ pushMemUses (UseAccess, WorkList, Visited );
1538
1533
continue ;
1539
1534
}
1540
1535
@@ -1559,7 +1554,7 @@ struct DSEState {
1559
1554
1560
1555
if (isNoopIntrinsic (cast<MemoryUseOrDef>(UseAccess)->getMemoryInst ())) {
1561
1556
LLVM_DEBUG (dbgs () << " ... adding uses of intrinsic\n " );
1562
- PushMemUses (UseAccess);
1557
+ pushMemUses (UseAccess, WorkList, Visited );
1563
1558
continue ;
1564
1559
}
1565
1560
@@ -1618,7 +1613,7 @@ struct DSEState {
1618
1613
return std::nullopt;
1619
1614
}
1620
1615
} else
1621
- PushMemUses (UseDef);
1616
+ pushMemUses (UseDef, WorkList, Visited );
1622
1617
}
1623
1618
}
1624
1619
@@ -1821,8 +1816,11 @@ struct DSEState {
1821
1816
1822
1817
Instruction *DefI = Def->getMemoryInst ();
1823
1818
auto DefLoc = getLocForWrite (DefI);
1824
- if (!DefLoc || !isRemovable (DefI))
1819
+ if (!DefLoc || !isRemovable (DefI)) {
1820
+ LLVM_DEBUG (dbgs () << " ... could not get location for write or "
1821
+ " instruction not removable.\n " );
1825
1822
continue ;
1823
+ }
1826
1824
1827
1825
// NOTE: Currently eliminating writes at the end of a function is
1828
1826
// limited to MemoryDefs with a single underlying object, to save
@@ -1833,7 +1831,7 @@ struct DSEState {
1833
1831
if (!isInvisibleToCallerAfterRet (UO))
1834
1832
continue ;
1835
1833
1836
- if (isWriteAtEndOfFunction (Def)) {
1834
+ if (isWriteAtEndOfFunction (Def, *DefLoc )) {
1837
1835
// See through pointer-to-pointer bitcasts
1838
1836
LLVM_DEBUG (dbgs () << " ... MemoryDef is not accessed until the end "
1839
1837
" of the function\n " );
0 commit comments