Skip to content

Commit 15df301

Browse files
committed
Make smaller stores generated for stores that are partly dead deterministic
We do not have problem right now because the we only do partial dead store when we end up generating only 1 single smaller store.
1 parent c4eda1a commit 15df301

File tree

2 files changed

+37
-9
lines changed

2 files changed

+37
-9
lines changed

lib/SILOptimizer/Transforms/DeadStoreElimination.cpp

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,12 @@
7878

7979
using namespace swift;
8080

81+
/// If a large store is broken down to too many smaller stores, bail out.
82+
/// Currently, we only do partial dead store if we can form a single contiguous
83+
/// non-dead store.
84+
static llvm::cl::opt<unsigned> MaxPartialStoreCount("max-partial-store-count",
85+
llvm::cl::init(1), llvm::cl::Hidden);
86+
8187
STATISTIC(NumDeadStores, "Number of dead stores removed");
8288
STATISTIC(NumPartialDeadStores, "Number of partial dead stores removed");
8389

@@ -163,10 +169,6 @@ constexpr unsigned MaxLSLocationBBMultiplicationNone = 256*256;
163169
/// and 64 locations which is a sizeable function.
164170
constexpr unsigned MaxLSLocationBBMultiplicationPessimistic = 64*64;
165171

166-
/// If a large store is broken down to too many smaller stores, bail out.
167-
/// Currently, we only do partial dead store if we can form a single contiguous
168-
/// non-dead store.
169-
constexpr unsigned MaxPartialDeadStoreCountLimit = 1;
170172

171173
/// forward declaration.
172174
class DSEContext;
@@ -246,6 +248,7 @@ class BlockState {
246248
///
247249
/// The first SILValue keeps the address of the live store and the second
248250
/// SILValue keeps the value of the store.
251+
llvm::SetVector<SILValue> LiveAddr;
249252
llvm::DenseMap<SILValue, SILValue> LiveStores;
250253

251254
/// Constructors.
@@ -956,7 +959,7 @@ void DSEContext::processWrite(SILInstruction *I, SILValue Val, SILValue Mem,
956959
LSLocation::reduce(L, Mod, Alives);
957960

958961
// Oops, we have too many smaller stores generated, bail out.
959-
if (Alives.size() > MaxPartialDeadStoreCountLimit)
962+
if (Alives.size() > MaxPartialStoreCount)
960963
return;
961964

962965
// At this point, we are performing a partial dead store elimination.
@@ -976,6 +979,7 @@ void DSEContext::processWrite(SILInstruction *I, SILValue Val, SILValue Mem,
976979
for (auto &X : Alives) {
977980
SILValue Value = X.getPath()->createExtract(Val, I, true);
978981
SILValue Addr = X.getPath()->createExtract(Mem, I, false);
982+
S->LiveAddr.insert(Addr);
979983
S->LiveStores[Addr] = Value;
980984
}
981985

@@ -1200,12 +1204,14 @@ bool DSEContext::run() {
12001204
bool Changed = false;
12011205
for (SILBasicBlock &BB : *F) {
12021206
// Create the stores that are alive due to partial dead stores.
1203-
for (auto &I : getBlockState(&BB)->LiveStores) {
1207+
auto *S = getBlockState(&BB);
1208+
for (auto &X : S->LiveAddr) {
12041209
Changed = true;
1205-
SILInstruction *Inst = cast<SILInstruction>(I.first);
1210+
auto I = S->LiveStores.find(X);
1211+
SILInstruction *Inst = cast<SILInstruction>(I->first);
12061212
auto *IT = &*std::next(Inst->getIterator());
12071213
SILBuilderWithScope Builder(IT);
1208-
Builder.createStore(Inst->getLoc(), I.second, Inst);
1214+
Builder.createStore(Inst->getLoc(), I->second, Inst);
12091215
}
12101216
// Delete the dead stores.
12111217
for (auto &I : getBlockState(&BB)->DeadStores) {

test/SILOptimizer/dead_store_elim.sil

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-sil-opt %s -dead-store-elim -enable-sil-verify-all | FileCheck %s
1+
// RUN: %target-sil-opt %s -dead-store-elim -max-partial-store-count=2 -enable-sil-verify-all | FileCheck %s
22

33
sil_stage canonical
44

@@ -1075,6 +1075,28 @@ bb0(%0 : $*S6):
10751075
return %9 : $()
10761076
}
10771077

1078+
/// Make sure we generate the store to field x first.
1079+
///
1080+
/// CHECK-LABEL : sil hidden @discontiguous_partial_dead_store_lives_insert_determinstically
1081+
/// CHECK: bb0([[A:%.*]] : $*S6):
1082+
/// CHECK: [[IN:%.*]] = apply
1083+
/// CHECK: [[EXT1:%.*]] = struct_extract [[IN]] : $S6, #S6.x
1084+
/// CHECK: [[EXT2:%.*]] = struct_element_addr [[A]] : $*S6, #S6.x
1085+
/// CHECK: store [[EXT1]] to [[EXT2]] : $*Int
1086+
sil hidden @discontiguous_partial_dead_store_lives_insert_determinstically : $@convention(thin) (@inout S6) -> () {
1087+
bb0(%0 : $*S6):
1088+
%1 = function_ref @S6_init : $@convention(thin) (@thin S6.Type) -> S6
1089+
%2 = metatype $@thin S6.Type
1090+
%3 = apply %1(%2) : $@convention(thin) (@thin S6.Type) -> S6
1091+
store %3 to %0 : $*S6
1092+
%5 = integer_literal $Builtin.Int64, 10
1093+
%6 = struct $Int (%5 : $Builtin.Int64)
1094+
%7 = struct_element_addr %0 : $*S6, #S6.y
1095+
store %6 to %7 : $*Int
1096+
%9 = tuple ()
1097+
return %9 : $()
1098+
}
1099+
10781100
/// Make sure we do not generate too many stores from a large store that
10791101
/// is partially dead.
10801102
///

0 commit comments

Comments
 (0)