Skip to content

Commit 6d7f3f6

Browse files
Merge pull request #24622 from aschwaighofer/opaque_specializer_fixes-5.1
[5.1] Opaque specializer fixes
2 parents 4563bf8 + 5d7ae16 commit 6d7f3f6

File tree

2 files changed

+129
-29
lines changed

2 files changed

+129
-29
lines changed

lib/SILOptimizer/Transforms/SpecializeOpaqueArchetypes.cpp

Lines changed: 68 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -138,18 +138,30 @@ class OpaqueSpecializerCloner
138138
void visitEnumInst(EnumInst *Inst) {
139139
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
140140
SILValue opd = SILValue();
141+
auto newTy = getOpType(Inst->getType());
141142
if (Inst->hasOperand()) {
142-
SILType caseTy = Inst->getType().getEnumElementType(
143-
Inst->getElement(), getBuilder().getFunction().getModule());
144143
opd = getOpValue(Inst->getOperand());
145-
if (opd->getType() != caseTy) {
146-
opd = createCast(getOpLocation(Inst->getLoc()), opd, caseTy);
147-
}
144+
SILType newCaseTy = newTy.getEnumElementType(
145+
Inst->getElement(), getBuilder().getFunction().getModule());
146+
if (opd->getType() != newCaseTy)
147+
opd = createCast(getOpLocation(Inst->getLoc()), opd, newCaseTy);
148148
}
149149
recordClonedInstruction(
150150
Inst, getBuilder().createEnum(getOpLocation(Inst->getLoc()), opd,
151-
Inst->getElement(),
152-
getOpType(Inst->getType())));
151+
Inst->getElement(), newTy));
152+
}
153+
154+
void visitInitEnumDataAddrInst(InitEnumDataAddrInst *Inst) {
155+
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
156+
auto opd = getOpValue(Inst->getOperand());
157+
auto caseTy = opd->getType().getEnumElementType(
158+
Inst->getElement(), getBuilder().getFunction().getModule());
159+
auto expectedTy = getOpType(Inst->getType());
160+
if (expectedTy != caseTy)
161+
expectedTy = caseTy;
162+
recordClonedInstruction(Inst, getBuilder().createInitEnumDataAddr(
163+
getOpLocation(Inst->getLoc()), opd,
164+
Inst->getElement(), expectedTy));
153165
}
154166

155167
/// Projections should not change the type if the type is not specialized.
@@ -337,24 +349,48 @@ class OpaqueSpecializerCloner
337349
loc, opd, type, /*withoutActuallyEscaping*/ false);
338350
} else if (opd->getType().isTrivial(CurFn)) {
339351
return getBuilder().createUncheckedTrivialBitCast(loc, opd, type);
340-
} else if (opd->getType().isObject()) {
352+
} else if (opd->getType().canRefCast(opd->getType(), type,
353+
CurFn.getModule())) {
341354
return getBuilder().createUncheckedRefCast(loc, opd, type);
342355
} else {
343356
// This could be improved upon by recursively recomposing the type.
344357
auto *stackLoc = getBuilder().createAllocStack(loc, type);
345-
auto *addr =
346-
getBuilder().createUncheckedAddrCast(loc, stackLoc, opd->getType());
347-
getBuilder().createTrivialStoreOr(loc, addr, opd,
348-
StoreOwnershipQualifier::Init);
358+
auto *addr = getBuilder().createUncheckedAddrCast(
359+
loc, stackLoc, opd->getType().getAddressType());
360+
getBuilder().createTrivialStoreOr(loc, opd, addr,
361+
StoreOwnershipQualifier::Init, true);
349362
SILValue res = getBuilder().createTrivialLoadOr(
350-
loc, addr, LoadOwnershipQualifier::Take);
363+
loc, stackLoc, LoadOwnershipQualifier::Take, true);
351364
getBuilder().createDeallocStack(loc, stackLoc);
352365
return res;
353366
}
354367
}
355368

369+
void replaceBlockArgumentType(SILLocation loc, SILBasicBlock *destBlock,
370+
SILType withType) {
371+
assert(destBlock->getArguments().size() == 1);
372+
373+
auto origType = (*destBlock->args_begin())->getType();
374+
auto origPhi = destBlock->getPhiArguments()[0];
375+
SILValue undef = SILUndef::get(origType, getBuilder().getFunction());
376+
SmallVector<Operand *, 8> useList(origPhi->use_begin(), origPhi->use_end());
377+
for (auto *use : useList) {
378+
use->set(undef);
379+
}
380+
381+
auto *newPhi =
382+
destBlock->replacePhiArgument(0, withType, origPhi->getOwnershipKind());
383+
384+
getBuilder().setInsertionPoint(destBlock->begin());
385+
auto cast = createCast(loc, newPhi, origType);
386+
for (auto *use : useList) {
387+
use->set(cast);
388+
}
389+
}
390+
356391
void fixUp(SILFunction *) {
357-
for (auto &BB : getBuilder().getFunction()) {
392+
auto &clonedFunction = getBuilder().getFunction();
393+
for (auto &BB : clonedFunction) {
358394
for (auto &cloned : BB) {
359395
// Fix up the type of try_apply successor block arguments.
360396
if (auto *tryApply = dyn_cast<TryApplyInst>(&cloned)) {
@@ -365,22 +401,25 @@ class OpaqueSpecializerCloner
365401
auto normalBBType = (*normalBB->args_begin())->getType();
366402
auto applyResultType = calleeConv.getSILResultType();
367403
if (normalBBType != calleeConv.getSILResultType()) {
368-
auto origPhi = normalBB->getPhiArguments()[0];
369-
SILValue undef =
370-
SILUndef::get(normalBBType, getBuilder().getFunction());
371-
SmallVector<Operand *, 8> useList(origPhi->use_begin(),
372-
origPhi->use_end());
373-
for (auto *use : useList) {
374-
use->set(undef);
375-
}
376-
377-
auto *newPhi = normalBB->replacePhiArgument(
378-
0, applyResultType, origPhi->getOwnershipKind());
404+
replaceBlockArgumentType(tryApply->getLoc(), normalBB, applyResultType);
405+
}
406+
}
407+
// Fix up the type of switch_enum successor block arguments.
408+
if (auto *switchEnum = dyn_cast<SwitchEnumInst>(&cloned)) {
409+
SILType enumTy = switchEnum->getOperand()->getType();
410+
for (unsigned i = 0, e = switchEnum->getNumCases(); i < e; ++i) {
411+
EnumElementDecl *elt;
412+
SILBasicBlock *dest;
413+
std::tie(elt, dest) = switchEnum->getCase(i);
414+
415+
if (elt->hasAssociatedValues() &&
416+
dest->getArguments().size() == 1) {
417+
SILType eltArgTy =
418+
enumTy.getEnumElementType(elt, clonedFunction.getModule());
419+
SILType bbArgTy = dest->getArguments()[0]->getType();
420+
if (eltArgTy != bbArgTy)
421+
replaceBlockArgumentType(switchEnum->getLoc(), dest, eltArgTy);
379422

380-
getBuilder().setInsertionPoint(normalBB->begin());
381-
auto cast = createCast(tryApply->getLoc(), newPhi, normalBBType);
382-
for (auto *use : useList) {
383-
use->set(cast);
384423
}
385424
}
386425
}

test/SILOptimizer/specialize_opaque_type_archetypes.swift

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,3 +476,64 @@ extension PA {
476476
useP(p.1(5))
477477
}
478478
}
479+
480+
public struct Foo {
481+
var id : Int = 0
482+
var p : Int64 = 1
483+
}
484+
485+
struct Test : RandomAccessCollection {
486+
struct Index : Comparable, Hashable {
487+
var identifier: AnyHashable?
488+
var offset: Int
489+
490+
static func < (lhs: Index, rhs: Index) -> Bool {
491+
return lhs.offset < rhs.offset
492+
}
493+
494+
func hash(into hasher: inout Hasher) {
495+
hasher.combine(identifier)
496+
hasher.combine(offset)
497+
}
498+
}
499+
500+
let foos: [Foo]
501+
let ids: [AnyHashable]
502+
503+
init(foos: [Foo]) {
504+
self.foos = foos
505+
self.ids = foos.map { $0.id }
506+
}
507+
508+
func _index(atOffset n: Int) -> Index {
509+
return Index(identifier: ids.isEmpty ? nil : ids[n], offset: n)
510+
}
511+
512+
var startIndex: Index {
513+
return _index(atOffset: 0)
514+
}
515+
516+
var endIndex: Index {
517+
return Index(identifier: nil, offset: ids.endIndex)
518+
}
519+
520+
func index(after i: Index) -> Index {
521+
return _index(atOffset: i.offset + 1)
522+
}
523+
524+
func index(before i: Index) -> Index {
525+
return _index(atOffset: i.offset - 1)
526+
}
527+
528+
func distance(from start: Index, to end: Index) -> Int {
529+
return end.offset - start.offset
530+
}
531+
532+
func index(_ i: Index, offsetBy n: Int) -> Index {
533+
return _index(atOffset: i.offset + n)
534+
}
535+
536+
subscript(i: Index) -> some P {
537+
return foos[i.offset].p
538+
}
539+
}

0 commit comments

Comments
 (0)