// 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;
}
}