Skip to content

Commit 4011e08

Browse files
committed
Swift optimizer: add Value.makeAvailable and `Value.copy(at:andMakeAvailableIn:)
Utilities to make a value available to be used in another basic block. Inserts required `copy_value` and `destroy_value` operations in case the destination block is in a different control region than the value. For example, if the destination block is in a loop while the value is not in that loop, the value has to be copied for each loop iteration.
1 parent a91d541 commit 4011e08

File tree

1 file changed

+42
-0
lines changed

1 file changed

+42
-0
lines changed

SwiftCompilerSources/Sources/Optimizer/Utilities/OptUtils.swift

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,45 @@ extension Builder {
3535
}
3636
}
3737
}
38+
39+
extension Value {
40+
/// Makes this new owned value available to be used in the block `destBlock`.
41+
///
42+
/// Inserts required `copy_value` and `destroy_value` operations in case the `destBlock`
43+
/// is in a different control region than this value. For example, if `destBlock` is
44+
/// in a loop while this value is not in that loop, the value has to be copied for
45+
/// each loop iteration.
46+
func makeAvailable(in destBlock: BasicBlock, _ context: PassContext) -> Value {
47+
precondition(uses.isEmpty)
48+
precondition(ownership == .owned)
49+
50+
let beginBlock = definingBlock
51+
var useToDefRange = BasicBlockRange(begin: beginBlock, context)
52+
defer { useToDefRange.deinitialize() }
53+
54+
useToDefRange.insert(destBlock)
55+
56+
// The value needs to be destroyed at every exit of the liferange.
57+
for exitBlock in useToDefRange.exits {
58+
let builder = Builder(at: exitBlock.instructions.first!, context)
59+
builder.createDestroyValue(operand: self)
60+
}
61+
62+
if useToDefRange.contains(destBlock) {
63+
// The `destBlock` is within a loop, so we need to copy the value at each iteration.
64+
let builder = Builder(at: destBlock.instructions.first!, context)
65+
return builder.createCopyValue(operand: self)
66+
}
67+
return self
68+
}
69+
70+
/// Copies this value at `insertionPoint` and makes the copy available to be used in `destBlock`.
71+
///
72+
/// For details see `makeAvailable`.
73+
func copy(at insertionPoint: Instruction, andMakeAvailableIn destBlock: BasicBlock,
74+
_ context: PassContext) -> Value {
75+
let builder = Builder(at: insertionPoint, context)
76+
let copiedValue = builder.createCopyValue(operand: self)
77+
return copiedValue.makeAvailable(in: destBlock, context)
78+
}
79+
}

0 commit comments

Comments
 (0)