Skip to content

Commit 1cccd79

Browse files
authored
Merge pull request #72479 from meg-gupta/fixsilcombineagain
Fix SILCombine of inject_enum_addr to correctly check for unreferenceable storage
2 parents 5d55621 + af22813 commit 1cccd79

File tree

4 files changed

+53
-1
lines changed

4 files changed

+53
-1
lines changed

include/swift/SILOptimizer/Utils/InstOptUtils.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -604,6 +604,10 @@ bool specializeAppliesInFunction(SILFunction &F,
604604
/// types aggregated together at each level.
605605
SILValue createEmptyAndUndefValue(SILType ty, SILInstruction *insertionPoint,
606606
SILBuilderContext &ctx, bool noUndef = false);
607+
608+
/// Check if a struct or its fields can have unreferenceable storage.
609+
bool findUnreferenceableStorage(StructDecl *decl, SILType structType,
610+
SILFunction *func);
607611
} // end namespace swift
608612

609613
#endif // SWIFT_SILOPTIMIZER_UTILS_INSTOPTUTILS_H

lib/SILOptimizer/SILCombiner/SILCombinerMiscVisitors.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1246,7 +1246,7 @@ SILCombiner::visitInjectEnumAddrInst(InjectEnumAddrInst *IEAI) {
12461246

12471247
// We cannot create a struct when it has unreferenceable storage.
12481248
if (elemType.isEmpty(*IEAI->getFunction()) && structDecl &&
1249-
structDecl->hasUnreferenceableStorage()) {
1249+
findUnreferenceableStorage(structDecl, elemType, IEAI->getFunction())) {
12501250
return nullptr;
12511251
}
12521252

lib/SILOptimizer/Utils/InstOptUtils.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2009,3 +2009,21 @@ SILValue swift::createEmptyAndUndefValue(SILType ty,
20092009
assert(!noUndef);
20102010
return SILUndef::get(insertionPoint->getFunction(), ty);
20112011
}
2012+
2013+
bool swift::findUnreferenceableStorage(StructDecl *decl, SILType structType,
2014+
SILFunction *func) {
2015+
if (decl->hasUnreferenceableStorage()) {
2016+
return true;
2017+
}
2018+
// Check if any fields have unreferenceable stoage
2019+
for (auto *field : decl->getStoredProperties()) {
2020+
TypeExpansionContext tec = *func;
2021+
auto fieldTy = structType.getFieldType(field, func->getModule(), tec);
2022+
if (auto *fieldStructDecl = fieldTy.getStructOrBoundGenericStruct()) {
2023+
if (findUnreferenceableStorage(fieldStructDecl, fieldTy, func)) {
2024+
return true;
2025+
}
2026+
}
2027+
}
2028+
return false;
2029+
}

test/SILOptimizer/sil_combine_enum_addr.sil

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,3 +362,33 @@ bb3:
362362
%8 = tuple ()
363363
return %8 : $()
364364
}
365+
366+
struct NestedUnreferenceableStorage {
367+
let e: EmptyCUnion
368+
}
369+
370+
sil @no_init_nested_c_union : $@convention(thin) () -> (@out NestedUnreferenceableStorage)
371+
372+
// CHECK-LABEL: sil @test_empty_nested_c_union : $@convention(thin) () -> () {
373+
// CHECK: inject_enum_addr
374+
// CHECK-LABEL: } // end sil function 'test_empty_nested_c_union'
375+
sil @test_empty_nested_c_union : $@convention(thin) () -> () {
376+
bb0:
377+
%0 = alloc_stack $Optional<NestedUnreferenceableStorage>
378+
%1 = init_enum_data_addr %0 : $*Optional<NestedUnreferenceableStorage>, #Optional.some!enumelt
379+
%f = function_ref @no_init_nested_c_union : $@convention(thin) () -> (@out NestedUnreferenceableStorage)
380+
apply %f(%1) : $@convention(thin) () -> (@out NestedUnreferenceableStorage)
381+
inject_enum_addr %0 : $*Optional<NestedUnreferenceableStorage>, #Optional.some!enumelt
382+
switch_enum_addr %0 : $*Optional<NestedUnreferenceableStorage>, case #Optional.some!enumelt: bb1, case #Optional.none!enumelt: bb2
383+
384+
bb1:
385+
br bb3
386+
387+
bb2:
388+
br bb3
389+
390+
bb3:
391+
dealloc_stack %0 : $*Optional<NestedUnreferenceableStorage>
392+
%8 = tuple ()
393+
return %8 : $()
394+
}

0 commit comments

Comments
 (0)