Skip to content

Commit ed8922b

Browse files
committed
PerformanceInliner: always inline synthesized enum comparisons if one of the operands is a constant enum
If there is a "constant" enum argument to a synthesized enum comparison, we can always inline it, because most of it will be constant folded anyway. This ensures the compiler is not creating terrible code for very simple enum comparisons, like ``` if someEnum == .someCase { ... } ``` rdar://85677499
1 parent c2866b3 commit ed8922b

File tree

2 files changed

+92
-0
lines changed

2 files changed

+92
-0
lines changed

lib/SILOptimizer/Transforms/PerformanceInliner.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,14 @@ static bool hasConstantArguments(FullApplySite fas) {
524524
return true;
525525
}
526526

527+
static bool hasConstantEnumArgument(FullApplySite fas) {
528+
for (SILValue arg : fas.getArguments()) {
529+
if (isa<EnumInst>(arg))
530+
return true;
531+
}
532+
return false;
533+
}
534+
527535
bool SILPerformanceInliner::isProfitableToInline(
528536
FullApplySite AI, Weight CallerWeight, ConstantTracker &callerTracker,
529537
int &NumCallerBlocks,
@@ -597,6 +605,13 @@ bool SILPerformanceInliner::isProfitableToInline(
597605
return true;
598606
}
599607

608+
// If there is a "constant" enum argument to a synthesized enum comparison,
609+
// we can always inline it, because most of it will be constant folded anyway.
610+
if (Callee->hasSemanticsAttr(semantics::DERIVED_ENUM_EQUALS) &&
611+
hasConstantEnumArgument(AI)) {
612+
return true;
613+
}
614+
600615
// Bail out if this generic call can be optimized by means of
601616
// the generic specialization, because we prefer generic specialization
602617
// to inlining of generics.

test/SILOptimizer/enum-comparison.swift

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,59 @@ func comparene(_ a: E, _ b: E) -> Bool {
2626
return a != b
2727
}
2828

29+
enum LargeEnum: Equatable {
30+
case a1, a2, a3, a4, a5, a6, a7, a8, a9
31+
case b1, b2, b3, b4, b5, b6, b7, b8, b9
32+
case c1, c2, c3, c4, c5, c6, c7, c8, c9
33+
case d1, d2, d3, d4, d5, d6, d7, d8, d9
34+
case e1(Int64), e2(Int64), e3(Int64), e4(Int64), e5(Int64), e6(Int64), e7(Int64), e8(Int64), e9(Int64)
35+
case f1, f2, f3, f4, f5, f6, f7, f8, f9
36+
case g1, g2, g3, g4, g5, g6, g7, g8, g9
37+
}
38+
39+
// CHECK-LABEL: define {{.*}} i1 @"$s4test8compare1ySbAA9LargeEnumOF"(i64 %0, i8 %1)
40+
// CHECK: entry:
41+
// CHECK-NEXT: icmp
42+
// CHECK-NEXT: icmp
43+
// CHECK-NEXT: {{(and|select)}}
44+
// CHECK-NEXT: ret
45+
@inline(never)
46+
func compare1(_ x: LargeEnum) -> Bool {
47+
return x == .b2
48+
}
49+
50+
// CHECK-LABEL: define {{.*}} i1 @"$s4test8compare2ySbAA9LargeEnumOF"(i64 %0, i8 %1)
51+
// CHECK: entry:
52+
// CHECK-NEXT: icmp
53+
// CHECK-NEXT: icmp
54+
// CHECK-NEXT: {{(and|select)}}
55+
// CHECK-NEXT: ret
56+
@inline(never)
57+
func compare2(_ x: LargeEnum) -> Bool {
58+
return .f2 == x
59+
}
60+
61+
// CHECK-LABEL: define {{.*}} i1 @"$s4test8compare3ySbAA9LargeEnumOF"(i64 %0, i8 %1)
62+
// CHECK: entry:
63+
// CHECK-NEXT: icmp
64+
// CHECK-NEXT: icmp
65+
// CHECK-NEXT: {{(and|select)}}
66+
// CHECK-NEXT: ret
67+
@inline(never)
68+
func compare3(_ x: LargeEnum) -> Bool {
69+
return .e2(27) == x
70+
}
71+
72+
// CHECK-LABEL: define {{.*}} i1 @"$s4test8compare4ySbAA9LargeEnumOF"(i64 %0, i8 %1)
73+
// CHECK: entry:
74+
// CHECK-NEXT: icmp
75+
// CHECK-NEXT: icmp
76+
// CHECK-NEXT: {{(and|select)}}
77+
// CHECK-NEXT: ret
78+
@inline(never)
79+
func compare4(_ x: LargeEnum) -> Bool {
80+
return x == .e3(28)
81+
}
2982

3083
// OUT: 1: false
3184
print("1: \(compareeq(.c, .long_case_name_for_testing))")
@@ -39,3 +92,27 @@ print("3: \(comparene(.c, .long_case_name_for_testing))")
3992
// OUT: 4: false
4093
print("4: \(comparene(.c, .c))")
4194

95+
// OUT: 5: false
96+
print("5: \(compare1(.b1))")
97+
98+
// OUT: 6: true
99+
print("6: \(compare1(.b2))")
100+
101+
// OUT: 7: false
102+
print("7: \(compare2(.b1))")
103+
104+
// OUT: 8: true
105+
print("8: \(compare2(.f2))")
106+
107+
// OUT: 9: true
108+
print("9: \(compare3(.e2(27)))")
109+
110+
// OUT: 10: false
111+
print("10: \(compare3(.e2(28)))")
112+
113+
// OUT: 11: true
114+
print("11: \(compare4(.e3(28)))")
115+
116+
// OUT: 12: false
117+
print("12: \(compare4(.e3(27)))")
118+

0 commit comments

Comments
 (0)