// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-cir %s -o %t.cir // RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t-cir.ll // RUN: FileCheck --input-file=%t-cir.ll %s -check-prefix=LLVM // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll // RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG int a = 42; /* --- Compound literals */ struct foo { int x, y; }; int y; struct foo f = (struct foo){ __builtin_constant_p(y), 42 }; // CIR: cir.global external @f = #cir.const_record<{#cir.int<0> : !s32i, #cir.int<42> : !s32i}> : !rec_foo // LLVM: @f = global %struct.foo { i32 0, i32 42 } // OGCG: @f = global %struct.foo { i32 0, i32 42 } struct foo test0(int expr) { struct foo f = (struct foo){ __builtin_constant_p(expr), 42 }; return f; } // CIR: cir.func {{.*}} @test0(%[[ARG0:.*]]: !s32i {{.*}}) -> !rec_foo // CIR: %[[EXPR_ADDR:.*]] = cir.alloca !s32i, !cir.ptr, ["expr", init] // CIR: cir.store %[[ARG0]], %[[EXPR_ADDR]] // CIR: %[[EXPR:.*]] = cir.load{{.*}} %[[EXPR_ADDR]] // CIR: %[[IS_CONSTANT:.*]] = cir.is_constant %[[EXPR]] : !s32i -> !cir.bool // LLVM: define{{.*}} %struct.foo @test0(i32 {{.*}} %[[ARG0:.*]]) // LLVM: %[[EXPR_ADDR:.*]] = alloca i32 // LLVM: store i32 %[[ARG0]], ptr %[[EXPR_ADDR]] // LLVM: %[[EXPR:.*]] = load i32, ptr %[[EXPR_ADDR]] // LLVM: %[[IS_CONSTANT:.*]] = call i1 @llvm.is.constant.i32(i32 %[[EXPR]]) // OGCG: define{{.*}} i64 @test0(i32 {{.*}} %[[ARG0:.*]]) // OGCG: %[[EXPR_ADDR:.*]] = alloca i32 // OGCG: store i32 %[[ARG0]], ptr %[[EXPR_ADDR]] // OGCG: %[[EXPR:.*]] = load i32, ptr %[[EXPR_ADDR]] // OGCG: %[[IS_CONSTANT:.*]] = call i1 @llvm.is.constant.i32(i32 %[[EXPR]]) /* --- Pointer types */ int test1(void) { return __builtin_constant_p(&a - 13); } // CIR: cir.func {{.*}} @test1() -> !s32i // CIR: %[[TMP1:.*]] = cir.alloca !s32i, !cir.ptr, ["__retval"] // CIR: %[[ZERO:.*]] = cir.const #cir.int<0> : !s32i // CIR: cir.store %[[ZERO]], %[[TMP1]] : !s32i, !cir.ptr // CIR: %[[TMP2:.*]] = cir.load %[[TMP1]] : !cir.ptr, !s32i // CIR: cir.return %[[TMP2]] : !s32i // LLVM: define{{.*}} i32 @test1() // LLVM: %[[TMP1:.*]] = alloca i32 // LLVM: store i32 0, ptr %[[TMP1]] // LLVM: %[[TMP2:.*]] = load i32, ptr %[[TMP1]] // LLVM: ret i32 %[[TMP2]] // OGCG: define{{.*}} i32 @test1() // OGCG: ret i32 0 /* --- Aggregate types */ int b[] = {1, 2, 3}; int test2(void) { return __builtin_constant_p(b); } // CIR: cir.func {{.*}} @test2() -> !s32i // CIR: %[[TMP1:.*]] = cir.alloca !s32i, !cir.ptr, ["__retval"] // CIR: %[[ZERO:.*]] = cir.const #cir.int<0> : !s32i // CIR: cir.store %[[ZERO]], %[[TMP1]] : !s32i, !cir.ptr // CIR: %[[TMP2:.*]] = cir.load %[[TMP1]] : !cir.ptr, !s32i // CIR: cir.return %[[TMP2]] : !s32i // LLVM: define{{.*}} i32 @test2() // LLVM: %[[TMP1:.*]] = alloca i32 // LLVM: store i32 0, ptr %[[TMP1]] // LLVM: %[[TMP2:.*]] = load i32, ptr %[[TMP1]] // LLVM: ret i32 %[[TMP2]] // OGCG: define{{.*}} i32 @test2() // OGCG: ret i32 0 const char test3_c[] = {1, 2, 3, 0}; int test3(void) { return __builtin_constant_p(test3_c); } // CIR: cir.func {{.*}} @test3() -> !s32i // CIR: %[[TMP1:.*]] = cir.alloca !s32i, !cir.ptr, ["__retval"] // CIR: %[[ZERO:.*]] = cir.const #cir.int<0> : !s32i // CIR: cir.store %[[ZERO]], %[[TMP1]] : !s32i, !cir.ptr // CIR: %[[TMP2:.*]] = cir.load %[[TMP1]] : !cir.ptr, !s32i // CIR: cir.return %[[TMP2]] : !s32i // LLVM: define{{.*}} i32 @test3() // LLVM: %[[TMP1:.*]] = alloca i32 // LLVM: store i32 0, ptr %[[TMP1]] // LLVM: %[[TMP2:.*]] = load i32, ptr %[[TMP1]] // LLVM: ret i32 %[[TMP2]] // OGCG: define{{.*}} i32 @test3() // OGCG: ret i32 0 inline char test4_i(const char *x) { return x[1]; } int test4(void) { return __builtin_constant_p(test4_i(test3_c)); } // CIR: cir.func {{.*}} @test4() -> !s32i // CIR: %[[TMP1:.*]] = cir.alloca !s32i, !cir.ptr, ["__retval"] // CIR: %[[ZERO:.*]] = cir.const #cir.int<0> : !s32i // CIR: cir.store %[[ZERO]], %[[TMP1]] : !s32i, !cir.ptr // CIR: %[[TMP2:.*]] = cir.load %[[TMP1]] : !cir.ptr, !s32i // CIR: cir.return %[[TMP2]] : !s32i // LLVM: define{{.*}} i32 @test4() // LLVM: %[[TMP1:.*]] = alloca i32 // LLVM: store i32 0, ptr %[[TMP1]] // LLVM: %[[TMP2:.*]] = load i32, ptr %[[TMP1]] // LLVM: ret i32 %[[TMP2]] // OGCG: define{{.*}} i32 @test4() // OGCG: ret i32 0 /* --- Constant global variables */ const int c = 42; int test5(void) { return __builtin_constant_p(c); } // CIR: cir.func {{.*}} @test5() -> !s32i // CIR: %[[TMP1:.*]] = cir.alloca !s32i, !cir.ptr, ["__retval"] // CIR: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i // CIR: cir.store %[[ONE]], %[[TMP1]] : !s32i, !cir.ptr // CIR: %[[TMP2:.*]] = cir.load %[[TMP1]] : !cir.ptr, !s32i // CIR: cir.return %[[TMP2]] : !s32i // LLVM: define{{.*}} i32 @test5() // LLVM: %[[TMP1:.*]] = alloca i32 // LLVM: store i32 1, ptr %[[TMP1]] // LLVM: %[[TMP2:.*]] = load i32, ptr %[[TMP1]] // LLVM: ret i32 %[[TMP2]] // OGCG: define{{.*}} i32 @test5() // OGCG: ret i32 1 /* --- Array types */ int arr[] = { 1, 2, 3 }; int test6(void) { return __builtin_constant_p(arr[2]); } // CIR: cir.func {{.*}} @test6() -> !s32i // CIR: %[[TWO:.*]] = cir.const #cir.int<2> : !s64i // CIR: %[[ARR:.*]] = cir.get_global @arr : !cir.ptr> // CIR: %[[ELE_PTR:.*]] = cir.get_element %[[ARR]][%[[TWO]] : !s64i] : !cir.ptr> -> !cir.ptr // CIR: %[[ELE:.*]] = cir.load{{.*}} %[[ELE_PTR]] : !cir.ptr, !s32i // CIR: %[[IS_CONSTANT:.*]] = cir.is_constant %[[ELE]] : !s32i -> !cir.bool // LLVM: define {{.*}} i32 @test6() // LLVM: %[[TMP1:.*]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @arr, i64 8) // LLVM: %[[TMP2:.*]] = call i1 @llvm.is.constant.i32(i32 %[[TMP1]]) // OGCG: define {{.*}} i32 @test6() // OGCG: %[[TMP1:.*]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @arr, i64 8) // OGCG: %[[TMP2:.*]] = call i1 @llvm.is.constant.i32(i32 %[[TMP1]]) const int c_arr[] = { 1, 2, 3 }; int test7(void) { return __builtin_constant_p(c_arr[2]); } // CIR: cir.func {{.*}} @test7() -> !s32i // CIR: %[[TMP1:.*]] = cir.alloca !s32i, !cir.ptr, ["__retval"] // CIR: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i // CIR: cir.store %[[ONE]], %[[TMP1]] : !s32i, !cir.ptr // CIR: %[[TMP2:.*]] = cir.load %[[TMP1]] : !cir.ptr, !s32i // CIR: cir.return %[[TMP2]] : !s32i // LLVM: define{{.*}} i32 @test7() // LLVM: %[[TMP1:.*]] = alloca i32 // LLVM: store i32 1, ptr %[[TMP1]] // LLVM: %[[TMP2:.*]] = load i32, ptr %[[TMP1]] // LLVM: ret i32 %[[TMP2]] // OGCG: define{{.*}} i32 @test7() // OGCG: ret i32 1 int test8(void) { return __builtin_constant_p(c_arr); } // CIR: cir.func {{.*}} @test8() -> !s32i // CIR: %[[TMP1:.*]] = cir.alloca !s32i, !cir.ptr, ["__retval"] // CIR: %[[ZERO:.*]] = cir.const #cir.int<0> : !s32i // CIR: cir.store %[[ZERO]], %[[TMP1]] : !s32i, !cir.ptr // CIR: %[[TMP2:.*]] = cir.load %[[TMP1]] : !cir.ptr, !s32i // CIR: cir.return %[[TMP2]] : !s32i // LLVM: define{{.*}} i32 @test8() // LLVM: %[[TMP1:.*]] = alloca i32 // LLVM: store i32 0, ptr %[[TMP1]] // LLVM: %[[TMP2:.*]] = load i32, ptr %[[TMP1]] // LLVM: ret i32 %[[TMP2]] // OGCG: define{{.*}} i32 @test8() // OGCG: ret i32 0 /* --- Function pointers */ int test9(void) { return __builtin_constant_p(&test9); } // CIR: cir.func {{.*}} @test9() -> !s32i // CIR: %[[TMP1:.*]] = cir.alloca !s32i, !cir.ptr, ["__retval"] // CIR: %[[ZERO:.*]] = cir.const #cir.int<0> : !s32i // CIR: cir.store %[[ZERO]], %[[TMP1]] : !s32i, !cir.ptr // CIR: %[[TMP2:.*]] = cir.load %[[TMP1]] : !cir.ptr, !s32i // CIR: cir.return %[[TMP2]] : !s32i // LLVM: define{{.*}} i32 @test9() // LLVM: %[[TMP1:.*]] = alloca i32 // LLVM: store i32 0, ptr %[[TMP1]] // LLVM: %[[TMP2:.*]] = load i32, ptr %[[TMP1]] // LLVM: ret i32 %[[TMP2]] // OGCG: define{{.*}} i32 @test9() // OGCG: ret i32 0 int test10(void) { return __builtin_constant_p(&test10 != 0); } // CIR: cir.func {{.*}} @test10() -> !s32i // CIR: %[[TMP1:.*]] = cir.alloca !s32i, !cir.ptr, ["__retval"] // CIR: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i // CIR: cir.store %[[ONE]], %[[TMP1]] : !s32i, !cir.ptr // CIR: %[[TMP2:.*]] = cir.load %[[TMP1]] : !cir.ptr, !s32i // CIR: cir.return %[[TMP2]] : !s32i // LLVM: define{{.*}} i32 @test10() // LLVM: %[[TMP1:.*]] = alloca i32 // LLVM: store i32 1, ptr %[[TMP1]] // LLVM: %[[TMP2:.*]] = load i32, ptr %[[TMP1]] // LLVM: ret i32 %[[TMP2]] // OGCG: define{{.*}} i32 @test10() // OGCG: ret i32 1 int test11_f(void); void test11(void) { int a, b; (void)__builtin_constant_p((a = b, test11_f())); } // CIR: cir.func {{.*}} @test11() // CIR-NOT: call {{.*}}test11_f // LLVM: define{{.*}} void @test11() // LLVM-NOT: call {{.*}}test11_f // OGCG: define{{.*}} void @test11() // OGCG-NOT: call {{.*}}test11_f