// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py // RUN: %clang_cc1 -O1 -disable-llvm-passes -emit-llvm %s -o - -triple=x86_64-- | FileCheck %s extern volatile bool b; extern volatile int i; extern bool A(); extern bool B(); // CHECK-LABEL: @_Z1fv( // CHECK-NEXT: entry: // CHECK-NEXT: [[RETVAL:%.*]] = alloca i1, align 1 // CHECK-NEXT: [[TMP0:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[TBAA2:![0-9]+]], !range [[RNG6:![0-9]+]] // CHECK-NEXT: [[TOBOOL:%.*]] = trunc i8 [[TMP0]] to i1 // CHECK-NEXT: [[TOBOOL_EXPVAL:%.*]] = call i1 @llvm.expect.i1(i1 [[TOBOOL]], i1 true) // CHECK-NEXT: br i1 [[TOBOOL_EXPVAL]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] // CHECK: if.then: // CHECK-NEXT: [[CALL:%.*]] = call noundef zeroext i1 @_Z1Av() // CHECK-NEXT: store i1 [[CALL]], ptr [[RETVAL]], align 1 // CHECK-NEXT: br label [[RETURN:%.*]] // CHECK: if.end: // CHECK-NEXT: [[CALL1:%.*]] = call noundef zeroext i1 @_Z1Bv() // CHECK-NEXT: store i1 [[CALL1]], ptr [[RETVAL]], align 1 // CHECK-NEXT: br label [[RETURN]] // CHECK: return: // CHECK-NEXT: [[TMP1:%.*]] = load i1, ptr [[RETVAL]], align 1 // CHECK-NEXT: ret i1 [[TMP1]] // bool f() { if (b) [[likely]] { return A(); } return B(); } // CHECK-LABEL: @_Z1gv( // CHECK-NEXT: entry: // CHECK-NEXT: [[RETVAL:%.*]] = alloca i1, align 1 // CHECK-NEXT: [[TMP0:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[TBAA2]], !range [[RNG6]] // CHECK-NEXT: [[TOBOOL:%.*]] = trunc i8 [[TMP0]] to i1 // CHECK-NEXT: [[TOBOOL_EXPVAL:%.*]] = call i1 @llvm.expect.i1(i1 [[TOBOOL]], i1 false) // CHECK-NEXT: br i1 [[TOBOOL_EXPVAL]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] // CHECK: if.then: // CHECK-NEXT: [[CALL:%.*]] = call noundef zeroext i1 @_Z1Av() // CHECK-NEXT: store i1 [[CALL]], ptr [[RETVAL]], align 1 // CHECK-NEXT: br label [[RETURN:%.*]] // CHECK: if.end: // CHECK-NEXT: [[CALL1:%.*]] = call noundef zeroext i1 @_Z1Bv() // CHECK-NEXT: store i1 [[CALL1]], ptr [[RETVAL]], align 1 // CHECK-NEXT: br label [[RETURN]] // CHECK: return: // CHECK-NEXT: [[TMP1:%.*]] = load i1, ptr [[RETVAL]], align 1 // CHECK-NEXT: ret i1 [[TMP1]] // bool g() { if (b) [[unlikely]] { return A(); } return B(); } // CHECK-LABEL: @_Z1hv( // CHECK-NEXT: entry: // CHECK-NEXT: [[RETVAL:%.*]] = alloca i1, align 1 // CHECK-NEXT: [[TMP0:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[TBAA2]], !range [[RNG6]] // CHECK-NEXT: [[TOBOOL:%.*]] = trunc i8 [[TMP0]] to i1 // CHECK-NEXT: [[TOBOOL_EXPVAL:%.*]] = call i1 @llvm.expect.i1(i1 [[TOBOOL]], i1 false) // CHECK-NEXT: br i1 [[TOBOOL_EXPVAL]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] // CHECK: if.then: // CHECK-NEXT: [[CALL:%.*]] = call noundef zeroext i1 @_Z1Av() // CHECK-NEXT: store i1 [[CALL]], ptr [[RETVAL]], align 1 // CHECK-NEXT: br label [[RETURN:%.*]] // CHECK: if.end: // CHECK-NEXT: [[CALL1:%.*]] = call noundef zeroext i1 @_Z1Bv() // CHECK-NEXT: store i1 [[CALL1]], ptr [[RETVAL]], align 1 // CHECK-NEXT: br label [[RETURN]] // CHECK: return: // CHECK-NEXT: [[TMP1:%.*]] = load i1, ptr [[RETVAL]], align 1 // CHECK-NEXT: ret i1 [[TMP1]] // bool h() { if (b) [[unlikely]] return A(); return B(); } // CHECK-LABEL: @_Z8NullStmtv( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[TBAA2]], !range [[RNG6]] // CHECK-NEXT: [[TOBOOL:%.*]] = trunc i8 [[TMP0]] to i1 // CHECK-NEXT: [[TOBOOL_EXPVAL:%.*]] = call i1 @llvm.expect.i1(i1 [[TOBOOL]], i1 false) // CHECK-NEXT: br i1 [[TOBOOL_EXPVAL]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] // CHECK: if.then: // CHECK-NEXT: br label [[IF_END:%.*]] // CHECK: if.else: // CHECK-NEXT: store volatile i8 1, ptr @b, align 1, !tbaa [[TBAA2]] // CHECK-NEXT: br label [[IF_END]] // CHECK: if.end: // CHECK-NEXT: ret void // void NullStmt() { if (b) [[unlikely]]; else { // Make sure the branches aren't optimized away. b = true; } } // CHECK-LABEL: @_Z6IfStmtv( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[TBAA2]], !range [[RNG6]] // CHECK-NEXT: [[TOBOOL:%.*]] = trunc i8 [[TMP0]] to i1 // CHECK-NEXT: [[TOBOOL_EXPVAL:%.*]] = call i1 @llvm.expect.i1(i1 [[TOBOOL]], i1 false) // CHECK-NEXT: br i1 [[TOBOOL_EXPVAL]], label [[IF_THEN:%.*]], label [[IF_END2:%.*]] // CHECK: if.then: // CHECK-NEXT: [[CALL:%.*]] = call noundef zeroext i1 @_Z1Bv() // CHECK-NEXT: br i1 [[CALL]], label [[IF_THEN1:%.*]], label [[IF_END:%.*]] // CHECK: if.then1: // CHECK-NEXT: br label [[IF_END]] // CHECK: if.end: // CHECK-NEXT: br label [[IF_END2]] // CHECK: if.end2: // CHECK-NEXT: [[TMP1:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[TBAA2]], !range [[RNG6]] // CHECK-NEXT: [[TOBOOL3:%.*]] = trunc i8 [[TMP1]] to i1 // CHECK-NEXT: br i1 [[TOBOOL3]], label [[IF_THEN4:%.*]], label [[IF_END8:%.*]] // CHECK: if.then4: // CHECK-NEXT: [[CALL5:%.*]] = call noundef zeroext i1 @_Z1Bv() // CHECK-NEXT: [[CALL5_EXPVAL:%.*]] = call i1 @llvm.expect.i1(i1 [[CALL5]], i1 false) // CHECK-NEXT: br i1 [[CALL5_EXPVAL]], label [[IF_THEN6:%.*]], label [[IF_END7:%.*]] // CHECK: if.then6: // CHECK-NEXT: store volatile i8 0, ptr @b, align 1, !tbaa [[TBAA2]] // CHECK-NEXT: br label [[IF_END7]] // CHECK: if.end7: // CHECK-NEXT: br label [[IF_END8]] // CHECK: if.end8: // CHECK-NEXT: ret void // void IfStmt() { if (b) [[unlikely]] if (B()) {} if (b) { if (B()) [[unlikely]] { b = false; } } } // CHECK-LABEL: @_Z9WhileStmtv( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[TBAA2]], !range [[RNG6]] // CHECK-NEXT: [[TOBOOL:%.*]] = trunc i8 [[TMP0]] to i1 // CHECK-NEXT: [[TOBOOL_EXPVAL:%.*]] = call i1 @llvm.expect.i1(i1 [[TOBOOL]], i1 false) // CHECK-NEXT: br i1 [[TOBOOL_EXPVAL]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] // CHECK: if.then: // CHECK-NEXT: br label [[WHILE_COND:%.*]] // CHECK: while.cond: // CHECK-NEXT: [[CALL:%.*]] = call noundef zeroext i1 @_Z1Bv() // CHECK-NEXT: br i1 [[CALL]], label [[WHILE_BODY:%.*]], label [[WHILE_END:%.*]] // CHECK: while.body: // CHECK-NEXT: br label [[WHILE_COND]], !llvm.loop [[LOOP7:![0-9]+]] // CHECK: while.end: // CHECK-NEXT: br label [[IF_END]] // CHECK: if.end: // CHECK-NEXT: [[TMP1:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[TBAA2]], !range [[RNG6]] // CHECK-NEXT: [[TOBOOL1:%.*]] = trunc i8 [[TMP1]] to i1 // CHECK-NEXT: br i1 [[TOBOOL1]], label [[IF_THEN2:%.*]], label [[IF_END7:%.*]] // CHECK: if.then2: // CHECK-NEXT: br label [[WHILE_COND3:%.*]] // CHECK: while.cond3: // CHECK-NEXT: [[CALL4:%.*]] = call noundef zeroext i1 @_Z1Bv() // CHECK-NEXT: [[CALL4_EXPVAL:%.*]] = call i1 @llvm.expect.i1(i1 [[CALL4]], i1 false) // CHECK-NEXT: br i1 [[CALL4_EXPVAL]], label [[WHILE_BODY5:%.*]], label [[WHILE_END6:%.*]] // CHECK: while.body5: // CHECK-NEXT: store volatile i8 0, ptr @b, align 1, !tbaa [[TBAA2]] // CHECK-NEXT: br label [[WHILE_COND3]], !llvm.loop [[LOOP10:![0-9]+]] // CHECK: while.end6: // CHECK-NEXT: br label [[IF_END7]] // CHECK: if.end7: // CHECK-NEXT: ret void // void WhileStmt() { if (b) [[unlikely]] while (B()) {} if (b) while (B()) [[unlikely]] { b = false; } } // CHECK-LABEL: @_Z6DoStmtv( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[TBAA2]], !range [[RNG6]] // CHECK-NEXT: [[TOBOOL:%.*]] = trunc i8 [[TMP0]] to i1 // CHECK-NEXT: [[TOBOOL_EXPVAL:%.*]] = call i1 @llvm.expect.i1(i1 [[TOBOOL]], i1 false) // CHECK-NEXT: br i1 [[TOBOOL_EXPVAL]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] // CHECK: if.then: // CHECK-NEXT: br label [[DO_BODY:%.*]] // CHECK: do.body: // CHECK-NEXT: br label [[DO_COND:%.*]] // CHECK: do.cond: // CHECK-NEXT: [[CALL:%.*]] = call noundef zeroext i1 @_Z1Bv() // CHECK-NEXT: br i1 [[CALL]], label [[DO_BODY]], label [[DO_END:%.*]], !llvm.loop [[LOOP11:![0-9]+]] // CHECK: do.end: // CHECK-NEXT: br label [[IF_END]] // CHECK: if.end: // CHECK-NEXT: [[TMP1:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[TBAA2]], !range [[RNG6]] // CHECK-NEXT: [[TOBOOL1:%.*]] = trunc i8 [[TMP1]] to i1 // CHECK-NEXT: br i1 [[TOBOOL1]], label [[IF_THEN2:%.*]], label [[IF_END7:%.*]] // CHECK: if.then2: // CHECK-NEXT: br label [[DO_BODY3:%.*]] // CHECK: do.body3: // CHECK-NEXT: br label [[DO_COND4:%.*]] // CHECK: do.cond4: // CHECK-NEXT: [[CALL5:%.*]] = call noundef zeroext i1 @_Z1Bv() // CHECK-NEXT: br i1 [[CALL5]], label [[DO_BODY3]], label [[DO_END6:%.*]], !llvm.loop [[LOOP12:![0-9]+]] // CHECK: do.end6: // CHECK-NEXT: br label [[IF_END7]] // CHECK: if.end7: // CHECK-NEXT: ret void // void DoStmt() { if (b) [[unlikely]] do {} while (B()) ; if (b) do [[unlikely]] {} while (B()); } // CHECK-LABEL: @_Z7ForStmtv( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[TBAA2]], !range [[RNG6]] // CHECK-NEXT: [[TOBOOL:%.*]] = trunc i8 [[TMP0]] to i1 // CHECK-NEXT: [[TOBOOL_EXPVAL:%.*]] = call i1 @llvm.expect.i1(i1 [[TOBOOL]], i1 false) // CHECK-NEXT: br i1 [[TOBOOL_EXPVAL]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] // CHECK: if.then: // CHECK-NEXT: br label [[FOR_COND:%.*]] // CHECK: for.cond: // CHECK-NEXT: [[CALL:%.*]] = call noundef zeroext i1 @_Z1Bv() // CHECK-NEXT: br i1 [[CALL]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]] // CHECK: for.body: // CHECK-NEXT: br label [[FOR_COND]], !llvm.loop [[LOOP13:![0-9]+]] // CHECK: for.end: // CHECK-NEXT: br label [[IF_END]] // CHECK: if.end: // CHECK-NEXT: [[TMP1:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[TBAA2]], !range [[RNG6]] // CHECK-NEXT: [[TOBOOL1:%.*]] = trunc i8 [[TMP1]] to i1 // CHECK-NEXT: br i1 [[TOBOOL1]], label [[IF_THEN2:%.*]], label [[IF_END7:%.*]] // CHECK: if.then2: // CHECK-NEXT: br label [[FOR_COND3:%.*]] // CHECK: for.cond3: // CHECK-NEXT: [[CALL4:%.*]] = call noundef zeroext i1 @_Z1Bv() // CHECK-NEXT: [[CALL4_EXPVAL:%.*]] = call i1 @llvm.expect.i1(i1 [[CALL4]], i1 false) // CHECK-NEXT: br i1 [[CALL4_EXPVAL]], label [[FOR_BODY5:%.*]], label [[FOR_END6:%.*]] // CHECK: for.body5: // CHECK-NEXT: br label [[FOR_COND3]], !llvm.loop [[LOOP14:![0-9]+]] // CHECK: for.end6: // CHECK-NEXT: br label [[IF_END7]] // CHECK: if.end7: // CHECK-NEXT: ret void // void ForStmt() { if (b) [[unlikely]] for (; B();) {} if (b) for (; B();) [[unlikely]] {} } // CHECK-LABEL: @_Z8GotoStmtv( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[TBAA2]], !range [[RNG6]] // CHECK-NEXT: [[TOBOOL:%.*]] = trunc i8 [[TMP0]] to i1 // CHECK-NEXT: [[TOBOOL_EXPVAL:%.*]] = call i1 @llvm.expect.i1(i1 [[TOBOOL]], i1 false) // CHECK-NEXT: br i1 [[TOBOOL_EXPVAL]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] // CHECK: if.then: // CHECK-NEXT: br label [[END:%.*]] // CHECK: if.else: // CHECK-NEXT: store volatile i8 1, ptr @b, align 1, !tbaa [[TBAA2]] // CHECK-NEXT: br label [[IF_END:%.*]] // CHECK: if.end: // CHECK-NEXT: br label [[END]] // CHECK: end: // CHECK-NEXT: ret void // void GotoStmt() { if (b) [[unlikely]] goto end; else { // Make sure the branches aren't optimized away. b = true; } end:; } // CHECK-LABEL: @_Z10ReturnStmtv( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[TBAA2]], !range [[RNG6]] // CHECK-NEXT: [[TOBOOL:%.*]] = trunc i8 [[TMP0]] to i1 // CHECK-NEXT: [[TOBOOL_EXPVAL:%.*]] = call i1 @llvm.expect.i1(i1 [[TOBOOL]], i1 false) // CHECK-NEXT: br i1 [[TOBOOL_EXPVAL]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] // CHECK: if.then: // CHECK-NEXT: br label [[IF_END:%.*]] // CHECK: if.else: // CHECK-NEXT: store volatile i8 1, ptr @b, align 1, !tbaa [[TBAA2]] // CHECK-NEXT: br label [[IF_END]] // CHECK: if.end: // CHECK-NEXT: ret void // void ReturnStmt() { if (b) [[unlikely]] return; else { // Make sure the branches aren't optimized away. b = true; } } // CHECK-LABEL: @_Z10SwitchStmtv( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[TBAA2]], !range [[RNG6]] // CHECK-NEXT: [[TOBOOL:%.*]] = trunc i8 [[TMP0]] to i1 // CHECK-NEXT: [[TOBOOL_EXPVAL:%.*]] = call i1 @llvm.expect.i1(i1 [[TOBOOL]], i1 false) // CHECK-NEXT: br i1 [[TOBOOL_EXPVAL]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] // CHECK: if.then: // CHECK-NEXT: [[TMP1:%.*]] = load volatile i32, ptr @i, align 4, !tbaa [[TBAA15:![0-9]+]] // CHECK-NEXT: switch i32 [[TMP1]], label [[SW_EPILOG:%.*]] [ // CHECK-NEXT: ] // CHECK: sw.epilog: // CHECK-NEXT: br label [[IF_END:%.*]] // CHECK: if.else: // CHECK-NEXT: store volatile i8 1, ptr @b, align 1, !tbaa [[TBAA2]] // CHECK-NEXT: br label [[IF_END]] // CHECK: if.end: // CHECK-NEXT: [[TMP2:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[TBAA2]], !range [[RNG6]] // CHECK-NEXT: [[TOBOOL1:%.*]] = trunc i8 [[TMP2]] to i1 // CHECK-NEXT: br i1 [[TOBOOL1]], label [[IF_THEN2:%.*]], label [[IF_ELSE4:%.*]] // CHECK: if.then2: // CHECK-NEXT: [[TMP3:%.*]] = load volatile i32, ptr @i, align 4, !tbaa [[TBAA15]] // CHECK-NEXT: switch i32 [[TMP3]], label [[SW_EPILOG3:%.*]] [ // CHECK-NEXT: ] // CHECK: sw.epilog3: // CHECK-NEXT: br label [[IF_END5:%.*]] // CHECK: if.else4: // CHECK-NEXT: store volatile i8 1, ptr @b, align 1, !tbaa [[TBAA2]] // CHECK-NEXT: br label [[IF_END5]] // CHECK: if.end5: // CHECK-NEXT: ret void // void SwitchStmt() { if (b) [[unlikely]] switch (i) {} else { // Make sure the branches aren't optimized away. b = true; } if (b) switch (i) [[unlikely]] {} else { // Make sure the branches aren't optimized away. b = true; } }