@@ -437,6 +437,54 @@ extension Instruction {
437
437
return false
438
438
}
439
439
}
440
+
441
+ /// Returns true if `otherInst` is in the same block and dominated by this instruction.
442
+ /// To be used as simple dominance check if both instructions are most likely located in the same block
443
+ /// and no DominatorTree is available (like in instruction simplification).
444
+ func dominatesInSameBlock( _ otherInst: Instruction ) -> Bool {
445
+ if parentBlock != otherInst. parentBlock {
446
+ return false
447
+ }
448
+ // Walk in both directions. This is most efficient if both instructions are located nearby but it's not clear
449
+ // which one comes first in the block's instruction list.
450
+ var forwardIter = self
451
+ var backwardIter = self
452
+ while let f = forwardIter. next {
453
+ if f == otherInst {
454
+ return true
455
+ }
456
+ forwardIter = f
457
+ if let b = backwardIter. previous {
458
+ if b == otherInst {
459
+ return false
460
+ }
461
+ backwardIter = b
462
+ }
463
+ }
464
+ return false
465
+ }
466
+
467
+ /// If this instruction uses a (single) existential archetype, i.e. it has a type-dependent operand,
468
+ /// returns the concrete type if it is known.
469
+ var concreteTypeOfDependentExistentialArchetype : CanonicalType ? {
470
+ // For simplicity only support a single type dependent operand, which is true in most of the cases anyway.
471
+ if let openArchetypeOp = typeDependentOperands. singleElement,
472
+ // Match the sequence
473
+ // %1 = metatype $T
474
+ // %2 = init_existential_metatype %1, any P.Type
475
+ // %3 = open_existential_metatype %2 to $@opened(...)
476
+ // this_instruction_which_uses $@opened(...) // type-defs: %3
477
+ let oemt = openArchetypeOp. value as? OpenExistentialMetatypeInst ,
478
+ let iemt = oemt. operand. value as? InitExistentialMetatypeInst ,
479
+ let mt = iemt. metatype as? MetatypeInst
480
+ {
481
+ return mt. type. astType. instanceTypeOfMetatype
482
+ }
483
+ // TODO: also handle open_existential_addr and open_existential_ref.
484
+ // Those cases are currently handled in SILCombine's `propagateConcreteTypeOfInitExistential`.
485
+ // Eventually we want to replace the SILCombine implementation with this one.
486
+ return nil
487
+ }
440
488
}
441
489
442
490
// Match the pattern:
0 commit comments