Eric Fiselier | add16a8 | 2019-04-24 02:23:30 +0000 | [diff] [blame] | 1 | // RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm %s -std=c++2a -o %t.ll |
| 2 | // RUN: FileCheck -check-prefix=CHECK-FN-CG -input-file=%t.ll %s |
| 3 | // RUN: FileCheck -check-prefix=CHECK-STATIC -input-file=%t.ll %s |
| 4 | // RUN: FileCheck -check-prefix=CHECK-DYN -input-file=%t.ll %s |
| 5 | // RUN: FileCheck -check-prefix=CHECK-ARR -input-file=%t.ll %s |
| 6 | // RUN: FileCheck -check-prefix=CHECK-FOLD -input-file=%t.ll %s |
| 7 | |
| 8 | using size_t = decltype(sizeof(int)); |
| 9 | |
| 10 | #define CONSTINIT __attribute__((require_constant_initialization)) |
| 11 | |
| 12 | extern "C" [[noreturn]] void BOOM(); |
| 13 | extern "C" void OK(); |
| 14 | extern "C" size_t RANDU(); |
| 15 | |
| 16 | namespace std { |
| 17 | inline constexpr bool is_constant_evaluated() noexcept { |
| 18 | return __builtin_is_constant_evaluated(); |
| 19 | } |
| 20 | } // namespace std |
| 21 | |
Fangrui Song | dbc96b5 | 2020-02-03 10:09:39 -0800 | [diff] [blame] | 22 | // CHECK-FN-CG-LABEL: define zeroext i1 @_Z3foov() |
Eric Fiselier | add16a8 | 2019-04-24 02:23:30 +0000 | [diff] [blame] | 23 | // CHECK-FN-CG: ret i1 false |
| 24 | bool foo() { |
| 25 | return __builtin_is_constant_evaluated(); |
| 26 | } |
| 27 | |
Fangrui Song | dbc96b5 | 2020-02-03 10:09:39 -0800 | [diff] [blame] | 28 | // CHECK-FN-CG-LABEL: define linkonce_odr i32 @_Z1fv() |
Eric Fiselier | add16a8 | 2019-04-24 02:23:30 +0000 | [diff] [blame] | 29 | constexpr int f() { |
| 30 | // CHECK-FN-CG: store i32 13, i32* %n, align 4 |
| 31 | // CHECK-FN-CG: store i32 17, i32* %m, align 4 |
| 32 | // CHECK-FN-CG: %1 = load i32, i32* %m, align 4 |
| 33 | // CHECK-FN-CG: %add = add nsw i32 %1, 13 |
| 34 | // CHECK-FN-CG: ret i32 %add |
| 35 | const int n = __builtin_is_constant_evaluated() && std::is_constant_evaluated() ? 13 : 17; // n == 13 |
| 36 | int m = __builtin_is_constant_evaluated() ? 13 : 17; // m might be 13 or 17 (see below) |
| 37 | char arr[n] = {}; // char[13] |
| 38 | return m + int(sizeof(arr)); |
| 39 | } |
| 40 | |
Fangrui Song | dbc96b5 | 2020-02-03 10:09:39 -0800 | [diff] [blame] | 41 | // CHECK-STATIC-DAG: @p = global i32 26, |
Eric Fiselier | add16a8 | 2019-04-24 02:23:30 +0000 | [diff] [blame] | 42 | CONSTINIT int p = f(); // f().m == 13; initialized to 26 |
Fangrui Song | dbc96b5 | 2020-02-03 10:09:39 -0800 | [diff] [blame] | 43 | // CHECK-STATIC-DAG: @p2 = global i32 26, |
Eric Fiselier | add16a8 | 2019-04-24 02:23:30 +0000 | [diff] [blame] | 44 | int p2 = f(); // same result without CONSTINIT |
| 45 | |
| 46 | // CHECK-DYN-LABEL: define internal void @__cxx_global_var_init() |
| 47 | // CHECK-DYN: %0 = load i32, i32* @p, align 4 |
| 48 | // CHECK-DYN-NEXT: %call = call i32 @_Z1fv() |
| 49 | // CHECK-DYN-NEXT: %add = add nsw i32 %0, %call |
| 50 | // CHECK-DYN-NEXT: store i32 %add, i32* @q, align 4 |
| 51 | // CHECK-DYN-NEXT: ret void |
| 52 | int q = p + f(); // m == 17 for this call; initialized to 56 |
| 53 | |
| 54 | int y; |
| 55 | |
Fangrui Song | dbc96b5 | 2020-02-03 10:09:39 -0800 | [diff] [blame] | 56 | // CHECK-STATIC-DAG: @b = global i32 2, |
Eric Fiselier | add16a8 | 2019-04-24 02:23:30 +0000 | [diff] [blame] | 57 | CONSTINIT int b = __builtin_is_constant_evaluated() ? 2 : y; // static initialization to 2 |
| 58 | |
| 59 | // CHECK-DYN-LABEL: define internal void @__cxx_global_var_init.1() |
| 60 | // CHECK-DYN: %0 = load i32, i32* @y, align 4 |
| 61 | // CHECK-DYN: %1 = load i32, i32* @y, align 4 |
| 62 | // CHECK-DYN-NEXT: %add = add |
| 63 | // CHECK-DYN-NEXT: store i32 %add, i32* @c, |
| 64 | int c = y + (__builtin_is_constant_evaluated() ? 2 : y); // dynamic initialization to y+y |
| 65 | |
| 66 | // CHECK-DYN-LABEL: define internal void @__cxx_global_var_init.2() |
| 67 | // CHECK-DYN: store i32 1, i32* @_ZL1a, align 4 |
| 68 | // CHECK-DYN-NEXT: ret void |
| 69 | const int a = __builtin_is_constant_evaluated() ? y : 1; // dynamic initialization to 1 |
| 70 | const int *a_sink = &a; |
| 71 | |
Fangrui Song | dbc96b5 | 2020-02-03 10:09:39 -0800 | [diff] [blame] | 72 | // CHECK-ARR-LABEL: define void @_Z13test_arr_exprv |
Eric Fiselier | add16a8 | 2019-04-24 02:23:30 +0000 | [diff] [blame] | 73 | void test_arr_expr() { |
| 74 | // CHECK-ARR: %x1 = alloca [101 x i8], |
| 75 | char x1[std::is_constant_evaluated() && __builtin_is_constant_evaluated() ? 101 : 1]; |
| 76 | |
| 77 | // CHECK-ARR: %x2 = alloca [42 x i8], |
| 78 | char x2[std::is_constant_evaluated() && __builtin_is_constant_evaluated() ? 42 : RANDU()]; |
| 79 | |
| 80 | // CHECK-ARR: call i8* @llvm.stacksave() |
| 81 | // CHECK-ARR: %vla = alloca i8, i64 13, |
| 82 | char x3[std::is_constant_evaluated() || __builtin_is_constant_evaluated() ? RANDU() : 13]; |
| 83 | } |
| 84 | |
Fangrui Song | dbc96b5 | 2020-02-03 10:09:39 -0800 | [diff] [blame] | 85 | // CHECK-ARR-LABEL: define void @_Z17test_new_arr_exprv |
Eric Fiselier | add16a8 | 2019-04-24 02:23:30 +0000 | [diff] [blame] | 86 | void test_new_arr_expr() { |
Roman Lebedev | 3dd5a29 | 2020-02-26 01:37:17 +0300 | [diff] [blame^] | 87 | // CHECK-ARR: call noalias nonnull i8* @_Znam(i64 17) |
Eric Fiselier | add16a8 | 2019-04-24 02:23:30 +0000 | [diff] [blame] | 88 | new char[std::is_constant_evaluated() || __builtin_is_constant_evaluated() ? 1 : 17]; |
| 89 | } |
| 90 | |
| 91 | // CHECK-FOLD-LABEL: @_Z31test_constant_initialized_locali( |
| 92 | bool test_constant_initialized_local(int k) { |
| 93 | // CHECK-FOLD: store i8 1, i8* %n, |
| 94 | // CHECK-FOLD: store volatile i8* %n, i8** %p, |
| 95 | const bool n = __builtin_is_constant_evaluated() && std::is_constant_evaluated(); |
| 96 | const bool *volatile p = &n; |
| 97 | return *p; |
| 98 | } |
| 99 | |
Fangrui Song | dbc96b5 | 2020-02-03 10:09:39 -0800 | [diff] [blame] | 100 | // CHECK-FOLD-LABEL: define void @_Z21test_ir_constant_foldv() |
Eric Fiselier | add16a8 | 2019-04-24 02:23:30 +0000 | [diff] [blame] | 101 | void test_ir_constant_fold() { |
| 102 | // CHECK-FOLD-NEXT: entry: |
| 103 | // CHECK-FOLD-NEXT: call void @OK() |
| 104 | // CHECK-FOLD-NEXT: call void @OK() |
| 105 | // CHECK-FOLD-NEXT: ret void |
| 106 | if (std::is_constant_evaluated()) { |
| 107 | BOOM(); |
| 108 | } else { |
| 109 | OK(); |
| 110 | } |
| 111 | std::is_constant_evaluated() ? BOOM() : OK(); |
| 112 | } |
| 113 | |
Fangrui Song | dbc96b5 | 2020-02-03 10:09:39 -0800 | [diff] [blame] | 114 | // CHECK-STATIC-DAG: @ir = constant i32* @i_constant, |
Eric Fiselier | add16a8 | 2019-04-24 02:23:30 +0000 | [diff] [blame] | 115 | int i_constant; |
| 116 | int i_not_constant; |
| 117 | int &ir = __builtin_is_constant_evaluated() ? i_constant : i_not_constant; |
| 118 | |
| 119 | // CHECK-FOLD-LABEL: @_Z35test_ref_initialization_local_scopev() |
| 120 | void test_ref_initialization_local_scope() { |
| 121 | const int i_constant = 42; |
| 122 | const int i_non_constant = 101; |
| 123 | // CHECK-FOLD: store i32* %i_non_constant, i32** %r, |
| 124 | const int &r = __builtin_is_constant_evaluated() ? i_constant : i_non_constant; |
| 125 | } |
| 126 | |
| 127 | // CHECK-FOLD-LABEL: @_Z22test_ref_to_static_varv() |
| 128 | void test_ref_to_static_var() { |
| 129 | static int i_constant = 42; |
| 130 | static int i_non_constant = 101; |
| 131 | // CHECK-FOLD: store i32* @_ZZ22test_ref_to_static_varvE10i_constant, i32** %r, |
| 132 | int &r = __builtin_is_constant_evaluated() ? i_constant : i_non_constant; |
Roman Lebedev | 3dd5a29 | 2020-02-26 01:37:17 +0300 | [diff] [blame^] | 133 | } |