@@ -437,6 +437,54 @@ extension Instruction {
437437 return false
438438 }
439439 }
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+ }
440488}
441489
442490// Match the pattern:
0 commit comments