mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Revert "IRGen: Peephole improvements for enum switch codegen."
This may be the cause of a crash and burn on the iOS builders: Assertion failed: (Offset <= PieceOffset && "overlapping or duplicate pieces"), function finalize Swift SVN r29027
This commit is contained in:
@@ -357,7 +357,7 @@ static void emitSubSwitch(IRGenFunction &IGF,
|
|||||||
MutableArrayRef<EnumPayload::LazyValue> values,
|
MutableArrayRef<EnumPayload::LazyValue> values,
|
||||||
APInt mask,
|
APInt mask,
|
||||||
MutableArrayRef<std::pair<APInt, llvm::BasicBlock *>> cases,
|
MutableArrayRef<std::pair<APInt, llvm::BasicBlock *>> cases,
|
||||||
SwitchDefaultDest dflt) {
|
llvm::BasicBlock *dflt) {
|
||||||
recur:
|
recur:
|
||||||
assert(!values.empty() && "didn't exit out when exhausting all values?!");
|
assert(!values.empty() && "didn't exit out when exhausting all values?!");
|
||||||
|
|
||||||
@@ -432,28 +432,21 @@ recur:
|
|||||||
// If there's only one case, do a cond_br.
|
// If there's only one case, do a cond_br.
|
||||||
if (subCases.size() == 1) {
|
if (subCases.size() == 1) {
|
||||||
auto &subCase = *subCases.begin();
|
auto &subCase = *subCases.begin();
|
||||||
llvm::BasicBlock *block = blockForCases(subCase.second);
|
|
||||||
// If the default case is unreachable, we don't need to conditionally
|
|
||||||
// branch.
|
|
||||||
if (dflt.getInt()) {
|
|
||||||
IGF.Builder.CreateBr(block);
|
|
||||||
goto next;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto &valuePiece = subCase.first;
|
auto &valuePiece = subCase.first;
|
||||||
llvm::Value *valueConstant = llvm::ConstantInt::get(payloadIntTy,
|
llvm::Value *valueConstant = llvm::ConstantInt::get(payloadIntTy,
|
||||||
valuePiece);
|
valuePiece);
|
||||||
valueConstant = IGF.Builder.CreateBitOrPointerCast(valueConstant,
|
valueConstant = IGF.Builder.CreateBitOrPointerCast(valueConstant,
|
||||||
v->getType());
|
v->getType());
|
||||||
auto cmp = IGF.Builder.CreateICmpEQ(v, valueConstant);
|
auto cmp = IGF.Builder.CreateICmpEQ(v, valueConstant);
|
||||||
IGF.Builder.CreateCondBr(cmp, block, dflt.getPointer());
|
llvm::BasicBlock *block = blockForCases(subCase.second);
|
||||||
|
IGF.Builder.CreateCondBr(cmp, block, dflt);
|
||||||
goto next;
|
goto next;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, do a switch.
|
// Otherwise, do a switch.
|
||||||
{
|
{
|
||||||
v = IGF.Builder.CreateBitOrPointerCast(v, payloadIntTy);
|
v = IGF.Builder.CreateBitOrPointerCast(v, payloadIntTy);
|
||||||
auto swi = IGF.Builder.CreateSwitch(v, dflt.getPointer(), subCases.size());
|
auto swi = IGF.Builder.CreateSwitch(v, dflt, subCases.size());
|
||||||
|
|
||||||
for (auto &subCase : subCases) {
|
for (auto &subCase : subCases) {
|
||||||
auto &valuePiece = subCase.first;
|
auto &valuePiece = subCase.first;
|
||||||
@@ -475,17 +468,11 @@ next:
|
|||||||
void EnumPayload::emitSwitch(IRGenFunction &IGF,
|
void EnumPayload::emitSwitch(IRGenFunction &IGF,
|
||||||
APInt mask,
|
APInt mask,
|
||||||
ArrayRef<std::pair<APInt, llvm::BasicBlock *>> cases,
|
ArrayRef<std::pair<APInt, llvm::BasicBlock *>> cases,
|
||||||
SwitchDefaultDest dflt) const {
|
llvm::BasicBlock *dflt) const {
|
||||||
// If there's only one case to test, do a simple compare and branch.
|
// If there's only one case to test, do a simple compare and branch.
|
||||||
if (cases.size() == 1) {
|
if (cases.size() == 1) {
|
||||||
// If the default case is unreachable, don't bother branching at all.
|
|
||||||
if (dflt.getInt()) {
|
|
||||||
IGF.Builder.CreateBr(cases[0].second);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto *cmp = emitCompare(IGF, mask, cases[0].first);
|
auto *cmp = emitCompare(IGF, mask, cases[0].first);
|
||||||
IGF.Builder.CreateCondBr(cmp, cases[0].second, dflt.getPointer());
|
IGF.Builder.CreateCondBr(cmp, cases[0].second, dflt);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -80,15 +80,6 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Is a switch default destination unreachable?
|
|
||||||
enum IsUnreachable_t: bool {
|
|
||||||
IsNotUnreachable = false,
|
|
||||||
IsUnreachable = true,
|
|
||||||
};
|
|
||||||
|
|
||||||
using SwitchDefaultDest
|
|
||||||
= llvm::PointerIntPair<llvm::BasicBlock*, 1, IsUnreachable_t>;
|
|
||||||
|
|
||||||
/// An enum payload value. The payload is represented as an explosion of
|
/// An enum payload value. The payload is represented as an explosion of
|
||||||
/// integers and pointers that together represent the bit pattern of
|
/// integers and pointers that together represent the bit pattern of
|
||||||
/// the payload.
|
/// the payload.
|
||||||
@@ -152,7 +143,7 @@ public:
|
|||||||
void emitSwitch(IRGenFunction &IGF,
|
void emitSwitch(IRGenFunction &IGF,
|
||||||
APInt mask,
|
APInt mask,
|
||||||
ArrayRef<std::pair<APInt, llvm::BasicBlock*>> cases,
|
ArrayRef<std::pair<APInt, llvm::BasicBlock*>> cases,
|
||||||
SwitchDefaultDest dflt) const;
|
llvm::BasicBlock *dflt) const;
|
||||||
|
|
||||||
/// Emit an equality comparison operation that payload & mask == value.
|
/// Emit an equality comparison operation that payload & mask == value.
|
||||||
llvm::Value *emitCompare(IRGenFunction &IGF,
|
llvm::Value *emitCompare(IRGenFunction &IGF,
|
||||||
|
|||||||
@@ -1393,6 +1393,37 @@ namespace {
|
|||||||
llvm::BasicBlock *payloadDest = blockForCase(getPayloadElement());
|
llvm::BasicBlock *payloadDest = blockForCase(getPayloadElement());
|
||||||
unsigned extraInhabitantCount = getNumExtraInhabitantTagValues();
|
unsigned extraInhabitantCount = getNumExtraInhabitantTagValues();
|
||||||
|
|
||||||
|
// If there are extra tag bits, switch over them first.
|
||||||
|
SmallVector<llvm::BasicBlock*, 2> tagBitBlocks;
|
||||||
|
if (ExtraTagBitCount > 0) {
|
||||||
|
llvm::Value *tagBits = value.claimNext();
|
||||||
|
|
||||||
|
auto *swi = IGF.Builder.CreateSwitch(tagBits, unreachableBB,
|
||||||
|
NumExtraTagValues);
|
||||||
|
|
||||||
|
// If we have extra inhabitants, we need to check for them in the
|
||||||
|
// zero-tag case. Otherwise, we switch directly to the payload case.
|
||||||
|
if (extraInhabitantCount > 0) {
|
||||||
|
auto bb = llvm::BasicBlock::Create(C);
|
||||||
|
tagBitBlocks.push_back(bb);
|
||||||
|
swi->addCase(llvm::ConstantInt::get(C,APInt(ExtraTagBitCount,0)), bb);
|
||||||
|
} else {
|
||||||
|
tagBitBlocks.push_back(payloadDest);
|
||||||
|
swi->addCase(llvm::ConstantInt::get(C,APInt(ExtraTagBitCount,0)),
|
||||||
|
payloadDest);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned i = 1; i < NumExtraTagValues; ++i) {
|
||||||
|
auto bb = llvm::BasicBlock::Create(C);
|
||||||
|
tagBitBlocks.push_back(bb);
|
||||||
|
swi->addCase(llvm::ConstantInt::get(C,APInt(ExtraTagBitCount,i)), bb);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Continue by emitting the extra inhabitant dispatch, if any.
|
||||||
|
if (extraInhabitantCount > 0)
|
||||||
|
IGF.Builder.emitBlock(tagBitBlocks[0]);
|
||||||
|
}
|
||||||
|
|
||||||
auto elements = getPayloadElement()->getParentEnum()->getAllElements();
|
auto elements = getPayloadElement()->getParentEnum()->getAllElements();
|
||||||
auto elti = elements.begin(), eltEnd = elements.end();
|
auto elti = elements.begin(), eltEnd = elements.end();
|
||||||
if (*elti == getPayloadElement())
|
if (*elti == getPayloadElement())
|
||||||
@@ -1408,72 +1439,11 @@ namespace {
|
|||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
// If there are extra tag bits, switch over them first.
|
|
||||||
SmallVector<llvm::BasicBlock*, 2> tagBitBlocks;
|
|
||||||
if (ExtraTagBitCount > 0) {
|
|
||||||
llvm::Value *tagBits = value.claimNext();
|
|
||||||
assert(NumExtraTagValues > 1
|
|
||||||
&& "should have more than two tag values if there are extra "
|
|
||||||
"tag bits!");
|
|
||||||
|
|
||||||
llvm::BasicBlock *zeroDest;
|
|
||||||
// If we have extra inhabitants, we need to check for them in the
|
|
||||||
// zero-tag case. Otherwise, we switch directly to the payload case.
|
|
||||||
if (extraInhabitantCount > 0)
|
|
||||||
zeroDest = llvm::BasicBlock::Create(C);
|
|
||||||
else
|
|
||||||
zeroDest = payloadDest;
|
|
||||||
|
|
||||||
// If there are only two interesting cases, do a cond_br instead of
|
|
||||||
// a switch.
|
|
||||||
if (ExtraTagBitCount == 1) {
|
|
||||||
tagBitBlocks.push_back(zeroDest);
|
|
||||||
llvm::BasicBlock *oneDest;
|
|
||||||
|
|
||||||
// If there's only one no-payload case, we can jump to it directly.
|
|
||||||
if (ElementsWithNoPayload.size() == 1) {
|
|
||||||
oneDest = blockForCase(nextCase());
|
|
||||||
} else {
|
|
||||||
oneDest = llvm::BasicBlock::Create(C);
|
|
||||||
tagBitBlocks.push_back(oneDest);
|
|
||||||
}
|
|
||||||
IGF.Builder.CreateCondBr(tagBits, oneDest, zeroDest);
|
|
||||||
} else {
|
|
||||||
auto *swi = IGF.Builder.CreateSwitch(tagBits, unreachableBB,
|
|
||||||
NumExtraTagValues);
|
|
||||||
|
|
||||||
// If we have extra inhabitants, we need to check for them in the
|
|
||||||
// zero-tag case. Otherwise, we switch directly to the payload case.
|
|
||||||
tagBitBlocks.push_back(zeroDest);
|
|
||||||
swi->addCase(llvm::ConstantInt::get(C,APInt(ExtraTagBitCount,0)),
|
|
||||||
zeroDest);
|
|
||||||
|
|
||||||
for (unsigned i = 1; i < NumExtraTagValues; ++i) {
|
|
||||||
// If there's only one no-payload case, or the payload is empty,
|
|
||||||
// we can jump directly to cases without more branching.
|
|
||||||
llvm::BasicBlock *bb;
|
|
||||||
|
|
||||||
if (ElementsWithNoPayload.size() == 1
|
|
||||||
|| PayloadBitCount == 0) {
|
|
||||||
bb = blockForCase(nextCase());
|
|
||||||
} else {
|
|
||||||
bb = llvm::BasicBlock::Create(C);
|
|
||||||
tagBitBlocks.push_back(bb);
|
|
||||||
}
|
|
||||||
swi->addCase(llvm::ConstantInt::get(C, APInt(ExtraTagBitCount, i)),
|
|
||||||
bb);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Continue by emitting the extra inhabitant dispatch, if any.
|
|
||||||
if (extraInhabitantCount > 0)
|
|
||||||
IGF.Builder.emitBlock(tagBitBlocks[0]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If there are no extra tag bits, or they're set to zero, then we either
|
// If there are no extra tag bits, or they're set to zero, then we either
|
||||||
// have a payload, or an empty case represented using an extra inhabitant.
|
// have a payload, or an empty case represented using an extra inhabitant.
|
||||||
// Check the extra inhabitant cases if we have any.
|
// Check the extra inhabitant cases if we have any.
|
||||||
auto &fpTypeInfo = getFixedPayloadTypeInfo();
|
auto &fpTypeInfo = getFixedPayloadTypeInfo();
|
||||||
|
unsigned payloadBits = fpTypeInfo.getFixedSize().getValueInBits();
|
||||||
if (extraInhabitantCount > 0) {
|
if (extraInhabitantCount > 0) {
|
||||||
// Switch over the extra inhabitant patterns we used.
|
// Switch over the extra inhabitant patterns we used.
|
||||||
APInt mask = fpTypeInfo.getFixedExtraInhabitantMask(IGF.IGM);
|
APInt mask = fpTypeInfo.getFixedExtraInhabitantMask(IGF.IGM);
|
||||||
@@ -1481,13 +1451,12 @@ namespace {
|
|||||||
SmallVector<std::pair<APInt, llvm::BasicBlock *>, 4> cases;
|
SmallVector<std::pair<APInt, llvm::BasicBlock *>, 4> cases;
|
||||||
for (auto i = 0U; i < extraInhabitantCount && elti != eltEnd; ++i) {
|
for (auto i = 0U; i < extraInhabitantCount && elti != eltEnd; ++i) {
|
||||||
cases.push_back({
|
cases.push_back({
|
||||||
fpTypeInfo.getFixedExtraInhabitantValue(IGF.IGM, PayloadBitCount,i),
|
fpTypeInfo.getFixedExtraInhabitantValue(IGF.IGM, payloadBits, i),
|
||||||
blockForCase(nextCase())
|
blockForCase(nextCase())
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
payload.emitSwitch(IGF, mask, cases,
|
payload.emitSwitch(IGF, mask, cases, payloadDest);
|
||||||
SwitchDefaultDest(payloadDest, IsNotUnreachable));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// We should have handled the payload case either in extra inhabitant
|
// We should have handled the payload case either in extra inhabitant
|
||||||
@@ -1495,12 +1464,19 @@ namespace {
|
|||||||
assert(IGF.Builder.hasPostTerminatorIP() &&
|
assert(IGF.Builder.hasPostTerminatorIP() &&
|
||||||
"did not handle payload case");
|
"did not handle payload case");
|
||||||
|
|
||||||
|
// If there's an empty payload, each tag value corresponds to a single
|
||||||
|
// empty case.
|
||||||
|
// TODO: Skip the waypoint blocks here.
|
||||||
|
if (payloadBits == 0) {
|
||||||
|
for (unsigned i = 1, e = tagBitBlocks.size(); i < e; ++i) {
|
||||||
|
assert(elti != eltEnd &&
|
||||||
|
"ran out of cases before running out of extra tags?");
|
||||||
|
IGF.Builder.emitBlock(tagBitBlocks[i]);
|
||||||
|
IGF.Builder.CreateBr(blockForCase(nextCase()));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
// Handle the cases covered by each tag bit value.
|
// Handle the cases covered by each tag bit value.
|
||||||
// If there was only one no-payload case, or the payload is empty, we
|
unsigned casesPerTag = payloadBits >= 32 ? UINT_MAX : 1U << payloadBits;
|
||||||
// already branched in the first switch.
|
|
||||||
if (PayloadBitCount > 0 && ElementsWithNoPayload.size() > 1) {
|
|
||||||
unsigned casesPerTag = PayloadBitCount >= 32
|
|
||||||
? UINT_MAX : 1U << PayloadBitCount;
|
|
||||||
for (unsigned i = 1, e = tagBitBlocks.size(); i < e; ++i) {
|
for (unsigned i = 1, e = tagBitBlocks.size(); i < e; ++i) {
|
||||||
assert(elti != eltEnd &&
|
assert(elti != eltEnd &&
|
||||||
"ran out of cases before running out of extra tags?");
|
"ran out of cases before running out of extra tags?");
|
||||||
@@ -1508,20 +1484,16 @@ namespace {
|
|||||||
|
|
||||||
SmallVector<std::pair<APInt, llvm::BasicBlock *>, 4> cases;
|
SmallVector<std::pair<APInt, llvm::BasicBlock *>, 4> cases;
|
||||||
for (unsigned tag = 0; tag < casesPerTag && elti != eltEnd; ++tag) {
|
for (unsigned tag = 0; tag < casesPerTag && elti != eltEnd; ++tag) {
|
||||||
cases.push_back({APInt(PayloadBitCount, tag),
|
cases.push_back({APInt(payloadBits, tag),
|
||||||
blockForCase(nextCase())});
|
blockForCase(nextCase())});
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Provide a mask to only match the bits in the payload
|
// FIXME: Provide a mask for
|
||||||
// whose extra inhabitants differ.
|
payload.emitSwitch(IGF, APInt::getAllOnesValue(payloadBits), cases,
|
||||||
payload.emitSwitch(IGF, APInt::getAllOnesValue(PayloadBitCount),
|
unreachableBB);
|
||||||
cases,
|
|
||||||
SwitchDefaultDest(unreachableBB, IsUnreachable));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(elti == eltEnd && "did not branch to all cases?!");
|
|
||||||
|
|
||||||
// Delete the unreachable default block if we didn't use it, or emit it
|
// Delete the unreachable default block if we didn't use it, or emit it
|
||||||
// if we did.
|
// if we did.
|
||||||
if (unreachableBB->use_empty()) {
|
if (unreachableBB->use_empty()) {
|
||||||
@@ -1720,26 +1692,22 @@ namespace {
|
|||||||
testFixedEnumContainsPayload(IRGenFunction &IGF,
|
testFixedEnumContainsPayload(IRGenFunction &IGF,
|
||||||
const EnumPayload &payload,
|
const EnumPayload &payload,
|
||||||
llvm::Value *extraBits) const {
|
llvm::Value *extraBits) const {
|
||||||
auto *nonzeroBB = llvm::BasicBlock::Create(IGF.IGM.getLLVMContext());
|
auto *falseBB = llvm::BasicBlock::Create(IGF.IGM.getLLVMContext());
|
||||||
|
|
||||||
// We only need to apply the payload operation if the enum contains a
|
// We only need to apply the payload operation if the enum contains a
|
||||||
// value of the payload case.
|
// value of the payload case.
|
||||||
|
|
||||||
// If we have extra tag bits, they will be zero if we contain a payload.
|
// If we have extra tag bits, they will be zero if we contain a payload.
|
||||||
if (ExtraTagBitCount > 0) {
|
if (ExtraTagBitCount > 0) {
|
||||||
assert(extraBits);
|
assert(extraBits);
|
||||||
llvm::Value *isNonzero;
|
|
||||||
if (ExtraTagBitCount == 1) {
|
|
||||||
isNonzero = extraBits;
|
|
||||||
} else {
|
|
||||||
llvm::Value *zero = llvm::ConstantInt::get(extraBits->getType(), 0);
|
llvm::Value *zero = llvm::ConstantInt::get(extraBits->getType(), 0);
|
||||||
isNonzero = IGF.Builder.CreateICmp(llvm::CmpInst::ICMP_NE,
|
llvm::Value *isZero = IGF.Builder.CreateICmp(llvm::CmpInst::ICMP_EQ,
|
||||||
extraBits, zero);
|
extraBits, zero);
|
||||||
}
|
|
||||||
|
|
||||||
auto *zeroBB = llvm::BasicBlock::Create(IGF.IGM.getLLVMContext());
|
auto *trueBB = llvm::BasicBlock::Create(IGF.IGM.getLLVMContext());
|
||||||
IGF.Builder.CreateCondBr(isNonzero, nonzeroBB, zeroBB);
|
IGF.Builder.CreateCondBr(isZero, trueBB, falseBB);
|
||||||
|
|
||||||
IGF.Builder.emitBlock(zeroBB);
|
IGF.Builder.emitBlock(trueBB);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we used extra inhabitants to represent empty case discriminators,
|
// If we used extra inhabitants to represent empty case discriminators,
|
||||||
@@ -1760,17 +1728,16 @@ namespace {
|
|||||||
++i, ++inhabitant) {
|
++i, ++inhabitant) {
|
||||||
auto xi = getFixedPayloadTypeInfo()
|
auto xi = getFixedPayloadTypeInfo()
|
||||||
.getFixedExtraInhabitantValue(IGF.IGM, bitWidth, inhabitant);
|
.getFixedExtraInhabitantValue(IGF.IGM, bitWidth, inhabitant);
|
||||||
cases.push_back({xi, nonzeroBB});
|
cases.push_back({xi, falseBB});
|
||||||
}
|
}
|
||||||
|
|
||||||
auto mask
|
auto mask
|
||||||
= getFixedPayloadTypeInfo().getFixedExtraInhabitantMask(IGF.IGM);
|
= getFixedPayloadTypeInfo().getFixedExtraInhabitantMask(IGF.IGM);
|
||||||
payload.emitSwitch(IGF, mask, cases,
|
payload.emitSwitch(IGF, mask, cases, payloadBB);
|
||||||
SwitchDefaultDest(payloadBB, IsNotUnreachable));
|
|
||||||
IGF.Builder.emitBlock(payloadBB);
|
IGF.Builder.emitBlock(payloadBB);
|
||||||
}
|
}
|
||||||
|
|
||||||
return nonzeroBB;
|
return falseBB;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Emits the test(s) that determine whether the enum contains a payload
|
/// Emits the test(s) that determine whether the enum contains a payload
|
||||||
@@ -2949,8 +2916,7 @@ namespace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
parts.payload.emitSwitch(IGF, APInt::getAllOnesValue(PayloadBitCount),
|
parts.payload.emitSwitch(IGF, APInt::getAllOnesValue(PayloadBitCount),
|
||||||
cases,
|
cases, unreachableBB);
|
||||||
SwitchDefaultDest(unreachableBB, IsUnreachable));
|
|
||||||
++tagIndex;
|
++tagIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -450,9 +450,12 @@ enum SinglePayloadNoXI2 {
|
|||||||
sil @single_payload_no_xi_switch : $@convention(thin) (SinglePayloadNoXI2) -> () {
|
sil @single_payload_no_xi_switch : $@convention(thin) (SinglePayloadNoXI2) -> () {
|
||||||
// CHECK: entry:
|
// CHECK: entry:
|
||||||
entry(%u : $SinglePayloadNoXI2):
|
entry(%u : $SinglePayloadNoXI2):
|
||||||
// CHECK: br i1 %1, label %[[TAGS:[0-9]+]], label %[[X_DEST:[0-9]+]]
|
// CHECK: switch i1 %1, label %[[DFLT:[0-9]+]] [
|
||||||
|
// CHECK: i1 false, label %[[X_DEST:[0-9]+]]
|
||||||
|
// CHECK: i1 true, label %[[TAGS:[0-9]+]]
|
||||||
|
// CHECK: ]
|
||||||
// CHECK: ; <label>:[[TAGS]]
|
// CHECK: ; <label>:[[TAGS]]
|
||||||
// CHECK: switch [[WORD]] %0, label %[[DFLT:[0-9]+]] [
|
// CHECK: switch [[WORD]] %0, label %[[DFLT]] [
|
||||||
// CHECK: [[WORD]] 0, label %[[Y_DEST:[0-9]+]]
|
// CHECK: [[WORD]] 0, label %[[Y_DEST:[0-9]+]]
|
||||||
// CHECK: [[WORD]] 1, label %[[Z_DEST:[0-9]+]]
|
// CHECK: [[WORD]] 1, label %[[Z_DEST:[0-9]+]]
|
||||||
// CHECK: [[WORD]] 2, label %[[W_DEST:[0-9]+]]
|
// CHECK: [[WORD]] 2, label %[[W_DEST:[0-9]+]]
|
||||||
@@ -523,7 +526,10 @@ end:
|
|||||||
sil @single_payload_no_xi_switch_arg : $@convention(thin) (SinglePayloadNoXI2) -> () {
|
sil @single_payload_no_xi_switch_arg : $@convention(thin) (SinglePayloadNoXI2) -> () {
|
||||||
// CHECK: entry:
|
// CHECK: entry:
|
||||||
entry(%u : $SinglePayloadNoXI2):
|
entry(%u : $SinglePayloadNoXI2):
|
||||||
// CHECK: br i1 %1, label %[[TAGS:[0-9]+]], label %[[X_PREDEST:[0-9]+]]
|
// CHECK: switch i1 %1, label %[[DFLT:[0-9]+]] [
|
||||||
|
// CHECK: i1 false, label %[[X_PREDEST:[0-9]+]]
|
||||||
|
// CHECK: i1 true, label %[[TAGS:[0-9]+]]
|
||||||
|
// CHECK: ]
|
||||||
// CHECK: ; <label>:[[TAGS]]
|
// CHECK: ; <label>:[[TAGS]]
|
||||||
// CHECK: switch [[WORD]] %0, label %[[DFLT:[0-9]+]] [
|
// CHECK: switch [[WORD]] %0, label %[[DFLT:[0-9]+]] [
|
||||||
// CHECK: [[WORD]] 0, label %[[Y_DEST:[0-9]+]]
|
// CHECK: [[WORD]] 0, label %[[Y_DEST:[0-9]+]]
|
||||||
|
|||||||
Reference in New Issue
Block a user