Skip to content

Commit 427117f

Browse files
authored
Merge pull request #1929 from swiftwasm/main
[pull] swiftwasm from main
2 parents 5c9d468 + 9c9f3f5 commit 427117f

File tree

2 files changed

+82
-3
lines changed

2 files changed

+82
-3
lines changed

lib/SILOptimizer/Analysis/RCIdentityAnalysis.cpp

+23-3
Original file line numberDiff line numberDiff line change
@@ -58,14 +58,31 @@ static bool isRCIdentityPreservingCast(ValueKind Kind) {
5858
}
5959
}
6060

61+
/// Returns a null SILValue if V has a trivial type, otherwise returns V.
62+
///
63+
/// RCIdentityAnalysis must not look through casts which cast from a trivial
64+
/// type, like a metatype, to something which is retainable, like an AnyObject.
65+
/// On some platforms such casts dynamically allocate a ref-counted box for the
66+
/// metatype.
67+
/// Now, if the RCRoot of such an AnyObject would be a trivial type, ARC
68+
/// optimizations get confused and might eliminate a retain of such an object
69+
/// completely.
70+
static SILValue noTrivialType(SILValue V, SILFunction *F) {
71+
if (V->getType().isTrivial(*F))
72+
return SILValue();
73+
return V;
74+
}
75+
6176
//===----------------------------------------------------------------------===//
6277
// RC Identity Root Instruction Casting
6378
//===----------------------------------------------------------------------===//
6479

6580
static SILValue stripRCIdentityPreservingInsts(SILValue V) {
6681
// First strip off RC identity preserving casts.
67-
if (isRCIdentityPreservingCast(V->getKind()))
68-
return cast<SingleValueInstruction>(V)->getOperand(0);
82+
if (isRCIdentityPreservingCast(V->getKind())) {
83+
auto *inst = cast<SingleValueInstruction>(V);
84+
return noTrivialType(inst->getOperand(0), inst->getFunction());
85+
}
6986

7087
// Then if we have a struct_extract that is extracting a non-trivial member
7188
// from a struct with no other non-trivial members, a ref count operation on
@@ -118,7 +135,7 @@ static SILValue stripRCIdentityPreservingInsts(SILValue V) {
118135
// purposes.
119136
if (auto *A = dyn_cast<SILPhiArgument>(V))
120137
if (SILValue Result = A->getSingleTerminatorOperand())
121-
return Result;
138+
return noTrivialType(Result, A->getFunction());
122139

123140
return SILValue();
124141
}
@@ -321,6 +338,9 @@ SILValue RCIdentityFunctionInfo::stripRCIdentityPreservingArgs(SILValue V,
321338
}
322339

323340
unsigned IVListSize = IncomingValues.size();
341+
if (IVListSize == 1 &&
342+
!noTrivialType(IncomingValues[0].second, A->getFunction()))
343+
return SILValue();
324344

325345
assert(IVListSize != 1 && "Should have been handled in "
326346
"stripRCIdentityPreservingInsts");

test/SILOptimizer/retain_release_code_motion.sil

+59
Original file line numberDiff line numberDiff line change
@@ -718,6 +718,65 @@ bb2:
718718
return %9999 : $()
719719
}
720720

721+
// Don't remove a retain of an AnyObject which comes from a metatype.
722+
//
723+
// CHECK-LABEL: sil @conditional_metatype_cast
724+
// CHECK: bb2([[ARG:%[0-9]+]] : $AnyObject):
725+
// CHECK: strong_retain [[ARG]]
726+
// CHECK: checked_cast_addr_br
727+
// CHECK: } // end sil function 'conditional_metatype_cast'
728+
sil @conditional_metatype_cast : $@convention(thin) () -> AnyObject {
729+
bb0:
730+
%0 = metatype $@thick Int.Type
731+
checked_cast_br %0 : $@thick Int.Type to AnyObject, bb2, bb1
732+
733+
bb1:
734+
unreachable
735+
736+
bb2(%6 : $AnyObject):
737+
strong_retain %6 : $AnyObject
738+
%9 = alloc_stack $AnyObject
739+
store %6 to %9 : $*AnyObject
740+
%11 = alloc_stack $@thick Int.Type
741+
checked_cast_addr_br take_always AnyObject in %9 : $*AnyObject to Int.Type in %11 : $*@thick Int.Type, bb3, bb4
742+
743+
bb3:
744+
dealloc_stack %11 : $*@thick Int.Type
745+
dealloc_stack %9 : $*AnyObject
746+
return %6 : $AnyObject
747+
748+
bb4:
749+
unreachable
750+
}
751+
752+
// Don't remove a retain of an AnyObject which comes from a metatype.
753+
//
754+
// CHECK-LABEL: sil @unconditional_metatype_cast
755+
// CHECK: [[O:%[0-9]+]] = unconditional_checked_cast
756+
// CHECK: strong_retain [[O]]
757+
// CHECK: checked_cast_addr_br
758+
// CHECK: } // end sil function 'unconditional_metatype_cast'
759+
sil @unconditional_metatype_cast : $@convention(thin) () -> AnyObject {
760+
bb0:
761+
%0 = metatype $@thick Int.Type
762+
%6 = unconditional_checked_cast %0 : $@thick Int.Type to AnyObject
763+
strong_retain %6 : $AnyObject
764+
%9 = alloc_stack $AnyObject
765+
store %6 to %9 : $*AnyObject
766+
%11 = alloc_stack $@thick Int.Type
767+
checked_cast_addr_br take_always AnyObject in %9 : $*AnyObject to Int.Type in %11 : $*@thick Int.Type, bb3, bb4
768+
769+
bb3:
770+
dealloc_stack %11 : $*@thick Int.Type
771+
dealloc_stack %9 : $*AnyObject
772+
return %6 : $AnyObject
773+
774+
bb4:
775+
unreachable
776+
}
777+
778+
779+
721780
// Hoist releases above dealloc_stack
722781
// CHECK-LABEL: sil @testReleaseHoistDeallocStack : $@convention(thin) (AnyObject) -> () {
723782
// CHECK: bb0(%0 : $AnyObject):

0 commit comments

Comments
 (0)