[Sema, CodeGen] Implement [[likely]] and [[unlikely]] in SwitchStmt
This implements the likelihood attribute for the switch statement. Based on the
discussion in D85091 and D86559 it only handles the attribute when placed on
the case labels or the default labels.
It also marks the likelihood attribute as feature complete. There are more QoI
patches in the pipeline.
Differential Revision: https://reviews.llvm.org/D89210
diff --git a/clang/test/CodeGenCXX/attr-likelihood-switch-branch-weights.cpp b/clang/test/CodeGenCXX/attr-likelihood-switch-branch-weights.cpp
new file mode 100644
index 0000000..5fb7a67
--- /dev/null
+++ b/clang/test/CodeGenCXX/attr-likelihood-switch-branch-weights.cpp
@@ -0,0 +1,194 @@
+// RUN: %clang_cc1 -O1 -disable-llvm-passes -emit-llvm %s -o - -triple=x86_64-linux-gnu | FileCheck %s
+
+extern volatile int i;
+
+void OneCaseL() {
+ // CHECK-LABEL: define{{.*}}OneCaseL
+ // CHECK: switch
+ // CHECK: {{.*}} !prof !6
+ switch (i) {
+ [[likely]] case 1: break;
+ }
+}
+
+void OneCaseU() {
+ // CHECK-LABEL: define{{.*}}OneCaseU
+ // CHECK: switch
+ // CHECK: {{.*}} !prof !7
+ switch (i) {
+ [[unlikely]] case 1: ++i; break;
+ }
+}
+
+void TwoCasesLN() {
+ // CHECK-LABEL: define{{.*}}TwoCasesLN
+ // CHECK: switch
+ // CHECK: {{.*}} !prof !8
+ switch (i) {
+ [[likely]] case 1: break;
+ case 2: break;
+ }
+}
+
+void TwoCasesUN() {
+ // CHECK-LABEL: define{{.*}}TwoCasesUN
+ // CHECK: switch
+ // CHECK: {{.*}} !prof !9
+ switch (i) {
+ [[unlikely]] case 1: break;
+ case 2: break;
+ }
+}
+
+void TwoCasesLU() {
+ // CHECK-LABEL: define{{.*}}TwoCasesLU
+ // CHECK: switch
+ // CHECK: {{.*}} !prof !10
+ switch (i) {
+ [[likely]] case 1: break;
+ [[unlikely]] case 2: break;
+ }
+}
+
+void CasesFallthroughNNLN() {
+ // CHECK-LABEL: define{{.*}}CasesFallthroughNNLN
+ // CHECK: switch
+ // CHECK: {{.*}} !prof !11
+ switch (i) {
+ case 1:
+ case 2:
+ [[likely]] case 3:
+ case 4: break;
+ }
+}
+
+void CasesFallthroughNNUN() {
+ // CHECK-LABEL: define{{.*}}CasesFallthroughNNUN
+ // CHECK: switch
+ // CHECK: {{.*}} !prof !12
+ switch (i) {
+ case 1:
+ case 2:
+ [[unlikely]] case 3:
+ case 4: break;
+ }
+}
+
+void CasesFallthroughRangeSmallLN() {
+ // CHECK-LABEL: define{{.*}}CasesFallthroughRangeSmallLN
+ // CHECK: switch
+ // CHECK: {{.*}} !prof !13
+ switch (i) {
+ case 1 ... 5: ++i;
+ case 102:
+ [[likely]] case 103:
+ case 104: break;
+ }
+}
+
+void CasesFallthroughRangeSmallUN() {
+ // CHECK-LABEL: define{{.*}}CasesFallthroughRangeSmallUN
+ // CHECK: switch
+ // CHECK: {{.*}} !prof !14
+ switch (i) {
+ case 1 ... 5: ++i;
+ case 102:
+ [[unlikely]] case 103:
+ case 104: break;
+ }
+}
+
+void CasesFallthroughRangeLargeLLN() {
+ // CHECK-LABEL: define{{.*}}CasesFallthroughRangeLargeLLN
+ // CHECK: switch
+ // CHECK: {{.*}} !prof !8
+ // CHECK: caserange
+ // CHECK: br{{.*}} !prof !15
+ switch (i) {
+ [[likely]] case 0 ... 64:
+ [[likely]] case 1003:
+ case 104: break;
+ }
+}
+
+void CasesFallthroughRangeLargeUUN() {
+ // CHECK-LABEL: define{{.*}}CasesFallthroughRangeLargeUUN
+ // CHECK: switch
+ // CHECK: {{.*}} !prof !9
+ // CHECK: caserange
+ // CHECK: br{{.*}} !prof !16
+ switch (i) {
+ [[unlikely]] case 0 ... 64:
+ [[unlikely]] case 1003:
+ case 104: break;
+ }
+}
+
+void OneCaseDefaultL() {
+ // CHECK-LABEL: define{{.*}}OneCaseDefaultL
+ // CHECK: switch
+ // CHECK: {{.*}} !prof !17
+ switch (i) {
+ case 1: break;
+ [[likely]] default: break;
+ }
+}
+
+void OneCaseDefaultU() {
+ // CHECK-LABEL: define{{.*}}OneCaseDefaultU
+ // CHECK: switch
+ // CHECK: {{.*}} !prof !18
+ switch (i) {
+ case 1: break;
+ [[unlikely]] default: break;
+ }
+}
+
+void TwoCasesDefaultLNL() {
+ // CHECK-LABEL: define{{.*}}TwoCasesDefaultLNL
+ // CHECK: switch
+ // CHECK: {{.*}} !prof !19
+ switch (i) {
+ [[likely]] case 1: break;
+ case 2: break;
+ [[likely]] default: break;
+ }
+}
+
+void TwoCasesDefaultLNN() {
+ // CHECK-LABEL: define{{.*}}TwoCasesDefaultLNN
+ // CHECK: switch
+ // CHECK: {{.*}} !prof !8
+ switch (i) {
+ [[likely]] case 1: break;
+ case 2: break;
+ default: break;
+ }
+}
+
+void TwoCasesDefaultLNU() {
+ // CHECK-LABEL: define{{.*}}TwoCasesDefaultLNU
+ // CHECK: switch
+ // CHECK: {{.*}} !prof !20
+ switch (i) {
+ [[likely]] case 1: break;
+ case 2: break;
+ [[unlikely]] default: break;
+ }
+}
+
+// CHECK: !6 = !{!"branch_weights", i32 357913942, i32 715827883}
+// CHECK: !7 = !{!"branch_weights", i32 536870912, i32 1}
+// CHECK: !8 = !{!"branch_weights", i32 238609295, i32 715827883, i32 238609295}
+// CHECK: !9 = !{!"branch_weights", i32 357913942, i32 1, i32 357913942}
+// CHECK: !10 = !{!"branch_weights", i32 357913942, i32 715827883, i32 1}
+// CHECK: !11 = !{!"branch_weights", i32 143165577, i32 143165577, i32 143165577, i32 715827883, i32 143165577}
+// CHECK: !12 = !{!"branch_weights", i32 214748365, i32 214748365, i32 214748365, i32 1, i32 214748365}
+// CHECK: !13 = !{!"branch_weights", i32 79536432, i32 79536432, i32 79536432, i32 79536432, i32 79536432, i32 79536432, i32 79536432, i32 715827883, i32 79536432}
+// CHECK: !14 = !{!"branch_weights", i32 119304648, i32 119304648, i32 119304648, i32 119304648, i32 119304648, i32 119304648, i32 119304648, i32 1, i32 119304648}
+// CHECK: !15 = !{!"branch_weights", i32 2000, i32 1}
+// CHECK: !16 = !{!"branch_weights", i32 1, i32 2000}
+// CHECK: !17 = !{!"branch_weights", i32 715827883, i32 357913942}
+// CHECK: !18 = !{!"branch_weights", i32 1, i32 536870912}
+// CHECK: !19 = !{!"branch_weights", i32 536870912, i32 536870912, i32 268435456}
+// CHECK: !20 = !{!"branch_weights", i32 1, i32 715827883, i32 357913942}