1 // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --function-signature --include-generated-funcs --replace-value-regex "__omp_offloading_[0-9a-z]+_[0-9a-z]+" "reduction_size[.].+[.]" "pl_cond[.].+[.|,]" --prefix-filecheck-ir-name _ 2 // Test target codegen - host bc file has to be created first. 3 // RUN: %clang_cc1 -verify -fopenmp -fopenmp-cuda-mode -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc %s -o %t-ppc-host.bc 4 // RUN: %clang_cc1 -verify -fopenmp -fopenmp-cuda-mode -x c++ -triple nvptx64-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - -disable-llvm-optzns | FileCheck %s --check-prefix=CHECK1 5 // RUN: %clang_cc1 -verify -fopenmp -fopenmp-cuda-mode -x c++ -triple i386-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm-bc %s -o %t-x86-host.bc 6 // RUN: %clang_cc1 -verify -fopenmp -fopenmp-cuda-mode -x c++ -triple nvptx-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - -disable-llvm-optzns | FileCheck %s --check-prefix=CHECK2 7 // RUN: %clang_cc1 -verify -fopenmp -fopenmp-cuda-mode -fexceptions -fcxx-exceptions -x c++ -triple nvptx-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - -disable-llvm-optzns | FileCheck %s --check-prefix=CHECK3 8 9 // expected-no-diagnostics 10 #ifndef HEADER 11 #define HEADER 12 13 void work(int *C) { 14 #pragma omp atomic 15 ++(*C); 16 } 17 18 void use(int *C) { 19 #pragma omp parallel num_threads(2) 20 work(C); 21 } 22 23 int main() { 24 int C = 0; 25 #pragma omp target map(C) 26 { 27 use(&C); 28 #pragma omp parallel num_threads(2) 29 use(&C); 30 } 31 32 return C; 33 } 34 35 #endif 36 // CHECK1-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l25 37 // CHECK1-SAME: (i32* nonnull align 4 dereferenceable(4) [[C:%.*]]) #[[ATTR0:[0-9]+]] { 38 // CHECK1-NEXT: entry: 39 // CHECK1-NEXT: [[C_ADDR:%.*]] = alloca i32*, align 8 40 // CHECK1-NEXT: [[OMP_OUTLINED_ARG_AGG_:%.*]] = alloca [[STRUCT_ANON:%.*]], align 8 41 // CHECK1-NEXT: [[CAPTURED_VARS_ADDRS:%.*]] = alloca [1 x i8*], align 8 42 // CHECK1-NEXT: store i32* [[C]], i32** [[C_ADDR]], align 8 43 // CHECK1-NEXT: [[TMP0:%.*]] = load i32*, i32** [[C_ADDR]], align 8 44 // CHECK1-NEXT: [[TMP1:%.*]] = call i32 @__kmpc_target_init(%struct.ident_t* @[[GLOB1:[0-9]+]], i1 false, i1 true, i1 true) 45 // CHECK1-NEXT: [[EXEC_USER_CODE:%.*]] = icmp eq i32 [[TMP1]], -1 46 // CHECK1-NEXT: br i1 [[EXEC_USER_CODE]], label [[USER_CODE_ENTRY:%.*]], label [[WORKER_EXIT:%.*]] 47 // CHECK1: user_code.entry: 48 // CHECK1-NEXT: [[TMP2:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* @[[GLOB1]]) 49 // CHECK1-NEXT: call void @_Z3usePi(i32* [[TMP0]]) #[[ATTR5:[0-9]+]] 50 // CHECK1-NEXT: call void @__kmpc_push_num_threads(%struct.ident_t* @[[GLOB1]], i32 [[TMP2]], i32 2) 51 // CHECK1-NEXT: [[TMP3:%.*]] = getelementptr inbounds [[STRUCT_ANON]], %struct.anon* [[OMP_OUTLINED_ARG_AGG_]], i32 0, i32 0 52 // CHECK1-NEXT: store i32* [[TMP0]], i32** [[TMP3]], align 8 53 // CHECK1-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x i8*], [1 x i8*]* [[CAPTURED_VARS_ADDRS]], i64 0, i64 0 54 // CHECK1-NEXT: [[TMP5:%.*]] = call i8* @__kmpc_alloc_shared(i64 8) 55 // CHECK1-NEXT: [[TMP6:%.*]] = load [[STRUCT_ANON]], %struct.anon* [[OMP_OUTLINED_ARG_AGG_]], align 8 56 // CHECK1-NEXT: [[TMP7:%.*]] = bitcast i8* [[TMP5]] to %struct.anon* 57 // CHECK1-NEXT: store [[STRUCT_ANON]] [[TMP6]], %struct.anon* [[TMP7]], align 8 58 // CHECK1-NEXT: store i8* [[TMP5]], i8** [[TMP4]], align 8 59 // CHECK1-NEXT: [[TMP8:%.*]] = bitcast [1 x i8*]* [[CAPTURED_VARS_ADDRS]] to i8** 60 // CHECK1-NEXT: call void @__kmpc_parallel_51(%struct.ident_t* @[[GLOB1]], i32 [[TMP2]], i32 1, i32 -1, i32 -1, i8* bitcast (void (i32*, i32*, %struct.anon*)* @__omp_outlined__ to i8*), i8* bitcast (void (i16, i32)* @__omp_outlined___wrapper to i8*), i8** [[TMP8]], i64 1) 61 // CHECK1-NEXT: call void @__kmpc_free_shared(i8* [[TMP5]]) 62 // CHECK1-NEXT: call void @__kmpc_target_deinit(%struct.ident_t* @[[GLOB1]], i1 false, i1 true) 63 // CHECK1-NEXT: ret void 64 // CHECK1: worker.exit: 65 // CHECK1-NEXT: ret void 66 // 67 // 68 // CHECK1-LABEL: define {{[^@]+}}@_Z3usePi 69 // CHECK1-SAME: (i32* [[C:%.*]]) #[[ATTR1:[0-9]+]] { 70 // CHECK1-NEXT: entry: 71 // CHECK1-NEXT: [[C_ADDR:%.*]] = alloca i32*, align 8 72 // CHECK1-NEXT: [[OMP_OUTLINED_ARG_AGG_:%.*]] = alloca [[STRUCT_ANON_0:%.*]], align 8 73 // CHECK1-NEXT: [[CAPTURED_VARS_ADDRS:%.*]] = alloca [1 x i8*], align 8 74 // CHECK1-NEXT: [[TMP0:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* @[[GLOB2:[0-9]+]]) 75 // CHECK1-NEXT: store i32* [[C]], i32** [[C_ADDR]], align 8 76 // CHECK1-NEXT: call void @__kmpc_push_num_threads(%struct.ident_t* @[[GLOB2]], i32 [[TMP0]], i32 2) 77 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT_ANON_0]], %struct.anon.0* [[OMP_OUTLINED_ARG_AGG_]], i32 0, i32 0 78 // CHECK1-NEXT: store i32** [[C_ADDR]], i32*** [[TMP1]], align 8 79 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [1 x i8*], [1 x i8*]* [[CAPTURED_VARS_ADDRS]], i64 0, i64 0 80 // CHECK1-NEXT: [[TMP3:%.*]] = call i8* @__kmpc_alloc_shared(i64 8) 81 // CHECK1-NEXT: [[TMP4:%.*]] = load [[STRUCT_ANON_0]], %struct.anon.0* [[OMP_OUTLINED_ARG_AGG_]], align 8 82 // CHECK1-NEXT: [[TMP5:%.*]] = bitcast i8* [[TMP3]] to %struct.anon.0* 83 // CHECK1-NEXT: store [[STRUCT_ANON_0]] [[TMP4]], %struct.anon.0* [[TMP5]], align 8 84 // CHECK1-NEXT: store i8* [[TMP3]], i8** [[TMP2]], align 8 85 // CHECK1-NEXT: [[TMP6:%.*]] = bitcast [1 x i8*]* [[CAPTURED_VARS_ADDRS]] to i8** 86 // CHECK1-NEXT: call void @__kmpc_parallel_51(%struct.ident_t* @[[GLOB2]], i32 [[TMP0]], i32 1, i32 -1, i32 -1, i8* bitcast (void (i32*, i32*, %struct.anon.0*)* @__omp_outlined__1 to i8*), i8* bitcast (void (i16, i32)* @__omp_outlined__1_wrapper to i8*), i8** [[TMP6]], i64 1) 87 // CHECK1-NEXT: call void @__kmpc_free_shared(i8* [[TMP3]]) 88 // CHECK1-NEXT: ret void 89 // 90 // 91 // CHECK1-LABEL: define {{[^@]+}}@__omp_outlined__ 92 // CHECK1-SAME: (i32* noalias [[DOTGLOBAL_TID_:%.*]], i32* noalias [[DOTBOUND_TID_:%.*]], %struct.anon* noalias [[__CONTEXT:%.*]]) #[[ATTR0]] { 93 // CHECK1-NEXT: entry: 94 // CHECK1-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca i32*, align 8 95 // CHECK1-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca i32*, align 8 96 // CHECK1-NEXT: [[__CONTEXT_ADDR:%.*]] = alloca %struct.anon*, align 8 97 // CHECK1-NEXT: store i32* [[DOTGLOBAL_TID_]], i32** [[DOTGLOBAL_TID__ADDR]], align 8 98 // CHECK1-NEXT: store i32* [[DOTBOUND_TID_]], i32** [[DOTBOUND_TID__ADDR]], align 8 99 // CHECK1-NEXT: store %struct.anon* [[__CONTEXT]], %struct.anon** [[__CONTEXT_ADDR]], align 8 100 // CHECK1-NEXT: [[TMP0:%.*]] = load %struct.anon*, %struct.anon** [[__CONTEXT_ADDR]], align 8 101 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT_ANON:%.*]], %struct.anon* [[TMP0]], i32 0, i32 0 102 // CHECK1-NEXT: [[TMP2:%.*]] = load i32*, i32** [[TMP1]], align 8 103 // CHECK1-NEXT: call void @_Z3usePi(i32* [[TMP2]]) #[[ATTR5]] 104 // CHECK1-NEXT: ret void 105 // 106 // 107 // CHECK1-LABEL: define {{[^@]+}}@__omp_outlined___wrapper 108 // CHECK1-SAME: (i16 zeroext [[TMP0:%.*]], i32 [[TMP1:%.*]]) #[[ATTR2:[0-9]+]] { 109 // CHECK1-NEXT: entry: 110 // CHECK1-NEXT: [[DOTADDR:%.*]] = alloca i16, align 2 111 // CHECK1-NEXT: [[DOTADDR1:%.*]] = alloca i32, align 4 112 // CHECK1-NEXT: [[DOTZERO_ADDR:%.*]] = alloca i32, align 4 113 // CHECK1-NEXT: [[GLOBAL_ARGS:%.*]] = alloca i8**, align 8 114 // CHECK1-NEXT: store i32 0, i32* [[DOTZERO_ADDR]], align 4 115 // CHECK1-NEXT: store i16 [[TMP0]], i16* [[DOTADDR]], align 2 116 // CHECK1-NEXT: store i32 [[TMP1]], i32* [[DOTADDR1]], align 4 117 // CHECK1-NEXT: call void @__kmpc_get_shared_variables(i8*** [[GLOBAL_ARGS]]) 118 // CHECK1-NEXT: [[TMP2:%.*]] = load i8**, i8*** [[GLOBAL_ARGS]], align 8 119 // CHECK1-NEXT: [[TMP3:%.*]] = getelementptr inbounds i8*, i8** [[TMP2]], i64 0 120 // CHECK1-NEXT: [[TMP4:%.*]] = bitcast i8** [[TMP3]] to %struct.anon** 121 // CHECK1-NEXT: [[TMP5:%.*]] = load %struct.anon*, %struct.anon** [[TMP4]], align 8 122 // CHECK1-NEXT: call void @__omp_outlined__(i32* [[DOTADDR1]], i32* [[DOTZERO_ADDR]], %struct.anon* [[TMP5]]) #[[ATTR3:[0-9]+]] 123 // CHECK1-NEXT: ret void 124 // 125 // 126 // CHECK1-LABEL: define {{[^@]+}}@__omp_outlined__1 127 // CHECK1-SAME: (i32* noalias [[DOTGLOBAL_TID_:%.*]], i32* noalias [[DOTBOUND_TID_:%.*]], %struct.anon.0* noalias [[__CONTEXT:%.*]]) #[[ATTR0]] { 128 // CHECK1-NEXT: entry: 129 // CHECK1-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca i32*, align 8 130 // CHECK1-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca i32*, align 8 131 // CHECK1-NEXT: [[__CONTEXT_ADDR:%.*]] = alloca %struct.anon.0*, align 8 132 // CHECK1-NEXT: store i32* [[DOTGLOBAL_TID_]], i32** [[DOTGLOBAL_TID__ADDR]], align 8 133 // CHECK1-NEXT: store i32* [[DOTBOUND_TID_]], i32** [[DOTBOUND_TID__ADDR]], align 8 134 // CHECK1-NEXT: store %struct.anon.0* [[__CONTEXT]], %struct.anon.0** [[__CONTEXT_ADDR]], align 8 135 // CHECK1-NEXT: [[TMP0:%.*]] = load %struct.anon.0*, %struct.anon.0** [[__CONTEXT_ADDR]], align 8 136 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT_ANON_0:%.*]], %struct.anon.0* [[TMP0]], i32 0, i32 0 137 // CHECK1-NEXT: [[TMP2:%.*]] = load i32**, i32*** [[TMP1]], align 8 138 // CHECK1-NEXT: [[TMP3:%.*]] = load i32*, i32** [[TMP2]], align 8 139 // CHECK1-NEXT: call void @_Z4workPi(i32* [[TMP3]]) #[[ATTR5]] 140 // CHECK1-NEXT: ret void 141 // 142 // 143 // CHECK1-LABEL: define {{[^@]+}}@_Z4workPi 144 // CHECK1-SAME: (i32* [[C:%.*]]) #[[ATTR1]] { 145 // CHECK1-NEXT: entry: 146 // CHECK1-NEXT: [[C_ADDR:%.*]] = alloca i32*, align 8 147 // CHECK1-NEXT: [[ATOMIC_TEMP:%.*]] = alloca i32, align 4 148 // CHECK1-NEXT: [[ATOMIC_TEMP1:%.*]] = alloca i32, align 4 149 // CHECK1-NEXT: store i32* [[C]], i32** [[C_ADDR]], align 8 150 // CHECK1-NEXT: [[TMP0:%.*]] = load i32*, i32** [[C_ADDR]], align 8 151 // CHECK1-NEXT: [[TMP1:%.*]] = bitcast i32* [[TMP0]] to i8* 152 // CHECK1-NEXT: [[TMP2:%.*]] = bitcast i32* [[ATOMIC_TEMP]] to i8* 153 // CHECK1-NEXT: call void @__atomic_load(i64 4, i8* [[TMP1]], i8* [[TMP2]], i32 0) #[[ATTR5]] 154 // CHECK1-NEXT: br label [[ATOMIC_CONT:%.*]] 155 // CHECK1: atomic_cont: 156 // CHECK1-NEXT: [[TMP3:%.*]] = load i32, i32* [[ATOMIC_TEMP]], align 4 157 // CHECK1-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP3]], 1 158 // CHECK1-NEXT: store i32 [[ADD]], i32* [[ATOMIC_TEMP1]], align 4 159 // CHECK1-NEXT: [[TMP4:%.*]] = bitcast i32* [[TMP0]] to i8* 160 // CHECK1-NEXT: [[TMP5:%.*]] = bitcast i32* [[ATOMIC_TEMP]] to i8* 161 // CHECK1-NEXT: [[TMP6:%.*]] = bitcast i32* [[ATOMIC_TEMP1]] to i8* 162 // CHECK1-NEXT: [[CALL:%.*]] = call zeroext i1 @__atomic_compare_exchange(i64 4, i8* [[TMP4]], i8* [[TMP5]], i8* [[TMP6]], i32 0, i32 0) #[[ATTR5]] 163 // CHECK1-NEXT: br i1 [[CALL]], label [[ATOMIC_EXIT:%.*]], label [[ATOMIC_CONT]] 164 // CHECK1: atomic_exit: 165 // CHECK1-NEXT: ret void 166 // 167 // 168 // CHECK1-LABEL: define {{[^@]+}}@__omp_outlined__1_wrapper 169 // CHECK1-SAME: (i16 zeroext [[TMP0:%.*]], i32 [[TMP1:%.*]]) #[[ATTR2]] { 170 // CHECK1-NEXT: entry: 171 // CHECK1-NEXT: [[DOTADDR:%.*]] = alloca i16, align 2 172 // CHECK1-NEXT: [[DOTADDR1:%.*]] = alloca i32, align 4 173 // CHECK1-NEXT: [[DOTZERO_ADDR:%.*]] = alloca i32, align 4 174 // CHECK1-NEXT: [[GLOBAL_ARGS:%.*]] = alloca i8**, align 8 175 // CHECK1-NEXT: store i32 0, i32* [[DOTZERO_ADDR]], align 4 176 // CHECK1-NEXT: store i16 [[TMP0]], i16* [[DOTADDR]], align 2 177 // CHECK1-NEXT: store i32 [[TMP1]], i32* [[DOTADDR1]], align 4 178 // CHECK1-NEXT: call void @__kmpc_get_shared_variables(i8*** [[GLOBAL_ARGS]]) 179 // CHECK1-NEXT: [[TMP2:%.*]] = load i8**, i8*** [[GLOBAL_ARGS]], align 8 180 // CHECK1-NEXT: [[TMP3:%.*]] = getelementptr inbounds i8*, i8** [[TMP2]], i64 0 181 // CHECK1-NEXT: [[TMP4:%.*]] = bitcast i8** [[TMP3]] to %struct.anon.0** 182 // CHECK1-NEXT: [[TMP5:%.*]] = load %struct.anon.0*, %struct.anon.0** [[TMP4]], align 8 183 // CHECK1-NEXT: call void @__omp_outlined__1(i32* [[DOTADDR1]], i32* [[DOTZERO_ADDR]], %struct.anon.0* [[TMP5]]) #[[ATTR3]] 184 // CHECK1-NEXT: ret void 185 // 186 // 187 // CHECK2-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l25 188 // CHECK2-SAME: (i32* nonnull align 4 dereferenceable(4) [[C:%.*]]) #[[ATTR0:[0-9]+]] { 189 // CHECK2-NEXT: entry: 190 // CHECK2-NEXT: [[C_ADDR:%.*]] = alloca i32*, align 4 191 // CHECK2-NEXT: [[OMP_OUTLINED_ARG_AGG_:%.*]] = alloca [[STRUCT_ANON:%.*]], align 4 192 // CHECK2-NEXT: [[CAPTURED_VARS_ADDRS:%.*]] = alloca [1 x i8*], align 4 193 // CHECK2-NEXT: store i32* [[C]], i32** [[C_ADDR]], align 4 194 // CHECK2-NEXT: [[TMP0:%.*]] = load i32*, i32** [[C_ADDR]], align 4 195 // CHECK2-NEXT: [[TMP1:%.*]] = call i32 @__kmpc_target_init(%struct.ident_t* @[[GLOB1:[0-9]+]], i1 false, i1 true, i1 true) 196 // CHECK2-NEXT: [[EXEC_USER_CODE:%.*]] = icmp eq i32 [[TMP1]], -1 197 // CHECK2-NEXT: br i1 [[EXEC_USER_CODE]], label [[USER_CODE_ENTRY:%.*]], label [[WORKER_EXIT:%.*]] 198 // CHECK2: user_code.entry: 199 // CHECK2-NEXT: [[TMP2:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* @[[GLOB1]]) 200 // CHECK2-NEXT: call void @_Z3usePi(i32* [[TMP0]]) #[[ATTR5:[0-9]+]] 201 // CHECK2-NEXT: call void @__kmpc_push_num_threads(%struct.ident_t* @[[GLOB1]], i32 [[TMP2]], i32 2) 202 // CHECK2-NEXT: [[TMP3:%.*]] = getelementptr inbounds [[STRUCT_ANON]], %struct.anon* [[OMP_OUTLINED_ARG_AGG_]], i32 0, i32 0 203 // CHECK2-NEXT: store i32* [[TMP0]], i32** [[TMP3]], align 4 204 // CHECK2-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x i8*], [1 x i8*]* [[CAPTURED_VARS_ADDRS]], i32 0, i32 0 205 // CHECK2-NEXT: [[TMP5:%.*]] = call i8* @__kmpc_alloc_shared(i32 4) 206 // CHECK2-NEXT: [[TMP6:%.*]] = load [[STRUCT_ANON]], %struct.anon* [[OMP_OUTLINED_ARG_AGG_]], align 4 207 // CHECK2-NEXT: [[TMP7:%.*]] = bitcast i8* [[TMP5]] to %struct.anon* 208 // CHECK2-NEXT: store [[STRUCT_ANON]] [[TMP6]], %struct.anon* [[TMP7]], align 4 209 // CHECK2-NEXT: store i8* [[TMP5]], i8** [[TMP4]], align 4 210 // CHECK2-NEXT: [[TMP8:%.*]] = bitcast [1 x i8*]* [[CAPTURED_VARS_ADDRS]] to i8** 211 // CHECK2-NEXT: call void @__kmpc_parallel_51(%struct.ident_t* @[[GLOB1]], i32 [[TMP2]], i32 1, i32 -1, i32 -1, i8* bitcast (void (i32*, i32*, %struct.anon*)* @__omp_outlined__ to i8*), i8* bitcast (void (i16, i32)* @__omp_outlined___wrapper to i8*), i8** [[TMP8]], i32 1) 212 // CHECK2-NEXT: call void @__kmpc_free_shared(i8* [[TMP5]]) 213 // CHECK2-NEXT: call void @__kmpc_target_deinit(%struct.ident_t* @[[GLOB1]], i1 false, i1 true) 214 // CHECK2-NEXT: ret void 215 // CHECK2: worker.exit: 216 // CHECK2-NEXT: ret void 217 // 218 // 219 // CHECK2-LABEL: define {{[^@]+}}@_Z3usePi 220 // CHECK2-SAME: (i32* [[C:%.*]]) #[[ATTR1:[0-9]+]] { 221 // CHECK2-NEXT: entry: 222 // CHECK2-NEXT: [[C_ADDR:%.*]] = alloca i32*, align 4 223 // CHECK2-NEXT: [[OMP_OUTLINED_ARG_AGG_:%.*]] = alloca [[STRUCT_ANON_0:%.*]], align 4 224 // CHECK2-NEXT: [[CAPTURED_VARS_ADDRS:%.*]] = alloca [1 x i8*], align 4 225 // CHECK2-NEXT: [[TMP0:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* @[[GLOB2:[0-9]+]]) 226 // CHECK2-NEXT: store i32* [[C]], i32** [[C_ADDR]], align 4 227 // CHECK2-NEXT: call void @__kmpc_push_num_threads(%struct.ident_t* @[[GLOB2]], i32 [[TMP0]], i32 2) 228 // CHECK2-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT_ANON_0]], %struct.anon.0* [[OMP_OUTLINED_ARG_AGG_]], i32 0, i32 0 229 // CHECK2-NEXT: store i32** [[C_ADDR]], i32*** [[TMP1]], align 4 230 // CHECK2-NEXT: [[TMP2:%.*]] = getelementptr inbounds [1 x i8*], [1 x i8*]* [[CAPTURED_VARS_ADDRS]], i32 0, i32 0 231 // CHECK2-NEXT: [[TMP3:%.*]] = call i8* @__kmpc_alloc_shared(i32 4) 232 // CHECK2-NEXT: [[TMP4:%.*]] = load [[STRUCT_ANON_0]], %struct.anon.0* [[OMP_OUTLINED_ARG_AGG_]], align 4 233 // CHECK2-NEXT: [[TMP5:%.*]] = bitcast i8* [[TMP3]] to %struct.anon.0* 234 // CHECK2-NEXT: store [[STRUCT_ANON_0]] [[TMP4]], %struct.anon.0* [[TMP5]], align 4 235 // CHECK2-NEXT: store i8* [[TMP3]], i8** [[TMP2]], align 4 236 // CHECK2-NEXT: [[TMP6:%.*]] = bitcast [1 x i8*]* [[CAPTURED_VARS_ADDRS]] to i8** 237 // CHECK2-NEXT: call void @__kmpc_parallel_51(%struct.ident_t* @[[GLOB2]], i32 [[TMP0]], i32 1, i32 -1, i32 -1, i8* bitcast (void (i32*, i32*, %struct.anon.0*)* @__omp_outlined__1 to i8*), i8* bitcast (void (i16, i32)* @__omp_outlined__1_wrapper to i8*), i8** [[TMP6]], i32 1) 238 // CHECK2-NEXT: call void @__kmpc_free_shared(i8* [[TMP3]]) 239 // CHECK2-NEXT: ret void 240 // 241 // 242 // CHECK2-LABEL: define {{[^@]+}}@__omp_outlined__ 243 // CHECK2-SAME: (i32* noalias [[DOTGLOBAL_TID_:%.*]], i32* noalias [[DOTBOUND_TID_:%.*]], %struct.anon* noalias [[__CONTEXT:%.*]]) #[[ATTR0]] { 244 // CHECK2-NEXT: entry: 245 // CHECK2-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca i32*, align 4 246 // CHECK2-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca i32*, align 4 247 // CHECK2-NEXT: [[__CONTEXT_ADDR:%.*]] = alloca %struct.anon*, align 4 248 // CHECK2-NEXT: store i32* [[DOTGLOBAL_TID_]], i32** [[DOTGLOBAL_TID__ADDR]], align 4 249 // CHECK2-NEXT: store i32* [[DOTBOUND_TID_]], i32** [[DOTBOUND_TID__ADDR]], align 4 250 // CHECK2-NEXT: store %struct.anon* [[__CONTEXT]], %struct.anon** [[__CONTEXT_ADDR]], align 4 251 // CHECK2-NEXT: [[TMP0:%.*]] = load %struct.anon*, %struct.anon** [[__CONTEXT_ADDR]], align 4 252 // CHECK2-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT_ANON:%.*]], %struct.anon* [[TMP0]], i32 0, i32 0 253 // CHECK2-NEXT: [[TMP2:%.*]] = load i32*, i32** [[TMP1]], align 4 254 // CHECK2-NEXT: call void @_Z3usePi(i32* [[TMP2]]) #[[ATTR5]] 255 // CHECK2-NEXT: ret void 256 // 257 // 258 // CHECK2-LABEL: define {{[^@]+}}@__omp_outlined___wrapper 259 // CHECK2-SAME: (i16 zeroext [[TMP0:%.*]], i32 [[TMP1:%.*]]) #[[ATTR2:[0-9]+]] { 260 // CHECK2-NEXT: entry: 261 // CHECK2-NEXT: [[DOTADDR:%.*]] = alloca i16, align 2 262 // CHECK2-NEXT: [[DOTADDR1:%.*]] = alloca i32, align 4 263 // CHECK2-NEXT: [[DOTZERO_ADDR:%.*]] = alloca i32, align 4 264 // CHECK2-NEXT: [[GLOBAL_ARGS:%.*]] = alloca i8**, align 4 265 // CHECK2-NEXT: store i32 0, i32* [[DOTZERO_ADDR]], align 4 266 // CHECK2-NEXT: store i16 [[TMP0]], i16* [[DOTADDR]], align 2 267 // CHECK2-NEXT: store i32 [[TMP1]], i32* [[DOTADDR1]], align 4 268 // CHECK2-NEXT: call void @__kmpc_get_shared_variables(i8*** [[GLOBAL_ARGS]]) 269 // CHECK2-NEXT: [[TMP2:%.*]] = load i8**, i8*** [[GLOBAL_ARGS]], align 4 270 // CHECK2-NEXT: [[TMP3:%.*]] = getelementptr inbounds i8*, i8** [[TMP2]], i32 0 271 // CHECK2-NEXT: [[TMP4:%.*]] = bitcast i8** [[TMP3]] to %struct.anon** 272 // CHECK2-NEXT: [[TMP5:%.*]] = load %struct.anon*, %struct.anon** [[TMP4]], align 4 273 // CHECK2-NEXT: call void @__omp_outlined__(i32* [[DOTADDR1]], i32* [[DOTZERO_ADDR]], %struct.anon* [[TMP5]]) #[[ATTR3:[0-9]+]] 274 // CHECK2-NEXT: ret void 275 // 276 // 277 // CHECK2-LABEL: define {{[^@]+}}@__omp_outlined__1 278 // CHECK2-SAME: (i32* noalias [[DOTGLOBAL_TID_:%.*]], i32* noalias [[DOTBOUND_TID_:%.*]], %struct.anon.0* noalias [[__CONTEXT:%.*]]) #[[ATTR0]] { 279 // CHECK2-NEXT: entry: 280 // CHECK2-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca i32*, align 4 281 // CHECK2-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca i32*, align 4 282 // CHECK2-NEXT: [[__CONTEXT_ADDR:%.*]] = alloca %struct.anon.0*, align 4 283 // CHECK2-NEXT: store i32* [[DOTGLOBAL_TID_]], i32** [[DOTGLOBAL_TID__ADDR]], align 4 284 // CHECK2-NEXT: store i32* [[DOTBOUND_TID_]], i32** [[DOTBOUND_TID__ADDR]], align 4 285 // CHECK2-NEXT: store %struct.anon.0* [[__CONTEXT]], %struct.anon.0** [[__CONTEXT_ADDR]], align 4 286 // CHECK2-NEXT: [[TMP0:%.*]] = load %struct.anon.0*, %struct.anon.0** [[__CONTEXT_ADDR]], align 4 287 // CHECK2-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT_ANON_0:%.*]], %struct.anon.0* [[TMP0]], i32 0, i32 0 288 // CHECK2-NEXT: [[TMP2:%.*]] = load i32**, i32*** [[TMP1]], align 4 289 // CHECK2-NEXT: [[TMP3:%.*]] = load i32*, i32** [[TMP2]], align 4 290 // CHECK2-NEXT: call void @_Z4workPi(i32* [[TMP3]]) #[[ATTR5]] 291 // CHECK2-NEXT: ret void 292 // 293 // 294 // CHECK2-LABEL: define {{[^@]+}}@_Z4workPi 295 // CHECK2-SAME: (i32* [[C:%.*]]) #[[ATTR1]] { 296 // CHECK2-NEXT: entry: 297 // CHECK2-NEXT: [[C_ADDR:%.*]] = alloca i32*, align 4 298 // CHECK2-NEXT: [[ATOMIC_TEMP:%.*]] = alloca i32, align 4 299 // CHECK2-NEXT: [[ATOMIC_TEMP1:%.*]] = alloca i32, align 4 300 // CHECK2-NEXT: store i32* [[C]], i32** [[C_ADDR]], align 4 301 // CHECK2-NEXT: [[TMP0:%.*]] = load i32*, i32** [[C_ADDR]], align 4 302 // CHECK2-NEXT: [[TMP1:%.*]] = bitcast i32* [[TMP0]] to i8* 303 // CHECK2-NEXT: [[TMP2:%.*]] = bitcast i32* [[ATOMIC_TEMP]] to i8* 304 // CHECK2-NEXT: call void @__atomic_load(i32 4, i8* [[TMP1]], i8* [[TMP2]], i32 0) #[[ATTR5]] 305 // CHECK2-NEXT: br label [[ATOMIC_CONT:%.*]] 306 // CHECK2: atomic_cont: 307 // CHECK2-NEXT: [[TMP3:%.*]] = load i32, i32* [[ATOMIC_TEMP]], align 4 308 // CHECK2-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP3]], 1 309 // CHECK2-NEXT: store i32 [[ADD]], i32* [[ATOMIC_TEMP1]], align 4 310 // CHECK2-NEXT: [[TMP4:%.*]] = bitcast i32* [[TMP0]] to i8* 311 // CHECK2-NEXT: [[TMP5:%.*]] = bitcast i32* [[ATOMIC_TEMP]] to i8* 312 // CHECK2-NEXT: [[TMP6:%.*]] = bitcast i32* [[ATOMIC_TEMP1]] to i8* 313 // CHECK2-NEXT: [[CALL:%.*]] = call zeroext i1 @__atomic_compare_exchange(i32 4, i8* [[TMP4]], i8* [[TMP5]], i8* [[TMP6]], i32 0, i32 0) #[[ATTR5]] 314 // CHECK2-NEXT: br i1 [[CALL]], label [[ATOMIC_EXIT:%.*]], label [[ATOMIC_CONT]] 315 // CHECK2: atomic_exit: 316 // CHECK2-NEXT: ret void 317 // 318 // 319 // CHECK2-LABEL: define {{[^@]+}}@__omp_outlined__1_wrapper 320 // CHECK2-SAME: (i16 zeroext [[TMP0:%.*]], i32 [[TMP1:%.*]]) #[[ATTR2]] { 321 // CHECK2-NEXT: entry: 322 // CHECK2-NEXT: [[DOTADDR:%.*]] = alloca i16, align 2 323 // CHECK2-NEXT: [[DOTADDR1:%.*]] = alloca i32, align 4 324 // CHECK2-NEXT: [[DOTZERO_ADDR:%.*]] = alloca i32, align 4 325 // CHECK2-NEXT: [[GLOBAL_ARGS:%.*]] = alloca i8**, align 4 326 // CHECK2-NEXT: store i32 0, i32* [[DOTZERO_ADDR]], align 4 327 // CHECK2-NEXT: store i16 [[TMP0]], i16* [[DOTADDR]], align 2 328 // CHECK2-NEXT: store i32 [[TMP1]], i32* [[DOTADDR1]], align 4 329 // CHECK2-NEXT: call void @__kmpc_get_shared_variables(i8*** [[GLOBAL_ARGS]]) 330 // CHECK2-NEXT: [[TMP2:%.*]] = load i8**, i8*** [[GLOBAL_ARGS]], align 4 331 // CHECK2-NEXT: [[TMP3:%.*]] = getelementptr inbounds i8*, i8** [[TMP2]], i32 0 332 // CHECK2-NEXT: [[TMP4:%.*]] = bitcast i8** [[TMP3]] to %struct.anon.0** 333 // CHECK2-NEXT: [[TMP5:%.*]] = load %struct.anon.0*, %struct.anon.0** [[TMP4]], align 4 334 // CHECK2-NEXT: call void @__omp_outlined__1(i32* [[DOTADDR1]], i32* [[DOTZERO_ADDR]], %struct.anon.0* [[TMP5]]) #[[ATTR3]] 335 // CHECK2-NEXT: ret void 336 // 337 // 338 // CHECK3-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l25 339 // CHECK3-SAME: (i32* nonnull align 4 dereferenceable(4) [[C:%.*]]) #[[ATTR0:[0-9]+]] { 340 // CHECK3-NEXT: entry: 341 // CHECK3-NEXT: [[C_ADDR:%.*]] = alloca i32*, align 4 342 // CHECK3-NEXT: [[OMP_OUTLINED_ARG_AGG_:%.*]] = alloca [[STRUCT_ANON:%.*]], align 4 343 // CHECK3-NEXT: [[CAPTURED_VARS_ADDRS:%.*]] = alloca [1 x i8*], align 4 344 // CHECK3-NEXT: store i32* [[C]], i32** [[C_ADDR]], align 4 345 // CHECK3-NEXT: [[TMP0:%.*]] = load i32*, i32** [[C_ADDR]], align 4 346 // CHECK3-NEXT: [[TMP1:%.*]] = call i32 @__kmpc_target_init(%struct.ident_t* @[[GLOB1:[0-9]+]], i1 false, i1 true, i1 true) 347 // CHECK3-NEXT: [[EXEC_USER_CODE:%.*]] = icmp eq i32 [[TMP1]], -1 348 // CHECK3-NEXT: br i1 [[EXEC_USER_CODE]], label [[USER_CODE_ENTRY:%.*]], label [[WORKER_EXIT:%.*]] 349 // CHECK3: user_code.entry: 350 // CHECK3-NEXT: [[TMP2:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* @[[GLOB1]]) 351 // CHECK3-NEXT: call void @_Z3usePi(i32* [[TMP0]]) #[[ATTR5:[0-9]+]] 352 // CHECK3-NEXT: call void @__kmpc_push_num_threads(%struct.ident_t* @[[GLOB1]], i32 [[TMP2]], i32 2) 353 // CHECK3-NEXT: [[TMP3:%.*]] = getelementptr inbounds [[STRUCT_ANON]], %struct.anon* [[OMP_OUTLINED_ARG_AGG_]], i32 0, i32 0 354 // CHECK3-NEXT: store i32* [[TMP0]], i32** [[TMP3]], align 4 355 // CHECK3-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x i8*], [1 x i8*]* [[CAPTURED_VARS_ADDRS]], i32 0, i32 0 356 // CHECK3-NEXT: [[TMP5:%.*]] = call i8* @__kmpc_alloc_shared(i32 4) 357 // CHECK3-NEXT: [[TMP6:%.*]] = load [[STRUCT_ANON]], %struct.anon* [[OMP_OUTLINED_ARG_AGG_]], align 4 358 // CHECK3-NEXT: [[TMP7:%.*]] = bitcast i8* [[TMP5]] to %struct.anon* 359 // CHECK3-NEXT: store [[STRUCT_ANON]] [[TMP6]], %struct.anon* [[TMP7]], align 4 360 // CHECK3-NEXT: store i8* [[TMP5]], i8** [[TMP4]], align 4 361 // CHECK3-NEXT: [[TMP8:%.*]] = bitcast [1 x i8*]* [[CAPTURED_VARS_ADDRS]] to i8** 362 // CHECK3-NEXT: call void @__kmpc_parallel_51(%struct.ident_t* @[[GLOB1]], i32 [[TMP2]], i32 1, i32 -1, i32 -1, i8* bitcast (void (i32*, i32*, %struct.anon*)* @__omp_outlined__ to i8*), i8* bitcast (void (i16, i32)* @__omp_outlined___wrapper to i8*), i8** [[TMP8]], i32 1) 363 // CHECK3-NEXT: call void @__kmpc_free_shared(i8* [[TMP5]]) 364 // CHECK3-NEXT: call void @__kmpc_target_deinit(%struct.ident_t* @[[GLOB1]], i1 false, i1 true) 365 // CHECK3-NEXT: ret void 366 // CHECK3: worker.exit: 367 // CHECK3-NEXT: ret void 368 // 369 // 370 // CHECK3-LABEL: define {{[^@]+}}@_Z3usePi 371 // CHECK3-SAME: (i32* [[C:%.*]]) #[[ATTR1:[0-9]+]] { 372 // CHECK3-NEXT: entry: 373 // CHECK3-NEXT: [[C_ADDR:%.*]] = alloca i32*, align 4 374 // CHECK3-NEXT: [[OMP_OUTLINED_ARG_AGG_:%.*]] = alloca [[STRUCT_ANON_0:%.*]], align 4 375 // CHECK3-NEXT: [[CAPTURED_VARS_ADDRS:%.*]] = alloca [1 x i8*], align 4 376 // CHECK3-NEXT: [[TMP0:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* @[[GLOB2:[0-9]+]]) 377 // CHECK3-NEXT: store i32* [[C]], i32** [[C_ADDR]], align 4 378 // CHECK3-NEXT: call void @__kmpc_push_num_threads(%struct.ident_t* @[[GLOB2]], i32 [[TMP0]], i32 2) 379 // CHECK3-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT_ANON_0]], %struct.anon.0* [[OMP_OUTLINED_ARG_AGG_]], i32 0, i32 0 380 // CHECK3-NEXT: store i32** [[C_ADDR]], i32*** [[TMP1]], align 4 381 // CHECK3-NEXT: [[TMP2:%.*]] = getelementptr inbounds [1 x i8*], [1 x i8*]* [[CAPTURED_VARS_ADDRS]], i32 0, i32 0 382 // CHECK3-NEXT: [[TMP3:%.*]] = call i8* @__kmpc_alloc_shared(i32 4) 383 // CHECK3-NEXT: [[TMP4:%.*]] = load [[STRUCT_ANON_0]], %struct.anon.0* [[OMP_OUTLINED_ARG_AGG_]], align 4 384 // CHECK3-NEXT: [[TMP5:%.*]] = bitcast i8* [[TMP3]] to %struct.anon.0* 385 // CHECK3-NEXT: store [[STRUCT_ANON_0]] [[TMP4]], %struct.anon.0* [[TMP5]], align 4 386 // CHECK3-NEXT: store i8* [[TMP3]], i8** [[TMP2]], align 4 387 // CHECK3-NEXT: [[TMP6:%.*]] = bitcast [1 x i8*]* [[CAPTURED_VARS_ADDRS]] to i8** 388 // CHECK3-NEXT: call void @__kmpc_parallel_51(%struct.ident_t* @[[GLOB2]], i32 [[TMP0]], i32 1, i32 -1, i32 -1, i8* bitcast (void (i32*, i32*, %struct.anon.0*)* @__omp_outlined__1 to i8*), i8* bitcast (void (i16, i32)* @__omp_outlined__1_wrapper to i8*), i8** [[TMP6]], i32 1) 389 // CHECK3-NEXT: call void @__kmpc_free_shared(i8* [[TMP3]]) 390 // CHECK3-NEXT: ret void 391 // 392 // 393 // CHECK3-LABEL: define {{[^@]+}}@__omp_outlined__ 394 // CHECK3-SAME: (i32* noalias [[DOTGLOBAL_TID_:%.*]], i32* noalias [[DOTBOUND_TID_:%.*]], %struct.anon* noalias [[__CONTEXT:%.*]]) #[[ATTR0]] { 395 // CHECK3-NEXT: entry: 396 // CHECK3-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca i32*, align 4 397 // CHECK3-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca i32*, align 4 398 // CHECK3-NEXT: [[__CONTEXT_ADDR:%.*]] = alloca %struct.anon*, align 4 399 // CHECK3-NEXT: store i32* [[DOTGLOBAL_TID_]], i32** [[DOTGLOBAL_TID__ADDR]], align 4 400 // CHECK3-NEXT: store i32* [[DOTBOUND_TID_]], i32** [[DOTBOUND_TID__ADDR]], align 4 401 // CHECK3-NEXT: store %struct.anon* [[__CONTEXT]], %struct.anon** [[__CONTEXT_ADDR]], align 4 402 // CHECK3-NEXT: [[TMP0:%.*]] = load %struct.anon*, %struct.anon** [[__CONTEXT_ADDR]], align 4 403 // CHECK3-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT_ANON:%.*]], %struct.anon* [[TMP0]], i32 0, i32 0 404 // CHECK3-NEXT: [[TMP2:%.*]] = load i32*, i32** [[TMP1]], align 4 405 // CHECK3-NEXT: call void @_Z3usePi(i32* [[TMP2]]) #[[ATTR5]] 406 // CHECK3-NEXT: ret void 407 // 408 // 409 // CHECK3-LABEL: define {{[^@]+}}@__omp_outlined___wrapper 410 // CHECK3-SAME: (i16 zeroext [[TMP0:%.*]], i32 [[TMP1:%.*]]) #[[ATTR2:[0-9]+]] { 411 // CHECK3-NEXT: entry: 412 // CHECK3-NEXT: [[DOTADDR:%.*]] = alloca i16, align 2 413 // CHECK3-NEXT: [[DOTADDR1:%.*]] = alloca i32, align 4 414 // CHECK3-NEXT: [[DOTZERO_ADDR:%.*]] = alloca i32, align 4 415 // CHECK3-NEXT: [[GLOBAL_ARGS:%.*]] = alloca i8**, align 4 416 // CHECK3-NEXT: store i32 0, i32* [[DOTZERO_ADDR]], align 4 417 // CHECK3-NEXT: store i16 [[TMP0]], i16* [[DOTADDR]], align 2 418 // CHECK3-NEXT: store i32 [[TMP1]], i32* [[DOTADDR1]], align 4 419 // CHECK3-NEXT: call void @__kmpc_get_shared_variables(i8*** [[GLOBAL_ARGS]]) 420 // CHECK3-NEXT: [[TMP2:%.*]] = load i8**, i8*** [[GLOBAL_ARGS]], align 4 421 // CHECK3-NEXT: [[TMP3:%.*]] = getelementptr inbounds i8*, i8** [[TMP2]], i32 0 422 // CHECK3-NEXT: [[TMP4:%.*]] = bitcast i8** [[TMP3]] to %struct.anon** 423 // CHECK3-NEXT: [[TMP5:%.*]] = load %struct.anon*, %struct.anon** [[TMP4]], align 4 424 // CHECK3-NEXT: call void @__omp_outlined__(i32* [[DOTADDR1]], i32* [[DOTZERO_ADDR]], %struct.anon* [[TMP5]]) #[[ATTR3:[0-9]+]] 425 // CHECK3-NEXT: ret void 426 // 427 // 428 // CHECK3-LABEL: define {{[^@]+}}@__omp_outlined__1 429 // CHECK3-SAME: (i32* noalias [[DOTGLOBAL_TID_:%.*]], i32* noalias [[DOTBOUND_TID_:%.*]], %struct.anon.0* noalias [[__CONTEXT:%.*]]) #[[ATTR0]] { 430 // CHECK3-NEXT: entry: 431 // CHECK3-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca i32*, align 4 432 // CHECK3-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca i32*, align 4 433 // CHECK3-NEXT: [[__CONTEXT_ADDR:%.*]] = alloca %struct.anon.0*, align 4 434 // CHECK3-NEXT: store i32* [[DOTGLOBAL_TID_]], i32** [[DOTGLOBAL_TID__ADDR]], align 4 435 // CHECK3-NEXT: store i32* [[DOTBOUND_TID_]], i32** [[DOTBOUND_TID__ADDR]], align 4 436 // CHECK3-NEXT: store %struct.anon.0* [[__CONTEXT]], %struct.anon.0** [[__CONTEXT_ADDR]], align 4 437 // CHECK3-NEXT: [[TMP0:%.*]] = load %struct.anon.0*, %struct.anon.0** [[__CONTEXT_ADDR]], align 4 438 // CHECK3-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT_ANON_0:%.*]], %struct.anon.0* [[TMP0]], i32 0, i32 0 439 // CHECK3-NEXT: [[TMP2:%.*]] = load i32**, i32*** [[TMP1]], align 4 440 // CHECK3-NEXT: [[TMP3:%.*]] = load i32*, i32** [[TMP2]], align 4 441 // CHECK3-NEXT: call void @_Z4workPi(i32* [[TMP3]]) #[[ATTR5]] 442 // CHECK3-NEXT: ret void 443 // 444 // 445 // CHECK3-LABEL: define {{[^@]+}}@_Z4workPi 446 // CHECK3-SAME: (i32* [[C:%.*]]) #[[ATTR1]] { 447 // CHECK3-NEXT: entry: 448 // CHECK3-NEXT: [[C_ADDR:%.*]] = alloca i32*, align 4 449 // CHECK3-NEXT: [[ATOMIC_TEMP:%.*]] = alloca i32, align 4 450 // CHECK3-NEXT: [[ATOMIC_TEMP1:%.*]] = alloca i32, align 4 451 // CHECK3-NEXT: store i32* [[C]], i32** [[C_ADDR]], align 4 452 // CHECK3-NEXT: [[TMP0:%.*]] = load i32*, i32** [[C_ADDR]], align 4 453 // CHECK3-NEXT: [[TMP1:%.*]] = bitcast i32* [[TMP0]] to i8* 454 // CHECK3-NEXT: [[TMP2:%.*]] = bitcast i32* [[ATOMIC_TEMP]] to i8* 455 // CHECK3-NEXT: call void @__atomic_load(i32 4, i8* [[TMP1]], i8* [[TMP2]], i32 0) #[[ATTR5]] 456 // CHECK3-NEXT: br label [[ATOMIC_CONT:%.*]] 457 // CHECK3: atomic_cont: 458 // CHECK3-NEXT: [[TMP3:%.*]] = load i32, i32* [[ATOMIC_TEMP]], align 4 459 // CHECK3-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP3]], 1 460 // CHECK3-NEXT: store i32 [[ADD]], i32* [[ATOMIC_TEMP1]], align 4 461 // CHECK3-NEXT: [[TMP4:%.*]] = bitcast i32* [[TMP0]] to i8* 462 // CHECK3-NEXT: [[TMP5:%.*]] = bitcast i32* [[ATOMIC_TEMP]] to i8* 463 // CHECK3-NEXT: [[TMP6:%.*]] = bitcast i32* [[ATOMIC_TEMP1]] to i8* 464 // CHECK3-NEXT: [[CALL:%.*]] = call zeroext i1 @__atomic_compare_exchange(i32 4, i8* [[TMP4]], i8* [[TMP5]], i8* [[TMP6]], i32 0, i32 0) #[[ATTR5]] 465 // CHECK3-NEXT: br i1 [[CALL]], label [[ATOMIC_EXIT:%.*]], label [[ATOMIC_CONT]] 466 // CHECK3: atomic_exit: 467 // CHECK3-NEXT: ret void 468 // 469 // 470 // CHECK3-LABEL: define {{[^@]+}}@__omp_outlined__1_wrapper 471 // CHECK3-SAME: (i16 zeroext [[TMP0:%.*]], i32 [[TMP1:%.*]]) #[[ATTR2]] { 472 // CHECK3-NEXT: entry: 473 // CHECK3-NEXT: [[DOTADDR:%.*]] = alloca i16, align 2 474 // CHECK3-NEXT: [[DOTADDR1:%.*]] = alloca i32, align 4 475 // CHECK3-NEXT: [[DOTZERO_ADDR:%.*]] = alloca i32, align 4 476 // CHECK3-NEXT: [[GLOBAL_ARGS:%.*]] = alloca i8**, align 4 477 // CHECK3-NEXT: store i32 0, i32* [[DOTZERO_ADDR]], align 4 478 // CHECK3-NEXT: store i16 [[TMP0]], i16* [[DOTADDR]], align 2 479 // CHECK3-NEXT: store i32 [[TMP1]], i32* [[DOTADDR1]], align 4 480 // CHECK3-NEXT: call void @__kmpc_get_shared_variables(i8*** [[GLOBAL_ARGS]]) 481 // CHECK3-NEXT: [[TMP2:%.*]] = load i8**, i8*** [[GLOBAL_ARGS]], align 4 482 // CHECK3-NEXT: [[TMP3:%.*]] = getelementptr inbounds i8*, i8** [[TMP2]], i32 0 483 // CHECK3-NEXT: [[TMP4:%.*]] = bitcast i8** [[TMP3]] to %struct.anon.0** 484 // CHECK3-NEXT: [[TMP5:%.*]] = load %struct.anon.0*, %struct.anon.0** [[TMP4]], align 4 485 // CHECK3-NEXT: call void @__omp_outlined__1(i32* [[DOTADDR1]], i32* [[DOTZERO_ADDR]], %struct.anon.0* [[TMP5]]) #[[ATTR3]] 486 // CHECK3-NEXT: ret void 487 // 488