Let Clang emit `llvm.tbaa.errno` metadata in order to let LLVM carry out optimizations around errno-writing libcalls to, as long as it is proved the involved memory location does not alias `errno`. Previous discussion: https://discourse.llvm.org/t/rfc-modelling-errno-memory-effects/82972.
403 lines
16 KiB
C++
403 lines
16 KiB
C++
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 6
|
|
// 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: define dso_local noundef zeroext i1 @_Z1fv(
|
|
// CHECK-SAME: ) #[[ATTR0:[0-9]+]] {
|
|
// CHECK-NEXT: [[ENTRY:.*:]]
|
|
// CHECK-NEXT: [[RETVAL:%.*]] = alloca i1, align 1
|
|
// CHECK-NEXT: [[TMP0:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[BOOL_TBAA6:![0-9]+]], !range [[RNG8:![0-9]+]], !noundef [[META9:![0-9]+]]
|
|
// CHECK-NEXT: [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1
|
|
// CHECK-NEXT: [[LOADEDV_EXPVAL:%.*]] = call i1 @llvm.expect.i1(i1 [[LOADEDV]], i1 true)
|
|
// CHECK-NEXT: br i1 [[LOADEDV_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: define dso_local noundef zeroext i1 @_Z1gv(
|
|
// CHECK-SAME: ) #[[ATTR0]] {
|
|
// CHECK-NEXT: [[ENTRY:.*:]]
|
|
// CHECK-NEXT: [[RETVAL:%.*]] = alloca i1, align 1
|
|
// CHECK-NEXT: [[TMP0:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[BOOL_TBAA6]], !range [[RNG8]], !noundef [[META9]]
|
|
// CHECK-NEXT: [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1
|
|
// CHECK-NEXT: [[LOADEDV_EXPVAL:%.*]] = call i1 @llvm.expect.i1(i1 [[LOADEDV]], i1 false)
|
|
// CHECK-NEXT: br i1 [[LOADEDV_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: define dso_local noundef zeroext i1 @_Z1hv(
|
|
// CHECK-SAME: ) #[[ATTR0]] {
|
|
// CHECK-NEXT: [[ENTRY:.*:]]
|
|
// CHECK-NEXT: [[RETVAL:%.*]] = alloca i1, align 1
|
|
// CHECK-NEXT: [[TMP0:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[BOOL_TBAA6]], !range [[RNG8]], !noundef [[META9]]
|
|
// CHECK-NEXT: [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1
|
|
// CHECK-NEXT: [[LOADEDV_EXPVAL:%.*]] = call i1 @llvm.expect.i1(i1 [[LOADEDV]], i1 false)
|
|
// CHECK-NEXT: br i1 [[LOADEDV_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: define dso_local void @_Z8NullStmtv(
|
|
// CHECK-SAME: ) #[[ATTR0]] {
|
|
// CHECK-NEXT: [[ENTRY:.*:]]
|
|
// CHECK-NEXT: [[TMP0:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[BOOL_TBAA6]], !range [[RNG8]], !noundef [[META9]]
|
|
// CHECK-NEXT: [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1
|
|
// CHECK-NEXT: [[LOADEDV_EXPVAL:%.*]] = call i1 @llvm.expect.i1(i1 [[LOADEDV]], i1 false)
|
|
// CHECK-NEXT: br i1 [[LOADEDV_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 [[BOOL_TBAA6]]
|
|
// 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: define dso_local void @_Z6IfStmtv(
|
|
// CHECK-SAME: ) #[[ATTR0]] {
|
|
// CHECK-NEXT: [[ENTRY:.*:]]
|
|
// CHECK-NEXT: [[TMP0:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[BOOL_TBAA6]], !range [[RNG8]], !noundef [[META9]]
|
|
// CHECK-NEXT: [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1
|
|
// CHECK-NEXT: [[LOADEDV_EXPVAL:%.*]] = call i1 @llvm.expect.i1(i1 [[LOADEDV]], i1 false)
|
|
// CHECK-NEXT: br i1 [[LOADEDV_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 [[BOOL_TBAA6]], !range [[RNG8]], !noundef [[META9]]
|
|
// CHECK-NEXT: [[LOADEDV3:%.*]] = trunc i8 [[TMP1]] to i1
|
|
// CHECK-NEXT: br i1 [[LOADEDV3]], 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 [[BOOL_TBAA6]]
|
|
// 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: define dso_local void @_Z9WhileStmtv(
|
|
// CHECK-SAME: ) #[[ATTR0]] {
|
|
// CHECK-NEXT: [[ENTRY:.*:]]
|
|
// CHECK-NEXT: [[TMP0:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[BOOL_TBAA6]], !range [[RNG8]], !noundef [[META9]]
|
|
// CHECK-NEXT: [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1
|
|
// CHECK-NEXT: [[LOADEDV_EXPVAL:%.*]] = call i1 @llvm.expect.i1(i1 [[LOADEDV]], i1 false)
|
|
// CHECK-NEXT: br i1 [[LOADEDV_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 [[LOOP10:![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 [[BOOL_TBAA6]], !range [[RNG8]], !noundef [[META9]]
|
|
// CHECK-NEXT: [[LOADEDV1:%.*]] = trunc i8 [[TMP1]] to i1
|
|
// CHECK-NEXT: br i1 [[LOADEDV1]], 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 [[BOOL_TBAA6]]
|
|
// CHECK-NEXT: br label %[[WHILE_COND3]], !llvm.loop [[LOOP13:![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: define dso_local void @_Z6DoStmtv(
|
|
// CHECK-SAME: ) #[[ATTR0]] {
|
|
// CHECK-NEXT: [[ENTRY:.*:]]
|
|
// CHECK-NEXT: [[TMP0:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[BOOL_TBAA6]], !range [[RNG8]], !noundef [[META9]]
|
|
// CHECK-NEXT: [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1
|
|
// CHECK-NEXT: [[LOADEDV_EXPVAL:%.*]] = call i1 @llvm.expect.i1(i1 [[LOADEDV]], i1 false)
|
|
// CHECK-NEXT: br i1 [[LOADEDV_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 [[LOOP14:![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 [[BOOL_TBAA6]], !range [[RNG8]], !noundef [[META9]]
|
|
// CHECK-NEXT: [[LOADEDV1:%.*]] = trunc i8 [[TMP1]] to i1
|
|
// CHECK-NEXT: br i1 [[LOADEDV1]], 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 [[LOOP15:![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: define dso_local void @_Z7ForStmtv(
|
|
// CHECK-SAME: ) #[[ATTR0]] {
|
|
// CHECK-NEXT: [[ENTRY:.*:]]
|
|
// CHECK-NEXT: [[TMP0:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[BOOL_TBAA6]], !range [[RNG8]], !noundef [[META9]]
|
|
// CHECK-NEXT: [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1
|
|
// CHECK-NEXT: [[LOADEDV_EXPVAL:%.*]] = call i1 @llvm.expect.i1(i1 [[LOADEDV]], i1 false)
|
|
// CHECK-NEXT: br i1 [[LOADEDV_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 [[LOOP16:![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 [[BOOL_TBAA6]], !range [[RNG8]], !noundef [[META9]]
|
|
// CHECK-NEXT: [[LOADEDV1:%.*]] = trunc i8 [[TMP1]] to i1
|
|
// CHECK-NEXT: br i1 [[LOADEDV1]], 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 [[LOOP17:![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: define dso_local void @_Z8GotoStmtv(
|
|
// CHECK-SAME: ) #[[ATTR0]] {
|
|
// CHECK-NEXT: [[ENTRY:.*:]]
|
|
// CHECK-NEXT: [[TMP0:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[BOOL_TBAA6]], !range [[RNG8]], !noundef [[META9]]
|
|
// CHECK-NEXT: [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1
|
|
// CHECK-NEXT: [[LOADEDV_EXPVAL:%.*]] = call i1 @llvm.expect.i1(i1 [[LOADEDV]], i1 false)
|
|
// CHECK-NEXT: br i1 [[LOADEDV_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 [[BOOL_TBAA6]]
|
|
// 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: define dso_local void @_Z10ReturnStmtv(
|
|
// CHECK-SAME: ) #[[ATTR0]] {
|
|
// CHECK-NEXT: [[ENTRY:.*:]]
|
|
// CHECK-NEXT: [[TMP0:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[BOOL_TBAA6]], !range [[RNG8]], !noundef [[META9]]
|
|
// CHECK-NEXT: [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1
|
|
// CHECK-NEXT: [[LOADEDV_EXPVAL:%.*]] = call i1 @llvm.expect.i1(i1 [[LOADEDV]], i1 false)
|
|
// CHECK-NEXT: br i1 [[LOADEDV_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 [[BOOL_TBAA6]]
|
|
// 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: define dso_local void @_Z10SwitchStmtv(
|
|
// CHECK-SAME: ) #[[ATTR0]] {
|
|
// CHECK-NEXT: [[ENTRY:.*:]]
|
|
// CHECK-NEXT: [[TMP0:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[BOOL_TBAA6]], !range [[RNG8]], !noundef [[META9]]
|
|
// CHECK-NEXT: [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1
|
|
// CHECK-NEXT: [[LOADEDV_EXPVAL:%.*]] = call i1 @llvm.expect.i1(i1 [[LOADEDV]], i1 false)
|
|
// CHECK-NEXT: br i1 [[LOADEDV_EXPVAL]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]]
|
|
// CHECK: [[IF_THEN]]:
|
|
// CHECK-NEXT: [[TMP1:%.*]] = load volatile i32, ptr @i, align 4, !tbaa [[INT_TBAA2:![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 [[BOOL_TBAA6]]
|
|
// CHECK-NEXT: br label %[[IF_END]]
|
|
// CHECK: [[IF_END]]:
|
|
// CHECK-NEXT: [[TMP2:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[BOOL_TBAA6]], !range [[RNG8]], !noundef [[META9]]
|
|
// CHECK-NEXT: [[LOADEDV1:%.*]] = trunc i8 [[TMP2]] to i1
|
|
// CHECK-NEXT: br i1 [[LOADEDV1]], label %[[IF_THEN2:.*]], label %[[IF_ELSE4:.*]]
|
|
// CHECK: [[IF_THEN2]]:
|
|
// CHECK-NEXT: [[TMP3:%.*]] = load volatile i32, ptr @i, align 4, !tbaa [[INT_TBAA2]]
|
|
// 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 [[BOOL_TBAA6]]
|
|
// 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;
|
|
}
|
|
}
|
|
|
|
//.
|
|
// CHECK: [[INT_TBAA2]] = !{[[META3:![0-9]+]], [[META3]], i64 0}
|
|
// CHECK: [[META3]] = !{!"int", [[META4:![0-9]+]], i64 0}
|
|
// CHECK: [[META4]] = !{!"omnipotent char", [[META5:![0-9]+]], i64 0}
|
|
// CHECK: [[META5]] = !{!"Simple C++ TBAA"}
|
|
// CHECK: [[BOOL_TBAA6]] = !{[[META7:![0-9]+]], [[META7]], i64 0}
|
|
// CHECK: [[META7]] = !{!"bool", [[META4]], i64 0}
|
|
// CHECK: [[RNG8]] = !{i8 0, i8 2}
|
|
// CHECK: [[META9]] = !{}
|
|
// CHECK: [[LOOP10]] = distinct !{[[LOOP10]], [[META11:![0-9]+]], [[META12:![0-9]+]]}
|
|
// CHECK: [[META11]] = !{!"llvm.loop.mustprogress"}
|
|
// CHECK: [[META12]] = !{!"llvm.loop.unroll.disable"}
|
|
// CHECK: [[LOOP13]] = distinct !{[[LOOP13]], [[META11]], [[META12]]}
|
|
// CHECK: [[LOOP14]] = distinct !{[[LOOP14]], [[META11]], [[META12]]}
|
|
// CHECK: [[LOOP15]] = distinct !{[[LOOP15]], [[META11]], [[META12]]}
|
|
// CHECK: [[LOOP16]] = distinct !{[[LOOP16]], [[META11]], [[META12]]}
|
|
// CHECK: [[LOOP17]] = distinct !{[[LOOP17]], [[META11]], [[META12]]}
|
|
//.
|