Skip to content

Commit f3c2dec

Browse files
committed
Address review comments
1 parent 7a6ed1a commit f3c2dec

File tree

1 file changed

+69
-50
lines changed

1 file changed

+69
-50
lines changed

lib/SILOptimizer/Transforms/TempRValueElimination.cpp

Lines changed: 69 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,10 @@ class TempRValueOptPass : public SILFunctionTransform {
7979
checkTempObjectDestroy(AllocStackInst *tempObj, CopyAddrInst *copyInst,
8080
ValueLifetimeAnalysis::Frontier &tempAddressFrontier);
8181

82+
bool checkNoTempObjectModificationInApply(Operand *tempObjUser,
83+
SILInstruction *inst,
84+
SILValue srcAddr);
85+
8286
bool tryOptimizeCopyIntoTemp(CopyAddrInst *copyInst);
8387
std::pair<SILBasicBlock::iterator, bool>
8488
tryOptimizeStoreIntoTemp(StoreInst *si);
@@ -111,6 +115,61 @@ bool TempRValueOptPass::collectLoadsFromProjection(
111115
return true;
112116
}
113117

118+
bool TempRValueOptPass::checkNoTempObjectModificationInApply(
119+
Operand *tempObjUser, SILInstruction *applyInst, SILValue srcAddr) {
120+
ApplySite apply(applyInst);
121+
122+
// Check if the function can just read from tempObjUser.
123+
auto convention = apply.getArgumentConvention(*tempObjUser);
124+
if (!convention.isGuaranteedConvention()) {
125+
LLVM_DEBUG(llvm::dbgs() << " Temp consuming use may write/destroy "
126+
"its source"
127+
<< *applyInst);
128+
return false;
129+
}
130+
131+
// If we do not have an src address, but are indirect, bail. We would need
132+
// to perform function signature specialization to change the functions
133+
// signature to pass something direct.
134+
if (!srcAddr && convention.isIndirectConvention()) {
135+
LLVM_DEBUG(
136+
llvm::dbgs()
137+
<< " Temp used to materialize value for indirect convention?! Can "
138+
"not remove temporary without func sig opts"
139+
<< *applyInst);
140+
return false;
141+
}
142+
143+
// Check if there is another function argument, which is inout which might
144+
// modify the source address if we have one.
145+
//
146+
// When a use of the temporary is an apply, then we need to prove that the
147+
// function called by the apply cannot modify the temporary's source
148+
// value. By design, this should be handled by
149+
// `checkNoSourceModification`. However, this would be too conservative
150+
// since it's common for the apply to have an @out argument, and alias
151+
// analysis cannot prove that the @out does not alias with `src`. Instead,
152+
// `checkNoSourceModification` always avoids analyzing the current use, so
153+
// applies need to be handled here. We already know that an @out cannot
154+
// alias with `src` because the `src` value must be initialized at the point
155+
// of the call. Hence, it is sufficient to check specifically for another
156+
// @inout that might alias with `src`.
157+
if (srcAddr) {
158+
auto calleeConv = apply.getSubstCalleeConv();
159+
unsigned calleeArgIdx = apply.getCalleeArgIndexOfFirstAppliedArg();
160+
for (const auto &operand : apply.getArgumentOperands()) {
161+
auto argConv = calleeConv.getSILArgumentConvention(calleeArgIdx);
162+
if (argConv.isInoutConvention()) {
163+
if (!aa->isNoAlias(operand.get(), srcAddr)) {
164+
return false;
165+
}
166+
}
167+
++calleeArgIdx;
168+
}
169+
}
170+
return true;
171+
}
172+
114173
/// Transitively explore all data flow uses of the given \p address until
115174
/// reaching a load or returning false.
116175
///
@@ -171,61 +230,21 @@ bool TempRValueOptPass::collectLoads(
171230
return false;
172231
LLVM_FALLTHROUGH;
173232
case SILInstructionKind::ApplyInst:
174-
case SILInstructionKind::BeginApplyInst:
175233
case SILInstructionKind::TryApplyInst: {
176-
ApplySite apply(user);
177-
178-
// Check if the function can just read from userOp.
179-
auto convention = apply.getArgumentConvention(*userOp);
180-
if (!convention.isGuaranteedConvention()) {
181-
LLVM_DEBUG(llvm::dbgs() << " Temp consuming use may write/destroy "
182-
"its source"
183-
<< *user);
234+
if (!checkNoTempObjectModificationInApply(userOp, user, srcAddr))
184235
return false;
185-
}
186-
187-
// If we do not have an src address, but are indirect, bail. We would need
188-
// to perform function signature specialization to change the functions
189-
// signature to pass something direct.
190-
if (!srcAddr && convention.isIndirectConvention()) {
191-
LLVM_DEBUG(
192-
llvm::dbgs()
193-
<< " Temp used to materialize value for indirect convention?! Can "
194-
"not remove temporary without func sig opts"
195-
<< *user);
236+
// Everything is okay with the function call. Register it as a "load".
237+
loadInsts.insert(user);
238+
return true;
239+
}
240+
case SILInstructionKind::BeginApplyInst: {
241+
if (!checkNoTempObjectModificationInApply(userOp, user, srcAddr))
196242
return false;
197-
}
198243

199-
// Check if there is another function argument, which is inout which might
200-
// modify the source address if we have one.
201-
//
202-
// When a use of the temporary is an apply, then we need to prove that the
203-
// function called by the apply cannot modify the temporary's source
204-
// value. By design, this should be handled by
205-
// `checkNoSourceModification`. However, this would be too conservative
206-
// since it's common for the apply to have an @out argument, and alias
207-
// analysis cannot prove that the @out does not alias with `src`. Instead,
208-
// `checkNoSourceModification` always avoids analyzing the current use, so
209-
// applies need to be handled here. We already know that an @out cannot
210-
// alias with `src` because the `src` value must be initialized at the point
211-
// of the call. Hence, it is sufficient to check specifically for another
212-
// @inout that might alias with `src`.
213-
if (srcAddr) {
214-
auto calleeConv = apply.getSubstCalleeConv();
215-
unsigned calleeArgIdx = apply.getCalleeArgIndexOfFirstAppliedArg();
216-
for (const auto &operand : apply.getArgumentOperands()) {
217-
auto argConv = calleeConv.getSILArgumentConvention(calleeArgIdx);
218-
if (argConv.isInoutConvention()) {
219-
if (!aa->isNoAlias(operand.get(), srcAddr)) {
220-
return false;
221-
}
222-
}
223-
++calleeArgIdx;
224-
}
244+
auto beginApply = cast<BeginApplyInst>(user);
245+
for (auto tokenUses : beginApply->getTokenResult()->getUses()) {
246+
loadInsts.insert(tokenUses->getUser());
225247
}
226-
227-
// Everything is okay with the function call. Register it as a "load".
228-
loadInsts.insert(user);
229248
return true;
230249
}
231250
case SILInstructionKind::OpenExistentialAddrInst: {

0 commit comments

Comments
 (0)