@@ -89,9 +89,6 @@ class TempRValueOptPass : public SILFunctionTransform {
8989 checkTempObjectDestroy (AllocStackInst *tempObj, CopyAddrInst *copyInst,
9090 ValueLifetimeAnalysis::Frontier &tempAddressFrontier);
9191
92- bool canApplyBeTreatedAsLoad (Operand *tempObjUser, ApplySite apply,
93- SILValue srcAddr);
94-
9592 bool tryOptimizeCopyIntoTemp (CopyAddrInst *copyInst);
9693 std::pair<SILBasicBlock::iterator, bool >
9794 tryOptimizeStoreIntoTemp (StoreInst *si);
@@ -116,31 +113,6 @@ bool TempRValueOptPass::collectLoadsFromProjection(
116113 return true ;
117114}
118115
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-
144116// / Transitively explore all data flow uses of the given \p address until
145117// / reaching a load or returning false.
146118// /
@@ -204,28 +176,23 @@ collectLoads(Operand *addressUse, CopyAddrInst *originalCopy,
204176 return false ;
205177 LLVM_FALLTHROUGH;
206178 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:
215180 case SILInstructionKind::BeginApplyInst: {
216- if (! canApplyBeTreatedAsLoad (addressUse, ApplySite (user),
217- originalCopy-> getSrc () ))
181+ auto convention = ApplySite (user). getArgumentConvention (*addressUse);
182+ if (!convention. isGuaranteedConvention ( ))
218183 return false ;
219184
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+ }
229196 }
230197 return true ;
231198 }
@@ -321,8 +288,17 @@ bool TempRValueOptPass::checkNoSourceModification(
321288
322289 // If this is the last use of the temp we are ok. After this point,
323290 // 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+
325300 return true ;
301+ }
326302
327303 if (aa->mayWriteToMemory (inst, copySrc)) {
328304 LLVM_DEBUG (llvm::dbgs () << " Source modified by" << *iter);
0 commit comments