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