Skip to content

Commit b194435

Browse files
committed
[sil-cloner] Strip out the argument of default blocks of switch_enum/checked_cast_br when cloning from ossa into non-ossa code.
1 parent c12e556 commit b194435

File tree

4 files changed

+107
-4
lines changed

4 files changed

+107
-4
lines changed

include/swift/SIL/SILCloner.h

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -715,12 +715,43 @@ void SILCloner<ImplClass>::visitBlocksDepthFirst(SILBasicBlock *startBB) {
715715
template<typename ImplClass>
716716
void
717717
SILCloner<ImplClass>::doFixUp(SILFunction *F) {
718+
// If our source function is in ossa form, but the function into which we are
719+
// cloning is not in ossa, after we clone, eliminate default arguments.
720+
if (!getBuilder().hasOwnership() && F->hasOwnership()) {
721+
for (auto &Block : getBuilder().getFunction()) {
722+
auto *Term = Block.getTerminator();
723+
if (auto *CCBI = dyn_cast<CheckedCastBranchInst>(Term)) {
724+
// Check if we have a default argument.
725+
auto *FailureBlock = CCBI->getFailureBB();
726+
assert(FailureBlock->getNumArguments() <= 1 &&
727+
"We should either have no args or a single default arg");
728+
if (0 == FailureBlock->getNumArguments())
729+
continue;
730+
FailureBlock->getArgument(0)->replaceAllUsesWith(CCBI->getOperand());
731+
FailureBlock->eraseArgument(0);
732+
continue;
733+
}
734+
735+
if (auto *SEI = dyn_cast<SwitchEnumInst>(Term)) {
736+
if (auto DefaultBlock = SEI->getDefaultBBOrNull()) {
737+
assert(DefaultBlock.get()->getNumArguments() <= 1 &&
738+
"We should either have no args or a single default arg");
739+
if (0 == DefaultBlock.get()->getNumArguments())
740+
continue;
741+
DefaultBlock.get()->getArgument(0)->replaceAllUsesWith(
742+
SEI->getOperand());
743+
DefaultBlock.get()->eraseArgument(0);
744+
continue;
745+
}
746+
}
747+
}
748+
}
749+
718750
// Remove any code after unreachable instructions.
719751

720-
// NOTE: It is unfortunate that it essentially duplicates
721-
// the code from sil-combine, but doing so allows for
722-
// avoiding any cross-layer invocations between SIL and
723-
// SILOptimizer layers.
752+
// NOTE: It is unfortunate that it essentially duplicates the code from
753+
// sil-combine, but doing so allows for avoiding any cross-layer invocations
754+
// between SIL and SILOptimizer layers.
724755

725756
for (auto *BB : BlocksWithUnreachables) {
726757
for (auto &I : *BB) {

include/swift/SIL/SILInstruction.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7207,10 +7207,14 @@ class SwitchEnumInstBase : public TermInst {
72077207
bool hasDefault() const {
72087208
return SILInstruction::Bits.SwitchEnumInstBase.HasDefault;
72097209
}
7210+
72107211
SILBasicBlock *getDefaultBB() const {
72117212
assert(hasDefault() && "doesn't have a default");
72127213
return getSuccessorBuf()[getNumCases()];
72137214
}
7215+
7216+
NullablePtr<SILBasicBlock> getDefaultBBOrNull() const;
7217+
72147218
ProfileCounter getDefaultCount() const {
72157219
assert(hasDefault() && "doesn't have a default");
72167220
return getSuccessorBuf()[getNumCases()].getCount();

lib/SIL/SILInstructions.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1566,6 +1566,12 @@ SwitchEnumInstBase::getUniqueCaseForDestination(SILBasicBlock *BB) {
15661566
return D;
15671567
}
15681568

1569+
NullablePtr<SILBasicBlock> SwitchEnumInstBase::getDefaultBBOrNull() const {
1570+
if (!hasDefault())
1571+
return nullptr;
1572+
return getDefaultBB();
1573+
}
1574+
15691575
SwitchEnumInst *SwitchEnumInst::create(
15701576
SILDebugLocation Loc, SILValue Operand, SILBasicBlock *DefaultBB,
15711577
ArrayRef<std::pair<EnumElementDecl *, SILBasicBlock *>> CaseBBs,

test/SILOptimizer/mandatory_inlining_ossa_to_non_ossa.sil

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,12 @@ sil @in_guaranteed_user : $@convention(thin) (@in_guaranteed Builtin.NativeObjec
1414
sil @guaranteed_user : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
1515
sil @owned_user : $@convention(thin) (@owned Builtin.NativeObject) -> ()
1616

17+
class Klass {}
18+
enum FakeOptional<T> {
19+
case some(T)
20+
case none
21+
}
22+
1723
///////////
1824
// Tests //
1925
///////////
@@ -231,3 +237,59 @@ bb0(%0 : $Builtin.NativeObject):
231237
return %9999 : $()
232238
}
233239

240+
sil [transparent] [ossa] @term_ossa_callee : $@convention(thin) (@owned Builtin.NativeObject, @owned FakeOptional<Klass>) -> () {
241+
bb0(%0 : @owned $Builtin.NativeObject, %1 : @owned $FakeOptional<Klass>):
242+
checked_cast_br %0 : $Builtin.NativeObject to $Klass, bb1, bb2
243+
244+
bb1(%1a : @owned $Klass):
245+
destroy_value %1a : $Klass
246+
br bb3
247+
248+
bb2(%2 : @owned $Builtin.NativeObject):
249+
destroy_value %2 : $Builtin.NativeObject
250+
br bb3
251+
252+
bb3:
253+
switch_enum %1 : $FakeOptional<Klass>, case #FakeOptional.some: bb4, default bb5
254+
255+
bb4(%3 : @owned $Klass):
256+
destroy_value %3 : $Klass
257+
br bb6
258+
259+
bb5(%4 : @owned $FakeOptional<Klass>):
260+
destroy_value %4 : $FakeOptional<Klass>
261+
br bb6
262+
263+
bb6:
264+
%9999 = tuple()
265+
return %9999 : $()
266+
}
267+
268+
// CHECK-LABEL: sil @term_non_ossa_caller : $@convention(thin) (@owned Builtin.NativeObject, @owned FakeOptional<Klass>) -> () {
269+
// CHECK: bb0([[ARG0:%.*]] : $Builtin.NativeObject, [[ARG1:%.*]] : $FakeOptional<Klass>):
270+
// CHECK: checked_cast_br [[ARG0]] : $Builtin.NativeObject to $Klass, [[YES:bb[0-9]+]], [[NO:bb[0-9]+]]
271+
//
272+
// CHECK: [[YES]]([[SUCC:%.*]] :
273+
// CHECK: release_value [[SUCC]]
274+
// CHECK: br [[CONT:bb[0-9]+]]
275+
//
276+
// CHECK: [[NO]]:
277+
// CHECK: release_value [[ARG0]]
278+
// CHECK: br [[CONT]]
279+
//
280+
// CHECK: [[CONT]]:
281+
// CHECK: switch_enum [[ARG1]] : $FakeOptional<Klass>, case #FakeOptional.some!enumelt.1: [[SOME:bb[0-9]+]], default [[DEFAULT:bb[0-9]+]]
282+
//
283+
// CHECK: [[SOME]]([[PAYLOAD:%.*]] :
284+
// CHECK: release_value [[PAYLOAD]]
285+
//
286+
// CHECK: [[DEFAULT]]
287+
// CHECK: release_value [[ARG1]]
288+
// CHECK: } // end sil function 'term_non_ossa_caller'
289+
sil @term_non_ossa_caller : $@convention(thin) (@owned Builtin.NativeObject, @owned FakeOptional<Klass>) -> () {
290+
bb0(%0 : $Builtin.NativeObject, %1 : $FakeOptional<Klass>):
291+
%2 = function_ref @term_ossa_callee : $@convention(thin) (@owned Builtin.NativeObject, @owned FakeOptional<Klass>) -> ()
292+
apply %2(%0, %1) : $@convention(thin) (@owned Builtin.NativeObject, @owned FakeOptional<Klass>) -> ()
293+
%9999 = tuple()
294+
return %9999 : $()
295+
}

0 commit comments

Comments
 (0)