|
13 | 13 | /// PhiStorageOptimizer implements an analysis used by AddressLowering
|
14 | 14 | /// to reuse storage across block arguments.
|
15 | 15 | ///
|
| 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 | +/// |
16 | 70 | /// TODO: This does not yet coalesce the copy_value instructions that produce a
|
17 | 71 | /// phi operand. Such a copy implies that both the operand and phi value are
|
18 | 72 | /// live past the phi. Nonetheleses, they could still be coalesced as
|
19 | 73 | /// 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. |
21 | 76 | ///
|
22 | 77 | /// TODO: This approach uses on-the-fly liveness discovery for all incoming
|
23 | 78 | /// values at once. It requires no storage for liveness. Hopefully this is
|
|
0 commit comments