Skip to content

Commit 5016e35

Browse files
committed
Optimizer: add two small utilities for instructions
* `func Instruction.dominatesInSameBlock(_ otherInst: Instruction) -> Bool` * `var Instruction.concreteTypeOfDependentExistentialArchetype`
1 parent 213da24 commit 5016e35

File tree

1 file changed

+48
-0
lines changed

1 file changed

+48
-0
lines changed

SwiftCompilerSources/Sources/Optimizer/Utilities/OptUtils.swift

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)