Skip to content

Commit 0a0f8cf

Browse files
committed
[sil-combine] Update switch_enum_addr -> switch_enum for loadable types for ownership.
1 parent a5e7c3f commit 0a0f8cf

File tree

2 files changed

+114
-20
lines changed

2 files changed

+114
-20
lines changed

lib/SILOptimizer/SILCombiner/SILCombinerMiscVisitors.cpp

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -147,9 +147,6 @@ static EnumElementDecl *getInjectEnumCaseTo(SILValue Addr) {
147147
}
148148

149149
SILInstruction *SILCombiner::visitSwitchEnumAddrInst(SwitchEnumAddrInst *SEAI) {
150-
if (SEAI->getFunction()->hasOwnership())
151-
return nullptr;
152-
153150
// Convert switch_enum_addr -> br
154151
// if the only thing which writes to the address is an inject_enum_addr.
155152
SILValue Addr = SEAI->getOperand();
@@ -172,15 +169,44 @@ SILInstruction *SILCombiner::visitSwitchEnumAddrInst(SwitchEnumAddrInst *SEAI) {
172169
// ->
173170
// %value = load %ptr
174171
// switch_enum %value
175-
SmallVector<std::pair<EnumElementDecl*, SILBasicBlock*>, 8> Cases;
176-
for (int i = 0, e = SEAI->getNumCases(); i < e; ++i)
172+
//
173+
// If we are using ownership, we perform a load_borrow right before the new
174+
// switch_enum and end the borrow scope right afterwards.
175+
Builder.setCurrentDebugScope(SEAI->getDebugScope());
176+
SmallVector<std::pair<EnumElementDecl *, SILBasicBlock *>, 8> Cases;
177+
for (int i : range(SEAI->getNumCases())) {
177178
Cases.push_back(SEAI->getCase(i));
179+
}
178180

179-
Builder.setCurrentDebugScope(SEAI->getDebugScope());
180181
SILBasicBlock *Default = SEAI->hasDefault() ? SEAI->getDefaultBB() : nullptr;
181-
LoadInst *EnumVal = Builder.createLoad(SEAI->getLoc(), Addr,
182-
LoadOwnershipQualifier::Unqualified);
183-
Builder.createSwitchEnum(SEAI->getLoc(), EnumVal, Default, Cases);
182+
SILValue EnumVal = Builder.emitLoadBorrowOperation(SEAI->getLoc(), Addr);
183+
auto *sei = Builder.createSwitchEnum(SEAI->getLoc(), EnumVal, Default, Cases);
184+
185+
if (Builder.hasOwnership()) {
186+
for (int i : range(sei->getNumCases())) {
187+
auto c = sei->getCase(i);
188+
if (c.first->hasAssociatedValues()) {
189+
auto eltType = Addr->getType().getEnumElementType(
190+
c.first, Builder.getModule(), Builder.getTypeExpansionContext());
191+
eltType = eltType.getObjectType();
192+
if (eltType.isTrivial(Builder.getFunction())) {
193+
c.second->createPhiArgument(eltType, OwnershipKind::None);
194+
} else {
195+
c.second->createPhiArgument(eltType, OwnershipKind::Guaranteed);
196+
}
197+
}
198+
Builder.setInsertionPoint(c.second->front().getIterator());
199+
Builder.emitEndBorrowOperation(SEAI->getLoc(), EnumVal);
200+
}
201+
202+
if (auto defaultBlock = sei->getDefaultBBOrNull()) {
203+
defaultBlock.get()->createPhiArgument(EnumVal->getType(),
204+
OwnershipKind::Guaranteed);
205+
Builder.setInsertionPoint(defaultBlock.get()->front().getIterator());
206+
Builder.emitEndBorrowOperation(SEAI->getLoc(), EnumVal);
207+
}
208+
}
209+
184210
return eraseInstFromFunction(*SEAI);
185211
}
186212

test/SILOptimizer/sil_combine_ossa.sil

Lines changed: 79 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1329,6 +1329,9 @@ bb0(%0 : @owned $E):
13291329
return %2 : $Builtin.NativeObject
13301330
}
13311331

1332+
// NOTE: We currently promote the switch_enum, but we do not handle the
1333+
// unchecked_take_enum_data_addr yet.
1334+
//
13321335
// CHECK-LABEL: sil [ossa] @unchecked_take_enum_data_addr_promotion : $@convention(thin) (@inout FakeOptional<B>) -> @owned B {
13331336
// XHECK: bb0(%0 : $*FakeOptional<B>):
13341337
// XHECK-NEXT: [[BORROW:%.*]] = load_borrow
@@ -2254,12 +2257,13 @@ struct FakeInt32 {
22542257
var val : Builtin.Int32
22552258
}
22562259

2257-
// CHECK-LABEL: sil [ossa] @loadable_switchenumaddr_promotion : $@convention(thin) (@in FakeOptional<Builtin.RawPointer>) -> () {
2258-
// XHECK-NOT: switch_enum_addr
2259-
// XHECK: load
2260-
// XHECK-NEXT: switch_enum
2261-
// XHECK-NOT: switch_enum_addr
2262-
sil [ossa] @loadable_switchenumaddr_promotion : $@convention(thin) (@in FakeOptional<Builtin.RawPointer>) -> () {
2260+
// CHECK-LABEL: sil [ossa] @loadable_switchenumaddr_promotion_trivial : $@convention(thin) (@in FakeOptional<Builtin.RawPointer>) -> () {
2261+
// CHECK-NOT: switch_enum_addr
2262+
// CHECK: load [trivial]
2263+
// CHECK-NEXT: switch_enum
2264+
// CHECK-NOT: switch_enum_addr
2265+
// CHECK: } // end sil function 'loadable_switchenumaddr_promotion_trivial'
2266+
sil [ossa] @loadable_switchenumaddr_promotion_trivial : $@convention(thin) (@in FakeOptional<Builtin.RawPointer>) -> () {
22632267
bb0(%0 : $*FakeOptional<Builtin.RawPointer>):
22642268
switch_enum_addr %0 : $*FakeOptional<Builtin.RawPointer>, case #FakeOptional.some!enumelt: bb1, case #FakeOptional.none!enumelt: bb2
22652269

@@ -2274,11 +2278,75 @@ bb3:
22742278
return %2 : $()
22752279
}
22762280

2277-
// CHECK-LABEL: sil [ossa] @resilient_enum_case_propagation
2278-
// XHECK: bb0:
2279-
// XHECK: br bb2
2280-
// XHECK: bb1:
2281-
// XHECK: return
2281+
// CHECK-LABEL: sil [ossa] @loadable_switchenumaddr_promotion_nontrivial : $@convention(thin) (@in_guaranteed FakeOptional<Builtin.NativeObject>) -> () {
2282+
// CHECK-NOT: switch_enum_addr
2283+
// CHECK: load_borrow
2284+
// CHECK-NEXT: switch_enum
2285+
// CHECK-NOT: switch_enum_addr
2286+
// CHECK: } // end sil function 'loadable_switchenumaddr_promotion_nontrivial'
2287+
sil [ossa] @loadable_switchenumaddr_promotion_nontrivial : $@convention(thin) (@in_guaranteed FakeOptional<Builtin.NativeObject>) -> () {
2288+
bb0(%0 : $*FakeOptional<Builtin.NativeObject>):
2289+
switch_enum_addr %0 : $*FakeOptional<Builtin.NativeObject>, case #FakeOptional.some!enumelt: bb1, case #FakeOptional.none!enumelt: bb2
2290+
2291+
bb1:
2292+
br bb3
2293+
2294+
bb2:
2295+
br bb3
2296+
2297+
bb3:
2298+
%2 = tuple()
2299+
return %2 : $()
2300+
}
2301+
2302+
// CHECK-LABEL: sil [ossa] @loadable_switchenumaddr_promotion_trivial_default : $@convention(thin) (@in FakeOptional<Builtin.RawPointer>) -> () {
2303+
// CHECK-NOT: switch_enum_addr
2304+
// CHECK: load [trivial]
2305+
// CHECK-NEXT: switch_enum
2306+
// CHECK-NOT: switch_enum_addr
2307+
// CHECK: } // end sil function 'loadable_switchenumaddr_promotion_trivial_default'
2308+
sil [ossa] @loadable_switchenumaddr_promotion_trivial_default : $@convention(thin) (@in FakeOptional<Builtin.RawPointer>) -> () {
2309+
bb0(%0 : $*FakeOptional<Builtin.RawPointer>):
2310+
switch_enum_addr %0 : $*FakeOptional<Builtin.RawPointer>, case #FakeOptional.some!enumelt: bb1, default bb2
2311+
2312+
bb1:
2313+
br bb3
2314+
2315+
bb2:
2316+
br bb3
2317+
2318+
bb3:
2319+
%2 = tuple()
2320+
return %2 : $()
2321+
}
2322+
2323+
// CHECK-LABEL: sil [ossa] @loadable_switchenumaddr_promotion_nontrivial_default : $@convention(thin) (@in_guaranteed FakeOptional<Builtin.NativeObject>) -> () {
2324+
// CHECK-NOT: switch_enum_addr
2325+
// CHECK: load_borrow
2326+
// CHECK-NEXT: switch_enum
2327+
// CHECK-NOT: switch_enum_addr
2328+
// CHECK: } // end sil function 'loadable_switchenumaddr_promotion_nontrivial_default'
2329+
sil [ossa] @loadable_switchenumaddr_promotion_nontrivial_default : $@convention(thin) (@in_guaranteed FakeOptional<Builtin.NativeObject>) -> () {
2330+
bb0(%0 : $*FakeOptional<Builtin.NativeObject>):
2331+
switch_enum_addr %0 : $*FakeOptional<Builtin.NativeObject>, case #FakeOptional.some!enumelt: bb1, default bb2
2332+
2333+
bb1:
2334+
br bb3
2335+
2336+
bb2:
2337+
br bb3
2338+
2339+
bb3:
2340+
%2 = tuple()
2341+
return %2 : $()
2342+
}
2343+
2344+
// CHECK-LABEL: sil [ossa] @resilient_enum_case_propagation :
2345+
// CHECK: bb0:
2346+
// CHECK: br bb2
2347+
// CHECK: bb1:
2348+
// CHECK: return
2349+
// CHECK: } // end sil function 'resilient_enum_case_propagation'
22822350
sil [ossa] @resilient_enum_case_propagation : $@convention(thin) () -> Builtin.Int64 {
22832351
bb0:
22842352
%0 = alloc_stack $FloatingPointRoundingRule

0 commit comments

Comments
 (0)