xref: /llvm-project/llvm/test/Transforms/OpenMP/parallel_deletion.ll (revision 29441e4f5fa5f5c7709f7cf180815ba97f611297)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature
2; RUN: opt -S -passes='attributor,cgscc(openmp-opt-cgscc)'  < %s | FileCheck %s
3;
4target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
5
6%struct.ident_t = type { i32, i32, i32, i32, ptr }
7
8@.str = private unnamed_addr constant [23 x i8] c";unknown;unknown;0;0;;\00", align 1
9@0 = private unnamed_addr global %struct.ident_t { i32 0, i32 2, i32 0, i32 0, ptr @.str }, align 8
10@1 = private unnamed_addr global %struct.ident_t { i32 0, i32 322, i32 0, i32 0, ptr @.str }, align 8
11@.gomp_critical_user_.reduction.var = common global [8 x i32] zeroinitializer
12@2 = private unnamed_addr global %struct.ident_t { i32 0, i32 18, i32 0, i32 0, ptr @.str }, align 8
13
14;    void delete_parallel_0(void) {
15;    #pragma omp parallel
16;      { unknown_willreturn(); }
17;    #pragma omp parallel
18;      { readonly_willreturn(); }
19;    #pragma omp parallel
20;      { readnone_willreturn(); }
21;    #pragma omp parallel
22;      {}
23;    }
24;
25; We delete all but the first of the parallel regions in this test.
26define void @delete_parallel_0() {
27; CHECK-LABEL: define {{[^@]+}}@delete_parallel_0() {
28; CHECK-NEXT:  entry:
29; CHECK-NEXT:    call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr noundef nonnull align 8 dereferenceable(24) @[[GLOB0:[0-9]+]], i32 noundef 0, ptr noundef nonnull @.omp_outlined.willreturn)
30; CHECK-NEXT:    ret void
31;
32; CHECK1-LABEL: define {{[^@]+}}@delete_parallel_0() {
33; CHECK1-NEXT:  entry:
34; CHECK1-NEXT:    call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr noundef nonnull align 8 dereferenceable(24) @[[GLOB0:[0-9]+]], i32 noundef 0, ptr noundef @.omp_outlined.willreturn)
35; CHECK1-NEXT:    ret void
36; CHECK2-LABEL: define {{[^@]+}}@delete_parallel_0() {
37; CHECK2-NEXT:  entry:
38; CHECK2-NEXT:    call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr noundef nonnull align 8 dereferenceable(24) @[[GLOB0:[0-9]+]], i32 noundef 0, ptr noundef @.omp_outlined.willreturn)
39; CHECK2-NEXT:    ret void
40entry:
41  call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr nonnull @0, i32 0, ptr @.omp_outlined.willreturn)
42  call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr nonnull @0, i32 0, ptr @.omp_outlined.willreturn.0)
43  call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr nonnull @0, i32 0, ptr @.omp_outlined.willreturn.1)
44  call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr nonnull @0, i32 0, ptr @.omp_outlined.willreturn.2)
45  ret void
46}
47
48define internal void @.omp_outlined.willreturn(ptr noalias %.global_tid., ptr noalias %.bound_tid.) {
49; CHECK-LABEL: define {{[^@]+}}@.omp_outlined.willreturn
50; CHECK-SAME: (ptr noalias nofree readnone captures(none) [[DOTGLOBAL_TID_:%.*]], ptr noalias nofree readnone captures(none) [[DOTBOUND_TID_:%.*]]) #[[ATTR0:[0-9]+]] {
51; CHECK-NEXT:  entry:
52; CHECK-NEXT:    call void @unknown() #[[ATTR15:[0-9]+]]
53; CHECK-NEXT:    ret void
54;
55; CHECK1-LABEL: define {{[^@]+}}@.omp_outlined.willreturn
56; CHECK1-SAME: (ptr noalias nocapture nofree readnone [[DOTGLOBAL_TID_:%.*]], ptr noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]]) #[[ATTR0:[0-9]+]] {
57; CHECK1-NEXT:  entry:
58; CHECK1-NEXT:    call void @unknown() #[[ATTR0]]
59; CHECK1-NEXT:    ret void
60; CHECK2-LABEL: define {{[^@]+}}@.omp_outlined.willreturn
61; CHECK2-SAME: (ptr noalias nocapture nofree readnone [[DOTGLOBAL_TID_:%.*]], ptr noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]]) #[[ATTR0:[0-9]+]] {
62; CHECK2-NEXT:  entry:
63; CHECK2-NEXT:    call void @unknown() #[[ATTR0]]
64; CHECK2-NEXT:    ret void
65entry:
66  call void @unknown() willreturn
67  ret void
68}
69
70define internal void @.omp_outlined.willreturn.0(ptr noalias %.global_tid., ptr noalias %.bound_tid.) willreturn {
71; CHECK-LABEL: define {{[^@]+}}@.omp_outlined.willreturn.0
72; CHECK-SAME: (ptr noalias nofree readnone captures(none) [[DOTGLOBAL_TID_:%.*]], ptr noalias nofree readnone captures(none) [[DOTBOUND_TID_:%.*]]) #[[ATTR1:[0-9]+]] {
73; CHECK-NEXT:  entry:
74; CHECK-NEXT:    call void @readonly() #[[ATTR4:[0-9]+]]
75; CHECK-NEXT:    ret void
76;
77; CHECK1-LABEL: define {{[^@]+}}@.omp_outlined.willreturn.0
78; CHECK1-SAME: (ptr noalias nocapture nofree readnone [[DOTGLOBAL_TID_:%.*]], ptr noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]]) #[[ATTR1:[0-9]+]] {
79; CHECK1-NEXT:  entry:
80; CHECK1-NEXT:    call void @readonly() #[[ATTR4:[0-9]+]]
81; CHECK1-NEXT:    ret void
82; CHECK2-LABEL: define {{[^@]+}}@.omp_outlined.willreturn.0
83; CHECK2-SAME: (ptr noalias nocapture nofree readnone [[DOTGLOBAL_TID_:%.*]], ptr noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]]) #[[ATTR1:[0-9]+]] {
84; CHECK2-NEXT:  entry:
85; CHECK2-NEXT:    call void @readonly() #[[ATTR4:[0-9]+]]
86; CHECK2-NEXT:    ret void
87entry:
88  call void @readonly()
89  ret void
90}
91
92define internal void @.omp_outlined.willreturn.1(ptr noalias %.global_tid., ptr noalias %.bound_tid.) {
93; CHECK-LABEL: define {{[^@]+}}@.omp_outlined.willreturn.1
94; CHECK-SAME: (ptr noalias nofree readnone captures(none) [[DOTGLOBAL_TID_:%.*]], ptr noalias nofree readnone captures(none) [[DOTBOUND_TID_:%.*]]) #[[ATTR2:[0-9]+]] {
95; CHECK-NEXT:  entry:
96; CHECK-NEXT:    call void @readnone() #[[ATTR16:[0-9]+]]
97; CHECK-NEXT:    ret void
98;
99; CHECK1-LABEL: define {{[^@]+}}@.omp_outlined.willreturn.1
100; CHECK1-SAME: (ptr noalias nocapture nofree readnone [[DOTGLOBAL_TID_:%.*]], ptr noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]]) #[[ATTR2:[0-9]+]] {
101; CHECK1-NEXT:  entry:
102; CHECK1-NEXT:    call void @readnone() #[[ATTR0]]
103; CHECK1-NEXT:    ret void
104; CHECK2-LABEL: define {{[^@]+}}@.omp_outlined.willreturn.1
105; CHECK2-SAME: (ptr noalias nocapture nofree readnone [[DOTGLOBAL_TID_:%.*]], ptr noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]]) #[[ATTR2:[0-9]+]] {
106; CHECK2-NEXT:  entry:
107; CHECK2-NEXT:    call void @readnone() #[[ATTR0]]
108; CHECK2-NEXT:    ret void
109entry:
110  call void @readnone() willreturn
111  ret void
112}
113
114define internal void @.omp_outlined.willreturn.2(ptr noalias %.global_tid., ptr noalias %.bound_tid.) {
115; CHECK-LABEL: define {{[^@]+}}@.omp_outlined.willreturn.2
116; CHECK-SAME: (ptr noalias nofree readnone captures(none) [[DOTGLOBAL_TID_:%.*]], ptr noalias nofree readnone captures(none) [[DOTBOUND_TID_:%.*]]) #[[ATTR3:[0-9]+]] {
117; CHECK-NEXT:  entry:
118; CHECK-NEXT:    ret void
119;
120; CHECK1-LABEL: define {{[^@]+}}@.omp_outlined.willreturn.2
121; CHECK1-SAME: (ptr noalias nocapture nofree readnone [[DOTGLOBAL_TID_:%.*]], ptr noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]]) #[[ATTR3:[0-9]+]] {
122; CHECK1-NEXT:  entry:
123; CHECK1-NEXT:    ret void
124; CHECK2-LABEL: define {{[^@]+}}@.omp_outlined.willreturn.2
125; CHECK2-SAME: (ptr noalias nocapture nofree readnone [[DOTGLOBAL_TID_:%.*]], ptr noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]]) #[[ATTR3:[0-9]+]] {
126; CHECK2-NEXT:  entry:
127; CHECK2-NEXT:    ret void
128entry:
129  ret void
130}
131
132;    void delete_parallel_1(void) {
133;    #pragma omp parallel
134;      { unknown(); }
135;    #pragma omp parallel
136;      { readonly(); }
137;    #pragma omp parallel
138;      { readnone(); }
139;    #pragma omp parallel
140;      {}
141;    }
142;
143; We delete only the last parallel regions in this test because the others might not return.
144define void @delete_parallel_1() {
145; CHECK-LABEL: define {{[^@]+}}@delete_parallel_1() {
146; CHECK-NEXT:  entry:
147; CHECK-NEXT:    call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr noundef nonnull align 8 dereferenceable(24) @[[GLOB0]], i32 noundef 0, ptr noundef nonnull @.omp_outlined.)
148; CHECK-NEXT:    call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr noundef nonnull align 8 dereferenceable(24) @[[GLOB0]], i32 noundef 0, ptr noundef nonnull @.omp_outlined..0)
149; CHECK-NEXT:    call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr noundef nonnull align 8 dereferenceable(24) @[[GLOB0]], i32 noundef 0, ptr noundef nonnull @.omp_outlined..1)
150; CHECK-NEXT:    ret void
151;
152; CHECK1-LABEL: define {{[^@]+}}@delete_parallel_1() {
153; CHECK1-NEXT:  entry:
154; CHECK1-NEXT:    call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr noundef nonnull align 8 dereferenceable(24) @[[GLOB0]], i32 noundef 0, ptr noundef @.omp_outlined.)
155; CHECK1-NEXT:    call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr noundef nonnull align 8 dereferenceable(24) @[[GLOB0]], i32 noundef 0, ptr noundef @.omp_outlined..0)
156; CHECK1-NEXT:    call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr noundef nonnull align 8 dereferenceable(24) @[[GLOB0]], i32 noundef 0, ptr noundef @.omp_outlined..1)
157; CHECK1-NEXT:    ret void
158; CHECK2-LABEL: define {{[^@]+}}@delete_parallel_1() {
159; CHECK2-NEXT:  entry:
160; CHECK2-NEXT:    call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr noundef nonnull align 8 dereferenceable(24) @[[GLOB0]], i32 noundef 0, ptr noundef @.omp_outlined.)
161; CHECK2-NEXT:    call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr noundef nonnull align 8 dereferenceable(24) @[[GLOB0]], i32 noundef 0, ptr noundef @.omp_outlined..0)
162; CHECK2-NEXT:    call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr noundef nonnull align 8 dereferenceable(24) @[[GLOB0]], i32 noundef 0, ptr noundef @.omp_outlined..1)
163; CHECK2-NEXT:    ret void
164entry:
165  call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr nonnull @0, i32 0, ptr @.omp_outlined.)
166  call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr nonnull @0, i32 0, ptr @.omp_outlined..0)
167  call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr nonnull @0, i32 0, ptr @.omp_outlined..1)
168  call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr nonnull @0, i32 0, ptr @.omp_outlined..2)
169  ret void
170}
171
172define internal void @.omp_outlined.(ptr noalias %.global_tid., ptr noalias %.bound_tid.) {
173; CHECK-LABEL: define {{[^@]+}}@.omp_outlined.
174; CHECK-SAME: (ptr noalias nofree readnone captures(none) [[DOTGLOBAL_TID_:%.*]], ptr noalias nofree readnone captures(none) [[DOTBOUND_TID_:%.*]]) {
175; CHECK-NEXT:  entry:
176; CHECK-NEXT:    call void @unknown()
177; CHECK-NEXT:    ret void
178;
179; CHECK1-LABEL: define {{[^@]+}}@.omp_outlined.
180; CHECK1-SAME: (ptr noalias nocapture nofree readnone [[DOTGLOBAL_TID_:%.*]], ptr noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]]) {
181; CHECK1-NEXT:  entry:
182; CHECK1-NEXT:    call void @unknown()
183; CHECK1-NEXT:    ret void
184; CHECK2-LABEL: define {{[^@]+}}@.omp_outlined.
185; CHECK2-SAME: (ptr noalias nocapture nofree readnone [[DOTGLOBAL_TID_:%.*]], ptr noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]]) {
186; CHECK2-NEXT:  entry:
187; CHECK2-NEXT:    call void @unknown()
188; CHECK2-NEXT:    ret void
189entry:
190  call void @unknown()
191  ret void
192}
193
194define internal void @.omp_outlined..0(ptr noalias %.global_tid., ptr noalias %.bound_tid.) {
195; CHECK-LABEL: define {{[^@]+}}@.omp_outlined..0
196; CHECK-SAME: (ptr noalias nofree readnone captures(none) [[DOTGLOBAL_TID_:%.*]], ptr noalias nofree readnone captures(none) [[DOTBOUND_TID_:%.*]]) #[[ATTR4]] {
197; CHECK-NEXT:  entry:
198; CHECK-NEXT:    call void @readonly() #[[ATTR4]]
199; CHECK-NEXT:    ret void
200;
201; CHECK1-LABEL: define {{[^@]+}}@.omp_outlined..0
202; CHECK1-SAME: (ptr noalias nocapture nofree readnone [[DOTGLOBAL_TID_:%.*]], ptr noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]]) #[[ATTR4]] {
203; CHECK1-NEXT:  entry:
204; CHECK1-NEXT:    call void @readonly() #[[ATTR4]]
205; CHECK1-NEXT:    ret void
206; CHECK2-LABEL: define {{[^@]+}}@.omp_outlined..0
207; CHECK2-SAME: (ptr noalias nocapture nofree readnone [[DOTGLOBAL_TID_:%.*]], ptr noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]]) #[[ATTR4]] {
208; CHECK2-NEXT:  entry:
209; CHECK2-NEXT:    call void @readonly() #[[ATTR4]]
210; CHECK2-NEXT:    ret void
211entry:
212  call void @readonly()
213  ret void
214}
215
216define internal void @.omp_outlined..1(ptr noalias %.global_tid., ptr noalias %.bound_tid.) {
217; CHECK-LABEL: define {{[^@]+}}@.omp_outlined..1
218; CHECK-SAME: (ptr noalias nofree readnone captures(none) [[DOTGLOBAL_TID_:%.*]], ptr noalias nofree readnone captures(none) [[DOTBOUND_TID_:%.*]]) #[[ATTR5:[0-9]+]] {
219; CHECK-NEXT:  entry:
220; CHECK-NEXT:    call void @readnone() #[[ATTR17:[0-9]+]]
221; CHECK-NEXT:    ret void
222;
223; CHECK1-LABEL: define {{[^@]+}}@.omp_outlined..1
224; CHECK1-SAME: (ptr noalias nocapture nofree readnone [[DOTGLOBAL_TID_:%.*]], ptr noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]]) #[[ATTR5:[0-9]+]] {
225; CHECK1-NEXT:  entry:
226; CHECK1-NEXT:    call void @readnone()
227; CHECK1-NEXT:    ret void
228; CHECK2-LABEL: define {{[^@]+}}@.omp_outlined..1
229; CHECK2-SAME: (ptr noalias nocapture nofree readnone [[DOTGLOBAL_TID_:%.*]], ptr noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]]) #[[ATTR5:[0-9]+]] {
230; CHECK2-NEXT:  entry:
231; CHECK2-NEXT:    call void @readnone()
232; CHECK2-NEXT:    ret void
233entry:
234  call void @readnone()
235  ret void
236}
237
238define internal void @.omp_outlined..2(ptr noalias %.global_tid., ptr noalias %.bound_tid.) {
239; CHECK-LABEL: define {{[^@]+}}@.omp_outlined..2
240; CHECK-SAME: (ptr noalias nofree readnone captures(none) [[DOTGLOBAL_TID_:%.*]], ptr noalias nofree readnone captures(none) [[DOTBOUND_TID_:%.*]]) #[[ATTR3]] {
241; CHECK-NEXT:  entry:
242; CHECK-NEXT:    ret void
243;
244; CHECK1-LABEL: define {{[^@]+}}@.omp_outlined..2
245; CHECK1-SAME: (ptr noalias nocapture nofree readnone [[DOTGLOBAL_TID_:%.*]], ptr noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]]) #[[ATTR3]] {
246; CHECK1-NEXT:  entry:
247; CHECK1-NEXT:    ret void
248; CHECK2-LABEL: define {{[^@]+}}@.omp_outlined..2
249; CHECK2-SAME: (ptr noalias nocapture nofree readnone [[DOTGLOBAL_TID_:%.*]], ptr noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]]) #[[ATTR3]] {
250; CHECK2-NEXT:  entry:
251; CHECK2-NEXT:    ret void
252entry:
253  ret void
254}
255
256;    void delete_parallel_2(void) {
257;      int a = 0;
258;    #pragma omp parallel
259;      {
260;        if (omp_get_thread_num() == 0)
261;          ++a;
262;      }
263;    #pragma omp parallel
264;      {
265;    #pragma omp master
266;        ++a;
267;      }
268;    #pragma omp parallel
269;      {
270;    #pragma omp single
271;        ++a;
272;      }
273;    #pragma omp parallel reduction(+: a)
274;      {
275;        ++a;
276;      }
277;    }
278;
279; FIXME: We do not realize that `a` is dead and all accesses to it can be removed
280;        making the parallel regions readonly and deletable.
281define void @delete_parallel_2() {
282; CHECK-LABEL: define {{[^@]+}}@delete_parallel_2() {
283; CHECK-NEXT:  entry:
284; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4
285; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 noundef 4, ptr noundef nonnull align 4 dereferenceable(4) [[A]]) #[[ATTR18:[0-9]+]]
286; CHECK-NEXT:    store i32 0, ptr [[A]], align 4
287; CHECK-NEXT:    call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr noundef nonnull align 8 dereferenceable(24) @[[GLOB0]], i32 noundef 1, ptr noundef nonnull @.omp_outlined..3, ptr nofree noundef nonnull align 4 captures(none) dereferenceable(4) [[A]])
288; CHECK-NEXT:    call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr noundef nonnull align 8 dereferenceable(24) @[[GLOB0]], i32 noundef 1, ptr noundef nonnull @.omp_outlined..4, ptr nofree noundef nonnull align 4 captures(none) dereferenceable(4) [[A]])
289; CHECK-NEXT:    call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr noundef nonnull align 8 dereferenceable(24) @[[GLOB0]], i32 noundef 1, ptr noundef nonnull @.omp_outlined..5, ptr nofree noundef nonnull align 4 captures(none) dereferenceable(4) [[A]])
290; CHECK-NEXT:    call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr noundef nonnull align 8 dereferenceable(24) @[[GLOB0]], i32 noundef 1, ptr noundef nonnull @.omp_outlined..6, ptr noundef nonnull align 4 captures(none) dereferenceable(4) [[A]])
291; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 noundef 4, ptr noundef nonnull [[A]])
292; CHECK-NEXT:    ret void
293;
294; CHECK1-LABEL: define {{[^@]+}}@delete_parallel_2() {
295; CHECK1-NEXT:  entry:
296; CHECK1-NEXT:    [[A:%.*]] = alloca i32, align 4
297; CHECK1-NEXT:    call void @llvm.lifetime.start.p0(i64 noundef 4, ptr noundef nonnull align 4 dereferenceable(4) [[A]]) #[[ATTR0]]
298; CHECK1-NEXT:    store i32 0, ptr [[A]], align 4
299; CHECK1-NEXT:    call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr noundef nonnull align 8 dereferenceable(24) @[[GLOB0]], i32 noundef 1, ptr noundef @.omp_outlined..3, ptr nocapture nofree noundef nonnull align 4 dereferenceable(4) [[A]])
300; CHECK1-NEXT:    call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr noundef nonnull align 8 dereferenceable(24) @[[GLOB0]], i32 noundef 1, ptr noundef @.omp_outlined..4, ptr nocapture nofree noundef nonnull align 4 dereferenceable(4) [[A]])
301; CHECK1-NEXT:    call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr noundef nonnull align 8 dereferenceable(24) @[[GLOB0]], i32 noundef 1, ptr noundef @.omp_outlined..5, ptr nocapture nofree noundef nonnull align 4 dereferenceable(4) [[A]])
302; CHECK1-NEXT:    call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr noundef nonnull align 8 dereferenceable(24) @[[GLOB0]], i32 noundef 1, ptr noundef @.omp_outlined..6, ptr nocapture noundef nonnull align 4 dereferenceable(4) [[A]])
303; CHECK1-NEXT:    call void @llvm.lifetime.end.p0(i64 noundef 4, ptr noundef nonnull [[A]])
304; CHECK1-NEXT:    ret void
305; CHECK2-LABEL: define {{[^@]+}}@delete_parallel_2() {
306; CHECK2-NEXT:  entry:
307; CHECK2-NEXT:    [[A:%.*]] = alloca i32, align 4
308; CHECK2-NEXT:    call void @llvm.lifetime.start.p0(i64 noundef 4, ptr noundef nonnull align 4 dereferenceable(4) [[A]]) #[[ATTR0]]
309; CHECK2-NEXT:    store i32 0, ptr [[A]], align 4
310; CHECK2-NEXT:    call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr noundef nonnull align 8 dereferenceable(24) @[[GLOB0]], i32 noundef 1, ptr noundef @.omp_outlined..3, ptr nocapture nofree noundef nonnull align 4 dereferenceable(4) [[A]])
311; CHECK2-NEXT:    call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr noundef nonnull align 8 dereferenceable(24) @[[GLOB0]], i32 noundef 1, ptr noundef @.omp_outlined..4, ptr nocapture nofree noundef nonnull align 4 dereferenceable(4) [[A]])
312; CHECK2-NEXT:    call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr noundef nonnull align 8 dereferenceable(24) @[[GLOB0]], i32 noundef 1, ptr noundef @.omp_outlined..5, ptr nocapture nofree noundef nonnull align 4 dereferenceable(4) [[A]])
313; CHECK2-NEXT:    call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr noundef nonnull align 8 dereferenceable(24) @[[GLOB0]], i32 noundef 1, ptr noundef @.omp_outlined..6, ptr nocapture noundef nonnull align 4 dereferenceable(4) [[A]])
314; CHECK2-NEXT:    call void @llvm.lifetime.end.p0(i64 noundef 4, ptr noundef nonnull [[A]])
315; CHECK2-NEXT:    ret void
316entry:
317  %a = alloca i32, align 4
318  call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %a)
319  store i32 0, ptr %a, align 4
320  call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr nonnull @0, i32 1, ptr @.omp_outlined..3, ptr nonnull %a)
321  call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr nonnull @0, i32 1, ptr @.omp_outlined..4, ptr nonnull %a)
322  call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr nonnull @0, i32 1, ptr @.omp_outlined..5, ptr nonnull %a)
323  call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr nonnull @0, i32 1, ptr @.omp_outlined..6, ptr nonnull %a)
324  call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %a)
325  ret void
326}
327
328define internal void @.omp_outlined..3(ptr noalias %.global_tid., ptr noalias %.bound_tid., ptr dereferenceable(4) %a) {
329; CHECK-LABEL: define {{[^@]+}}@.omp_outlined..3
330; CHECK-SAME: (ptr noalias nofree readnone captures(none) [[DOTGLOBAL_TID_:%.*]], ptr noalias nofree readnone captures(none) [[DOTBOUND_TID_:%.*]], ptr nofree noundef nonnull align 4 captures(none) dereferenceable(4) [[A:%.*]]) #[[ATTR6:[0-9]+]] {
331; CHECK-NEXT:  entry:
332; CHECK-NEXT:    [[CALL:%.*]] = call i32 @omp_get_thread_num() #[[ATTR19:[0-9]+]]
333; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[CALL]], 0
334; CHECK-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
335; CHECK:       if.then:
336; CHECK-NEXT:    [[TMP:%.*]] = load i32, ptr [[A]], align 4
337; CHECK-NEXT:    [[INC:%.*]] = add nsw i32 [[TMP]], 1
338; CHECK-NEXT:    store i32 [[INC]], ptr [[A]], align 4
339; CHECK-NEXT:    br label [[IF_END]]
340; CHECK:       if.end:
341; CHECK-NEXT:    ret void
342;
343; CHECK1-LABEL: define {{[^@]+}}@.omp_outlined..3
344; CHECK1-SAME: (ptr noalias nocapture nofree readnone [[DOTGLOBAL_TID_:%.*]], ptr noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]], ptr nocapture nofree noundef nonnull align 4 dereferenceable(4) [[A:%.*]]) #[[ATTR6:[0-9]+]] {
345; CHECK1-NEXT:  entry:
346; CHECK1-NEXT:    [[CALL:%.*]] = call i32 @omp_get_thread_num() #[[ATTR14:[0-9]+]]
347; CHECK1-NEXT:    [[CMP:%.*]] = icmp eq i32 [[CALL]], 0
348; CHECK1-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
349; CHECK1:       if.then:
350; CHECK1-NEXT:    [[TMP:%.*]] = load i32, ptr [[A]], align 4
351; CHECK1-NEXT:    [[INC:%.*]] = add nsw i32 [[TMP]], 1
352; CHECK1-NEXT:    store i32 [[INC]], ptr [[A]], align 4
353; CHECK1-NEXT:    br label [[IF_END]]
354; CHECK1:       if.end:
355; CHECK1-NEXT:    ret void
356; CHECK2-LABEL: define {{[^@]+}}@.omp_outlined..3
357; CHECK2-SAME: (ptr noalias nocapture nofree readnone [[DOTGLOBAL_TID_:%.*]], ptr noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]], ptr nocapture nofree noundef nonnull align 4 dereferenceable(4) [[A:%.*]]) #[[ATTR6:[0-9]+]] {
358; CHECK2-NEXT:  entry:
359; CHECK2-NEXT:    [[CALL:%.*]] = call i32 @omp_get_thread_num() #[[ATTR14:[0-9]+]]
360; CHECK2-NEXT:    [[CMP:%.*]] = icmp eq i32 [[CALL]], 0
361; CHECK2-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
362; CHECK2:       if.then:
363; CHECK2-NEXT:    [[TMP:%.*]] = load i32, ptr [[A]], align 4
364; CHECK2-NEXT:    [[INC:%.*]] = add nsw i32 [[TMP]], 1
365; CHECK2-NEXT:    store i32 [[INC]], ptr [[A]], align 4
366; CHECK2-NEXT:    br label [[IF_END]]
367; CHECK2:       if.end:
368; CHECK2-NEXT:    ret void
369entry:
370  %call = call i32 @omp_get_thread_num()
371  %cmp = icmp eq i32 %call, 0
372  br i1 %cmp, label %if.then, label %if.end
373
374if.then:                                          ; preds = %entry
375  %tmp = load i32, ptr %a, align 4
376  %inc = add nsw i32 %tmp, 1
377  store i32 %inc, ptr %a, align 4
378  br label %if.end
379
380if.end:                                           ; preds = %if.then, %entry
381  ret void
382}
383
384define internal void @.omp_outlined..4(ptr noalias %.global_tid., ptr noalias %.bound_tid., ptr dereferenceable(4) %a) {
385; CHECK-LABEL: define {{[^@]+}}@.omp_outlined..4
386; CHECK-SAME: (ptr noalias nofree noundef nonnull readonly align 4 captures(none) dereferenceable(4) [[DOTGLOBAL_TID_:%.*]], ptr noalias nofree readnone captures(none) [[DOTBOUND_TID_:%.*]], ptr nofree noundef nonnull align 4 captures(none) dereferenceable(4) [[A:%.*]]) {
387; CHECK-NEXT:  entry:
388; CHECK-NEXT:    [[TMP:%.*]] = load i32, ptr [[DOTGLOBAL_TID_]], align 4
389; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @__kmpc_master(ptr noundef nonnull @[[GLOB0]], i32 [[TMP]])
390; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 0
391; CHECK-NEXT:    br i1 [[TMP2]], label [[OMP_IF_END:%.*]], label [[OMP_IF_THEN:%.*]]
392; CHECK:       omp_if.then:
393; CHECK-NEXT:    [[TMP3:%.*]] = load i32, ptr [[A]], align 4
394; CHECK-NEXT:    [[INC:%.*]] = add nsw i32 [[TMP3]], 1
395; CHECK-NEXT:    store i32 [[INC]], ptr [[A]], align 4
396; CHECK-NEXT:    call void @__kmpc_end_master(ptr noundef nonnull @[[GLOB0]], i32 [[TMP]])
397; CHECK-NEXT:    br label [[OMP_IF_END]]
398; CHECK:       omp_if.end:
399; CHECK-NEXT:    ret void
400;
401; CHECK1-LABEL: define {{[^@]+}}@.omp_outlined..4
402; CHECK1-SAME: (ptr noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[DOTGLOBAL_TID_:%.*]], ptr noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]], ptr nocapture nofree noundef nonnull align 4 dereferenceable(4) [[A:%.*]]) {
403; CHECK1-NEXT:  entry:
404; CHECK1-NEXT:    [[TMP:%.*]] = load i32, ptr [[DOTGLOBAL_TID_]], align 4
405; CHECK1-NEXT:    [[TMP1:%.*]] = call i32 @__kmpc_master(ptr noundef nonnull @[[GLOB0]], i32 [[TMP]])
406; CHECK1-NEXT:    [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 0
407; CHECK1-NEXT:    br i1 [[TMP2]], label [[OMP_IF_END:%.*]], label [[OMP_IF_THEN:%.*]]
408; CHECK1:       omp_if.then:
409; CHECK1-NEXT:    [[TMP3:%.*]] = load i32, ptr [[A]], align 4
410; CHECK1-NEXT:    [[INC:%.*]] = add nsw i32 [[TMP3]], 1
411; CHECK1-NEXT:    store i32 [[INC]], ptr [[A]], align 4
412; CHECK1-NEXT:    call void @__kmpc_end_master(ptr noundef nonnull @[[GLOB0]], i32 [[TMP]])
413; CHECK1-NEXT:    br label [[OMP_IF_END]]
414; CHECK1:       omp_if.end:
415; CHECK1-NEXT:    ret void
416; CHECK2-LABEL: define {{[^@]+}}@.omp_outlined..4
417; CHECK2-SAME: (ptr noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[DOTGLOBAL_TID_:%.*]], ptr noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]], ptr nocapture nofree noundef nonnull align 4 dereferenceable(4) [[A:%.*]]) {
418; CHECK2-NEXT:  entry:
419; CHECK2-NEXT:    [[TMP:%.*]] = load i32, ptr [[DOTGLOBAL_TID_]], align 4
420; CHECK2-NEXT:    [[TMP1:%.*]] = call i32 @__kmpc_master(ptr noundef nonnull @[[GLOB0]], i32 [[TMP]])
421; CHECK2-NEXT:    [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 0
422; CHECK2-NEXT:    br i1 [[TMP2]], label [[OMP_IF_END:%.*]], label [[OMP_IF_THEN:%.*]]
423; CHECK2:       omp_if.then:
424; CHECK2-NEXT:    [[TMP3:%.*]] = load i32, ptr [[A]], align 4
425; CHECK2-NEXT:    [[INC:%.*]] = add nsw i32 [[TMP3]], 1
426; CHECK2-NEXT:    store i32 [[INC]], ptr [[A]], align 4
427; CHECK2-NEXT:    call void @__kmpc_end_master(ptr noundef nonnull @[[GLOB0]], i32 [[TMP]])
428; CHECK2-NEXT:    br label [[OMP_IF_END]]
429; CHECK2:       omp_if.end:
430; CHECK2-NEXT:    ret void
431entry:
432  %tmp = load i32, ptr %.global_tid., align 4
433  %tmp1 = call i32 @__kmpc_master(ptr nonnull @0, i32 %tmp)
434  %tmp2 = icmp eq i32 %tmp1, 0
435  br i1 %tmp2, label %omp_if.end, label %omp_if.then
436
437omp_if.then:                                      ; preds = %entry
438  %tmp3 = load i32, ptr %a, align 4
439  %inc = add nsw i32 %tmp3, 1
440  store i32 %inc, ptr %a, align 4
441  call void @__kmpc_end_master(ptr nonnull @0, i32 %tmp)
442  br label %omp_if.end
443
444omp_if.end:                                       ; preds = %entry, %omp_if.then
445  ret void
446}
447
448declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture)
449
450declare i32 @omp_get_thread_num() inaccessiblememonly nofree nosync nounwind readonly
451
452declare i32 @__kmpc_master(ptr, i32)
453
454declare void @__kmpc_end_master(ptr, i32)
455
456define internal void @.omp_outlined..5(ptr noalias %.global_tid., ptr noalias %.bound_tid., ptr dereferenceable(4) %a) {
457; CHECK-LABEL: define {{[^@]+}}@.omp_outlined..5
458; CHECK-SAME: (ptr noalias nofree readonly captures(none) [[DOTGLOBAL_TID_:%.*]], ptr noalias nofree readnone captures(none) [[DOTBOUND_TID_:%.*]], ptr nofree noundef nonnull align 4 captures(none) dereferenceable(4) [[A:%.*]]) {
459; CHECK-NEXT:  entry:
460; CHECK-NEXT:    [[OMP_GLOBAL_THREAD_NUM:%.*]] = call i32 @__kmpc_global_thread_num(ptr noundef nonnull @[[GLOB0]]) #[[ATTR19]]
461; CHECK-NEXT:    [[TMP:%.*]] = load i32, ptr [[DOTGLOBAL_TID_]], align 4
462; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @__kmpc_single(ptr noundef nonnull @[[GLOB0]], i32 [[TMP]])
463; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 0
464; CHECK-NEXT:    br i1 [[TMP2]], label [[OMP_IF_END:%.*]], label [[OMP_IF_THEN:%.*]]
465; CHECK:       omp_if.then:
466; CHECK-NEXT:    [[TMP3:%.*]] = load i32, ptr [[A]], align 4
467; CHECK-NEXT:    [[INC:%.*]] = add nsw i32 [[TMP3]], 1
468; CHECK-NEXT:    store i32 [[INC]], ptr [[A]], align 4
469; CHECK-NEXT:    call void @__kmpc_end_single(ptr noundef nonnull @[[GLOB0]], i32 [[TMP]])
470; CHECK-NEXT:    br label [[OMP_IF_END]]
471; CHECK:       omp_if.end:
472; CHECK-NEXT:    call void @__kmpc_barrier(ptr noundef nonnull @[[GLOB1:[0-9]+]], i32 [[OMP_GLOBAL_THREAD_NUM]])
473; CHECK-NEXT:    ret void
474;
475; CHECK1-LABEL: define {{[^@]+}}@.omp_outlined..5
476; CHECK1-SAME: (ptr noalias nocapture nofree readonly [[DOTGLOBAL_TID_:%.*]], ptr noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]], ptr nocapture nofree noundef nonnull align 4 dereferenceable(4) [[A:%.*]]) {
477; CHECK1-NEXT:  entry:
478; CHECK1-NEXT:    [[OMP_GLOBAL_THREAD_NUM:%.*]] = call i32 @__kmpc_global_thread_num(ptr noundef nonnull @[[GLOB0]]) #[[ATTR14]]
479; CHECK1-NEXT:    [[TMP:%.*]] = load i32, ptr [[DOTGLOBAL_TID_]], align 4
480; CHECK1-NEXT:    [[TMP1:%.*]] = call i32 @__kmpc_single(ptr noundef nonnull @[[GLOB0]], i32 [[TMP]])
481; CHECK1-NEXT:    [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 0
482; CHECK1-NEXT:    br i1 [[TMP2]], label [[OMP_IF_END:%.*]], label [[OMP_IF_THEN:%.*]]
483; CHECK1:       omp_if.then:
484; CHECK1-NEXT:    [[TMP3:%.*]] = load i32, ptr [[A]], align 4
485; CHECK1-NEXT:    [[INC:%.*]] = add nsw i32 [[TMP3]], 1
486; CHECK1-NEXT:    store i32 [[INC]], ptr [[A]], align 4
487; CHECK1-NEXT:    call void @__kmpc_end_single(ptr noundef nonnull @[[GLOB0]], i32 [[TMP]])
488; CHECK1-NEXT:    br label [[OMP_IF_END]]
489; CHECK1:       omp_if.end:
490; CHECK1-NEXT:    call void @__kmpc_barrier(ptr noundef nonnull @[[GLOB1:[0-9]+]], i32 [[OMP_GLOBAL_THREAD_NUM]])
491; CHECK1-NEXT:    ret void
492; CHECK2-LABEL: define {{[^@]+}}@.omp_outlined..5
493; CHECK2-SAME: (ptr noalias nocapture nofree readonly [[DOTGLOBAL_TID_:%.*]], ptr noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]], ptr nocapture nofree noundef nonnull align 4 dereferenceable(4) [[A:%.*]]) {
494; CHECK2-NEXT:  entry:
495; CHECK2-NEXT:    [[OMP_GLOBAL_THREAD_NUM:%.*]] = call i32 @__kmpc_global_thread_num(ptr noundef nonnull @[[GLOB0]]) #[[ATTR14]]
496; CHECK2-NEXT:    [[TMP:%.*]] = load i32, ptr [[DOTGLOBAL_TID_]], align 4
497; CHECK2-NEXT:    [[TMP1:%.*]] = call i32 @__kmpc_single(ptr noundef nonnull @[[GLOB0]], i32 [[TMP]])
498; CHECK2-NEXT:    [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 0
499; CHECK2-NEXT:    br i1 [[TMP2]], label [[OMP_IF_END:%.*]], label [[OMP_IF_THEN:%.*]]
500; CHECK2:       omp_if.then:
501; CHECK2-NEXT:    [[TMP3:%.*]] = load i32, ptr [[A]], align 4
502; CHECK2-NEXT:    [[INC:%.*]] = add nsw i32 [[TMP3]], 1
503; CHECK2-NEXT:    store i32 [[INC]], ptr [[A]], align 4
504; CHECK2-NEXT:    call void @__kmpc_end_single(ptr noundef nonnull @[[GLOB0]], i32 [[TMP]])
505; CHECK2-NEXT:    br label [[OMP_IF_END]]
506; CHECK2:       omp_if.end:
507; CHECK2-NEXT:    call void @__kmpc_barrier(ptr noundef nonnull @[[GLOB1:[0-9]+]], i32 [[OMP_GLOBAL_THREAD_NUM]])
508; CHECK2-NEXT:    ret void
509entry:
510  %omp_global_thread_num = call i32 @__kmpc_global_thread_num(ptr nonnull @0)
511  %tmp = load i32, ptr %.global_tid., align 4
512  %tmp1 = call i32 @__kmpc_single(ptr nonnull @0, i32 %tmp)
513  %tmp2 = icmp eq i32 %tmp1, 0
514  br i1 %tmp2, label %omp_if.end, label %omp_if.then
515
516omp_if.then:                                      ; preds = %entry
517  %tmp3 = load i32, ptr %a, align 4
518  %inc = add nsw i32 %tmp3, 1
519  store i32 %inc, ptr %a, align 4
520  call void @__kmpc_end_single(ptr nonnull @0, i32 %tmp)
521  br label %omp_if.end
522
523omp_if.end:                                       ; preds = %entry, %omp_if.then
524  call void @__kmpc_barrier(ptr nonnull @1, i32 %omp_global_thread_num) #6
525  ret void
526}
527
528define internal void @.omp_outlined..6(ptr noalias %.global_tid., ptr noalias %.bound_tid., ptr dereferenceable(4) %a) {
529; CHECK-LABEL: define {{[^@]+}}@.omp_outlined..6
530; CHECK-SAME: (ptr noalias nofree noundef nonnull readonly align 4 captures(none) dereferenceable(4) [[DOTGLOBAL_TID_:%.*]], ptr noalias nofree readnone captures(none) [[DOTBOUND_TID_:%.*]], ptr noundef nonnull align 4 captures(none) dereferenceable(4) [[A:%.*]]) {
531; CHECK-NEXT:  entry:
532; CHECK-NEXT:    [[A1:%.*]] = alloca i32, align 4
533; CHECK-NEXT:    [[DOTOMP_REDUCTION_RED_LIST:%.*]] = alloca [1 x ptr], align 8
534; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 noundef 4, ptr noundef nonnull align 4 [[A1]]) #[[ATTR20:[0-9]+]]
535; CHECK-NEXT:    store i32 1, ptr [[A1]], align 4
536; CHECK-NEXT:    store ptr [[A1]], ptr [[DOTOMP_REDUCTION_RED_LIST]], align 8
537; CHECK-NEXT:    [[TMP2:%.*]] = load i32, ptr [[DOTGLOBAL_TID_]], align 4
538; CHECK-NEXT:    [[TMP4:%.*]] = call i32 @__kmpc_reduce_nowait(ptr noundef nonnull @[[GLOB2:[0-9]+]], i32 [[TMP2]], i32 noundef 1, i64 noundef 8, ptr noundef nonnull align 8 [[DOTOMP_REDUCTION_RED_LIST]], ptr noundef nonnull @.omp.reduction.reduction_func, ptr noundef nonnull @.gomp_critical_user_.reduction.var)
539; CHECK-NEXT:    switch i32 [[TMP4]], label [[DOTOMP_REDUCTION_DEFAULT:%.*]] [
540; CHECK-NEXT:      i32 1, label [[DOTOMP_REDUCTION_CASE1:%.*]]
541; CHECK-NEXT:      i32 2, label [[DOTOMP_REDUCTION_CASE2:%.*]]
542; CHECK-NEXT:    ]
543; CHECK:       .omp.reduction.case1:
544; CHECK-NEXT:    [[TMP5:%.*]] = load i32, ptr [[A]], align 4
545; CHECK-NEXT:    [[TMP6:%.*]] = load i32, ptr [[A1]], align 4
546; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[TMP5]], [[TMP6]]
547; CHECK-NEXT:    store i32 [[ADD]], ptr [[A]], align 4
548; CHECK-NEXT:    call void @__kmpc_end_reduce_nowait(ptr noundef nonnull @[[GLOB2]], i32 [[TMP2]], ptr noundef nonnull @.gomp_critical_user_.reduction.var)
549; CHECK-NEXT:    br label [[DOTOMP_REDUCTION_DEFAULT]]
550; CHECK:       .omp.reduction.case2:
551; CHECK-NEXT:    [[TMP7:%.*]] = load i32, ptr [[A1]], align 4
552; CHECK-NEXT:    [[TMP8:%.*]] = atomicrmw add ptr [[A]], i32 [[TMP7]] monotonic, align 4
553; CHECK-NEXT:    br label [[DOTOMP_REDUCTION_DEFAULT]]
554; CHECK:       .omp.reduction.default:
555; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 noundef 4, ptr noundef nonnull [[A1]])
556; CHECK-NEXT:    ret void
557;
558; CHECK1-LABEL: define {{[^@]+}}@.omp_outlined..6
559; CHECK1-SAME: (ptr noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[DOTGLOBAL_TID_:%.*]], ptr noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]], ptr nocapture noundef nonnull align 4 dereferenceable(4) [[A:%.*]]) {
560; CHECK1-NEXT:  entry:
561; CHECK1-NEXT:    [[A1:%.*]] = alloca i32, align 4
562; CHECK1-NEXT:    [[DOTOMP_REDUCTION_RED_LIST:%.*]] = alloca [1 x ptr], align 8
563; CHECK1-NEXT:    call void @llvm.lifetime.start.p0(i64 noundef 4, ptr noundef nonnull align 4 [[A1]]) #[[ATTR0]]
564; CHECK1-NEXT:    store i32 1, ptr [[A1]], align 4
565; CHECK1-NEXT:    store ptr [[A1]], ptr [[DOTOMP_REDUCTION_RED_LIST]], align 8
566; CHECK1-NEXT:    [[TMP2:%.*]] = load i32, ptr [[DOTGLOBAL_TID_]], align 4
567; CHECK1-NEXT:    [[TMP4:%.*]] = call i32 @__kmpc_reduce_nowait(ptr noundef nonnull @[[GLOB2:[0-9]+]], i32 [[TMP2]], i32 noundef 1, i64 noundef 8, ptr noundef nonnull align 8 [[DOTOMP_REDUCTION_RED_LIST]], ptr noundef nonnull @.omp.reduction.reduction_func, ptr noundef nonnull @.gomp_critical_user_.reduction.var)
568; CHECK1-NEXT:    switch i32 [[TMP4]], label [[DOTOMP_REDUCTION_DEFAULT:%.*]] [
569; CHECK1-NEXT:    i32 1, label [[DOTOMP_REDUCTION_CASE1:%.*]]
570; CHECK1-NEXT:    i32 2, label [[DOTOMP_REDUCTION_CASE2:%.*]]
571; CHECK1-NEXT:    ]
572; CHECK1:       .omp.reduction.case1:
573; CHECK1-NEXT:    [[TMP5:%.*]] = load i32, ptr [[A]], align 4
574; CHECK1-NEXT:    [[TMP6:%.*]] = load i32, ptr [[A1]], align 4
575; CHECK1-NEXT:    [[ADD:%.*]] = add nsw i32 [[TMP5]], [[TMP6]]
576; CHECK1-NEXT:    store i32 [[ADD]], ptr [[A]], align 4
577; CHECK1-NEXT:    call void @__kmpc_end_reduce_nowait(ptr noundef nonnull @[[GLOB2]], i32 [[TMP2]], ptr noundef nonnull @.gomp_critical_user_.reduction.var)
578; CHECK1-NEXT:    br label [[DOTOMP_REDUCTION_DEFAULT]]
579; CHECK1:       .omp.reduction.case2:
580; CHECK1-NEXT:    [[TMP7:%.*]] = load i32, ptr [[A1]], align 4
581; CHECK1-NEXT:    [[TMP8:%.*]] = atomicrmw add ptr [[A]], i32 [[TMP7]] monotonic, align 4
582; CHECK1-NEXT:    br label [[DOTOMP_REDUCTION_DEFAULT]]
583; CHECK1:       .omp.reduction.default:
584; CHECK1-NEXT:    call void @llvm.lifetime.end.p0(i64 noundef 4, ptr noundef nonnull [[A1]])
585; CHECK1-NEXT:    ret void
586; CHECK2-LABEL: define {{[^@]+}}@.omp_outlined..6
587; CHECK2-SAME: (ptr noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[DOTGLOBAL_TID_:%.*]], ptr noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]], ptr nocapture noundef nonnull align 4 dereferenceable(4) [[A:%.*]]) {
588; CHECK2-NEXT:  entry:
589; CHECK2-NEXT:    [[A1:%.*]] = alloca i32, align 4
590; CHECK2-NEXT:    [[DOTOMP_REDUCTION_RED_LIST:%.*]] = alloca [1 x ptr], align 8
591; CHECK2-NEXT:    call void @llvm.lifetime.start.p0(i64 noundef 4, ptr noundef nonnull align 4 [[A1]]) #[[ATTR0]]
592; CHECK2-NEXT:    store i32 1, ptr [[A1]], align 4
593; CHECK2-NEXT:    store ptr [[A1]], ptr [[DOTOMP_REDUCTION_RED_LIST]], align 8
594; CHECK2-NEXT:    [[TMP2:%.*]] = load i32, ptr [[DOTGLOBAL_TID_]], align 4
595; CHECK2-NEXT:    [[TMP4:%.*]] = call i32 @__kmpc_reduce_nowait(ptr noundef nonnull @[[GLOB2:[0-9]+]], i32 [[TMP2]], i32 noundef 1, i64 noundef 8, ptr noundef nonnull align 8 [[DOTOMP_REDUCTION_RED_LIST]], ptr noundef nonnull @.omp.reduction.reduction_func, ptr noundef nonnull @.gomp_critical_user_.reduction.var)
596; CHECK2-NEXT:    switch i32 [[TMP4]], label [[DOTOMP_REDUCTION_DEFAULT:%.*]] [
597; CHECK2-NEXT:    i32 1, label [[DOTOMP_REDUCTION_CASE1:%.*]]
598; CHECK2-NEXT:    i32 2, label [[DOTOMP_REDUCTION_CASE2:%.*]]
599; CHECK2-NEXT:    ]
600; CHECK2:       .omp.reduction.case1:
601; CHECK2-NEXT:    [[TMP5:%.*]] = load i32, ptr [[A]], align 4
602; CHECK2-NEXT:    [[TMP6:%.*]] = load i32, ptr [[A1]], align 4
603; CHECK2-NEXT:    [[ADD:%.*]] = add nsw i32 [[TMP5]], [[TMP6]]
604; CHECK2-NEXT:    store i32 [[ADD]], ptr [[A]], align 4
605; CHECK2-NEXT:    call void @__kmpc_end_reduce_nowait(ptr noundef nonnull @[[GLOB2]], i32 [[TMP2]], ptr noundef nonnull @.gomp_critical_user_.reduction.var)
606; CHECK2-NEXT:    br label [[DOTOMP_REDUCTION_DEFAULT]]
607; CHECK2:       .omp.reduction.case2:
608; CHECK2-NEXT:    [[TMP7:%.*]] = load i32, ptr [[A1]], align 4
609; CHECK2-NEXT:    [[TMP8:%.*]] = atomicrmw add ptr [[A]], i32 [[TMP7]] monotonic, align 4
610; CHECK2-NEXT:    br label [[DOTOMP_REDUCTION_DEFAULT]]
611; CHECK2:       .omp.reduction.default:
612; CHECK2-NEXT:    call void @llvm.lifetime.end.p0(i64 noundef 4, ptr noundef nonnull [[A1]])
613; CHECK2-NEXT:    ret void
614entry:
615  %a1 = alloca i32, align 4
616  %.omp.reduction.red_list = alloca [1 x ptr], align 8
617  call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %a1)
618  store i32 1, ptr %a1, align 4
619  store ptr %a1, ptr %.omp.reduction.red_list, align 8
620  %tmp2 = load i32, ptr %.global_tid., align 4
621  %tmp4 = call i32 @__kmpc_reduce_nowait(ptr nonnull @2, i32 %tmp2, i32 1, i64 8, ptr nonnull %.omp.reduction.red_list, ptr nonnull @.omp.reduction.reduction_func, ptr nonnull @.gomp_critical_user_.reduction.var)
622  switch i32 %tmp4, label %.omp.reduction.default [
623  i32 1, label %.omp.reduction.case1
624  i32 2, label %.omp.reduction.case2
625  ]
626
627.omp.reduction.case1:                             ; preds = %entry
628  %tmp5 = load i32, ptr %a, align 4
629  %tmp6 = load i32, ptr %a1, align 4
630  %add = add nsw i32 %tmp5, %tmp6
631  store i32 %add, ptr %a, align 4
632  call void @__kmpc_end_reduce_nowait(ptr nonnull @2, i32 %tmp2, ptr nonnull @.gomp_critical_user_.reduction.var)
633  br label %.omp.reduction.default
634
635.omp.reduction.case2:                             ; preds = %entry
636  %tmp7 = load i32, ptr %a1, align 4
637  %tmp8 = atomicrmw add ptr %a, i32 %tmp7 monotonic
638  br label %.omp.reduction.default
639
640.omp.reduction.default:                           ; preds = %.omp.reduction.case2, %.omp.reduction.case1, %entry
641  call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %a1)
642  ret void
643}
644
645define internal void @.omp.reduction.reduction_func(ptr %arg, ptr %arg1) {
646; CHECK-LABEL: define {{[^@]+}}@.omp.reduction.reduction_func
647; CHECK-SAME: (ptr nofree noundef nonnull readonly align 8 captures(none) dereferenceable(8) [[ARG:%.*]], ptr nofree noundef nonnull readonly align 8 captures(none) dereferenceable(8) [[ARG1:%.*]]) #[[ATTR10:[0-9]+]] {
648; CHECK-NEXT:  entry:
649; CHECK-NEXT:    [[TMP2:%.*]] = load ptr, ptr [[ARG1]], align 8
650; CHECK-NEXT:    [[TMP4:%.*]] = load ptr, ptr [[ARG]], align 8
651; CHECK-NEXT:    [[TMP5:%.*]] = load i32, ptr [[TMP4]], align 4
652; CHECK-NEXT:    [[TMP6:%.*]] = load i32, ptr [[TMP2]], align 4
653; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[TMP5]], [[TMP6]]
654; CHECK-NEXT:    store i32 [[ADD]], ptr [[TMP4]], align 4
655; CHECK-NEXT:    ret void
656;
657; CHECK1-LABEL: define {{[^@]+}}@.omp.reduction.reduction_func
658; CHECK1-SAME: (ptr nocapture nofree nonnull readonly align 8 dereferenceable(8) [[ARG:%.*]], ptr nocapture nofree nonnull readonly align 8 dereferenceable(8) [[ARG1:%.*]]) #[[ATTR10:[0-9]+]] {
659; CHECK1-NEXT:  entry:
660; CHECK1-NEXT:    [[TMP2:%.*]] = load ptr, ptr [[ARG1]], align 8
661; CHECK1-NEXT:    [[TMP4:%.*]] = load ptr, ptr [[ARG]], align 8
662; CHECK1-NEXT:    [[TMP5:%.*]] = load i32, ptr [[TMP4]], align 4
663; CHECK1-NEXT:    [[TMP6:%.*]] = load i32, ptr [[TMP2]], align 4
664; CHECK1-NEXT:    [[ADD:%.*]] = add nsw i32 [[TMP5]], [[TMP6]]
665; CHECK1-NEXT:    store i32 [[ADD]], ptr [[TMP4]], align 4
666; CHECK1-NEXT:    ret void
667; CHECK2-LABEL: define {{[^@]+}}@.omp.reduction.reduction_func
668; CHECK2-SAME: (ptr nocapture nofree nonnull readonly align 8 dereferenceable(8) [[ARG:%.*]], ptr nocapture nofree nonnull readonly align 8 dereferenceable(8) [[ARG1:%.*]]) #[[ATTR10:[0-9]+]] {
669; CHECK2-NEXT:  entry:
670; CHECK2-NEXT:    [[TMP2:%.*]] = load ptr, ptr [[ARG1]], align 8
671; CHECK2-NEXT:    [[TMP4:%.*]] = load ptr, ptr [[ARG]], align 8
672; CHECK2-NEXT:    [[TMP5:%.*]] = load i32, ptr [[TMP4]], align 4
673; CHECK2-NEXT:    [[TMP6:%.*]] = load i32, ptr [[TMP2]], align 4
674; CHECK2-NEXT:    [[ADD:%.*]] = add nsw i32 [[TMP5]], [[TMP6]]
675; CHECK2-NEXT:    store i32 [[ADD]], ptr [[TMP4]], align 4
676; CHECK2-NEXT:    ret void
677entry:
678  %tmp2 = load ptr, ptr %arg1, align 8
679  %tmp4 = load ptr, ptr %arg, align 8
680  %tmp5 = load i32, ptr %tmp4, align 4
681  %tmp6 = load i32, ptr %tmp2, align 4
682  %add = add nsw i32 %tmp5, %tmp6
683  store i32 %add, ptr %tmp4, align 4
684  ret void
685}
686
687declare i32 @__kmpc_single(ptr, i32)
688
689declare void @__kmpc_end_single(ptr, i32)
690
691declare void @__kmpc_barrier(ptr, i32)
692
693declare i32 @__kmpc_global_thread_num(ptr) nofree nosync nounwind readonly
694
695declare i32 @__kmpc_reduce_nowait(ptr, i32, i32, i64, ptr, ptr, ptr)
696
697declare void @__kmpc_end_reduce_nowait(ptr, i32, ptr)
698
699declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture)
700
701declare !callback !2 void @__kmpc_fork_call(ptr, i32, ptr, ...)
702
703declare void @unknown()
704
705declare void @readonly() readonly
706
707declare void @readnone() readnone
708
709!llvm.module.flags = !{!8}
710
711!0 = !{i32 1, !"wchar_size", i32 4}
712!1 = !{!"clang"}
713!2 = !{!3}
714!3 = !{i64 2, i64 -1, i64 -1, i1 true}
715!4 = !{!5, !5, i64 0}
716!5 = !{!"int", !6, i64 0}
717!6 = !{!"omnipotent char", !7, i64 0}
718!7 = !{!"Simple C/C++ TBAA"}
719!8 = !{i32 7, !"openmp", i32 50}
720