Skip to content

Commit eac722e

Browse files
committed
SILOptimizer: Add various pack peepholes to SILCombiner
1 parent d59cce5 commit eac722e

File tree

2 files changed

+138
-0
lines changed

2 files changed

+138
-0
lines changed

lib/SILOptimizer/SILCombiner/SILCombiner.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,11 @@ class SILCombiner :
300300
SILInstruction *
301301
visitDifferentiableFunctionExtractInst(DifferentiableFunctionExtractInst *DFEI);
302302

303+
SILInstruction *visitPackLengthInst(PackLengthInst *PLI);
304+
SILInstruction *visitPackElementGetInst(PackElementGetInst *PEGI);
305+
SILInstruction *visitTuplePackElementAddrInst(TuplePackElementAddrInst *TPEAI);
306+
SILInstruction *visitCopyAddrInst(CopyAddrInst *CAI);
307+
303308
SILInstruction *legacyVisitGlobalValueInst(GlobalValueInst *globalValue);
304309

305310
#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+
}

0 commit comments

Comments
 (0)