@@ -89,9 +89,6 @@ class TempRValueOptPass : public SILFunctionTransform {
89
89
checkTempObjectDestroy (AllocStackInst *tempObj, CopyAddrInst *copyInst,
90
90
ValueLifetimeAnalysis::Frontier &tempAddressFrontier);
91
91
92
- bool canApplyBeTreatedAsLoad (Operand *tempObjUser, ApplySite apply,
93
- SILValue srcAddr);
94
-
95
92
bool tryOptimizeCopyIntoTemp (CopyAddrInst *copyInst);
96
93
std::pair<SILBasicBlock::iterator, bool >
97
94
tryOptimizeStoreIntoTemp (StoreInst *si);
@@ -116,31 +113,6 @@ bool TempRValueOptPass::collectLoadsFromProjection(
116
113
return true ;
117
114
}
118
115
119
- // / Check if \p tempObjUser, passed to the apply instruction, is only loaded,
120
- // / but not modified and if \p srcAddr is not modified as well.
121
- bool TempRValueOptPass::canApplyBeTreatedAsLoad (
122
- Operand *tempObjUser, ApplySite apply, SILValue srcAddr) {
123
- // Check if the function can just read from tempObjUser.
124
- auto convention = apply.getArgumentConvention (*tempObjUser);
125
- if (!convention.isGuaranteedConvention ()) {
126
- LLVM_DEBUG (llvm::dbgs () << " Temp consuming use may write/destroy "
127
- " its source"
128
- << *apply.getInstruction ());
129
- return false ;
130
- }
131
-
132
- // If the function may write to the source of the copy_addr, the apply
133
- // cannot be treated as a load: all (potential) writes of the source must
134
- // appear _after_ all loads of the temporary. But in case of a function call
135
- // we don't know in which order the writes and loads are executed inside the
136
- // called function. The source may be written before the temporary is
137
- // loaded, which would make the optization invalid.
138
- if (aa->mayWriteToMemory (apply.getInstruction (), srcAddr))
139
- return false ;
140
-
141
- return true ;
142
- }
143
-
144
116
// / Transitively explore all data flow uses of the given \p address until
145
117
// / reaching a load or returning false.
146
118
// /
@@ -204,28 +176,23 @@ collectLoads(Operand *addressUse, CopyAddrInst *originalCopy,
204
176
return false ;
205
177
LLVM_FALLTHROUGH;
206
178
case SILInstructionKind::ApplyInst:
207
- case SILInstructionKind::TryApplyInst: {
208
- if (!canApplyBeTreatedAsLoad (addressUse, ApplySite (user),
209
- originalCopy->getSrc ()))
210
- return false ;
211
- // Everything is okay with the function call. Register it as a "load".
212
- loadInsts.insert (user);
213
- return true ;
214
- }
179
+ case SILInstructionKind::TryApplyInst:
215
180
case SILInstructionKind::BeginApplyInst: {
216
- if (! canApplyBeTreatedAsLoad (addressUse, ApplySite (user),
217
- originalCopy-> getSrc () ))
181
+ auto convention = ApplySite (user). getArgumentConvention (*addressUse);
182
+ if (!convention. isGuaranteedConvention ( ))
218
183
return false ;
219
184
220
- auto beginApply = cast<BeginApplyInst>(user);
221
- // Register 'end_apply'/'abort_apply' as loads as well
222
- // 'checkNoSourceModification' should check instructions until
223
- // 'end_apply'/'abort_apply'.
224
- for (auto tokenUse : beginApply->getTokenResult ()->getUses ()) {
225
- SILInstruction *user = tokenUse->getUser ();
226
- if (user->getParent () != block)
227
- return false ;
228
- loadInsts.insert (tokenUse->getUser ());
185
+ loadInsts.insert (user);
186
+ if (auto *beginApply = dyn_cast<BeginApplyInst>(user)) {
187
+ // Register 'end_apply'/'abort_apply' as loads as well
188
+ // 'checkNoSourceModification' should check instructions until
189
+ // 'end_apply'/'abort_apply'.
190
+ for (auto tokenUse : beginApply->getTokenResult ()->getUses ()) {
191
+ SILInstruction *tokenUser = tokenUse->getUser ();
192
+ if (tokenUser->getParent () != block)
193
+ return false ;
194
+ loadInsts.insert (tokenUser);
195
+ }
229
196
}
230
197
return true ;
231
198
}
@@ -321,8 +288,17 @@ bool TempRValueOptPass::checkNoSourceModification(
321
288
322
289
// If this is the last use of the temp we are ok. After this point,
323
290
// modifications to the source don't matter anymore.
324
- if (numLoadsFound == useInsts.size ())
291
+ // Note that we are assuming here that if an instruction loads and writes
292
+ // to copySrc at the same time (like a copy_addr could do), the write
293
+ // takes effect after the load.
294
+ if (numLoadsFound == useInsts.size ()) {
295
+ // Function calls are an exception: in a called function a potential
296
+ // modification of copySrc could occur _before_ the read of the temporary.
297
+ if (FullApplySite::isa (inst) && aa->mayWriteToMemory (inst, copySrc))
298
+ return false ;
299
+
325
300
return true ;
301
+ }
326
302
327
303
if (aa->mayWriteToMemory (inst, copySrc)) {
328
304
LLVM_DEBUG (llvm::dbgs () << " Source modified by" << *iter);
0 commit comments