12
12
13
13
import SIL
14
14
15
- extension BuiltinInst : OnoneSimplifiable {
15
+ extension BuiltinInst : OnoneSimplifiable , SILCombineSimplifiable {
16
16
func simplify( _ context: SimplifyContext ) {
17
17
switch id {
18
18
case . IsConcrete:
@@ -53,6 +53,8 @@ extension BuiltinInst : OnoneSimplifiable {
53
53
constantFoldIntegerEquality ( isEqual: true , context)
54
54
case . ICMP_NE:
55
55
constantFoldIntegerEquality ( isEqual: false , context)
56
+ case . Xor:
57
+ simplifyNegation ( context)
56
58
default :
57
59
if let literal = constantFold ( context) {
58
60
uses. replaceAll ( with: literal, context)
@@ -165,6 +167,11 @@ private extension BuiltinInst {
165
167
case . Sizeof:
166
168
value = ty. getStaticSize ( context: context)
167
169
case . Strideof:
170
+ if isUsedAsStrideOfIndexRawPointer ( context) {
171
+ // Constant folding `stride` would prevent index_raw_pointer simplification.
172
+ // See `simplifyIndexRawPointer` in SimplifyPointerToAddress.swift.
173
+ return
174
+ }
168
175
value = ty. getStaticStride ( context: context)
169
176
case . Alignof:
170
177
value = ty. getStaticAlignment ( context: context)
@@ -181,7 +188,33 @@ private extension BuiltinInst {
181
188
uses. replaceAll ( with: literal, context)
182
189
context. erase ( instruction: self )
183
190
}
184
-
191
+
192
+ private func isUsedAsStrideOfIndexRawPointer( _ context: SimplifyContext ) -> Bool {
193
+ var worklist = ValueWorklist ( context)
194
+ defer { worklist. deinitialize ( ) }
195
+ worklist. pushIfNotVisited ( self )
196
+ while let v = worklist. pop ( ) {
197
+ for use in v. uses {
198
+ switch use. instruction {
199
+ case let builtin as BuiltinInst :
200
+ switch builtin. id {
201
+ case . SMulOver, . TruncOrBitCast, . SExtOrBitCast, . ZExtOrBitCast:
202
+ worklist. pushIfNotVisited ( builtin)
203
+ default :
204
+ break
205
+ }
206
+ case let tupleExtract as TupleExtractInst where tupleExtract. fieldIndex == 0 :
207
+ worklist. pushIfNotVisited ( tupleExtract)
208
+ case is IndexRawPointerInst :
209
+ return true
210
+ default :
211
+ break
212
+ }
213
+ }
214
+ }
215
+ return false
216
+ }
217
+
185
218
func optimizeArgumentToThinMetatype( argument: Int , _ context: SimplifyContext ) {
186
219
let type : Type
187
220
@@ -224,6 +257,53 @@ private extension BuiltinInst {
224
257
}
225
258
return false
226
259
}
260
+
261
+ /// Replaces a builtin "xor", which negates its operand comparison
262
+ /// ```
263
+ /// %3 = builtin "cmp_slt_Int64"(%1, %2) : $Builtin.Int1
264
+ /// %4 = integer_literal $Builtin.Int1, -1
265
+ /// %5 = builtin "xor_Int1"(%3, %4) : $Builtin.Int1
266
+ /// ```
267
+ /// with the negated comparison
268
+ /// ```
269
+ /// %5 = builtin "cmp_ge_Int64"(%1, %2) : $Builtin.Int1
270
+ /// ```
271
+ func simplifyNegation( _ context: SimplifyContext ) {
272
+ assert ( id == . Xor)
273
+ guard let one = arguments [ 1 ] as? IntegerLiteralInst ,
274
+ let oneValue = one. value,
275
+ oneValue == - 1 ,
276
+ let lhsBuiltin = arguments [ 0 ] as? BuiltinInst ,
277
+ lhsBuiltin. type. isBuiltinInteger,
278
+ let negatedBuiltinName = lhsBuiltin. negatedComparisonBuiltinName
279
+ else {
280
+ return
281
+ }
282
+
283
+ let builder = Builder ( before: lhsBuiltin, context)
284
+ let negated = builder. createBuiltinBinaryFunction ( name: negatedBuiltinName,
285
+ operandType: lhsBuiltin. arguments [ 0 ] . type,
286
+ resultType: lhsBuiltin. type,
287
+ arguments: Array ( lhsBuiltin. arguments) )
288
+ self . replace ( with: negated, context)
289
+ }
290
+
291
+ private var negatedComparisonBuiltinName : String ? {
292
+ switch id {
293
+ case . ICMP_EQ: return " cmp_ne "
294
+ case . ICMP_NE: return " cmp_eq "
295
+ case . ICMP_SLE: return " cmp_sgt "
296
+ case . ICMP_SLT: return " cmp_sge "
297
+ case . ICMP_SGE: return " cmp_slt "
298
+ case . ICMP_SGT: return " cmp_sle "
299
+ case . ICMP_ULE: return " cmp_ugt "
300
+ case . ICMP_ULT: return " cmp_uge "
301
+ case . ICMP_UGE: return " cmp_ult "
302
+ case . ICMP_UGT: return " cmp_ule "
303
+ default :
304
+ return nil
305
+ }
306
+ }
227
307
}
228
308
229
309
private extension Value {
0 commit comments