// RUN: %clang_cc1 -O1 -emit-llvm %s -o - -triple=x86_64-linux-gnu | FileCheck -DLIKELY=2000 -DUNLIKELY=1 %s // 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 extern volatile bool b; extern volatile int i; extern bool A(); extern bool B(); bool f() { // CHECK-LABEL: define zeroext i1 @_Z1fv // CHECK: br {{.*}} !prof !7 if (b) [[likely]] { return A(); } return B(); } bool g() { // CHECK-LABEL: define zeroext i1 @_Z1gv // CHECK: br {{.*}} !prof !8 if (b) [[unlikely]] { return A(); } return B(); } bool h() { // CHECK-LABEL: define zeroext i1 @_Z1hv // CHECK: br {{.*}} !prof !8 if (b) [[unlikely]] return A(); return B(); } void NullStmt() { // CHECK-LABEL: define{{.*}}NullStmt // CHECK: br {{.*}} !prof !8 if (b) [[unlikely]]; else { // Make sure the branches aren't optimized away. b = true; } } void IfStmt() { // CHECK-LABEL: define{{.*}}IfStmt // CHECK: br {{.*}} !prof !8 if (b) [[unlikely]] if (B()) {} // CHECK-NOT: br {{.*}} !prof // CHECK: br {{.*}} !prof if (b) { if (B()) [[unlikely]] { b = false; } } } void WhileStmt() { // CHECK-LABEL: define{{.*}}WhileStmt // CHECK: br {{.*}} !prof !8 if (b) [[unlikely]] while (B()) {} // CHECK-NOT: br {{.*}} %if.end{{.*}} !prof if (b) // CHECK: br {{.*}} !prof !7 while (B()) [[unlikely]] { b = false; } } void DoStmt() { // CHECK-LABEL: define{{.*}}DoStmt // CHECK: br {{.*}} !prof !8 if (b) [[unlikely]] do {} while (B()) ; // CHECK-NOT: br {{.*}} %if.end{{.*}} !prof if (b) do [[unlikely]] {} while (B()); } void ForStmt() { // CHECK-LABEL: define{{.*}}ForStmt // CHECK: br {{.*}} !prof !8 if (b) [[unlikely]] for (; B();) {} // CHECK-NOT: br {{.*}} %if.end{{.*}} !prof if (b) // CHECK: br {{.*}} !prof !7 for (; B();) [[unlikely]] {} } void GotoStmt() { // CHECK-LABEL: define{{.*}}GotoStmt // CHECK: br {{.*}} !prof !8 if (b) [[unlikely]] goto end; else { // Make sure the branches aren't optimized away. b = true; } end:; } void ReturnStmt() { // CHECK-LABEL: define{{.*}}ReturnStmt // CHECK: br {{.*}} !prof !8 if (b) [[unlikely]] return; else { // Make sure the branches aren't optimized away. b = true; } } void SwitchStmt() { // CHECK-LABEL: define{{.*}}SwitchStmt // CHECK: br {{.*}} !prof !8 if (b) [[unlikely]] switch (i) {} else { // Make sure the branches aren't optimized away. b = true; } // CHECK-NOT: br {{.*}} %if.end{{.*}} !prof if (b) switch (i) [[unlikely]] {} else { // Make sure the branches aren't optimized away. b = true; } } // CHECK: !7 = !{!"branch_weights", i32 [[UNLIKELY]], i32 [[LIKELY]]} // CHECK: !8 = !{!"branch_weights", i32 [[LIKELY]], i32 [[UNLIKELY]]}