|
11 | 11 | //===----------------------------------------------------------------------===//
|
12 | 12 |
|
13 | 13 | #include "swift/SIL/SILValue.h"
|
| 14 | +#include "swift/SIL/ScopedAddressUtils.h" |
14 | 15 | #include "swift/SILOptimizer/Utils/InstOptUtils.h"
|
15 | 16 | #include "swift/SILOptimizer/Utils/ValueLifetime.h"
|
16 | 17 |
|
@@ -59,34 +60,44 @@ class PartialApplyCombiner {
|
59 | 60 | /// apply instructions.
|
60 | 61 | bool PartialApplyCombiner::copyArgsToTemporaries(
|
61 | 62 | ArrayRef<FullApplySite> applies) {
|
| 63 | + SmallVector<Operand *, 8> argsToHandle; |
| 64 | + |
| 65 | + // Find args that need extension for a non-stack partial_apply |
62 | 66 | // A partial_apply [stack]'s argument are not owned by the partial_apply and
|
63 | 67 | // therefore their lifetime must outlive any uses.
|
64 |
| - if (pai->isOnStack()) |
65 |
| - return true; |
66 |
| - |
67 |
| - SmallVector<Operand *, 8> argsToHandle; |
68 |
| - getConsumedPartialApplyArgs(pai, argsToHandle, |
69 |
| - /*includeTrivialAddrArgs*/ true); |
70 |
| - if (argsToHandle.empty()) |
71 |
| - return true; |
| 68 | + if (!pai->isOnStack()) { |
| 69 | + getConsumedPartialApplyArgs(pai, argsToHandle, |
| 70 | + /*includeTrivialAddrArgs*/ true); |
| 71 | + } |
72 | 72 |
|
73 | 73 | // Compute the set of endpoints, which will be used to insert destroys of
|
74 | 74 | // temporaries.
|
75 |
| - SmallVector<SILInstruction *, 16> paiUsers; |
| 75 | + SmallVector<Operand *, 16> paiUses; |
76 | 76 |
|
77 | 77 | // Of course we must inlude all apply instructions which we want to optimize.
|
78 | 78 | for (FullApplySite ai : applies) {
|
79 |
| - paiUsers.push_back(ai.getInstruction()); |
| 79 | + paiUses.push_back(ai.getCalleeOperand()); |
| 80 | + } |
| 81 | + |
| 82 | + SmallVector<StoreBorrowInst *, 8> storeBorrowsToHandle; |
| 83 | + for (auto arg : pai->getArguments()) { |
| 84 | + if (auto *sbi = dyn_cast<StoreBorrowInst>(arg)) { |
| 85 | + storeBorrowsToHandle.push_back(sbi); |
| 86 | + } |
80 | 87 | }
|
81 | 88 |
|
| 89 | + if (argsToHandle.empty() && storeBorrowsToHandle.empty()) { |
| 90 | + return true; |
| 91 | + } |
82 | 92 | // Also include all destroys in the liferange for the arguments.
|
83 | 93 | // This is needed for later processing in tryDeleteDeadClosure: in case the
|
84 |
| - // pai gets dead after this optimization, tryDeleteDeadClosure relies on that |
85 |
| - // we already copied the pai arguments to extend their lifetimes until the pai |
86 |
| - // is finally destroyed. |
87 |
| - collectDestroys(pai, paiUsers); |
| 94 | + // pai gets dead after this optimization, tryDeleteDeadClosure relies on |
| 95 | + // that we already copied the pai arguments to extend their lifetimes until |
| 96 | + // the pai is finally destroyed. |
| 97 | + collectDestroys(pai, paiUses); |
88 | 98 |
|
89 |
| - ValueLifetimeAnalysis vla(pai, paiUsers); |
| 99 | + ValueLifetimeAnalysis vla(pai, |
| 100 | + llvm::makeArrayRef(paiUses.begin(), paiUses.end())); |
90 | 101 | ValueLifetimeAnalysis::Frontier partialApplyFrontier;
|
91 | 102 |
|
92 | 103 | // Computing the frontier may fail if the frontier is located on a critical
|
@@ -114,6 +125,23 @@ bool PartialApplyCombiner::copyArgsToTemporaries(
|
114 | 125 | // allocated temporary) at the end of the partial_apply's lifetime.
|
115 | 126 | endLifetimeAtFrontier(tmp, partialApplyFrontier, builderCtxt, callbacks);
|
116 | 127 | }
|
| 128 | + |
| 129 | + DeadEndBlocks deBlocks(pai->getFunction()); |
| 130 | + for (auto *storeBorrow : storeBorrowsToHandle) { |
| 131 | + if (extendStoreBorrow(storeBorrow, paiUses, &deBlocks, callbacks)) { |
| 132 | + continue; |
| 133 | + } |
| 134 | + SILBuilderWithScope builder(pai, builderCtxt); |
| 135 | + // Copy address-arguments into a stack-allocated temporary. |
| 136 | + auto *asi = builder.createAllocStack(pai->getLoc(), storeBorrow->getType()); |
| 137 | + builder.createCopyAddr(pai->getLoc(), storeBorrow, asi, IsTake_t::IsNotTake, |
| 138 | + IsInitialization_t::IsInitialization); |
| 139 | + argToTmpCopy.insert(std::make_pair(storeBorrow, asi)); |
| 140 | + |
| 141 | + // Destroy the argument value (either as SSA value or in the stack- |
| 142 | + // allocated temporary) at the end of the partial_apply's lifetime. |
| 143 | + endLifetimeAtFrontier(asi, partialApplyFrontier, builderCtxt, callbacks); |
| 144 | + } |
117 | 145 | return true;
|
118 | 146 | }
|
119 | 147 |
|
|
0 commit comments