1// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --check-globals --include-generated-funcs 2// Check that the CHECK lines are generated for clang-generated functions 3// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fopenmp %s -emit-llvm -o - | FileCheck --check-prefix=OMP %s 4// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu %s -emit-llvm -o - | FileCheck --check-prefix=NOOMP %s 5 6const int size = 1024 * 1024 * 32; 7 8double A[size]; 9 10void foo(void); 11 12int main(void) { 13 int i = 0; 14 15#pragma omp parallel for 16 for (i = 0; i < size; ++i) { 17 A[i] = 0.0; 18 } 19 20 foo(); 21 22 return 0; 23} 24 25void foo(void) { 26 int i = 0; 27 28#pragma omp parallel for 29 for (i = 0; i < size; ++i) { 30 A[i] = 1.0; 31 } 32} 33//. 34// OMP: @A = global [33554432 x double] zeroinitializer, align 16 35// OMP: @size = constant i32 33554432, align 4 36// OMP: @[[GLOB0:[0-9]+]] = private unnamed_addr constant [23 x i8] c" 37// OMP: @[[GLOB1:[0-9]+]] = private unnamed_addr constant %struct.ident_t { i32 0, i32 514, i32 0, i32 22, ptr @[[GLOB0]] }, align 8 38// OMP: @[[GLOB2:[0-9]+]] = private unnamed_addr constant %struct.ident_t { i32 0, i32 2, i32 0, i32 22, ptr @[[GLOB0]] }, align 8 39//. 40// NOOMP: @size = constant i32 33554432, align 4 41// NOOMP: @A = global [33554432 x double] zeroinitializer, align 16 42//. 43// OMP-LABEL: @main( 44// OMP-NEXT: entry: 45// OMP-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 46// OMP-NEXT: [[I:%.*]] = alloca i32, align 4 47// OMP-NEXT: store i32 0, ptr [[RETVAL]], align 4 48// OMP-NEXT: store i32 0, ptr [[I]], align 4 49// OMP-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @[[GLOB2]], i32 0, ptr @main.omp_outlined) 50// OMP-NEXT: call void @foo() 51// OMP-NEXT: ret i32 0 52// 53// 54// OMP-LABEL: @main.omp_outlined( 55// OMP-NEXT: entry: 56// OMP-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 8 57// OMP-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca ptr, align 8 58// OMP-NEXT: [[DOTOMP_IV:%.*]] = alloca i32, align 4 59// OMP-NEXT: [[TMP:%.*]] = alloca i32, align 4 60// OMP-NEXT: [[DOTOMP_LB:%.*]] = alloca i32, align 4 61// OMP-NEXT: [[DOTOMP_UB:%.*]] = alloca i32, align 4 62// OMP-NEXT: [[DOTOMP_STRIDE:%.*]] = alloca i32, align 4 63// OMP-NEXT: [[DOTOMP_IS_LAST:%.*]] = alloca i32, align 4 64// OMP-NEXT: [[I:%.*]] = alloca i32, align 4 65// OMP-NEXT: store ptr [[DOTGLOBAL_TID_:%.*]], ptr [[DOTGLOBAL_TID__ADDR]], align 8 66// OMP-NEXT: store ptr [[DOTBOUND_TID_:%.*]], ptr [[DOTBOUND_TID__ADDR]], align 8 67// OMP-NEXT: store i32 0, ptr [[DOTOMP_LB]], align 4 68// OMP-NEXT: store i32 33554431, ptr [[DOTOMP_UB]], align 4 69// OMP-NEXT: store i32 1, ptr [[DOTOMP_STRIDE]], align 4 70// OMP-NEXT: store i32 0, ptr [[DOTOMP_IS_LAST]], align 4 71// OMP-NEXT: [[TMP0:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 72// OMP-NEXT: [[TMP1:%.*]] = load i32, ptr [[TMP0]], align 4 73// OMP-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB1]], i32 [[TMP1]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) 74// OMP-NEXT: [[TMP2:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4 75// OMP-NEXT: [[CMP:%.*]] = icmp sgt i32 [[TMP2]], 33554431 76// OMP-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] 77// OMP: cond.true: 78// OMP-NEXT: br label [[COND_END:%.*]] 79// OMP: cond.false: 80// OMP-NEXT: [[TMP3:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4 81// OMP-NEXT: br label [[COND_END]] 82// OMP: cond.end: 83// OMP-NEXT: [[COND:%.*]] = phi i32 [ 33554431, [[COND_TRUE]] ], [ [[TMP3]], [[COND_FALSE]] ] 84// OMP-NEXT: store i32 [[COND]], ptr [[DOTOMP_UB]], align 4 85// OMP-NEXT: [[TMP4:%.*]] = load i32, ptr [[DOTOMP_LB]], align 4 86// OMP-NEXT: store i32 [[TMP4]], ptr [[DOTOMP_IV]], align 4 87// OMP-NEXT: br label [[OMP_INNER_FOR_COND:%.*]] 88// OMP: omp.inner.for.cond: 89// OMP-NEXT: [[TMP5:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4 90// OMP-NEXT: [[TMP6:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4 91// OMP-NEXT: [[CMP1:%.*]] = icmp sle i32 [[TMP5]], [[TMP6]] 92// OMP-NEXT: br i1 [[CMP1]], label [[OMP_INNER_FOR_BODY:%.*]], label [[OMP_INNER_FOR_END:%.*]] 93// OMP: omp.inner.for.body: 94// OMP-NEXT: [[TMP7:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4 95// OMP-NEXT: [[MUL:%.*]] = mul nsw i32 [[TMP7]], 1 96// OMP-NEXT: [[ADD:%.*]] = add nsw i32 0, [[MUL]] 97// OMP-NEXT: store i32 [[ADD]], ptr [[I]], align 4 98// OMP-NEXT: [[TMP8:%.*]] = load i32, ptr [[I]], align 4 99// OMP-NEXT: [[IDXPROM:%.*]] = sext i32 [[TMP8]] to i64 100// OMP-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [33554432 x double], ptr @A, i64 0, i64 [[IDXPROM]] 101// OMP-NEXT: store double 0.000000e+00, ptr [[ARRAYIDX]], align 8 102// OMP-NEXT: br label [[OMP_BODY_CONTINUE:%.*]] 103// OMP: omp.body.continue: 104// OMP-NEXT: br label [[OMP_INNER_FOR_INC:%.*]] 105// OMP: omp.inner.for.inc: 106// OMP-NEXT: [[TMP9:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4 107// OMP-NEXT: [[ADD2:%.*]] = add nsw i32 [[TMP9]], 1 108// OMP-NEXT: store i32 [[ADD2]], ptr [[DOTOMP_IV]], align 4 109// OMP-NEXT: br label [[OMP_INNER_FOR_COND]] 110// OMP: omp.inner.for.end: 111// OMP-NEXT: br label [[OMP_LOOP_EXIT:%.*]] 112// OMP: omp.loop.exit: 113// OMP-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP1]]) 114// OMP-NEXT: ret void 115// 116// 117// OMP-LABEL: @foo( 118// OMP-NEXT: entry: 119// OMP-NEXT: [[I:%.*]] = alloca i32, align 4 120// OMP-NEXT: store i32 0, ptr [[I]], align 4 121// OMP-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @[[GLOB2]], i32 0, ptr @foo.omp_outlined) 122// OMP-NEXT: ret void 123// 124// 125// OMP-LABEL: @foo.omp_outlined( 126// OMP-NEXT: entry: 127// OMP-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 8 128// OMP-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca ptr, align 8 129// OMP-NEXT: [[DOTOMP_IV:%.*]] = alloca i32, align 4 130// OMP-NEXT: [[TMP:%.*]] = alloca i32, align 4 131// OMP-NEXT: [[DOTOMP_LB:%.*]] = alloca i32, align 4 132// OMP-NEXT: [[DOTOMP_UB:%.*]] = alloca i32, align 4 133// OMP-NEXT: [[DOTOMP_STRIDE:%.*]] = alloca i32, align 4 134// OMP-NEXT: [[DOTOMP_IS_LAST:%.*]] = alloca i32, align 4 135// OMP-NEXT: [[I:%.*]] = alloca i32, align 4 136// OMP-NEXT: store ptr [[DOTGLOBAL_TID_:%.*]], ptr [[DOTGLOBAL_TID__ADDR]], align 8 137// OMP-NEXT: store ptr [[DOTBOUND_TID_:%.*]], ptr [[DOTBOUND_TID__ADDR]], align 8 138// OMP-NEXT: store i32 0, ptr [[DOTOMP_LB]], align 4 139// OMP-NEXT: store i32 33554431, ptr [[DOTOMP_UB]], align 4 140// OMP-NEXT: store i32 1, ptr [[DOTOMP_STRIDE]], align 4 141// OMP-NEXT: store i32 0, ptr [[DOTOMP_IS_LAST]], align 4 142// OMP-NEXT: [[TMP0:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 143// OMP-NEXT: [[TMP1:%.*]] = load i32, ptr [[TMP0]], align 4 144// OMP-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB1]], i32 [[TMP1]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) 145// OMP-NEXT: [[TMP2:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4 146// OMP-NEXT: [[CMP:%.*]] = icmp sgt i32 [[TMP2]], 33554431 147// OMP-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] 148// OMP: cond.true: 149// OMP-NEXT: br label [[COND_END:%.*]] 150// OMP: cond.false: 151// OMP-NEXT: [[TMP3:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4 152// OMP-NEXT: br label [[COND_END]] 153// OMP: cond.end: 154// OMP-NEXT: [[COND:%.*]] = phi i32 [ 33554431, [[COND_TRUE]] ], [ [[TMP3]], [[COND_FALSE]] ] 155// OMP-NEXT: store i32 [[COND]], ptr [[DOTOMP_UB]], align 4 156// OMP-NEXT: [[TMP4:%.*]] = load i32, ptr [[DOTOMP_LB]], align 4 157// OMP-NEXT: store i32 [[TMP4]], ptr [[DOTOMP_IV]], align 4 158// OMP-NEXT: br label [[OMP_INNER_FOR_COND:%.*]] 159// OMP: omp.inner.for.cond: 160// OMP-NEXT: [[TMP5:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4 161// OMP-NEXT: [[TMP6:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4 162// OMP-NEXT: [[CMP1:%.*]] = icmp sle i32 [[TMP5]], [[TMP6]] 163// OMP-NEXT: br i1 [[CMP1]], label [[OMP_INNER_FOR_BODY:%.*]], label [[OMP_INNER_FOR_END:%.*]] 164// OMP: omp.inner.for.body: 165// OMP-NEXT: [[TMP7:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4 166// OMP-NEXT: [[MUL:%.*]] = mul nsw i32 [[TMP7]], 1 167// OMP-NEXT: [[ADD:%.*]] = add nsw i32 0, [[MUL]] 168// OMP-NEXT: store i32 [[ADD]], ptr [[I]], align 4 169// OMP-NEXT: [[TMP8:%.*]] = load i32, ptr [[I]], align 4 170// OMP-NEXT: [[IDXPROM:%.*]] = sext i32 [[TMP8]] to i64 171// OMP-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [33554432 x double], ptr @A, i64 0, i64 [[IDXPROM]] 172// OMP-NEXT: store double 1.000000e+00, ptr [[ARRAYIDX]], align 8 173// OMP-NEXT: br label [[OMP_BODY_CONTINUE:%.*]] 174// OMP: omp.body.continue: 175// OMP-NEXT: br label [[OMP_INNER_FOR_INC:%.*]] 176// OMP: omp.inner.for.inc: 177// OMP-NEXT: [[TMP9:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4 178// OMP-NEXT: [[ADD2:%.*]] = add nsw i32 [[TMP9]], 1 179// OMP-NEXT: store i32 [[ADD2]], ptr [[DOTOMP_IV]], align 4 180// OMP-NEXT: br label [[OMP_INNER_FOR_COND]] 181// OMP: omp.inner.for.end: 182// OMP-NEXT: br label [[OMP_LOOP_EXIT:%.*]] 183// OMP: omp.loop.exit: 184// OMP-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP1]]) 185// OMP-NEXT: ret void 186// 187// 188// NOOMP-LABEL: @main( 189// NOOMP-NEXT: entry: 190// NOOMP-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 191// NOOMP-NEXT: [[I:%.*]] = alloca i32, align 4 192// NOOMP-NEXT: store i32 0, ptr [[RETVAL]], align 4 193// NOOMP-NEXT: store i32 0, ptr [[I]], align 4 194// NOOMP-NEXT: store i32 0, ptr [[I]], align 4 195// NOOMP-NEXT: br label [[FOR_COND:%.*]] 196// NOOMP: for.cond: 197// NOOMP-NEXT: [[TMP0:%.*]] = load i32, ptr [[I]], align 4 198// NOOMP-NEXT: [[CMP:%.*]] = icmp slt i32 [[TMP0]], 33554432 199// NOOMP-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]] 200// NOOMP: for.body: 201// NOOMP-NEXT: [[TMP1:%.*]] = load i32, ptr [[I]], align 4 202// NOOMP-NEXT: [[IDXPROM:%.*]] = sext i32 [[TMP1]] to i64 203// NOOMP-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [33554432 x double], ptr @A, i64 0, i64 [[IDXPROM]] 204// NOOMP-NEXT: store double 0.000000e+00, ptr [[ARRAYIDX]], align 8 205// NOOMP-NEXT: br label [[FOR_INC:%.*]] 206// NOOMP: for.inc: 207// NOOMP-NEXT: [[TMP2:%.*]] = load i32, ptr [[I]], align 4 208// NOOMP-NEXT: [[INC:%.*]] = add nsw i32 [[TMP2]], 1 209// NOOMP-NEXT: store i32 [[INC]], ptr [[I]], align 4 210// NOOMP-NEXT: br label [[FOR_COND]], !llvm.loop [[LOOP2:![0-9]+]] 211// NOOMP: for.end: 212// NOOMP-NEXT: call void @foo() 213// NOOMP-NEXT: ret i32 0 214// 215// 216// NOOMP-LABEL: @foo( 217// NOOMP-NEXT: entry: 218// NOOMP-NEXT: [[I:%.*]] = alloca i32, align 4 219// NOOMP-NEXT: store i32 0, ptr [[I]], align 4 220// NOOMP-NEXT: store i32 0, ptr [[I]], align 4 221// NOOMP-NEXT: br label [[FOR_COND:%.*]] 222// NOOMP: for.cond: 223// NOOMP-NEXT: [[TMP0:%.*]] = load i32, ptr [[I]], align 4 224// NOOMP-NEXT: [[CMP:%.*]] = icmp slt i32 [[TMP0]], 33554432 225// NOOMP-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]] 226// NOOMP: for.body: 227// NOOMP-NEXT: [[TMP1:%.*]] = load i32, ptr [[I]], align 4 228// NOOMP-NEXT: [[IDXPROM:%.*]] = sext i32 [[TMP1]] to i64 229// NOOMP-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [33554432 x double], ptr @A, i64 0, i64 [[IDXPROM]] 230// NOOMP-NEXT: store double 1.000000e+00, ptr [[ARRAYIDX]], align 8 231// NOOMP-NEXT: br label [[FOR_INC:%.*]] 232// NOOMP: for.inc: 233// NOOMP-NEXT: [[TMP2:%.*]] = load i32, ptr [[I]], align 4 234// NOOMP-NEXT: [[INC:%.*]] = add nsw i32 [[TMP2]], 1 235// NOOMP-NEXT: store i32 [[INC]], ptr [[I]], align 4 236// NOOMP-NEXT: br label [[FOR_COND]], !llvm.loop [[LOOP4:![0-9]+]] 237// NOOMP: for.end: 238// NOOMP-NEXT: ret void 239// 240//. 241// OMP: attributes #[[ATTR0:[0-9]+]] = { noinline nounwind optnone "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+cx8,+mmx,+sse,+sse2,+x87" } 242// OMP: attributes #[[ATTR1:[0-9]+]] = { noinline norecurse nounwind optnone "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+cx8,+mmx,+sse,+sse2,+x87" } 243// OMP: attributes #[[ATTR2:[0-9]+]] = { nounwind } 244//. 245// NOOMP: attributes #[[ATTR0:[0-9]+]] = { noinline nounwind optnone "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+cx8,+mmx,+sse,+sse2,+x87" } 246//. 247// OMP: [[META0:![0-9]+]] = !{i32 1, !"wchar_size", i32 4} 248// OMP: [[META1:![0-9]+]] = !{i32 7, !"openmp", i32 51} 249// OMP: [[META2:![0-9]+]] = !{!"{{.*}}clang version {{.*}}"} 250// OMP: [[META3:![0-9]+]] = !{[[META4:![0-9]+]]} 251// OMP: [[META4]] = !{i64 2, i64 -1, i64 -1, i1 true} 252//. 253// NOOMP: [[META0:![0-9]+]] = !{i32 1, !"wchar_size", i32 4} 254// NOOMP: [[META1:![0-9]+]] = !{!"{{.*}}clang version {{.*}}"} 255// NOOMP: [[LOOP2]] = distinct !{[[LOOP2]], [[META3:![0-9]+]]} 256// NOOMP: [[META3]] = !{!"llvm.loop.mustprogress"} 257// NOOMP: [[LOOP4]] = distinct !{[[LOOP4]], [[META3]]} 258//. 259