Skip to content

Commit fa819fe

Browse files
authored
Merge pull request #77560 from eeckstein/fix-silcombine
Optimizer: when propagating the concrete type of an existential, make sure to not violate dominance order
2 parents af58e6e + 63141b6 commit fa819fe

File tree

2 files changed

+59
-15
lines changed

2 files changed

+59
-15
lines changed

lib/SILOptimizer/Utils/InstOptUtils.cpp

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -904,30 +904,34 @@ swift::findInitAddressForTrivialEnum(UncheckedTakeEnumDataAddrInst *utedai) {
904904
if (!asi)
905905
return nullptr;
906906

907-
SILInstruction *singleUser = nullptr;
907+
InjectEnumAddrInst *singleInject = nullptr;
908+
InitEnumDataAddrInst *singleInit = nullptr;
908909
for (auto use : asi->getUses()) {
909910
auto *user = use->getUser();
910911
if (user == utedai)
911912
continue;
912913

913-
// As long as there's only one UncheckedTakeEnumDataAddrInst and one
914-
// InitEnumDataAddrInst, we don't care how many InjectEnumAddr and
915-
// DeallocStack users there are.
916-
if (isa<InjectEnumAddrInst>(user) || isa<DeallocStackInst>(user))
914+
// If there is a single init_enum_data_addr and a single inject_enum_addr,
915+
// those instructions must dominate the unchecked_take_enum_data_addr.
916+
// Otherwise the enum wouldn't be initialized on all control flow paths.
917+
if (auto *inj = dyn_cast<InjectEnumAddrInst>(user)) {
918+
if (singleInject)
919+
return nullptr;
920+
singleInject = inj;
917921
continue;
922+
}
918923

919-
if (singleUser)
920-
return nullptr;
924+
if (auto *init = dyn_cast<InitEnumDataAddrInst>(user)) {
925+
if (singleInit)
926+
return nullptr;
927+
singleInit = init;
928+
continue;
929+
}
921930

922-
singleUser = user;
931+
if (isa<DeallocStackInst>(user) || isa<DebugValueInst>(user))
932+
continue;
923933
}
924-
if (!singleUser)
925-
return nullptr;
926-
927-
// Assume, without checking, that the returned InitEnumDataAddr dominates the
928-
// given UncheckedTakeEnumDataAddrInst, because that's how SIL is defined. I
929-
// don't know where this is actually verified.
930-
return dyn_cast<InitEnumDataAddrInst>(singleUser);
934+
return singleInit;
931935
}
932936

933937
//===----------------------------------------------------------------------===//

test/SILOptimizer/sil_combine_enums.sil

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ enum Numerals {
1616
case Four
1717
}
1818

19+
protocol P {
20+
mutating func foo()
21+
}
22+
23+
sil @createit : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@thick τ_0_0.Type) -> @out τ_0_0
1924
sil @external_func: $@convention(thin) () -> ()
2025

2126
//CHECK-LABEL: eliminate_sw_enum_addr
@@ -663,3 +668,38 @@ bb0(%0 : $S):
663668
return %11 : $()
664669
}
665670

671+
// CHECK-LABEL: sil @dont_promote_existential_type_from_non_dominating_block :
672+
// Just check that this doesn't crash
673+
// CHECK: } // end sil function 'dont_promote_existential_type_from_non_dominating_block'
674+
sil @dont_promote_existential_type_from_non_dominating_block : $@convention(thin) (@thick any P.Type) -> () {
675+
bb0(%0 : $@thick any P.Type):
676+
%1 = alloc_stack $Optional<any P>
677+
cond_br undef, bb1, bb2
678+
679+
bb1:
680+
inject_enum_addr %1 : $*Optional<any P>, #Optional.none!enumelt
681+
br bb3
682+
683+
bb2:
684+
%5 = init_enum_data_addr %1 : $*Optional<any P>, #Optional.some!enumelt
685+
%6 = open_existential_metatype %0 : $@thick any P.Type to $@thick (@opened("B0100688-9C78-11EF-8A3C-4EA2A866E4C4", any P) Self).Type
686+
%7 = init_existential_addr %5 : $*any P, $@opened("B0100688-9C78-11EF-8A3C-4EA2A866E4C4", any P) Self
687+
%f = function_ref @createit : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@thick τ_0_0.Type) -> @out τ_0_0
688+
%a = apply %f<@opened("B0100688-9C78-11EF-8A3C-4EA2A866E4C4", any P) Self>(%7, %6) : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@thick τ_0_0.Type) -> @out τ_0_0
689+
inject_enum_addr %1 : $*Optional<any P>, #Optional.some!enumelt
690+
br bb3
691+
692+
bb3:
693+
%9 = unchecked_take_enum_data_addr %1 : $*Optional<any P>, #Optional.some!enumelt
694+
dealloc_stack %1 : $*Optional<any P>
695+
%11 = alloc_stack [lexical] [var_decl] $any P, var, name "comp"
696+
copy_addr [take] %9 to [init] %11 : $*any P
697+
%13 = open_existential_addr mutable_access %11 : $*any P to $*@opened("36EE10D8-9C78-11EF-8A3C-4EA2A866E4C4", any P) Self
698+
%14 = witness_method $@opened("36EE10D8-9C78-11EF-8A3C-4EA2A866E4C4", any P) Self, #P.foo : <Self where Self : P> (inout Self) -> () -> (), %13 : $*@opened("36EE10D8-9C78-11EF-8A3C-4EA2A866E4C4", any P) Self : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@inout τ_0_0) -> ()
699+
%15 = apply %14<@opened("36EE10D8-9C78-11EF-8A3C-4EA2A866E4C4", any P) Self>(%13) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@inout τ_0_0) -> ()
700+
destroy_addr %11 : $*any P
701+
dealloc_stack %11 : $*any P
702+
%18 = tuple ()
703+
return %18 : $()
704+
}
705+

0 commit comments

Comments
 (0)