1 // RUN: %clang_cc1 -O1 -emit-llvm %s -o - -triple=x86_64-linux-gnu | FileCheck -DLIKELY=2000 -DUNLIKELY=1 %s
2 // RUN: %clang_cc1 -O1 -emit-llvm %s -triple=x86_64-linux-gnu -mllvm -likely-branch-weight=99 -mllvm -unlikely-branch-weight=42 -o - | FileCheck -DLIKELY=99 -DUNLIKELY=42 %s
3 
4 extern volatile bool b;
5 extern volatile int i;
6 extern bool A();
7 extern bool B();
8 
f()9 bool f() {
10   // CHECK-LABEL: define{{.*}} zeroext i1 @_Z1fv
11   // CHECK: br {{.*}} !prof !7
12   if (b)
13     [[likely]] {
14       return A();
15     }
16   return B();
17 }
18 
g()19 bool g() {
20   // CHECK-LABEL: define{{.*}} zeroext i1 @_Z1gv
21   // CHECK: br {{.*}} !prof !8
22   if (b)
23     [[unlikely]] {
24       return A();
25     }
26 
27   return B();
28 }
29 
h()30 bool h() {
31   // CHECK-LABEL: define{{.*}} zeroext i1 @_Z1hv
32   // CHECK: br {{.*}} !prof !8
33   if (b)
34     [[unlikely]] return A();
35 
36   return B();
37 }
38 
NullStmt()39 void NullStmt() {
40   // CHECK-LABEL: define{{.*}}NullStmt
41   // CHECK: br {{.*}} !prof !8
42   if (b)
43     [[unlikely]];
44   else {
45     // Make sure the branches aren't optimized away.
46     b = true;
47   }
48 }
49 
IfStmt()50 void IfStmt() {
51   // CHECK-LABEL: define{{.*}}IfStmt
52   // CHECK: br {{.*}} !prof !8
53   if (b)
54     [[unlikely]] if (B()) {}
55 
56   // CHECK-NOT: br {{.*}} !prof
57   // CHECK: br {{.*}} !prof
58   if (b) {
59     if (B())
60       [[unlikely]] { b = false; }
61   }
62 }
63 
WhileStmt()64 void WhileStmt() {
65   // CHECK-LABEL: define{{.*}}WhileStmt
66   // CHECK: br {{.*}} !prof !8
67   if (b)
68     [[unlikely]] while (B()) {}
69 
70   // CHECK-NOT: br {{.*}} %if.end{{.*}} !prof
71   if (b)
72     // CHECK: br {{.*}} !prof !7
73     while (B())
74       [[unlikely]] { b = false; }
75 }
76 
DoStmt()77 void DoStmt() {
78   // CHECK-LABEL: define{{.*}}DoStmt
79   // CHECK: br {{.*}} !prof !8
80   if (b)
81     [[unlikely]] do {}
82     while (B())
83       ;
84 
85   // CHECK-NOT: br {{.*}} %if.end{{.*}} !prof
86   if (b)
87     do
88       [[unlikely]] {}
89     while (B());
90 }
91 
ForStmt()92 void ForStmt() {
93   // CHECK-LABEL: define{{.*}}ForStmt
94   // CHECK: br {{.*}} !prof !8
95   if (b)
96     [[unlikely]] for (; B();) {}
97 
98   // CHECK-NOT: br {{.*}} %if.end{{.*}} !prof
99   if (b)
100     // CHECK: br {{.*}} !prof !7
101     for (; B();)
102       [[unlikely]] {}
103 }
104 
GotoStmt()105 void GotoStmt() {
106   // CHECK-LABEL: define{{.*}}GotoStmt
107   // CHECK: br {{.*}} !prof !8
108   if (b)
109     [[unlikely]] goto end;
110   else {
111     // Make sure the branches aren't optimized away.
112     b = true;
113   }
114 end:;
115 }
116 
ReturnStmt()117 void ReturnStmt() {
118   // CHECK-LABEL: define{{.*}}ReturnStmt
119   // CHECK: br {{.*}} !prof !8
120   if (b)
121     [[unlikely]] return;
122   else {
123     // Make sure the branches aren't optimized away.
124     b = true;
125   }
126 }
127 
SwitchStmt()128 void SwitchStmt() {
129   // CHECK-LABEL: define{{.*}}SwitchStmt
130   // CHECK: br {{.*}} !prof !8
131   if (b)
132     [[unlikely]] switch (i) {}
133   else {
134     // Make sure the branches aren't optimized away.
135     b = true;
136   }
137   // CHECK-NOT: br {{.*}} %if.end{{.*}} !prof
138   if (b)
139     switch (i)
140       [[unlikely]] {}
141   else {
142     // Make sure the branches aren't optimized away.
143     b = true;
144   }
145 }
146 
147 // CHECK: !7 = !{!"branch_weights", i32 [[UNLIKELY]], i32 [[LIKELY]]}
148 // CHECK: !8 = !{!"branch_weights", i32 [[LIKELY]], i32 [[UNLIKELY]]}
149