@@ -686,6 +686,20 @@ SILInstruction *SILCombiner::visitCondFailInst(CondFailInst *CFI) {
686
686
return nullptr ;
687
687
}
688
688
689
+ static bool isValueToBridgeObjectremovable (ValueToBridgeObjectInst *VTBOI) {
690
+ SILValue operand = VTBOI->getOperand ();
691
+ // If operand is a struct $UInt (% : $Builtin.), fetch the real source
692
+ if (auto *SI = dyn_cast<StructInst>(operand)) {
693
+ assert (SI->SILInstruction ::getAllOperands ().size () == 1 &&
694
+ " Excted a single operand" );
695
+ operand = SI->getOperand (0 );
696
+ }
697
+ if (auto *BI = dyn_cast<BuiltinInst>(operand)) {
698
+ return (BI->getBuiltinInfo ().ID == BuiltinValueKind::StringObjectOr);
699
+ }
700
+ return false ;
701
+ }
702
+
689
703
SILInstruction *SILCombiner::visitStrongRetainInst (StrongRetainInst *SRI) {
690
704
// Retain of ThinToThickFunction is a no-op.
691
705
SILValue funcOper = SRI->getOperand ();
@@ -699,6 +713,15 @@ SILInstruction *SILCombiner::visitStrongRetainInst(StrongRetainInst *SRI) {
699
713
isa<ObjCMetatypeToObjectInst>(SRI->getOperand ()))
700
714
return eraseInstFromFunction (*SRI);
701
715
716
+ // Retain and Release of tagged strings is a no-op.
717
+ // The builtin code pattern to find tagged strings is:
718
+ // builtin "stringObjectOr_Int64" (or to tag the string)
719
+ // value_to_bridge_object (cast the UInt to bridge object)
720
+ if (auto *VTBOI = dyn_cast<ValueToBridgeObjectInst>(SRI->getOperand ())) {
721
+ if (isValueToBridgeObjectremovable (VTBOI))
722
+ return eraseInstFromFunction (*SRI);
723
+ }
724
+
702
725
// Sometimes in the stdlib due to hand offs, we will see code like:
703
726
//
704
727
// strong_release %0
@@ -1141,6 +1164,15 @@ SILInstruction *SILCombiner::visitStrongReleaseInst(StrongReleaseInst *SRI) {
1141
1164
isa<ObjCMetatypeToObjectInst>(SRI->getOperand ()))
1142
1165
return eraseInstFromFunction (*SRI);
1143
1166
1167
+ // Retain and Release of tagged strings is a no-op.
1168
+ // The builtin code pattern to find tagged strings is:
1169
+ // builtin "stringObjectOr_Int64" (or to tag the string)
1170
+ // value_to_bridge_object (cast the UInt to bridge object)
1171
+ if (auto *VTBOI = dyn_cast<ValueToBridgeObjectInst>(SRI->getOperand ())) {
1172
+ if (isValueToBridgeObjectremovable (VTBOI))
1173
+ return eraseInstFromFunction (*SRI);
1174
+ }
1175
+
1144
1176
// Release of a classbound existential converted from a class is just a
1145
1177
// release of the class, squish the conversion.
1146
1178
if (auto ier = dyn_cast<InitExistentialRefInst>(SRI->getOperand ()))
0 commit comments