Skip to content

Commit 1970f13

Browse files
committed
Reapply "IRGen: Fix select_enum for single-payload, multi-empty-case enums."
This reapplies 8643d14 with a test update to change the data type to Int32 so that it will pass on 32- and 64-bit targets with the same IR generated.
1 parent 48ec67c commit 1970f13

File tree

2 files changed

+46
-5
lines changed

2 files changed

+46
-5
lines changed

lib/IRGen/GenEnum.cpp

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1539,13 +1539,20 @@ namespace {
15391539
std::tie(payloadTag, extraTag) = getNoPayloadCaseValue(Case);
15401540

15411541
auto &ti = getFixedPayloadTypeInfo();
1542-
bool hasExtraInhabitants = ti.getFixedExtraInhabitantCount(IGF.IGM) > 0;
1543-
1542+
15441543
llvm::Value *payloadResult = nullptr;
1545-
if (hasExtraInhabitants)
1546-
payloadResult = payload.emitCompare(IGF,
1544+
// We can omit the payload check if this is the only case represented with
1545+
// the particular extra tag bit pattern set.
1546+
//
1547+
// TODO: This logic covers the most common case, when there's exactly one
1548+
// more no-payload case than extra inhabitants in the payload. This could
1549+
// be slightly generalized to cases where there's multiple tag bits and
1550+
// exactly one no-payload case in the highest used tag value.
1551+
if (!tagBits ||
1552+
ElementsWithNoPayload.size() != getFixedExtraInhabitantCount(IGF.IGM)+1)
1553+
payloadResult = payload.emitCompare(IGF,
15471554
ti.getFixedExtraInhabitantMask(IGF.IGM),
1548-
payloadTag);
1555+
payloadTag);
15491556

15501557
// If any tag bits are present, they must match.
15511558
llvm::Value *tagResult = nullptr;
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// RUN: %target-swift-frontend %s -emit-ir | FileCheck %s
2+
sil_stage canonical
3+
4+
import Builtin
5+
6+
enum ManyEmptyCases {
7+
case A
8+
case B
9+
case C(Builtin.Int32)
10+
}
11+
12+
// CHECK-LABEL: define i1 @select_enum_A(i32, i1)
13+
// CHECK: [[PAYLOAD:%.*]] = icmp eq i32 %0, 0
14+
// CHECK: [[EXTRA:%.*]] = and i1 %1, [[PAYLOAD]]
15+
// CHECK: ret i1 [[EXTRA]]
16+
sil @select_enum_A : $@convention(thin) (ManyEmptyCases) -> Builtin.Int1 {
17+
entry(%0 : $ManyEmptyCases):
18+
%4 = integer_literal $Builtin.Int1, -1 // user: %6
19+
%5 = integer_literal $Builtin.Int1, 0 // user: %6
20+
%6 = select_enum %0 : $ManyEmptyCases, case #ManyEmptyCases.A!enumelt: %4, default %5 : $Builtin.Int1
21+
return %6 : $Builtin.Int1
22+
}
23+
24+
// CHECK-LABEL: define i1 @select_enum_B(i32, i1)
25+
// CHECK: [[PAYLOAD:%.*]] = icmp eq i32 %0, 1
26+
// CHECK: [[EXTRA:%.*]] = and i1 %1, [[PAYLOAD]]
27+
// CHECK: ret i1 [[EXTRA]]
28+
sil @select_enum_B : $@convention(thin) (ManyEmptyCases) -> Builtin.Int1 {
29+
entry(%0 : $ManyEmptyCases):
30+
%4 = integer_literal $Builtin.Int1, -1 // user: %6
31+
%5 = integer_literal $Builtin.Int1, 0 // user: %6
32+
%6 = select_enum %0 : $ManyEmptyCases, case #ManyEmptyCases.B!enumelt: %4, default %5 : $Builtin.Int1
33+
return %6 : $Builtin.Int1
34+
}

0 commit comments

Comments
 (0)