Skip to content

Commit 86e5f32

Browse files
authored
Merge pull request #11026 from jckarter/fix-load-from-lvalue-peephole
SILGen: Ease off +0 peepholes for load exprs.
2 parents 2968b03 + 7705393 commit 86e5f32

File tree

7 files changed

+56
-16
lines changed

7 files changed

+56
-16
lines changed

lib/SILGen/SGFContext.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -152,9 +152,9 @@ class SGFContext {
152152
/// a value. The Initialization is not okay to propagate down, but
153153
/// the +0/+1-ness is.
154154
SGFContext withFollowingProjection() const {
155-
SGFContext copy;
156-
copy.state.setInt(state.getInt());
157-
return copy;
155+
SGFContext result;
156+
result.state.setInt(state.getInt());
157+
return result;
158158
}
159159
};
160160

lib/SILGen/SILGenExpr.cpp

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1299,7 +1299,10 @@ RValue RValueEmitter::visitLoadExpr(LoadExpr *E, SGFContext C) {
12991299
// Any writebacks here are tightly scoped.
13001300
FormalEvaluationScope writeback(SGF);
13011301
LValue lv = SGF.emitLValue(E->getSubExpr(), AccessKind::Read);
1302-
return SGF.emitLoadOfLValue(E, std::move(lv), C);
1302+
// We can't load at immediate +0 from the lvalue without deeper analysis,
1303+
// since the access will be immediately ended and might invalidate the value
1304+
// we loaded.
1305+
return SGF.emitLoadOfLValue(E, std::move(lv), C.withFollowingSideEffects());
13031306
}
13041307

13051308
SILValue SILGenFunction::emitTemporaryAllocation(SILLocation loc,
@@ -2367,7 +2370,9 @@ RValue RValueEmitter::visitMemberRefExpr(MemberRefExpr *E, SGFContext C) {
23672370
FormalEvaluationScope scope(SGF);
23682371

23692372
LValue lv = SGF.emitLValue(E, AccessKind::Read);
2370-
return SGF.emitLoadOfLValue(E, std::move(lv), C);
2373+
// We can't load at +0 without further analysis, since the formal access into
2374+
// the lvalue will end immediately.
2375+
return SGF.emitLoadOfLValue(E, std::move(lv), C.withFollowingSideEffects());
23712376
}
23722377

23732378
RValue RValueEmitter::visitDynamicMemberRefExpr(DynamicMemberRefExpr *E,
@@ -2386,7 +2391,9 @@ RValue RValueEmitter::visitSubscriptExpr(SubscriptExpr *E, SGFContext C) {
23862391
FormalEvaluationScope scope(SGF);
23872392

23882393
LValue lv = SGF.emitLValue(E, AccessKind::Read);
2389-
return SGF.emitLoadOfLValue(E, std::move(lv), C);
2394+
// We can't load at +0 without further analysis, since the formal access into
2395+
// the lvalue will end immediately.
2396+
return SGF.emitLoadOfLValue(E, std::move(lv), C.withFollowingSideEffects());
23902397
}
23912398

23922399
RValue RValueEmitter::visitDynamicSubscriptExpr(

lib/SILGen/SILGenLValue.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3127,7 +3127,7 @@ RValue SILGenFunction::emitLoadOfLValue(SILLocation loc, LValue &&src,
31273127
PathComponent &&component =
31283128
drillToLastComponent(*this, loc, std::move(src), addr, AccessKind::Read);
31293129

3130-
// If the last component is physical, just drill down and load from it.
3130+
// If the last component is physical, drill down and load from it.
31313131
if (component.isPhysical()) {
31323132
addr = std::move(component.asPhysical())
31333133
.offset(*this, loc, addr, AccessKind::Read);
@@ -3137,7 +3137,7 @@ RValue SILGenFunction::emitLoadOfLValue(SILLocation loc, LValue &&src,
31373137
isGuaranteedValid));
31383138
}
31393139

3140-
// If the last component is logical, just emit a get.
3140+
// If the last component is logical, emit a get.
31413141
return std::move(component.asLogical()).get(*this, loc, addr, C);
31423142
}
31433143

test/SILGen/dynamic_lookup.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ func direct_to_static_method(_ obj: AnyObject) {
6262
// CHECK: store [[ARG_COPY]] to [init] [[PBOBJ]] : $*AnyObject
6363
// CHECK: end_borrow [[BORROWED_ARG]] from [[ARG]]
6464
// CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PBOBJ]]
65-
// CHECK-NEXT: [[OBJCOPY:%[0-9]+]] = load_borrow [[READ]] : $*AnyObject
65+
// CHECK-NEXT: [[OBJCOPY:%[0-9]+]] = load [copy] [[READ]] : $*AnyObject
6666
// CHECK: end_access [[READ]]
6767
// CHECK-NEXT: [[OBJMETA:%[0-9]+]] = existential_metatype $@thick AnyObject.Type, [[OBJCOPY]] : $AnyObject
6868
// CHECK-NEXT: [[OPENMETA:%[0-9]+]] = open_existential_metatype [[OBJMETA]] : $@thick AnyObject.Type to $@thick (@opened([[UUID:".*"]]) AnyObject).Type
@@ -141,7 +141,7 @@ func opt_to_static_method(_ obj: AnyObject) {
141141
// CHECK: [[OPTBOX:%[0-9]+]] = alloc_box ${ var Optional<@callee_owned () -> ()> }
142142
// CHECK: [[PBO:%.*]] = project_box [[OPTBOX]]
143143
// CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PBOBJ]]
144-
// CHECK: [[OBJCOPY:%[0-9]+]] = load_borrow [[READ]] : $*AnyObject
144+
// CHECK: [[OBJCOPY:%[0-9]+]] = load [copy] [[READ]] : $*AnyObject
145145
// CHECK: [[OBJMETA:%[0-9]+]] = existential_metatype $@thick AnyObject.Type, [[OBJCOPY]] : $AnyObject
146146
// CHECK: [[OPENMETA:%[0-9]+]] = open_existential_metatype [[OBJMETA]] : $@thick AnyObject.Type to $@thick (@opened
147147
// CHECK: [[OBJCMETA:%[0-9]+]] = thick_to_objc_metatype [[OPENMETA]]

test/SILGen/functions.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ func calls(_ i:Int, j:Int, k:Int) {
176176
// -- Curry the Type onto static method argument lists.
177177

178178
// CHECK: [[READC:%.*]] = begin_access [read] [unknown] [[CADDR]]
179-
// CHECK: [[C:%[0-9]+]] = load_borrow [[READC]]
179+
// CHECK: [[C:%[0-9]+]] = load [copy] [[READC]]
180180
// CHECK: [[META:%.*]] = value_metatype $@thick SomeClass.Type, [[C]]
181181
// CHECK: [[METHOD:%[0-9]+]] = class_method [[META]] : {{.*}}, #SomeClass.static_method!1
182182
// CHECK: [[READI:%.*]] = begin_access [read] [unknown] [[IADDR]]
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// RUN: %target-swift-frontend -emit-silgen %s | %FileCheck %s
2+
3+
class A {
4+
lazy var b: B = B()
5+
}
6+
7+
final class B {
8+
var c: C? {
9+
get { return nil }
10+
set {}
11+
}
12+
}
13+
14+
struct C {
15+
let d: String
16+
}
17+
18+
// CHECK-LABEL: sil hidden @{{.*}}test
19+
func test(a: A) {
20+
let s: String?
21+
// CHECK: [[C_TEMP:%.*]] = alloc_stack $Optional<C>
22+
// CHECK: [[TAG:%.*]] = select_enum_addr [[C_TEMP]]
23+
// CHECK: cond_br [[TAG]], [[SOME:bb[0-9]+]], [[NONE:bb[0-9]+]]
24+
// CHECK: [[SOME]]:
25+
// CHECK: [[C_PAYLOAD:%.*]] = unchecked_take_enum_data_addr [[C_TEMP]]
26+
// -- This must be a copy, since we'll immediately destroy the value in the
27+
// temp buffer
28+
// CHECK: [[LOAD:%.*]] = load [copy] [[C_PAYLOAD]]
29+
// CHECK: destroy_addr [[C_TEMP]]
30+
s = a.b.c?.d
31+
print(s)
32+
}

test/SILGen/opaque_values_silgen.swift

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1022,20 +1022,21 @@ func s480_________getError(someError: Error) -> Any {
10221022
// CHECK-LABEL: sil private @_T020opaque_values_silgen21s490_______loadBorrowyyF3FooL_V3foo7ElementQzSg5IndexQz3pos_tF : $@convention(method) <Elements where Elements : Collection> (@in Elements.Index, @inout Foo<Elements>) -> @out Optional<Elements.Element> {
10231023
// CHECK: bb0(%0 : $Elements.Index, %1 : $*Foo<Elements>):
10241024
// CHECK: [[READ:%.*]] = begin_access [read] [unknown] %1 : $*Foo<Elements>
1025-
// CHECK: [[LOAD:%.*]] = load_borrow [[READ]] : $*Foo<Elements>
1025+
// CHECK: [[LOAD:%.*]] = load [copy] [[READ]] : $*Foo<Elements>
10261026
// CHECK: end_access [[READ]] : $*Foo<Elements>
1027-
// CHECK: [[EXTRACT:%.*]] = struct_extract [[LOAD]] : $Foo<Elements>, #<abstract function>Foo._elements
1027+
// CHECK: [[BORROW_LOAD:%.*]] = begin_borrow [[LOAD]]
1028+
// CHECK: [[EXTRACT:%.*]] = struct_extract [[BORROW_LOAD]] : $Foo<Elements>, #<abstract function>Foo._elements
10281029
// CHECK: [[COPYELT:%.*]] = copy_value [[EXTRACT]] : $Elements
10291030
// CHECK: [[BORROW:%.*]] = begin_borrow %0 : $Elements.Index
10301031
// CHECK: [[COPYIDX:%.*]] = copy_value [[BORROW]] : $Elements.Index
10311032
// CHECK: [[WT:%.*]] = witness_method $Elements, #Collection.subscript!getter.1 : <Self where Self : Collection> (Self) -> (Self.Index) -> Self.Element : $@convention(witness_method) <τ_0_0 where τ_0_0 : Collection> (@in τ_0_0.Index, @in_guaranteed τ_0_0) -> @out τ_0_0.Element
10321033
// CHECK: %{{.*}} = apply [[WT]]<Elements>([[COPYIDX]], [[COPYELT]]) : $@convention(witness_method) <τ_0_0 where τ_0_0 : Collection> (@in τ_0_0.Index, @in_guaranteed τ_0_0) -> @out τ_0_0.Element
10331034
// CHECK: destroy_value [[COPYELT]] : $Elements
1034-
// CHECK: [[ENUM:%.*]] = enum $Optional<Elements.Element>, #Optional.some!enumelt.1, %12 : $Elements.Element
1035+
// CHECK: [[ENUM:%.*]] = enum $Optional<Elements.Element>, #Optional.some!enumelt.1, %13 : $Elements.Element
10351036
// CHECK: end_borrow [[BORROW]] from %0 : $Elements.Index, $Elements.Index
1036-
// CHECK: end_borrow [[LOAD]] from [[READ]] : $Foo<Elements>, $*Foo<Elements>
1037+
// CHECK: destroy_value [[LOAD]]
10371038
// CHECK: destroy_value %0 : $Elements.Index
1038-
// CHECK: return %14 : $Optional<Elements.Element>
1039+
// CHECK: return %15 : $Optional<Elements.Element>
10391040
// CHECK-LABEL: } // end sil function '_T020opaque_values_silgen21s490_______loadBorrowyyF3FooL_V3foo7ElementQzSg5IndexQz3pos_tF'
10401041

10411042
func s490_______loadBorrow() {

0 commit comments

Comments
 (0)