Skip to content

Commit c3bf40c

Browse files
Merge pull request swiftlang#24621 from aschwaighofer/opaque_specializer_fixes
Opaque specializer fixes
2 parents 0da04ca + 9685aaf commit c3bf40c

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
@@ -133,18 +133,30 @@ class OpaqueSpecializerCloner
133133
void visitEnumInst(EnumInst *Inst) {
134134
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
135135
SILValue opd = SILValue();
136+
auto newTy = getOpType(Inst->getType());
136137
if (Inst->hasOperand()) {
137-
SILType caseTy = Inst->getType().getEnumElementType(
138-
Inst->getElement(), getBuilder().getFunction().getModule());
139138
opd = getOpValue(Inst->getOperand());
140-
if (opd->getType() != caseTy) {
141-
opd = createCast(getOpLocation(Inst->getLoc()), opd, caseTy);
142-
}
139+
SILType newCaseTy = newTy.getEnumElementType(
140+
Inst->getElement(), getBuilder().getFunction().getModule());
141+
if (opd->getType() != newCaseTy)
142+
opd = createCast(getOpLocation(Inst->getLoc()), opd, newCaseTy);
143143
}
144144
recordClonedInstruction(
145145
Inst, getBuilder().createEnum(getOpLocation(Inst->getLoc()), opd,
146-
Inst->getElement(),
147-
getOpType(Inst->getType())));
146+
Inst->getElement(), newTy));
147+
}
148+
149+
void visitInitEnumDataAddrInst(InitEnumDataAddrInst *Inst) {
150+
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
151+
auto opd = getOpValue(Inst->getOperand());
152+
auto caseTy = opd->getType().getEnumElementType(
153+
Inst->getElement(), getBuilder().getFunction().getModule());
154+
auto expectedTy = getOpType(Inst->getType());
155+
if (expectedTy != caseTy)
156+
expectedTy = caseTy;
157+
recordClonedInstruction(Inst, getBuilder().createInitEnumDataAddr(
158+
getOpLocation(Inst->getLoc()), opd,
159+
Inst->getElement(), expectedTy));
148160
}
149161

150162
/// Projections should not change the type if the type is not specialized.
@@ -332,24 +344,48 @@ class OpaqueSpecializerCloner
332344
loc, opd, type, /*withoutActuallyEscaping*/ false);
333345
} else if (opd->getType().isTrivial(CurFn)) {
334346
return getBuilder().createUncheckedTrivialBitCast(loc, opd, type);
335-
} else if (opd->getType().isObject()) {
347+
} else if (opd->getType().canRefCast(opd->getType(), type,
348+
CurFn.getModule())) {
336349
return getBuilder().createUncheckedRefCast(loc, opd, type);
337350
} else {
338351
// This could be improved upon by recursively recomposing the type.
339352
auto *stackLoc = getBuilder().createAllocStack(loc, type);
340-
auto *addr =
341-
getBuilder().createUncheckedAddrCast(loc, stackLoc, opd->getType());
342-
getBuilder().createTrivialStoreOr(loc, addr, opd,
343-
StoreOwnershipQualifier::Init);
353+
auto *addr = getBuilder().createUncheckedAddrCast(
354+
loc, stackLoc, opd->getType().getAddressType());
355+
getBuilder().createTrivialStoreOr(loc, opd, addr,
356+
StoreOwnershipQualifier::Init, true);
344357
SILValue res = getBuilder().createTrivialLoadOr(
345-
loc, addr, LoadOwnershipQualifier::Take);
358+
loc, stackLoc, LoadOwnershipQualifier::Take, true);
346359
getBuilder().createDeallocStack(loc, stackLoc);
347360
return res;
348361
}
349362
}
350363

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

375-
getBuilder().setInsertionPoint(normalBB->begin());
376-
auto cast = createCast(tryApply->getLoc(), newPhi, normalBBType);
377-
for (auto *use : useList) {
378-
use->set(cast);
379418
}
380419
}
381420
}

test/SILOptimizer/specialize_opaque_type_archetypes.swift

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

0 commit comments

Comments
 (0)