Skip to content

Commit 02fafc6

Browse files
committed
Optimizer: support the new array literal initialization pattern in the ForEachLoopUnroll pass
1 parent 8da6c8a commit 02fafc6

File tree

4 files changed

+143
-79
lines changed

4 files changed

+143
-79
lines changed

lib/SILOptimizer/Analysis/ArraySemantic.cpp

Lines changed: 40 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "swift/Basic/Assertions.h"
1515
#include "swift/SIL/DebugUtils.h"
1616
#include "swift/SIL/InstructionUtils.h"
17+
#include "swift/SIL/NodeDatastructures.h"
1718
#include "swift/SIL/SILArgument.h"
1819
#include "swift/SIL/SILBuilder.h"
1920
#include "swift/SIL/SILFunction.h"
@@ -732,14 +733,10 @@ SILValue swift::ArraySemanticsCall::getArrayElementStoragePointer() const {
732733
return getArrayUninitializedInitResult(*this, 1);
733734
}
734735

735-
bool swift::ArraySemanticsCall::mapInitializationStores(
736-
llvm::DenseMap<uint64_t, StoreInst *> &ElementValueMap) {
737-
if (getKind() != ArrayCallKind::kArrayUninitialized &&
738-
getKind() != ArrayCallKind::kArrayUninitializedIntrinsic)
739-
return false;
740-
SILValue ElementBuffer = getArrayElementStoragePointer();
736+
static SILValue getElementBaseAddress(ArraySemanticsCall initArray) {
737+
SILValue ElementBuffer = initArray.getArrayElementStoragePointer();
741738
if (!ElementBuffer)
742-
return false;
739+
return SILValue();
743740

744741
// Match initialization stores into ElementBuffer. E.g.
745742
// %82 = struct_extract %element_buffer : $UnsafeMutablePointer<Int>
@@ -756,9 +753,29 @@ bool swift::ArraySemanticsCall::mapInitializationStores(
756753
// mark_dependence can be an operand of the struct_extract or its user.
757754

758755
SILValue UnsafeMutablePointerExtract;
759-
if (getKind() == ArrayCallKind::kArrayUninitializedIntrinsic) {
756+
if (initArray.getKind() == ArrayCallKind::kArrayUninitializedIntrinsic) {
760757
UnsafeMutablePointerExtract = dyn_cast_or_null<MarkDependenceInst>(
761758
getSingleNonDebugUser(ElementBuffer));
759+
if (!UnsafeMutablePointerExtract) {
760+
SILValue array = initArray.getArrayValue();
761+
ValueWorklist worklist(array);
762+
while (SILValue v = worklist.pop()) {
763+
for (auto use : v->getUses()) {
764+
switch (use->getUser()->getKind()) {
765+
case SILInstructionKind::UncheckedRefCastInst:
766+
case SILInstructionKind::StructExtractInst:
767+
case SILInstructionKind::BeginBorrowInst:
768+
worklist.pushIfNotVisited(cast<SingleValueInstruction>(use->getUser()));
769+
break;
770+
case SILInstructionKind::RefTailAddrInst:
771+
return cast<RefTailAddrInst>(use->getUser());
772+
default:
773+
break;
774+
}
775+
}
776+
}
777+
return SILValue();
778+
}
762779
} else {
763780
auto user = getSingleNonDebugUser(ElementBuffer);
764781
// Match mark_dependence (struct_extract or
@@ -774,21 +791,33 @@ bool swift::ArraySemanticsCall::mapInitializationStores(
774791
}
775792
}
776793
if (!UnsafeMutablePointerExtract)
777-
return false;
794+
return SILValue();
778795

779796
auto *PointerToAddress = dyn_cast_or_null<PointerToAddressInst>(
780797
getSingleNonDebugUser(UnsafeMutablePointerExtract));
781798
if (!PointerToAddress)
799+
return SILValue();
800+
return PointerToAddress;
801+
}
802+
803+
bool swift::ArraySemanticsCall::mapInitializationStores(
804+
llvm::DenseMap<uint64_t, StoreInst *> &ElementValueMap) {
805+
if (getKind() != ArrayCallKind::kArrayUninitialized &&
806+
getKind() != ArrayCallKind::kArrayUninitializedIntrinsic)
807+
return false;
808+
809+
SILValue elementAddr = getElementBaseAddress(*this);
810+
if (!elementAddr)
782811
return false;
783812

784813
// Match the stores. We can have either a store directly to the address or
785814
// to an index_addr projection.
786-
for (auto *Op : PointerToAddress->getUses()) {
815+
for (auto *Op : elementAddr->getUses()) {
787816
auto *Inst = Op->getUser();
788817

789818
// Store to the base.
790819
auto *SI = dyn_cast<StoreInst>(Inst);
791-
if (SI && SI->getDest() == PointerToAddress) {
820+
if (SI && SI->getDest() == elementAddr) {
792821
// We have already seen an entry for this index bail.
793822
if (ElementValueMap.count(0))
794823
return false;

lib/SILOptimizer/LoopTransforms/ForEachLoopUnroll.cpp

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ class ArrayInfo {
174174
/// Classify uses of the array into forEach uses, read-only uses etc. and set
175175
/// the fields of this instance appropriately. This function will recursively
176176
/// classify the uses of borrows and copy-values of the array as well.
177-
void classifyUsesOfArray(SILValue arrayValue);
177+
void classifyUsesOfArray(SILValue arrayValue, bool isInInitSection);
178178

179179
public:
180180
ArrayInfo() {}
@@ -293,7 +293,7 @@ static TryApplyInst *isForEachUseOfArray(SILInstruction *user, SILValue array) {
293293
return apply;
294294
}
295295

296-
void ArrayInfo::classifyUsesOfArray(SILValue arrayValue) {
296+
void ArrayInfo::classifyUsesOfArray(SILValue arrayValue, bool isInInitSection) {
297297
for (Operand *operand : arrayValue->getUses()) {
298298
auto *user = operand->getUser();
299299
if (isIncidentalUse(user))
@@ -314,15 +314,21 @@ void ArrayInfo::classifyUsesOfArray(SILValue arrayValue) {
314314
}
315315
// Recursively classify begin_borrow, copy_value, and move_value uses.
316316
if (BeginBorrowInst *beginBorrow = dyn_cast<BeginBorrowInst>(user)) {
317-
classifyUsesOfArray(beginBorrow);
317+
if (isInInitSection) {
318+
// This begin_borrow is used to get the element addresses for array
319+
// initialization. This is happening between the allocate-uninitialized
320+
// and the finalize-array intrinsic calls. We can igore this.
321+
continue;
322+
}
323+
classifyUsesOfArray(beginBorrow, isInInitSection);
318324
continue;
319325
}
320326
if (CopyValueInst *copyValue = dyn_cast<CopyValueInst>(user)) {
321-
classifyUsesOfArray(copyValue);
327+
classifyUsesOfArray(copyValue, isInInitSection);
322328
continue;
323329
}
324330
if (MoveValueInst *moveValue = dyn_cast<MoveValueInst>(user)) {
325-
classifyUsesOfArray(moveValue);
331+
classifyUsesOfArray(moveValue, isInInitSection);
326332
continue;
327333
}
328334
if (DestroyValueInst *destroyValue = dyn_cast<DestroyValueInst>(user)) {
@@ -338,7 +344,7 @@ void ArrayInfo::classifyUsesOfArray(SILValue arrayValue) {
338344
continue;
339345

340346
if (arrayOp.getKind() == ArrayCallKind::kArrayFinalizeIntrinsic) {
341-
classifyUsesOfArray((ApplyInst *)arrayOp);
347+
classifyUsesOfArray((ApplyInst *)arrayOp, /*isInInitSection*/ false);
342348
continue;
343349
}
344350

@@ -357,7 +363,7 @@ bool ArrayInfo::tryInitialize(ApplyInst *apply) {
357363
if (!arrayAllocateUninitCall.mapInitializationStores(elementStoreMap))
358364
return false;
359365
// Collect information about uses of the array value.
360-
classifyUsesOfArray(arrayValue);
366+
classifyUsesOfArray(arrayValue, /*isInInitSection=*/ true);
361367
return true;
362368
}
363369

0 commit comments

Comments
 (0)