mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Merge pull request #85691 from eeckstein/fix-sil-combine
SILCombine: fix propagation of concrete existentials in enums
This commit is contained in:
@@ -213,14 +213,6 @@ castValueToABICompatibleType(SILBuilder *builder, SILPassManager *pm,
|
||||
/// ```
|
||||
bool layoutIsTypeDependent(NominalTypeDecl *decl);
|
||||
|
||||
/// Peek through trivial Enum initialization, typically for pointless
|
||||
/// Optionals.
|
||||
///
|
||||
/// The returned InitEnumDataAddr dominates the given
|
||||
/// UncheckedTakeEnumDataAddrInst.
|
||||
InitEnumDataAddrInst *
|
||||
findInitAddressForTrivialEnum(UncheckedTakeEnumDataAddrInst *utedai);
|
||||
|
||||
/// Returns a project_box if it is the next instruction after \p ABI and
|
||||
/// and has \p ABI as operand. Otherwise it creates a new project_box right
|
||||
/// after \p ABI and returns it.
|
||||
|
||||
@@ -171,20 +171,6 @@ static SILInstruction *getStackInitInst(SILValue allocStackAddr,
|
||||
if (auto *ASI = dyn_cast<AllocStackInst>(CAI->getSrc()))
|
||||
return getStackInitInst(ASI, CAI, isCopied);
|
||||
|
||||
// Peek through a stack location holding an Enum.
|
||||
// %stack_adr = alloc_stack
|
||||
// %data_adr = init_enum_data_addr %stk_adr
|
||||
// %enum_adr = inject_enum_addr %stack_adr
|
||||
// %copy_src = unchecked_take_enum_data_addr %enum_adr
|
||||
// Replace %copy_src with %data_adr and recurse.
|
||||
//
|
||||
// TODO: a general Optional elimination sil-combine could
|
||||
// supersede this check.
|
||||
if (auto *UTEDAI = dyn_cast<UncheckedTakeEnumDataAddrInst>(CAI->getSrc())) {
|
||||
if (InitEnumDataAddrInst *IEDAI = findInitAddressForTrivialEnum(UTEDAI))
|
||||
return getStackInitInst(IEDAI, CAI, isCopied);
|
||||
}
|
||||
|
||||
// Check if the CAISrc is a global_addr.
|
||||
if (auto *GAI = dyn_cast<GlobalAddrInst>(CAI->getSrc()))
|
||||
return findInitExistentialFromGlobalAddr(GAI, CAI);
|
||||
|
||||
@@ -886,55 +886,6 @@ ProjectBoxInst *swift::getOrCreateProjectBox(AllocBoxInst *abi,
|
||||
return builder.createProjectBox(abi->getLoc(), abi, index);
|
||||
}
|
||||
|
||||
// Peek through trivial Enum initialization, typically for pointless
|
||||
// Optionals.
|
||||
//
|
||||
// Given an UncheckedTakeEnumDataAddrInst, check that there are no
|
||||
// other uses of the Enum value and return the address used to initialized the
|
||||
// enum's payload:
|
||||
//
|
||||
// %stack_adr = alloc_stack
|
||||
// %data_adr = init_enum_data_addr %stk_adr
|
||||
// %enum_adr = inject_enum_addr %stack_adr
|
||||
// %copy_src = unchecked_take_enum_data_addr %enum_adr
|
||||
// dealloc_stack %stack_adr
|
||||
// (No other uses of %stack_adr.)
|
||||
InitEnumDataAddrInst *
|
||||
swift::findInitAddressForTrivialEnum(UncheckedTakeEnumDataAddrInst *utedai) {
|
||||
auto *asi = dyn_cast<AllocStackInst>(utedai->getOperand());
|
||||
if (!asi)
|
||||
return nullptr;
|
||||
|
||||
InjectEnumAddrInst *singleInject = nullptr;
|
||||
InitEnumDataAddrInst *singleInit = nullptr;
|
||||
for (auto use : asi->getUses()) {
|
||||
auto *user = use->getUser();
|
||||
if (user == utedai)
|
||||
continue;
|
||||
|
||||
// If there is a single init_enum_data_addr and a single inject_enum_addr,
|
||||
// those instructions must dominate the unchecked_take_enum_data_addr.
|
||||
// Otherwise the enum wouldn't be initialized on all control flow paths.
|
||||
if (auto *inj = dyn_cast<InjectEnumAddrInst>(user)) {
|
||||
if (singleInject)
|
||||
return nullptr;
|
||||
singleInject = inj;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (auto *init = dyn_cast<InitEnumDataAddrInst>(user)) {
|
||||
if (singleInit)
|
||||
return nullptr;
|
||||
singleInit = init;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isa<DeallocStackInst>(user) || isa<DebugValueInst>(user))
|
||||
continue;
|
||||
}
|
||||
return singleInit;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Closure Deletion
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@@ -786,6 +786,39 @@ bb0(%0 : $S):
|
||||
return %20 : $()
|
||||
}
|
||||
|
||||
protocol Q2 {
|
||||
func f()
|
||||
}
|
||||
|
||||
struct S2 : Q2 {
|
||||
func f()
|
||||
}
|
||||
|
||||
// CHECK-LABEL: sil [ossa] @overridden_enum_in_alloc_stack :
|
||||
// CHECK: witness_method $@opened
|
||||
// CHECK-LABEL: } // end sil function 'overridden_enum_in_alloc_stack'
|
||||
sil [ossa] @overridden_enum_in_alloc_stack : $@convention(thin) (S2, @in_guaranteed Optional<any Q2>) -> () {
|
||||
bb0(%0 : $S2, %1 : $*Optional<any Q2>):
|
||||
%2 = alloc_stack $Optional<any Q2>
|
||||
%3 = init_enum_data_addr %2, #Optional.some!enumelt
|
||||
%4 = init_existential_addr %3, $S2
|
||||
store %0 to [trivial] %4
|
||||
inject_enum_addr %2, #Optional.some!enumelt
|
||||
copy_addr %1 to %2
|
||||
%8 = unchecked_take_enum_data_addr %2, #Optional.some!enumelt
|
||||
%9 = alloc_stack $any Q2
|
||||
copy_addr %8 to [init] %9
|
||||
%11 = open_existential_addr immutable_access %9 to $*@opened("9EED66EA-C9C5-11F0-85FF-0EA13E3AABB2", any Q2) Self
|
||||
%12 = witness_method $@opened("9EED66EA-C9C5-11F0-85FF-0EA13E3AABB2", any Q2) Self, #Q2.f : <Self where Self : Q2> (Self) -> () -> (), %11 : $*@opened("9EED66EA-C9C5-11F0-85FF-0EA13E3AABB2", any Q2) Self : $@convention(witness_method: Q2) <τ_0_0 where τ_0_0 : Q2> (@in_guaranteed τ_0_0) -> ()
|
||||
%13 = apply %12<@opened("9EED66EA-C9C5-11F0-85FF-0EA13E3AABB2", any Q2) Self>(%11) : $@convention(witness_method: Q2) <τ_0_0 where τ_0_0 : Q2> (@in_guaranteed τ_0_0) -> ()
|
||||
destroy_addr %9
|
||||
dealloc_stack %9
|
||||
destroy_addr %2
|
||||
dealloc_stack %2
|
||||
%18 = tuple ()
|
||||
return %18
|
||||
}
|
||||
|
||||
sil_vtable SubscriptionViewControllerBuilder {}
|
||||
sil_vtable SubscriptionViewController {}
|
||||
sil_vtable ViewController {}
|
||||
|
||||
Reference in New Issue
Block a user