Skip to content

Commit 6d3f74a

Browse files
committed
SILOptimizer: only do SROA when it has a benefit.
Replacing an alloc_stack of a struct/tuple with multiple alloc_stacks of the struct/tuple elements should only be done if the elements are somehow accessed individually. If not, e.g. if the whole struct/tuple is just copied, there is no benefit of doing SROA. Although this change has little impact by its own (some small code size wins), it is important for the improvement of let-property optimization.
1 parent aa34eb2 commit 6d3f74a

File tree

4 files changed

+33
-1
lines changed

4 files changed

+33
-1
lines changed

lib/SILOptimizer/Transforms/SILSROA.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,8 @@ bool SROAMemoryUseAnalyzer::analyze() {
138138
return false;
139139
}
140140

141+
bool hasBenefit = false;
142+
141143
// Go through uses of the memory allocation of AI...
142144
for (auto *Operand : getNonDebugUses(SILValue(AI))) {
143145
SILInstruction *User = Operand->getUser();
@@ -150,6 +152,9 @@ bool SROAMemoryUseAnalyzer::analyze() {
150152
LLVM_DEBUG(llvm::dbgs() << " Found a store into the "
151153
"projection.\n");
152154
Stores.push_back(SI);
155+
SILValue Src = SI->getSrc();
156+
if (isa<StructInst>(Src) || isa<TupleInst>(Src))
157+
hasBenefit = true;
153158
continue;
154159
} else {
155160
LLVM_DEBUG(llvm::dbgs() << " Found a store of the "
@@ -163,6 +168,11 @@ bool SROAMemoryUseAnalyzer::analyze() {
163168
if (auto *LI = dyn_cast<LoadInst>(User)) {
164169
LLVM_DEBUG(llvm::dbgs() << " Found a load of the projection.\n");
165170
Loads.push_back(LI);
171+
for (auto useIter = LI->use_begin(), End = LI->use_end();
172+
!hasBenefit && useIter != End; useIter++) {
173+
hasBenefit = (isa<StructExtractInst>(useIter->get()) ||
174+
isa<TupleExtractInst>(useIter->get()));
175+
}
166176
continue;
167177
}
168178

@@ -171,6 +181,7 @@ bool SROAMemoryUseAnalyzer::analyze() {
171181
if (auto *ASI = dyn_cast<StructElementAddrInst>(User)) {
172182
LLVM_DEBUG(llvm::dbgs() << " Found a struct subprojection!\n");
173183
ExtractInsts.push_back(ASI);
184+
hasBenefit = true;
174185
continue;
175186
}
176187

@@ -179,6 +190,7 @@ bool SROAMemoryUseAnalyzer::analyze() {
179190
if (auto *TSI = dyn_cast<TupleElementAddrInst>(User)) {
180191
LLVM_DEBUG(llvm::dbgs() << " Found a tuple subprojection!\n");
181192
ExtractInsts.push_back(TSI);
193+
hasBenefit = true;
182194
continue;
183195
}
184196

@@ -195,7 +207,7 @@ bool SROAMemoryUseAnalyzer::analyze() {
195207

196208
// Analysis was successful. We can break up this allocation!
197209
++NumChoppedAllocas;
198-
return true;
210+
return hasBenefit;
199211
}
200212

201213
void

test/SILOptimizer/optionset.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ public struct TestOptions: OptionSet {
1616
// CHECK-NEXT: bb0:
1717
// CHECK-NEXT: integer_literal {{.*}}, 15
1818
// CHECK-NEXT: struct $Int
19+
// CHECK-NEXT: debug_value
1920
// CHECK-NEXT: struct $TestOptions
2021
// CHECK-NEXT: return
2122
public func returnTestOptions() -> TestOptions {
@@ -26,6 +27,7 @@ public func returnTestOptions() -> TestOptions {
2627
// CHECK-NEXT: global_addr
2728
// CHECK-NEXT: integer_literal {{.*}}, 15
2829
// CHECK-NEXT: struct $Int
30+
// CHECK-NEXT: debug_value
2931
// CHECK-NEXT: struct $TestOptions
3032
// CHECK-NEXT: store
3133
// CHECK-NEXT: tuple

test/SILOptimizer/specialize_unconditional_checked_cast.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ ArchetypeToConcreteConvertUInt8(t: f)
100100
// CHECK-LABEL: sil shared [noinline] @$S37specialize_unconditional_checked_cast31ArchetypeToConcreteConvertUInt8{{[_0-9a-zA-Z]*}}3Not{{.*}}Tg5 : $@convention(thin) (NotUInt8) -> NotUInt8 {
101101
// CHECK: bb0
102102
// CHECK-NEXT: debug_value %0
103+
// CHECK-NEXT: debug_value %0
103104
// CHECK-NEXT: return %0
104105

105106
// x -> y where y is a class but x is not.

test/SILOptimizer/sroa.sil

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,23 @@ bb0(%0 : $S1):
5656
return %6 : $()
5757
}
5858

59+
// CHECK-LABEL: sil @dont_sroa_without_benefit : $@convention(thin) (S1) -> S1
60+
// CHECK: bb0
61+
// CHECK-NEXT: alloc_stack $S1
62+
// CHECK-NEXT: store %0 to %1 : $*S1
63+
// CHECK-NEXT: load %1 : $*S1
64+
// CHECK-NEXT: dealloc_stack %1 : $*S1
65+
// CHECK-NEXT: return
66+
sil @dont_sroa_without_benefit : $@convention(thin) (S1) -> S1 {
67+
bb0(%0 : $S1):
68+
%1 = alloc_stack $S1
69+
store %0 to %1 : $*S1
70+
%3 = load %1 : $*S1
71+
dealloc_stack %1 : $*S1
72+
return %3 : $S1
73+
}
74+
75+
5976
///////////////////////////////
6077
// Struct With Struct Fields //
6178
///////////////////////////////

0 commit comments

Comments
 (0)