|
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