|
11 | 11 | //===----------------------------------------------------------------------===//
|
12 | 12 |
|
13 | 13 | import SIL
|
| 14 | +import AST |
14 | 15 |
|
15 | 16 | extension CheckedCastAddrBranchInst : OnoneSimplifiable {
|
16 | 17 | func simplify(_ context: SimplifyContext) {
|
@@ -53,3 +54,42 @@ private extension CheckedCastAddrBranchInst {
|
53 | 54 | context.erase(instruction: self)
|
54 | 55 | }
|
55 | 56 | }
|
| 57 | + |
| 58 | +extension UnconditionalCheckedCastInst : Simplifiable, SILCombineSimplifiable { |
| 59 | + func simplify(_ context: SimplifyContext) { |
| 60 | + tryOptimizeCastToExistentialMetatype(context) |
| 61 | + } |
| 62 | +} |
| 63 | + |
| 64 | +private extension UnconditionalCheckedCastInst { |
| 65 | + // Replace |
| 66 | + // %1 = unconditional_checked_cast %0 : $@thick T.Type to any P.Type |
| 67 | + // with |
| 68 | + // %1 = init_existential_metatype %0 : $@thick S.Type, $@thick any P.Type |
| 69 | + // if type T conforms to protocol P. |
| 70 | + // Note that init_existential_metatype is better than unconditional_checked_cast because it does not need |
| 71 | + // to do any runtime casting. |
| 72 | + func tryOptimizeCastToExistentialMetatype(_ context: SimplifyContext) { |
| 73 | + guard targetFormalType.isExistentialMetatypeType, |
| 74 | + sourceFormalType.isMetatypeType, |
| 75 | + !sourceFormalType.isExistentialMetatypeType |
| 76 | + else { |
| 77 | + return |
| 78 | + } |
| 79 | + |
| 80 | + let instanceTy = targetFormalType.instanceTypeOfMetatype |
| 81 | + guard let nominal = instanceTy.anyNominal, |
| 82 | + let proto = nominal as? ProtocolDecl |
| 83 | + else { |
| 84 | + return |
| 85 | + } |
| 86 | + let conformance = sourceFormalType.instanceTypeOfMetatype.checkConformance(to: proto) |
| 87 | + guard conformance.isValid else { |
| 88 | + return |
| 89 | + } |
| 90 | + |
| 91 | + let builder = Builder(before: self, context) |
| 92 | + let iemt = builder.createInitExistentialMetatype(metatype: operand.value, existentialType: self.type, conformances: [conformance]) |
| 93 | + self.replace(with: iemt, context) |
| 94 | + } |
| 95 | +} |
0 commit comments