Skip to content

Commit e116998

Browse files
committed
[SIL-opaque] in-depth top-level documentation for phi coalescing.
1 parent f79c6c8 commit e116998

File tree

1 file changed

+56
-1
lines changed

1 file changed

+56
-1
lines changed

lib/SILOptimizer/Mandatory/PhiStorageOptimizer.cpp

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,66 @@
1313
/// PhiStorageOptimizer implements an analysis used by AddressLowering
1414
/// to reuse storage across block arguments.
1515
///
16+
/// In OSSA, phi operands can often be coalesced because they are
17+
/// consuming--they end the lifetime of their operand. This optimization may
18+
/// fail to coalesce an operand for two major reasons:
19+
///
20+
/// 1. This phi operand is already coalesced with other storage, possibly of a
21+
/// different type:
22+
///
23+
/// %field = struct_extract %struct : $Struct<T>, #field
24+
/// br bb(%field : $T)
25+
///
26+
/// bb(%phi : @owned $T):
27+
/// ...
28+
///
29+
/// 2. This phi operand interferes with another coalesced phi operand.
30+
///
31+
/// Only one of the call results below, either %get0 or %get1, can be coalesced
32+
/// with %phi. The %phi will itself be coalesced with this function's indirect
33+
/// @out argument.
34+
///
35+
/// sil [ossa] @function : $@convention(thin) <T> () -> @out T {
36+
/// bb0:
37+
/// %get0 = apply %get<T>() : $@convention(thin) <τ_0_0>() -> @out τ_0_0
38+
/// %get1 = apply %get<T>() : $@convention(thin) <τ_0_0>() -> @out τ_0_0
39+
/// cond_br undef, bb2, bb1
40+
///
41+
/// bb1:
42+
/// destroy_value %get0 : $T
43+
/// br bb3(%get1 : $T)
44+
///
45+
/// bb2:
46+
/// destroy_value %get1 : $T
47+
/// br bb3(%get0 : $T)
48+
///
49+
/// bb3(%phi : @owned $T):
50+
/// return %phi : $T
51+
///
52+
/// TODO: Liveness is currently recorded at the block level. This could be
53+
/// extended to handle operand with nonoverlapping liveness in the same
54+
/// block. In this case, %get0 and %get1 could both be coalesced with a bit of
55+
/// extra book-keeping:
56+
///
57+
/// bb0:
58+
/// %get0 = apply %get<T>() : $@convention(thin) <τ_0_0>() -> @out τ_0_0
59+
///
60+
/// bb1:
61+
/// destroy_value %get0 : $T
62+
/// %get1 = apply %get<T>() : $@convention(thin) <τ_0_0>() -> @out τ_0_0
63+
/// br bb3(%get1 : $T)
64+
///
65+
/// bb2:
66+
/// br bb3(%get0 : $T)
67+
///
68+
/// bb3(%phi : @owned $T):
69+
///
1670
/// TODO: This does not yet coalesce the copy_value instructions that produce a
1771
/// phi operand. Such a copy implies that both the operand and phi value are
1872
/// live past the phi. Nonetheleses, they could still be coalesced as
1973
/// follows... First coalesce all direct phi operands. Then transitively
20-
/// coalesce copies by redoing the liveness traversal from the uses of the copy.
74+
/// coalesce copies by checking if the copy's source is coalescable, then
75+
/// redoing the liveness traversal from the uses of the copy.
2176
///
2277
/// TODO: This approach uses on-the-fly liveness discovery for all incoming
2378
/// values at once. It requires no storage for liveness. Hopefully this is

0 commit comments

Comments
 (0)