Skip to content

Commit 434fb4b

Browse files
authored
Merge pull request #65241 from slavapestov/sil-optimizer-variadic-generics-5.9
SIL Optimizer improvements for variadic generics [5.9]
2 parents 73f1097 + b215d61 commit 434fb4b

19 files changed

+445
-45
lines changed

lib/AST/SubstitutionMap.cpp

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include "swift/AST/InFlightSubstitution.h"
3232
#include "swift/AST/LazyResolver.h"
3333
#include "swift/AST/Module.h"
34+
#include "swift/AST/PackConformance.h"
3435
#include "swift/AST/ProtocolConformance.h"
3536
#include "swift/AST/TypeCheckRequests.h"
3637
#include "swift/AST/Types.h"
@@ -792,13 +793,29 @@ bool SubstitutionMap::isIdentity() const {
792793
if (empty())
793794
return true;
794795

796+
for (auto conf : getConformances()) {
797+
if (conf.isAbstract())
798+
continue;
799+
800+
if (conf.isPack()) {
801+
auto patternConfs = conf.getPack()->getPatternConformances();
802+
if (patternConfs.size() == 1 && patternConfs[0].isAbstract())
803+
continue;
804+
}
805+
806+
return false;
807+
}
808+
795809
GenericSignature sig = getGenericSignature();
796810
bool hasNonIdentityReplacement = false;
797811
auto replacements = getReplacementTypesBuffer();
798812

799813
sig->forEachParam([&](GenericTypeParamType *paramTy, bool isCanonical) {
800814
if (isCanonical) {
801-
if (!paramTy->isEqual(replacements[0]))
815+
Type wrappedParamTy = paramTy;
816+
if (paramTy->isParameterPack())
817+
wrappedParamTy = PackType::getSingletonPackExpansion(paramTy);
818+
if (!wrappedParamTy->isEqual(replacements[0]))
802819
hasNonIdentityReplacement = true;
803820
}
804821

lib/IRGen/Fulfillment.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,8 @@ static CanType getSingletonPackExpansionParameter(CanPackType packType,
188188
return expansion.getPatternType();
189189
}
190190
}
191+
192+
return CanType();
191193
}
192194

193195
bool FulfillmentMap::searchTypeMetadataPack(IRGenModule &IGM,

lib/SIL/IR/SILInstruction.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -881,6 +881,22 @@ namespace {
881881
return true;
882882
}
883883

884+
bool visitScalarPackIndexInst(const ScalarPackIndexInst *RHS) {
885+
auto *X = cast<ScalarPackIndexInst>(LHS);
886+
return (X->getIndexedPackType() == RHS->getIndexedPackType() &&
887+
X->getComponentIndex() == RHS->getComponentIndex());
888+
}
889+
890+
bool visitDynamicPackIndexInst(const DynamicPackIndexInst *RHS) {
891+
auto *X = cast<DynamicPackIndexInst>(LHS);
892+
return X->getIndexedPackType() == RHS->getIndexedPackType();
893+
}
894+
895+
bool visitTuplePackElementAddrInst(const TuplePackElementAddrInst *RHS) {
896+
auto *X = cast<TuplePackElementAddrInst>(LHS);
897+
return X->getElementType() == RHS->getElementType();
898+
}
899+
884900
private:
885901
const SILInstruction *LHS;
886902
};

lib/SILOptimizer/LoopTransforms/LoopUnroll.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,11 +163,21 @@ static Optional<uint64_t> getMaxLoopTripCount(SILLoop *Loop,
163163

164164
SILValue RecNext = Cmp->getArguments()[0];
165165
SILPhiArgument *RecArg;
166+
167+
// Match signed add with overflow, unsigned add with overflow and
168+
// add without overflow.
166169
if (!match(RecNext, m_TupleExtractOperation(
167170
m_ApplyInst(BuiltinValueKind::SAddOver,
168171
m_SILPhiArgument(RecArg), m_One()),
169-
0)))
172+
0)) &&
173+
!match(RecNext, m_TupleExtractOperation(
174+
m_ApplyInst(BuiltinValueKind::UAddOver,
175+
m_SILPhiArgument(RecArg), m_One()),
176+
0)) &&
177+
!match(RecNext, m_ApplyInst(BuiltinValueKind::Add,
178+
m_SILPhiArgument(RecArg), m_One()))) {
170179
return None;
180+
}
171181

172182
if (RecArg->getParent() != Header)
173183
return None;

lib/SILOptimizer/SILCombiner/SILCombiner.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,11 @@ class SILCombiner :
297297
SILInstruction *
298298
visitDifferentiableFunctionExtractInst(DifferentiableFunctionExtractInst *DFEI);
299299

300+
SILInstruction *visitPackLengthInst(PackLengthInst *PLI);
301+
SILInstruction *visitPackElementGetInst(PackElementGetInst *PEGI);
302+
SILInstruction *visitTuplePackElementAddrInst(TuplePackElementAddrInst *TPEAI);
303+
SILInstruction *visitCopyAddrInst(CopyAddrInst *CAI);
304+
300305
SILInstruction *legacyVisitGlobalValueInst(GlobalValueInst *globalValue);
301306

302307
#define PASS(ID, TAG, DESCRIPTION)

lib/SILOptimizer/SILCombiner/SILCombinerMiscVisitors.cpp

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2391,3 +2391,136 @@ SILCombiner::visitDifferentiableFunctionExtractInst(DifferentiableFunctionExtrac
23912391
replaceInstUsesWith(*DFEI, newValue);
23922392
return eraseInstFromFunction(*DFEI);
23932393
}
2394+
2395+
// Simplify `pack_length` with constant-length pack.
2396+
//
2397+
// Before:
2398+
// %len = pack_length $Pack{Int, String, Float}
2399+
//
2400+
// After:
2401+
// %len = integer_literal Builtin.Word, 3
2402+
SILInstruction *SILCombiner::visitPackLengthInst(PackLengthInst *PLI) {
2403+
auto PackTy = PLI->getPackType();
2404+
if (!PackTy->containsPackExpansionType()) {
2405+
return Builder.createIntegerLiteral(PLI->getLoc(), PLI->getType(),
2406+
PackTy->getNumElements());
2407+
}
2408+
2409+
return nullptr;
2410+
}
2411+
2412+
// Simplify `pack_element_get` where the index is a `dynamic_pack_index` with
2413+
// a constant operand.
2414+
//
2415+
// Before:
2416+
// %idx = integer_literal Builtin.Word, N
2417+
// %pack_idx = dynamic_pack_index %Pack{Int, String, Float}, %idx
2418+
// %pack_elt = pack_element_get %pack_value, %pack_idx, @element("...")
2419+
//
2420+
// After:
2421+
// %pack_idx = scalar_pack_index %Pack{Int, String, Float}, N
2422+
// %concrete_elt = pack_element_get %pack_value, %pack_idx, <<concrete type>>
2423+
// %pack_elt = unchecked_addr_cast %concrete_elt, @element("...")
2424+
SILInstruction *SILCombiner::visitPackElementGetInst(PackElementGetInst *PEGI) {
2425+
auto *DPII = dyn_cast<DynamicPackIndexInst>(PEGI->getIndex());
2426+
if (DPII == nullptr)
2427+
return nullptr;
2428+
2429+
auto PackTy = PEGI->getPackType();
2430+
if (PackTy->containsPackExpansionType())
2431+
return nullptr;
2432+
2433+
auto *Op = dyn_cast<IntegerLiteralInst>(DPII->getOperand());
2434+
if (Op == nullptr)
2435+
return nullptr;
2436+
2437+
if (Op->getValue().uge(PackTy->getNumElements()))
2438+
return nullptr;
2439+
2440+
unsigned Index = Op->getValue().getZExtValue();
2441+
auto *SPII = Builder.createScalarPackIndex(
2442+
DPII->getLoc(), Index, DPII->getIndexedPackType());
2443+
2444+
auto ElementTy = SILType::getPrimitiveAddressType(
2445+
PEGI->getPackType().getElementType(Index));
2446+
auto *NewPEGI = Builder.createPackElementGet(
2447+
PEGI->getLoc(), SPII, PEGI->getPack(),
2448+
ElementTy);
2449+
2450+
return Builder.createUncheckedAddrCast(
2451+
PEGI->getLoc(), NewPEGI, PEGI->getElementType());
2452+
}
2453+
2454+
// Simplify `tuple_pack_element_addr` where the index is a `dynamic_pack_index`
2455+
//with a constant operand.
2456+
//
2457+
// Before:
2458+
// %idx = integer_literal Builtin.Word, N
2459+
// %pack_idx = dynamic_pack_index %Pack{Int, String, Float}, %idx
2460+
// %tuple_elt = tuple_pack_element_addr %tuple_value, %pack_idx, @element("...")
2461+
//
2462+
// After:
2463+
// %concrete_elt = tuple_element_addr %tuple_value, N
2464+
// %tuple_elt = unchecked_addr_cast %concrete_elt, @element("...")
2465+
SILInstruction *
2466+
SILCombiner::visitTuplePackElementAddrInst(TuplePackElementAddrInst *TPEAI) {
2467+
auto *DPII = dyn_cast<DynamicPackIndexInst>(TPEAI->getIndex());
2468+
if (DPII == nullptr)
2469+
return nullptr;
2470+
2471+
auto PackTy = DPII->getIndexedPackType();
2472+
if (PackTy->containsPackExpansionType())
2473+
return nullptr;
2474+
2475+
auto *Op = dyn_cast<IntegerLiteralInst>(DPII->getOperand());
2476+
if (Op == nullptr)
2477+
return nullptr;
2478+
2479+
if (Op->getValue().uge(PackTy->getNumElements()))
2480+
return nullptr;
2481+
2482+
unsigned Index = Op->getValue().getZExtValue();
2483+
2484+
auto *TEAI = Builder.createTupleElementAddr(
2485+
TPEAI->getLoc(), TPEAI->getTuple(), Index);
2486+
return Builder.createUncheckedAddrCast(
2487+
TPEAI->getLoc(), TEAI, TPEAI->getElementType());
2488+
}
2489+
2490+
// This is a hack. When optimizing a simple pack expansion expression which
2491+
// forms a tuple from a pack, like `(repeat each t)`, after the above
2492+
// peepholes we end up with:
2493+
//
2494+
// %src = unchecked_addr_cast %real_src, @element("...")
2495+
// %dst = unchecked_addr_cast %real_dst, @element("...")
2496+
// copy_addr %src, %dst
2497+
//
2498+
// Simplify this to
2499+
//
2500+
// copy_addr %real_src, %real_dst
2501+
//
2502+
// Assuming that %real_src and %real_dst have the same type.
2503+
//
2504+
// In this simple case, this eliminates the opened element archetype entirely.
2505+
// However, a more principled peephole would be to transform an
2506+
// open_pack_element with a scalar index by replacing all usages of the
2507+
// element archetype with a concrete type.
2508+
SILInstruction *
2509+
SILCombiner::visitCopyAddrInst(CopyAddrInst *CAI) {
2510+
auto *Src = dyn_cast<UncheckedAddrCastInst>(CAI->getSrc());
2511+
auto *Dst = dyn_cast<UncheckedAddrCastInst>(CAI->getDest());
2512+
2513+
if (Src == nullptr || Dst == nullptr)
2514+
return nullptr;
2515+
2516+
if (Src->getType() != Dst->getType() ||
2517+
!Src->getType().is<ElementArchetypeType>())
2518+
return nullptr;
2519+
2520+
if (Src->getOperand()->getType() != Dst->getOperand()->getType())
2521+
return nullptr;
2522+
2523+
return Builder.createCopyAddr(
2524+
CAI->getLoc(), Src->getOperand(), Dst->getOperand(),
2525+
CAI->isTakeOfSrc(), CAI->isInitializationOfDest());
2526+
}

lib/SILOptimizer/Transforms/CSE.cpp

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,25 @@ class HashVisitor : public SILInstructionVisitor<HashVisitor, llvm::hash_code> {
515515
X->getKind(), tryLookThroughOwnershipInsts(&X->getOperandRef()),
516516
llvm::hash_combine_range(ConformsTo.begin(), ConformsTo.end()));
517517
}
518+
519+
hash_code visitScalarPackIndexInst(ScalarPackIndexInst *X) {
520+
return llvm::hash_combine(
521+
X->getKind(), X->getIndexedPackType(), X->getComponentIndex());
522+
}
523+
524+
hash_code visitDynamicPackIndexInst(DynamicPackIndexInst *X) {
525+
return llvm::hash_combine(
526+
X->getKind(), X->getIndexedPackType(),
527+
tryLookThroughOwnershipInsts(&X->getOperandRef()));
528+
}
529+
530+
hash_code visitTuplePackElementAddrInst(TuplePackElementAddrInst *X) {
531+
OperandValueArrayRef Operands(X->getAllOperands());
532+
return llvm::hash_combine(
533+
X->getKind(),
534+
llvm::hash_combine_range(Operands.begin(), Operands.end()),
535+
X->getElementType());
536+
}
518537
};
519538
} // end anonymous namespace
520539

@@ -567,7 +586,7 @@ bool llvm::DenseMapInfo<SimpleValue>::isEqual(SimpleValue LHS,
567586
};
568587
bool isEqual =
569588
LHSI->getKind() == RHSI->getKind() && LHSI->isIdenticalTo(RHSI, opCmp);
570-
#ifdef NDEBUG
589+
#ifndef NDEBUG
571590
if (isEqual && getHashValue(LHS) != getHashValue(RHS)) {
572591
llvm::dbgs() << "LHS: ";
573592
LHSI->dump();
@@ -1225,6 +1244,9 @@ bool CSE::canHandle(SILInstruction *Inst) {
12251244
case SILInstructionKind::MarkDependenceInst:
12261245
case SILInstructionKind::InitExistentialMetatypeInst:
12271246
case SILInstructionKind::WitnessMethodInst:
1247+
case SILInstructionKind::ScalarPackIndexInst:
1248+
case SILInstructionKind::DynamicPackIndexInst:
1249+
case SILInstructionKind::TuplePackElementAddrInst:
12281250
// Intentionally we don't handle (prev_)dynamic_function_ref.
12291251
// They change at runtime.
12301252
#define LOADABLE_REF_STORAGE(Name, ...) \

lib/SILOptimizer/Utils/ConstantFolding.cpp

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -588,8 +588,31 @@ static SILValue constantFoldBinary(BuiltinInst *BI,
588588
// Are there valid uses for these in stdlib?
589589
case BuiltinValueKind::Add:
590590
case BuiltinValueKind::Mul:
591-
case BuiltinValueKind::Sub:
592-
return nullptr;
591+
case BuiltinValueKind::Sub: {
592+
OperandValueArrayRef Args = BI->getArguments();
593+
auto *LHS = dyn_cast<IntegerLiteralInst>(Args[0]);
594+
auto *RHS = dyn_cast<IntegerLiteralInst>(Args[1]);
595+
if (!RHS || !LHS)
596+
return nullptr;
597+
APInt LHSI = LHS->getValue();
598+
APInt RHSI = RHS->getValue();
599+
600+
switch (ID) {
601+
default: llvm_unreachable("Not all cases are covered!");
602+
case BuiltinValueKind::Add:
603+
LHSI += RHSI;
604+
break;
605+
case BuiltinValueKind::Mul:
606+
LHSI *= RHSI;
607+
break;
608+
case BuiltinValueKind::Sub:
609+
LHSI -= RHSI;
610+
break;
611+
}
612+
613+
SILBuilderWithScope B(BI);
614+
return B.createIntegerLiteral(BI->getLoc(), BI->getType(), LHSI);
615+
}
593616

594617
case BuiltinValueKind::And:
595618
case BuiltinValueKind::AShr:

lib/Serialization/DeclTypeRecordNodes.def

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,6 @@ TYPE(NAME_ALIAS)
115115

116116
TYPE(PACK_EXPANSION)
117117
TYPE(PACK)
118-
TRAILING_INFO(PACK_TYPE_ELT)
119118
TYPE(SIL_PACK)
120119

121120
TYPE(ERROR)

lib/Serialization/Deserialization.cpp

Lines changed: 9 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6866,31 +6866,18 @@ Expected<Type> DESERIALIZE_TYPE(PACK_EXPANSION_TYPE)(
68666866

68676867
Expected<Type> DESERIALIZE_TYPE(PACK_TYPE)(
68686868
ModuleFile &MF, SmallVectorImpl<uint64_t> &scratch, StringRef blobData) {
6869-
// The pack record itself is empty. Read all trailing elements.
6870-
SmallVector<Type, 8> elements;
6871-
while (true) {
6872-
llvm::BitstreamEntry entry =
6873-
MF.fatalIfUnexpected(MF.DeclTypeCursor.advance(AF_DontPopBlockAtEnd));
6874-
if (entry.Kind != llvm::BitstreamEntry::Record)
6875-
break;
6876-
6877-
scratch.clear();
6878-
unsigned recordID = MF.fatalIfUnexpected(
6879-
MF.DeclTypeCursor.readRecord(entry.ID, scratch, &blobData));
6880-
if (recordID != decls_block::PACK_TYPE_ELT)
6881-
break;
6882-
6883-
TypeID typeID;
6884-
decls_block::PackTypeEltLayout::readRecord(scratch, typeID);
6885-
6886-
auto elementTy = MF.getTypeChecked(typeID);
6887-
if (!elementTy)
6888-
return elementTy.takeError();
6869+
ArrayRef<uint64_t> elementTypeIDs;
6870+
decls_block::PackTypeLayout::readRecord(scratch, elementTypeIDs);
68896871

6890-
elements.push_back(elementTy.get());
6872+
SmallVector<Type, 8> elementTypes;
6873+
for (auto elementTypeID : elementTypeIDs) {
6874+
auto elementType = MF.getTypeChecked(elementTypeID);
6875+
if (!elementType)
6876+
return elementType.takeError();
6877+
elementTypes.push_back(elementType.get());
68916878
}
68926879

6893-
return PackType::get(MF.getContext(), elements);
6880+
return PackType::get(MF.getContext(), elementTypes);
68946881
}
68956882

68966883
Expected<Type> DESERIALIZE_TYPE(SIL_PACK_TYPE)(

lib/Serialization/DeserializeSIL.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1285,11 +1285,10 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn,
12851285
RawOpCode = (unsigned)SILInstructionKind::HasSymbolInst;
12861286
break;
12871287
case SIL_PACK_ELEMENT_GET:
1288-
SILPackElementGetLayout::readRecord(scratch,
1288+
SILPackElementGetLayout::readRecord(scratch, RawOpCode,
12891289
TyID, TyCategory,
12901290
TyID2, TyCategory2, ValID2,
12911291
ValID3);
1292-
RawOpCode = (unsigned)SILInstructionKind::PackElementGetInst;
12931292
break;
12941293
case SIL_PACK_ELEMENT_SET:
12951294
SILPackElementSetLayout::readRecord(scratch,
@@ -1332,7 +1331,7 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn,
13321331
}
13331332
case SILInstructionKind::AllocPackInst: {
13341333
assert(RecordKind == SIL_ONE_TYPE && "Layout should be OneType.");
1335-
ResultInst = Builder.createAllocStack(
1334+
ResultInst = Builder.createAllocPack(
13361335
Loc, getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn));
13371336
break;
13381337
}

0 commit comments

Comments
 (0)