@@ -25,6 +25,9 @@ extension ApplyInst : OnoneSimplifiable, SILCombineSimplifiable {
25
25
if context. tryDevirtualize ( apply: self , isMandatory: false ) != nil {
26
26
return
27
27
}
28
+ if tryRemoveArrayCast ( apply: self , context) {
29
+ return
30
+ }
28
31
if !context. preserveDebugInfo {
29
32
_ = tryReplaceExistentialArchetype ( of: self , context)
30
33
}
@@ -73,6 +76,40 @@ private func tryTransformThickToThinCallee(of apply: ApplyInst, _ context: Simpl
73
76
return false
74
77
}
75
78
79
+ /// Removes casts between arrays of the same type.
80
+ ///
81
+ /// %1 = function_ref @_arrayConditionalCast : (@guaranteed Array<Int>) -> @owned Optional<Array<Int>>
82
+ /// %2 = apply %1(%0) : (@guaranteed Array<Int>) -> @owned Optional<Array<Int>>
83
+ /// ->
84
+ /// %1 = copy_value %0
85
+ /// %2 = enum $Optional<Array<Int>>, #Optional.some!enumelt, %1
86
+ ///
87
+ private func tryRemoveArrayCast( apply: ApplyInst , _ context: SimplifyContext ) -> Bool {
88
+ guard let callee = apply. referencedFunction,
89
+ callee. hasSemanticsAttribute ( " array.conditional_cast " ) ,
90
+ apply. parentFunction. hasOwnership,
91
+
92
+ // Check if the cast function has the expected calling convention
93
+ apply. arguments. count == 1 ,
94
+ apply. convention ( of: apply. argumentOperands [ 0 ] ) == . directGuaranteed,
95
+ apply. functionConvention. results [ 0 ] . convention == . owned,
96
+ apply. type. isOptional,
97
+
98
+ // Check if the source and target type of the cast is identical.
99
+ // Note that we are checking the _formal_ element types and not the lowered types, because
100
+ // the element types are replacement type in the Array's substitution map and this is a formal type.
101
+ apply. arguments [ 0 ] . type == apply. type. optionalPayloadType ( in: apply. parentFunction)
102
+ else {
103
+ return false
104
+ }
105
+
106
+ let builder = Builder ( after: apply, context)
107
+ let copiedArray = builder. createCopyValue ( operand: apply. arguments [ 0 ] )
108
+ let optional = builder. createEnum ( caseIndex: 1 , payload: copiedArray, enumType: apply. type)
109
+ apply. replace ( with: optional, context)
110
+ return true
111
+ }
112
+
76
113
/// If the apply uses an existential archetype (`@opened("...")`) and the concrete type is known,
77
114
/// replace the existential archetype with the concrete type
78
115
/// 1. in the apply's substitution map
@@ -199,3 +236,10 @@ private extension FullApplySite {
199
236
return SubstitutionMap ( genericSignature: genSig, replacementTypes: newReplacementTypes)
200
237
}
201
238
}
239
+
240
+ private extension Type {
241
+ func optionalPayloadType( in function: Function ) -> Type {
242
+ let subs = contextSubstitutionMap
243
+ return subs. replacementTypes [ 0 ] . loweredType ( in: function)
244
+ }
245
+ }
0 commit comments