Skip to content

Commit c8001d8

Browse files
committed
Add a wrapper type SelectEnumOperation
SelectEnumInstBase will be templated in the next commit. Instead of using templated SelectEnumInstBase everywhere, introduce a new wrapper type SelectEnumOperation.
1 parent 4bb51a2 commit c8001d8

File tree

8 files changed

+193
-107
lines changed

8 files changed

+193
-107
lines changed

include/swift/SIL/InstructionUtils.h

Lines changed: 96 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ struct PolymorphicBuiltinSpecializedOverloadInfo {
257257
/// return SILValue().
258258
SILValue getStaticOverloadForSpecializedPolymorphicBuiltin(BuiltinInst *bi);
259259

260-
/// An ADT for writing generic code against conversion instructions.
260+
/// A wrapper type for writing generic code against conversion instructions.
261261
struct ConversionOperation {
262262
SingleValueInstruction *inst = nullptr;
263263

@@ -331,6 +331,101 @@ struct ConversionOperation {
331331
SILValue getConverted() { return inst->getOperand(0); }
332332
};
333333

334+
/// A wrapper type for writing generic code against SelectEnumAddrInst and
335+
/// SelectEnumInst.
336+
///
337+
/// We use this instead of SelectEnumInstBase in order to avoid the need for
338+
/// templating SelectEnumInstBase.
339+
class SelectEnumOperation {
340+
PointerUnion<SelectEnumAddrInst *, SelectEnumInst *> value;
341+
342+
public:
343+
SelectEnumOperation(SelectEnumAddrInst *seai) : value(seai) {}
344+
SelectEnumOperation(SelectEnumInst *seai) : value(seai) {}
345+
SelectEnumOperation(SILInstruction *i) : value(nullptr) {
346+
if (auto *seai = dyn_cast<SelectEnumAddrInst>(i)) {
347+
value = seai;
348+
return;
349+
}
350+
351+
if (auto *sei = dyn_cast<SelectEnumInst>(i)) {
352+
value = sei;
353+
return;
354+
}
355+
}
356+
357+
SelectEnumOperation(const SILInstruction *i)
358+
: SelectEnumOperation(const_cast<SILInstruction *>(i)) {}
359+
360+
operator SingleValueInstruction *() const {
361+
if (auto *seai = value.dyn_cast<SelectEnumAddrInst *>())
362+
return seai;
363+
return value.get<SelectEnumInst *>();
364+
}
365+
366+
SingleValueInstruction *operator*() const {
367+
if (auto *seai = value.dyn_cast<SelectEnumAddrInst *>())
368+
return seai;
369+
return value.get<SelectEnumInst *>();
370+
}
371+
372+
SingleValueInstruction *operator->() const {
373+
if (auto *seai = value.dyn_cast<SelectEnumAddrInst *>())
374+
return seai;
375+
return value.get<SelectEnumInst *>();
376+
}
377+
378+
operator bool() const { return bool(value); }
379+
380+
SILValue getOperand() {
381+
if (auto *sei = value.dyn_cast<SelectEnumInst *>())
382+
return sei->getOperand();
383+
return value.get<SelectEnumAddrInst *>()->getOperand();
384+
}
385+
386+
SILValue getEnumOperand() { return getOperand(); }
387+
388+
const Operand &getEnumOperandRef() {
389+
if (auto *sei = value.dyn_cast<SelectEnumInst *>())
390+
return sei->getEnumOperandRef();
391+
return value.get<SelectEnumAddrInst *>()->getEnumOperandRef();
392+
}
393+
394+
unsigned getNumCases() const {
395+
if (auto *sei = value.dyn_cast<SelectEnumInst *>())
396+
return sei->getNumCases();
397+
return value.get<SelectEnumAddrInst *>()->getNumCases();
398+
}
399+
400+
std::pair<EnumElementDecl *, SILValue> getCase(unsigned i) const {
401+
if (auto *sei = value.dyn_cast<SelectEnumInst *>())
402+
return sei->getCase(i);
403+
return value.get<SelectEnumAddrInst *>()->getCase(i);
404+
}
405+
/// Return the value that will be used as the result for the specified enum
406+
/// case.
407+
SILValue getCaseResult(EnumElementDecl *D) {
408+
if (auto *sei = value.dyn_cast<SelectEnumInst *>())
409+
return sei->getCaseResult(D);
410+
return value.get<SelectEnumAddrInst *>()->getCaseResult(D);
411+
}
412+
413+
/// If the default refers to exactly one case decl, return it.
414+
NullablePtr<EnumElementDecl> getUniqueCaseForDefault();
415+
416+
bool hasDefault() const {
417+
if (auto *sei = value.dyn_cast<SelectEnumInst *>())
418+
return sei->hasDefault();
419+
return value.get<SelectEnumAddrInst *>()->hasDefault();
420+
}
421+
422+
SILValue getDefaultResult() const {
423+
if (auto *sei = value.dyn_cast<SelectEnumInst *>())
424+
return sei->getDefaultResult();
425+
return value.get<SelectEnumAddrInst *>()->getDefaultResult();
426+
}
427+
};
428+
334429
} // end namespace swift
335430

336431
#endif

lib/IRGen/IRGenSIL.cpp

Lines changed: 36 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -4408,13 +4408,10 @@ IRGenSILFunction::visitSwitchEnumAddrInst(SwitchEnumAddrInst *inst) {
44084408

44094409
// FIXME: We could lower select_enum directly to LLVM select in a lot of cases.
44104410
// For now, just emit a switch and phi nodes, like a chump.
4411-
template <class C, class T, class B>
4412-
static llvm::BasicBlock *
4413-
emitBBMapForSelect(IRGenSILFunction &IGF, Explosion &resultPHI,
4414-
SmallVectorImpl<std::pair<T, llvm::BasicBlock *>> &BBs,
4415-
llvm::BasicBlock *&defaultBB,
4416-
SelectInstBase<C, T, B> *inst) {
4417-
4411+
static llvm::BasicBlock *emitBBMapForSelect(
4412+
IRGenSILFunction &IGF, Explosion &resultPHI,
4413+
SmallVectorImpl<std::pair<EnumElementDecl *, llvm::BasicBlock *>> &BBs,
4414+
llvm::BasicBlock *&defaultBB, SelectEnumOperation inst) {
44184415
auto origBB = IGF.Builder.GetInsertBlock();
44194416

44204417
// Set up a continuation BB and phi nodes to receive the result value.
@@ -4425,8 +4422,7 @@ emitBBMapForSelect(IRGenSILFunction &IGF, Explosion &resultPHI,
44254422
SmallVector<llvm::Value*, 4> phis;
44264423
auto &ti = IGF.getTypeInfo(inst->getType());
44274424
emitPHINodesForType(IGF, inst->getType(), ti,
4428-
inst->getNumCases() + inst->hasDefault(),
4429-
phis);
4425+
inst.getNumCases() + inst.hasDefault(), phis);
44304426
resultPHI.add(phis);
44314427

44324428
IGF.Builder.SetInsertPoint(origBB);
@@ -4440,10 +4436,10 @@ emitBBMapForSelect(IRGenSILFunction &IGF, Explosion &resultPHI,
44404436
addIncomingExplosionToPHINodes(IGF, resultPHI.getAll(), ex);
44414437
}
44424438
};
4443-
4444-
for (unsigned i = 0, e = inst->getNumCases(); i < e; ++i) {
4445-
auto casePair = inst->getCase(i);
4446-
4439+
4440+
for (unsigned i = 0, e = inst.getNumCases(); i < e; ++i) {
4441+
auto casePair = inst.getCase(i);
4442+
44474443
// Create a basic block destination for this case.
44484444
llvm::BasicBlock *destBB = IGF.createBasicBlock("");
44494445
IGF.Builder.emitBlock(destBB);
@@ -4455,18 +4451,18 @@ emitBBMapForSelect(IRGenSILFunction &IGF, Explosion &resultPHI,
44554451
IGF.Builder.CreateBr(contBB);
44564452
BBs.push_back(std::make_pair(casePair.first, destBB));
44574453
}
4458-
4459-
if (inst->hasDefault()) {
4454+
4455+
if (inst.hasDefault()) {
44604456
defaultBB = IGF.createBasicBlock("");
44614457
IGF.Builder.emitBlock(defaultBB);
4462-
4463-
addIncoming(inst->getDefaultResult());
4464-
4458+
4459+
addIncoming(inst.getDefaultResult());
4460+
44654461
IGF.Builder.CreateBr(contBB);
44664462
} else {
44674463
defaultBB = nullptr;
44684464
}
4469-
4465+
44704466
IGF.Builder.emitBlock(contBB);
44714467

44724468
IGF.Builder.SetInsertPoint(origBB);
@@ -4545,10 +4541,9 @@ mapTriviallyToInt(IRGenSILFunction &IGF, const EnumImplStrategy &EIS, SelectEnum
45454541
return result;
45464542
}
45474543

4548-
template <class C, class T, class B>
45494544
static LoweredValue getLoweredValueForSelect(IRGenSILFunction &IGF,
45504545
Explosion &result,
4551-
SelectInstBase<C, T, B> *inst) {
4546+
SelectEnumOperation inst) {
45524547
if (inst->getType().isAddress())
45534548
// FIXME: Loses potentially better alignment info we might have.
45544549
return LoweredValue(Address(
@@ -4558,14 +4553,14 @@ static LoweredValue getLoweredValueForSelect(IRGenSILFunction &IGF,
45584553
}
45594554

45604555
static void emitSingleEnumMemberSelectResult(IRGenSILFunction &IGF,
4561-
SelectEnumInstBase *inst,
4556+
SelectEnumOperation seo,
45624557
llvm::Value *isTrue,
45634558
Explosion &result) {
4564-
assert((inst->getNumCases() == 1 && inst->hasDefault()) ||
4565-
(inst->getNumCases() == 2 && !inst->hasDefault()));
4566-
4559+
assert((seo.getNumCases() == 1 && seo.hasDefault()) ||
4560+
(seo.getNumCases() == 2 && !seo.hasDefault()));
4561+
45674562
// Extract the true values.
4568-
auto trueValue = inst->getCase(0).second;
4563+
auto trueValue = seo.getCase(0).second;
45694564
SmallVector<llvm::Value*, 4> TrueValues;
45704565
if (trueValue->getType().isAddress()) {
45714566
TrueValues.push_back(IGF.getLoweredAddress(trueValue).getAddress());
@@ -4577,7 +4572,7 @@ static void emitSingleEnumMemberSelectResult(IRGenSILFunction &IGF,
45774572

45784573
// Extract the false values.
45794574
auto falseValue =
4580-
inst->hasDefault() ? inst->getDefaultResult() : inst->getCase(1).second;
4575+
seo.hasDefault() ? seo.getDefaultResult() : seo.getCase(1).second;
45814576
SmallVector<llvm::Value*, 4> FalseValues;
45824577
if (falseValue->getType().isAddress()) {
45834578
FalseValues.push_back(IGF.getLoweredAddress(falseValue).getAddress());
@@ -4605,11 +4600,10 @@ static void emitSingleEnumMemberSelectResult(IRGenSILFunction &IGF,
46054600
}
46064601
}
46074602

4608-
46094603
void IRGenSILFunction::visitSelectEnumInst(SelectEnumInst *inst) {
46104604
auto &EIS = getEnumImplStrategy(IGM, inst->getEnumOperand()->getType());
4605+
auto seo = SelectEnumOperation(inst);
46114606
Explosion result;
4612-
46134607
if (llvm::Value *R = mapTriviallyToInt(*this, EIS, inst)) {
46144608
result.add(R);
46154609
} else if ((inst->getNumCases() == 1 && inst->hasDefault()) ||
@@ -4618,29 +4612,30 @@ void IRGenSILFunction::visitSelectEnumInst(SelectEnumInst *inst) {
46184612
// particularly common when testing optionals.
46194613
Explosion value = getLoweredExplosion(inst->getEnumOperand());
46204614
auto isTrue = EIS.emitValueCaseTest(*this, value, inst->getCase(0).first);
4621-
emitSingleEnumMemberSelectResult(*this, inst, isTrue, result);
4615+
emitSingleEnumMemberSelectResult(*this, SelectEnumOperation(inst), isTrue,
4616+
result);
46224617
} else {
46234618
Explosion value = getLoweredExplosion(inst->getEnumOperand());
46244619

46254620
// Map the SIL dest bbs to their LLVM bbs.
46264621
SmallVector<std::pair<EnumElementDecl*, llvm::BasicBlock*>, 4> dests;
46274622
llvm::BasicBlock *defaultDest;
4628-
llvm::BasicBlock *contBB
4629-
= emitBBMapForSelect(*this, result, dests, defaultDest, inst);
4630-
4623+
llvm::BasicBlock *contBB =
4624+
emitBBMapForSelect(*this, result, dests, defaultDest, seo);
4625+
46314626
// Emit the dispatch.
46324627
EIS.emitValueSwitch(*this, value, dests, defaultDest);
46334628

46344629
// emitBBMapForSelectEnum set up a continuation block and phi nodes to
46354630
// receive the result.
46364631
Builder.SetInsertPoint(contBB);
46374632
}
4638-
setLoweredValue(inst,
4639-
getLoweredValueForSelect(*this, result, inst));
4633+
setLoweredValue(inst, getLoweredValueForSelect(*this, result, seo));
46404634
}
46414635

46424636
void IRGenSILFunction::visitSelectEnumAddrInst(SelectEnumAddrInst *inst) {
46434637
Address value = getLoweredAddress(inst->getEnumOperand());
4638+
auto seo = SelectEnumOperation(inst);
46444639
Explosion result;
46454640

46464641
if ((inst->getNumCases() == 1 && inst->hasDefault()) ||
@@ -4651,14 +4646,15 @@ void IRGenSILFunction::visitSelectEnumAddrInst(SelectEnumAddrInst *inst) {
46514646
auto isTrue = EIS.emitIndirectCaseTest(*this,
46524647
inst->getEnumOperand()->getType(),
46534648
value, inst->getCase(0).first);
4654-
emitSingleEnumMemberSelectResult(*this, inst, isTrue, result);
4649+
emitSingleEnumMemberSelectResult(*this, SelectEnumOperation(inst), isTrue,
4650+
result);
46554651
} else {
46564652
// Map the SIL dest bbs to their LLVM bbs.
46574653
SmallVector<std::pair<EnumElementDecl*, llvm::BasicBlock*>, 4> dests;
46584654
llvm::BasicBlock *defaultDest;
4659-
llvm::BasicBlock *contBB
4660-
= emitBBMapForSelect(*this, result, dests, defaultDest, inst);
4661-
4655+
llvm::BasicBlock *contBB =
4656+
emitBBMapForSelect(*this, result, dests, defaultDest, seo);
4657+
46624658
// Emit the dispatch.
46634659
emitSwitchAddressOnlyEnumDispatch(*this, inst->getEnumOperand()->getType(),
46644660
value, dests, defaultDest);
@@ -4667,8 +4663,7 @@ void IRGenSILFunction::visitSelectEnumAddrInst(SelectEnumAddrInst *inst) {
46674663
Builder.SetInsertPoint(contBB);
46684664
}
46694665

4670-
setLoweredValue(inst,
4671-
getLoweredValueForSelect(*this, result, inst));
4666+
setLoweredValue(inst, getLoweredValueForSelect(*this, result, seo));
46724667
}
46734668

46744669
void IRGenSILFunction::visitDynamicMethodBranchInst(DynamicMethodBranchInst *i){

lib/SIL/IR/SILInstruction.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -665,28 +665,28 @@ namespace {
665665
return X->getElement() == RHS->getElement();
666666
}
667667

668-
bool visitSelectEnumInstBase(const SelectEnumInstBase *RHS) {
668+
bool visitSelectEnumOperation(SelectEnumOperation RHS) {
669669
// Check that the instructions match cases in the same order.
670-
auto *X = cast<SelectEnumInstBase>(LHS);
670+
auto X = SelectEnumOperation(LHS);
671671

672-
if (X->getNumCases() != RHS->getNumCases())
672+
if (X.getNumCases() != RHS.getNumCases())
673673
return false;
674-
if (X->hasDefault() != RHS->hasDefault())
674+
if (X.hasDefault() != RHS.hasDefault())
675675
return false;
676676

677-
for (unsigned i = 0, e = X->getNumCases(); i < e; ++i) {
678-
if (X->getCase(i).first != RHS->getCase(i).first)
677+
for (unsigned i = 0, e = X.getNumCases(); i < e; ++i) {
678+
if (X.getCase(i).first != RHS.getCase(i).first)
679679
return false;
680680
}
681681

682682
return true;
683683
}
684684

685685
bool visitSelectEnumInst(const SelectEnumInst *RHS) {
686-
return visitSelectEnumInstBase(RHS);
686+
return visitSelectEnumOperation(RHS);
687687
}
688688
bool visitSelectEnumAddrInst(const SelectEnumAddrInst *RHS) {
689-
return visitSelectEnumInstBase(RHS);
689+
return visitSelectEnumOperation(RHS);
690690
}
691691

692692
// Conversion instructions.

lib/SIL/IR/SILPrinter.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2694,20 +2694,20 @@ class SILPrinter : public SILInstructionVisitor<SILPrinter> {
26942694
printSwitchEnumInst(switchEnum);
26952695
}
26962696

2697-
void printSelectEnumInst(SelectEnumInstBase *SEI) {
2698-
*this << getIDAndType(SEI->getEnumOperand());
2697+
void printSelectEnumInst(SelectEnumOperation SEO) {
2698+
*this << getIDAndType(SEO.getEnumOperand());
26992699

2700-
for (unsigned i = 0, e = SEI->getNumCases(); i < e; ++i) {
2700+
for (unsigned i = 0, e = SEO.getNumCases(); i < e; ++i) {
27012701
EnumElementDecl *elt;
27022702
SILValue result;
2703-
std::tie(elt, result) = SEI->getCase(i);
2703+
std::tie(elt, result) = SEO.getCase(i);
27042704
*this << ", case " << SILDeclRef(elt, SILDeclRef::Kind::EnumElement)
27052705
<< ": " << Ctx.getID(result);
27062706
}
2707-
if (SEI->hasDefault())
2708-
*this << ", default " << Ctx.getID(SEI->getDefaultResult());
2707+
if (SEO.hasDefault())
2708+
*this << ", default " << Ctx.getID(SEO.getDefaultResult());
27092709

2710-
*this << " : " << SEI->getType();
2710+
*this << " : " << SEO->getType();
27112711
}
27122712

27132713
void visitSelectEnumInst(SelectEnumInst *SEI) {

0 commit comments

Comments
 (0)