mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
COWArrayOpt: Handle patterns of 2d array accesses after more aggresive alias analysis
Make sure we handle a code pattern that we will encounter after Erik's upcoming alias analysis changes. rdar://23938778
This commit is contained in:
@@ -936,24 +936,33 @@ findPreceedingCheckSubscriptOrMakeMutable(ApplyInst *GetElementAddr) {
|
||||
/// Matches the self parameter arguments, verifies that \p Self is called and
|
||||
/// stores the instructions in \p DepInsts in order.
|
||||
static bool
|
||||
matchSelfParameterSetup(ApplyInst *Call, LoadInst *Self,
|
||||
matchSelfParameterSetup(ArraySemanticsCall Call, LoadInst *Self,
|
||||
SmallVectorImpl<SILInstruction *> &DepInsts) {
|
||||
bool MayHaveBridgedObjectElementType = Call.mayHaveBridgedObjectElementType();
|
||||
// We only need the retain/release for the guaranteed parameter if the call
|
||||
// could release self. This can only happen if the array is backed by an
|
||||
// Objective-C array. If this is not the case we can safely hoist the call
|
||||
// without the retain/releases.
|
||||
auto *RetainArray = dyn_cast_or_null<StrongRetainInst>(getInstBefore(Call));
|
||||
if (!RetainArray)
|
||||
if (!RetainArray && MayHaveBridgedObjectElementType)
|
||||
return false;
|
||||
auto *ReleaseArray = dyn_cast_or_null<StrongReleaseInst>(getInstAfter(Call));
|
||||
if (!ReleaseArray)
|
||||
if (!ReleaseArray && MayHaveBridgedObjectElementType)
|
||||
return false;
|
||||
if (ReleaseArray->getOperand() != RetainArray->getOperand())
|
||||
if (ReleaseArray && ReleaseArray->getOperand() != RetainArray->getOperand())
|
||||
return false;
|
||||
|
||||
DepInsts.push_back(ReleaseArray);
|
||||
if (ReleaseArray)
|
||||
DepInsts.push_back(ReleaseArray);
|
||||
DepInsts.push_back(Call);
|
||||
DepInsts.push_back(RetainArray);
|
||||
if (RetainArray)
|
||||
DepInsts.push_back(RetainArray);
|
||||
|
||||
auto ArrayLoad = stripValueProjections(RetainArray->getOperand(), DepInsts);
|
||||
if (ArrayLoad != Self)
|
||||
return false;
|
||||
if (RetainArray) {
|
||||
auto ArrayLoad = stripValueProjections(RetainArray->getOperand(), DepInsts);
|
||||
if (ArrayLoad != Self)
|
||||
return false;
|
||||
}
|
||||
|
||||
DepInsts.push_back(Self);
|
||||
return true;
|
||||
@@ -1002,8 +1011,10 @@ struct HoistableMakeMutable {
|
||||
/// Hoist this make_mutable call and depend instructions to the preheader.
|
||||
void hoist() {
|
||||
auto *Term = Loop->getLoopPreheader()->getTerminator();
|
||||
for (auto *It : swift::reversed(DepInsts))
|
||||
It->moveBefore(Term);
|
||||
for (auto *It : swift::reversed(DepInsts)) {
|
||||
if (It->getParent() != Term->getParent())
|
||||
It->moveBefore(Term);
|
||||
}
|
||||
MakeMutable->moveBefore(Term);
|
||||
}
|
||||
|
||||
@@ -1056,7 +1067,9 @@ private:
|
||||
if (!UncheckedRefCast)
|
||||
return false;
|
||||
DepInsts.push_back(UncheckedRefCast);
|
||||
auto *BaseLoad = dyn_cast<LoadInst>(UncheckedRefCast->getOperand());
|
||||
|
||||
SILValue ArrayBuffer = stripValueProjections(UncheckedRefCast->getOperand(), DepInsts);
|
||||
auto *BaseLoad = dyn_cast<LoadInst>(ArrayBuffer);
|
||||
if (!BaseLoad || Loop->contains(BaseLoad->getOperand()->getParentBB()))
|
||||
return false;
|
||||
DepInsts.push_back(BaseLoad);
|
||||
|
||||
Reference in New Issue
Block a user