Skip to content

Commit de0e227

Browse files
Merge pull request swiftlang#42186 from nate-chandler/rdar83158525
[IRGen] Use condbrs for big int switches.
2 parents 2a68c61 + 602e2e7 commit de0e227

File tree

3 files changed

+142
-0
lines changed

3 files changed

+142
-0
lines changed

lib/IRGen/EnumPayload.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,24 @@ void EnumPayload::emitSwitch(IRGenFunction &IGF,
285285
return;
286286
}
287287

288+
if (mask.getBitWidth() > IGF.IGM.getPointerSize().getValueInBits() * 2) {
289+
for (int index = 0, size = cases.size(); index < size; ++index) {
290+
auto &c = cases[index];
291+
auto *cmp = emitCompare(IGF, mask, c.first);
292+
llvm::BasicBlock *elseBlock;
293+
if (index < size - 1) {
294+
elseBlock = IGF.createBasicBlock("");
295+
} else {
296+
elseBlock = dflt.getPointer();
297+
}
298+
IGF.Builder.CreateCondBr(cmp, c.second, elseBlock);
299+
if (index < size - 1) {
300+
IGF.Builder.emitBlock(elseBlock);
301+
}
302+
}
303+
return;
304+
}
305+
288306
// Otherwise emit a switch statement.
289307
auto &C = IGF.IGM.getLLVMContext();
290308
unsigned numBits = mask.countPopulation();

test/IRGen/enum_large.swift

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// RUN: %swift-target-frontend -emit-irgen %s | %FileCheck %s
2+
3+
// REQUIRES: PTRSIZE=64
4+
5+
public struct SpareBits {
6+
var o: UInt64 = 0
7+
var x: UInt8 = 0
8+
var y: UInt64 = 0
9+
var x_2: UInt8 = 0
10+
var y_2: UInt64 = 0
11+
var x_3: UInt8 = 0
12+
var y_3: UInt64 = 0
13+
var x_4: UInt8 = 0
14+
var y_4: UInt64 = 0
15+
var x_5: UInt8 = 0
16+
var y_5: UInt64 = 0
17+
var x_6: UInt8 = 0
18+
var y_6: UInt64 = 0
19+
}
20+
21+
public class MyClass {}
22+
23+
public enum Multipayload {
24+
case a
25+
case b(MyClass)
26+
case c(SpareBits)
27+
case e
28+
case f
29+
case g
30+
}
31+
32+
@inline(never)
33+
func dump<T>(_ t : T) {}
34+
func dumpInt(_ i: Int) {}
35+
36+
// CHECK-LABEL: define{{.*}} @"$s10enum_large6testIt1eyAA12MultipayloadO_tF"{{.*}}{
37+
// CHECK: switch i8 {{%[^,]+}}, label {{%[^,]+}} [
38+
// CHECK: i8 0, label {{%[^,]+}}
39+
// CHECK: i8 1, label {{%[^,]+}}
40+
// CHECK: i8 2, label %[[REGISTER_41:[^,]+]]
41+
// CHECK: [[REGISTER_41]]:
42+
// CHECK: br i1 {{%[^,]+}}, label {{%[^,]+}}, label %[[REGISTER_67:[^,]+]]
43+
// CHECK: [[REGISTER_67]]:
44+
// CHECK: br i1 {{%[^,]+}}, label {{%[^,]+}}, label %[[REGISTER_93:[^,]+]]
45+
// CHECK: [[REGISTER_93]]:
46+
// CHECK: br i1 {{%[^,]+}}, label {{%[^,]+}}, label %[[REGISTER_119:[^,]+]]
47+
// CHECK: [[REGISTER_119]]:
48+
// CHECK: br i1 {{%[^,]+}}, label %[[REGISTER_149:[^,]+]], label {{%[^,]+}}
49+
// CHECK: [[REGISTER_149]]
50+
// CHECK: call swiftcc void @"$s10enum_large7dumpIntyySiF"(i64 8675309)
51+
public func testIt(e : Multipayload) {
52+
switch e {
53+
case .a, .e, .f, .g:
54+
dumpInt(8675309)
55+
case .b(let c):
56+
dump(c)
57+
case .c(let s):
58+
dump(s)
59+
}
60+
}
61+
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// RUN: %target-run-simple-swift | %FileCheck %s
2+
// REQUIRES: executable_test
3+
4+
public struct SpareBits {
5+
var o: UInt64 = 0
6+
var x: UInt8 = 0
7+
var y: UInt64 = 0
8+
var x_2: UInt8 = 0
9+
var y_2: UInt64 = 0
10+
var x_3: UInt8 = 0
11+
var y_3: UInt64 = 0
12+
var x_4: UInt8 = 0
13+
var y_4: UInt64 = 0
14+
var x_5: UInt8 = 0
15+
var y_5: UInt64 = 0
16+
var x_6: UInt8 = 0
17+
var y_6: UInt64 = 0
18+
}
19+
20+
public class MyClass {}
21+
22+
public enum Multipayload {
23+
case a
24+
case b(MyClass)
25+
case c(SpareBits)
26+
case e
27+
case f
28+
case g
29+
}
30+
31+
public func testIt(_ e : Multipayload) {
32+
switch e {
33+
case .a:
34+
print(".a (no payload)")
35+
case .e:
36+
print(".e (no payload)")
37+
case .f:
38+
print(".f (no payload)")
39+
case .g:
40+
print(".g (no payload)")
41+
case .b(let s):
42+
print(".b(\(s))")
43+
case .c(let x):
44+
print(".c(\(x))")
45+
}
46+
}
47+
48+
func doit() {
49+
testIt(Multipayload.a)
50+
testIt(Multipayload.e)
51+
testIt(Multipayload.f)
52+
testIt(Multipayload.g)
53+
testIt(Multipayload.b(MyClass()))
54+
testIt(Multipayload.c(SpareBits()))
55+
}
56+
doit()
57+
58+
// CHECK: .a (no payload)
59+
// CHECK: .e (no payload)
60+
// CHECK: .f (no payload)
61+
// CHECK: .g (no payload)
62+
// CHECK: .b(main.MyClass)
63+
// CHECK: .c(SpareBits(o: 0, x: 0, y: 0, x_2: 0, y_2: 0, x_3: 0, y_3: 0, x_4: 0, y_4: 0, x_5: 0, y_5: 0, x_6: 0, y_6: 0))

0 commit comments

Comments
 (0)