Skip to content

Commit 96628e4

Browse files
committed
Merge pull request swiftlang#1485 from tkremenek/swift-2.2-PR-LetPropertiesOptPass-Miscompile
Fix a bug in LetPropertiesOptPass
2 parents 7a0b677 + 27123b9 commit 96628e4

File tree

2 files changed

+33
-6
lines changed

2 files changed

+33
-6
lines changed

lib/SILOptimizer/IPO/LetPropertiesOpts.cpp

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -246,8 +246,9 @@ static bool compareInsnSequences(SmallVectorImpl<SILInstruction *> &LHS,
246246
/// initializing a given property.
247247
SILValue findStoredValue(SILFunction *Init, VarDecl *Property,
248248
SmallVectorImpl<SILInstruction *> &Insns) {
249-
for (auto &BB: *Init) {
250-
for (auto &I: BB) {
249+
SILValue ResultValue;
250+
for (auto &BB : *Init) {
251+
for (auto &I : BB) {
251252
if (auto *RI = dyn_cast<ReturnInst>(&I)) {
252253
if (auto *SI = dyn_cast<StructInst>(RI->getOperand())) {
253254
auto Value = SI->getFieldValue(Property);
@@ -268,22 +269,24 @@ SILValue findStoredValue(SILFunction *Init, VarDecl *Property,
268269
auto REAI = dyn_cast<RefElementAddrInst>(Dest);
269270
if (!REAI || REAI->getField() != Property)
270271
continue;
271-
272+
// Bail, if it is not the only assignment to the
273+
// required property.
274+
if (ResultValue)
275+
return SILValue();
272276
auto Value = SI->getSrc();
273277
SmallVector<SILInstruction *, 8> ReverseInsns;
274-
// ReverseInsns.push_back(SI);
275278
if (!analyzeStaticInitializer(Value, ReverseInsns))
276279
return SILValue();
277280
// Produce a correct order of instructions.
278281
while (!ReverseInsns.empty()) {
279282
Insns.push_back(ReverseInsns.pop_back_val());
280283
}
281-
return Value;
284+
ResultValue = Value;
282285
}
283286
}
284287
}
285288

286-
return SILValue();
289+
return ResultValue;
287290
}
288291

289292
/// Try to find a sequence of instructions which initializes

test/SILOptimizer/let_properties_opts.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,18 @@ public struct Boo {
8686
public init(i:Int64) {}
8787
}
8888

89+
public class Foo2 {
90+
internal let x: Int32
91+
@inline(never)
92+
init(count: Int32) {
93+
if count < 2 {
94+
x = 5
95+
} else {
96+
x = 10
97+
}
98+
}
99+
}
100+
89101
// Check that Foo1.Prop1 is not constant-folded, because its value is unknown, since it is initialized differently
90102
// by Foo1 initializers.
91103

@@ -170,3 +182,15 @@ public func testStructLet(inout b: Boo) -> Int32 {
170182
public func testStructPublicLet(b: Boo) -> Int32 {
171183
return b.Prop0
172184
}
185+
186+
// Check that f.x is not constant folded, because the initializer of Foo2 has multiple
187+
// assignments to the property x with different values.
188+
// CHECK-LABEL: sil @_TF19let_properties_opts13testClassLet2FCS_4Foo2Vs5Int32 : $@convention(thin) (@owned Foo2) -> Int32
189+
// bb0
190+
// CHECK: ref_element_addr %{{[0-9]+}} : $Foo2, #Foo2.x
191+
// CHECK-NOT: ref_element_addr %{{[0-9]+}} : $Foo2, #Foo2.x
192+
// CHECK-NOT: ref_element_addr %{{[0-9]+}} : $Foo2, #Foo2.x
193+
// CHECK: return
194+
public func testClassLet2(f: Foo2) -> Int32 {
195+
return f.x + f.x
196+
}

0 commit comments

Comments
 (0)