Skip to content

Commit a8dc311

Browse files
committed
[AddressLowering] Handle multidefault switch_enum.
If a switch_enum instruction (1) exhaustively handles all cases, there is no default case or block corresponding to it. If (2) it handles all cases but one, the default case corresponds to the unique unhandled case. Otherwise, (3) the default case corresponds to all the unhandled cases. The first two scenarios were already handled by address lowering. Here, handling is added for case (3). It is similar to what is already done for rewriting cases except that no unchecked_take_enum_data_addr must be created and that the argument is always address-only (being the same type as the operand of the switch_enum which is only being rewritten because it was address-only).
1 parent 5eb8fa4 commit a8dc311

File tree

2 files changed

+32
-0
lines changed

2 files changed

+32
-0
lines changed

lib/SILOptimizer/Mandatory/AddressLowering.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3053,6 +3053,20 @@ void UseRewriter::visitSwitchEnumInst(SwitchEnumInst * switchEnum) {
30533053
defaultCounter = switchEnum->getDefaultCount();
30543054
if (auto defaultDecl = switchEnum->getUniqueCaseForDefault()) {
30553055
rewriteCase(defaultDecl.get(), defaultBB);
3056+
} else {
3057+
assert(defaultBB->getArguments().size() == 1);
3058+
SILArgument *arg = defaultBB->getArgument(0);
3059+
assert(arg->getType().isAddressOnly(*pass.function));
3060+
auto builder = pass.getBuilder(defaultBB->begin());
3061+
auto addr = enumAddr;
3062+
auto *load = builder.createTrivialLoadOr(switchEnum->getLoc(), addr,
3063+
LoadOwnershipQualifier::Take);
3064+
// Remap arg to the new dummy load which will be deleted during
3065+
// deleteRewrittenInstructions.
3066+
arg->replaceAllUsesWith(load);
3067+
pass.valueStorageMap.replaceValue(arg, load);
3068+
markRewritten(load, addr);
3069+
defaultBB->eraseArgument(0);
30563070
}
30573071
}
30583072
auto builder = pass.getTermBuilder(switchEnum);

test/SILOptimizer/address_lowering.sil

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1130,6 +1130,24 @@ bb4:
11301130
return %31 : $()
11311131
}
11321132

1133+
// Verify the handling of non-unique default case blocks when there is more
1134+
// than one case handled by default.
1135+
// CHECK-LABEL: sil [ossa] @f221_testSwitchDefault : $@convention(thin) <T> (@in Optional<T>) -> () {
1136+
// CHECK: {{bb[0-9]+}}([[INSTANCE:%[^,]+]] : $*Optional<T>):
1137+
// CHECK: switch_enum_addr [[INSTANCE]] : $*Optional<T>, default [[EXIT:bb[0-9]+]]
1138+
// CHECK: [[EXIT]]:
1139+
// CHECK: destroy_addr [[INSTANCE]] : $*Optional<T>
1140+
// CHECK-LABEL: } // end sil function 'f221_testSwitchDefault'
1141+
sil [ossa] @f221_testSwitchDefault : $@convention(thin) <T> (@in Optional<T>) -> () {
1142+
entry(%instance : @owned $Optional<T>):
1143+
switch_enum %instance : $Optional<T>, default exit
1144+
1145+
exit(%instance_2 : @owned $Optional<T>):
1146+
destroy_value %instance_2 : $Optional<T>
1147+
%retval = tuple ()
1148+
return %retval : $()
1149+
}
1150+
11331151
// CHECK-LABEL: sil [ossa] @f230_testTryApply : $@convention(thin) <T> (@in T) -> (@out T, @error any Error) {
11341152
// CHECK: bb0(%0 : $*T, %1 : $*T):
11351153
// CHECK: [[F:%.*]] = function_ref @throwsError : $@convention(thin) <τ_0_0> (@in τ_0_0) -> (@out τ_0_0, @error any Error)

0 commit comments

Comments
 (0)