Merge pull request #72479 from meg-gupta/fixsilcombineagain

Fix SILCombine of inject_enum_addr to correctly check for unreferenceable storage
This commit is contained in:
Meghana Gupta
2024-03-21 10:14:14 -07:00
committed by GitHub
4 changed files with 53 additions and 1 deletions

View File

@@ -604,6 +604,10 @@ bool specializeAppliesInFunction(SILFunction &F,
/// types aggregated together at each level.
SILValue createEmptyAndUndefValue(SILType ty, SILInstruction *insertionPoint,
SILBuilderContext &ctx, bool noUndef = false);
/// Check if a struct or its fields can have unreferenceable storage.
bool findUnreferenceableStorage(StructDecl *decl, SILType structType,
SILFunction *func);
} // end namespace swift
#endif // SWIFT_SILOPTIMIZER_UTILS_INSTOPTUTILS_H

View File

@@ -1246,7 +1246,7 @@ SILCombiner::visitInjectEnumAddrInst(InjectEnumAddrInst *IEAI) {
// We cannot create a struct when it has unreferenceable storage.
if (elemType.isEmpty(*IEAI->getFunction()) && structDecl &&
structDecl->hasUnreferenceableStorage()) {
findUnreferenceableStorage(structDecl, elemType, IEAI->getFunction())) {
return nullptr;
}

View File

@@ -2009,3 +2009,21 @@ SILValue swift::createEmptyAndUndefValue(SILType ty,
assert(!noUndef);
return SILUndef::get(insertionPoint->getFunction(), ty);
}
bool swift::findUnreferenceableStorage(StructDecl *decl, SILType structType,
SILFunction *func) {
if (decl->hasUnreferenceableStorage()) {
return true;
}
// Check if any fields have unreferenceable stoage
for (auto *field : decl->getStoredProperties()) {
TypeExpansionContext tec = *func;
auto fieldTy = structType.getFieldType(field, func->getModule(), tec);
if (auto *fieldStructDecl = fieldTy.getStructOrBoundGenericStruct()) {
if (findUnreferenceableStorage(fieldStructDecl, fieldTy, func)) {
return true;
}
}
}
return false;
}

View File

@@ -362,3 +362,33 @@ bb3:
%8 = tuple ()
return %8 : $()
}
struct NestedUnreferenceableStorage {
let e: EmptyCUnion
}
sil @no_init_nested_c_union : $@convention(thin) () -> (@out NestedUnreferenceableStorage)
// CHECK-LABEL: sil @test_empty_nested_c_union : $@convention(thin) () -> () {
// CHECK: inject_enum_addr
// CHECK-LABEL: } // end sil function 'test_empty_nested_c_union'
sil @test_empty_nested_c_union : $@convention(thin) () -> () {
bb0:
%0 = alloc_stack $Optional<NestedUnreferenceableStorage>
%1 = init_enum_data_addr %0 : $*Optional<NestedUnreferenceableStorage>, #Optional.some!enumelt
%f = function_ref @no_init_nested_c_union : $@convention(thin) () -> (@out NestedUnreferenceableStorage)
apply %f(%1) : $@convention(thin) () -> (@out NestedUnreferenceableStorage)
inject_enum_addr %0 : $*Optional<NestedUnreferenceableStorage>, #Optional.some!enumelt
switch_enum_addr %0 : $*Optional<NestedUnreferenceableStorage>, case #Optional.some!enumelt: bb1, case #Optional.none!enumelt: bb2
bb1:
br bb3
bb2:
br bb3
bb3:
dealloc_stack %0 : $*Optional<NestedUnreferenceableStorage>
%8 = tuple ()
return %8 : $()
}