1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals
2 ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,TUNIT
3 ; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,CGSCC
5 target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
7 %struct.ident_t = type { i32, i32, i32, i32, ptr }
9 @0 = private unnamed_addr constant [23 x i8] c";unknown;unknown;0;0;;\00", align 1
10 @1 = private unnamed_addr constant %struct.ident_t { i32 0, i32 514, i32 0, i32 0, ptr @0 }, align 8
11 @2 = private unnamed_addr constant %struct.ident_t { i32 0, i32 2, i32 0, i32 0, ptr @0 }, align 8
13 ; %a is write only, %b is read only, neither is captured or freed, or ...
14 ; FIXME: %a and %b are *not* readnone!
17 ; CHECK: @[[GLOB0:[0-9]+]] = private unnamed_addr constant [23 x i8] c"
18 ; CHECK: @[[GLOB1:[0-9]+]] = private unnamed_addr constant [[STRUCT_IDENT_T:%.*]] { i32 0, i32 514, i32 0, i32 0, ptr @[[GLOB0]] }, align 8
19 ; CHECK: @[[GLOB2:[0-9]+]] = private unnamed_addr constant [[STRUCT_IDENT_T:%.*]] { i32 0, i32 2, i32 0, i32 0, ptr @[[GLOB0]] }, align 8
21 define dso_local void @func(ptr nocapture %a, ptr %b, i32 %N) local_unnamed_addr #0 {
22 ; TUNIT: Function Attrs: nounwind uwtable
23 ; TUNIT-LABEL: define {{[^@]+}}@func
24 ; TUNIT-SAME: (ptr nocapture nofree writeonly [[A:%.*]], ptr nocapture nofree readonly [[B:%.*]], i32 [[N:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
26 ; TUNIT-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 8
27 ; TUNIT-NEXT: [[B_ADDR:%.*]] = alloca ptr, align 8
28 ; TUNIT-NEXT: [[N_ADDR:%.*]] = alloca i32, align 4
29 ; TUNIT-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 8
30 ; TUNIT-NEXT: store ptr [[B]], ptr [[B_ADDR]], align 8
31 ; TUNIT-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr noundef nonnull align 8 dereferenceable(24) @[[GLOB2]], i32 noundef 3, ptr noundef nonnull @.omp_outlined., ptr noalias nocapture nofree nonnull readnone align 4 dereferenceable(4) undef, ptr noalias nocapture nofree noundef nonnull readonly align 8 dereferenceable(8) [[A_ADDR]], ptr noalias nocapture nofree noundef nonnull readonly align 8 dereferenceable(8) [[B_ADDR]])
32 ; TUNIT-NEXT: ret void
34 ; CGSCC: Function Attrs: nounwind uwtable
35 ; CGSCC-LABEL: define {{[^@]+}}@func
36 ; CGSCC-SAME: (ptr nocapture nofree [[A:%.*]], ptr nofree [[B:%.*]], i32 [[N:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
38 ; CGSCC-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 8
39 ; CGSCC-NEXT: [[B_ADDR:%.*]] = alloca ptr, align 8
40 ; CGSCC-NEXT: [[N_ADDR:%.*]] = alloca i32, align 4
41 ; CGSCC-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 8
42 ; CGSCC-NEXT: store ptr [[B]], ptr [[B_ADDR]], align 8
43 ; CGSCC-NEXT: store i32 199, ptr [[N_ADDR]], align 4
44 ; CGSCC-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr noundef nonnull align 8 dereferenceable(24) @[[GLOB2]], i32 noundef 3, ptr noundef nonnull @.omp_outlined., ptr noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[N_ADDR]], ptr noalias nocapture nofree noundef nonnull readonly align 8 dereferenceable(8) [[A_ADDR]], ptr noalias nocapture nofree noundef nonnull readonly align 8 dereferenceable(8) [[B_ADDR]])
45 ; CGSCC-NEXT: ret void
48 %a.addr = alloca ptr, align 8
49 %b.addr = alloca ptr, align 8
50 %N.addr = alloca i32, align 4
51 store ptr %a, ptr %a.addr, align 8
52 store ptr %b, ptr %b.addr, align 8
53 store i32 199, ptr %N.addr, align 4
54 call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr nonnull @2, i32 3, ptr @.omp_outlined., ptr nonnull %N.addr, ptr nonnull %a.addr, ptr nonnull %b.addr)
58 ; FIXME: %N should not be loaded but 199 should be used.
60 define internal void @.omp_outlined.(ptr noalias nocapture readonly %.global_tid., ptr noalias nocapture readnone %.bound_tid., ptr nocapture nonnull readonly align 4 dereferenceable(4) %N, ptr nocapture nonnull readonly align 8 dereferenceable(8) %a, ptr nocapture nonnull readonly align 8 dereferenceable(8) %b) #1 {
61 ; TUNIT: Function Attrs: alwaysinline nofree norecurse nounwind uwtable
62 ; TUNIT-LABEL: define {{[^@]+}}@.omp_outlined.
63 ; TUNIT-SAME: (ptr noalias nocapture nofree readonly [[DOTGLOBAL_TID_:%.*]], ptr noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]], ptr noalias nocapture nofree noundef nonnull readnone align 4 dereferenceable(4) [[N:%.*]], ptr noalias nocapture nofree noundef nonnull readonly align 8 dereferenceable(8) [[A:%.*]], ptr noalias nocapture nofree noundef nonnull readonly align 8 dereferenceable(8) [[B:%.*]]) #[[ATTR1:[0-9]+]] {
65 ; TUNIT-NEXT: [[DOTOMP_LB:%.*]] = alloca i32, align 4
66 ; TUNIT-NEXT: [[DOTOMP_UB:%.*]] = alloca i32, align 4
67 ; TUNIT-NEXT: [[DOTOMP_STRIDE:%.*]] = alloca i32, align 4
68 ; TUNIT-NEXT: [[DOTOMP_IS_LAST:%.*]] = alloca i32, align 4
69 ; TUNIT-NEXT: br label [[OMP_PRECOND_THEN:%.*]]
70 ; TUNIT: omp.precond.then:
71 ; TUNIT-NEXT: call void @llvm.lifetime.start.p0(i64 noundef 4, ptr nocapture nofree noundef nonnull align 4 dereferenceable(4) [[DOTOMP_LB]]) #[[ATTR3:[0-9]+]]
72 ; TUNIT-NEXT: store i32 0, ptr [[DOTOMP_LB]], align 4
73 ; TUNIT-NEXT: call void @llvm.lifetime.start.p0(i64 noundef 4, ptr nocapture nofree noundef nonnull align 4 dereferenceable(4) [[DOTOMP_UB]]) #[[ATTR3]]
74 ; TUNIT-NEXT: store i32 197, ptr [[DOTOMP_UB]], align 4
75 ; TUNIT-NEXT: call void @llvm.lifetime.start.p0(i64 noundef 4, ptr nocapture nofree noundef nonnull align 4 dereferenceable(4) [[DOTOMP_STRIDE]]) #[[ATTR3]]
76 ; TUNIT-NEXT: store i32 1, ptr [[DOTOMP_STRIDE]], align 4
77 ; TUNIT-NEXT: call void @llvm.lifetime.start.p0(i64 noundef 4, ptr nocapture nofree noundef nonnull align 4 dereferenceable(4) [[DOTOMP_IS_LAST]]) #[[ATTR3]]
78 ; TUNIT-NEXT: store i32 0, ptr [[DOTOMP_IS_LAST]], align 4
79 ; TUNIT-NEXT: [[TMP0:%.*]] = load i32, ptr [[DOTGLOBAL_TID_]], align 4
80 ; TUNIT-NEXT: call void @__kmpc_for_static_init_4(ptr noundef nonnull align 8 dereferenceable(24) @[[GLOB1]], i32 [[TMP0]], i32 noundef 34, ptr noundef nonnull align 4 dereferenceable(4) [[DOTOMP_IS_LAST]], ptr noundef nonnull align 4 dereferenceable(4) [[DOTOMP_LB]], ptr noundef nonnull align 4 dereferenceable(4) [[DOTOMP_UB]], ptr noundef nonnull align 4 dereferenceable(4) [[DOTOMP_STRIDE]], i32 noundef 1, i32 noundef 1)
81 ; TUNIT-NEXT: [[TMP1:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4
82 ; TUNIT-NEXT: [[CMP4:%.*]] = icmp sgt i32 [[TMP1]], 197
83 ; TUNIT-NEXT: [[COND:%.*]] = select i1 [[CMP4]], i32 197, i32 [[TMP1]]
84 ; TUNIT-NEXT: store i32 [[COND]], ptr [[DOTOMP_UB]], align 4
85 ; TUNIT-NEXT: [[TMP2:%.*]] = load i32, ptr [[DOTOMP_LB]], align 4
86 ; TUNIT-NEXT: [[CMP513:%.*]] = icmp sgt i32 [[TMP2]], [[COND]]
87 ; TUNIT-NEXT: br i1 [[CMP513]], label [[OMP_LOOP_EXIT:%.*]], label [[OMP_INNER_FOR_BODY_LR_PH:%.*]]
88 ; TUNIT: omp.inner.for.body.lr.ph:
89 ; TUNIT-NEXT: [[TMP3:%.*]] = load ptr, ptr [[B]], align 8
90 ; TUNIT-NEXT: [[TMP4:%.*]] = load ptr, ptr [[A]], align 8
91 ; TUNIT-NEXT: [[TMP5:%.*]] = sext i32 [[TMP2]] to i64
92 ; TUNIT-NEXT: [[TMP6:%.*]] = sext i32 [[COND]] to i64
93 ; TUNIT-NEXT: br label [[OMP_INNER_FOR_BODY:%.*]]
94 ; TUNIT: omp.inner.for.body:
95 ; TUNIT-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[OMP_INNER_FOR_BODY]] ], [ [[TMP5]], [[OMP_INNER_FOR_BODY_LR_PH]] ]
96 ; TUNIT-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
97 ; TUNIT-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds float, ptr [[TMP3]], i64 [[INDVARS_IV_NEXT]]
98 ; TUNIT-NEXT: [[TMP7:%.*]] = load float, ptr [[ARRAYIDX]], align 4
99 ; TUNIT-NEXT: [[CONV7:%.*]] = fadd float [[TMP7]], 1.000000e+00
100 ; TUNIT-NEXT: [[ARRAYIDX9:%.*]] = getelementptr inbounds float, ptr [[TMP4]], i64 [[INDVARS_IV_NEXT]]
101 ; TUNIT-NEXT: store float [[CONV7]], ptr [[ARRAYIDX9]], align 4
102 ; TUNIT-NEXT: [[CMP5:%.*]] = icmp slt i64 [[INDVARS_IV]], [[TMP6]]
103 ; TUNIT-NEXT: br i1 [[CMP5]], label [[OMP_INNER_FOR_BODY]], label [[OMP_LOOP_EXIT]]
104 ; TUNIT: omp.loop.exit:
105 ; TUNIT-NEXT: call void @__kmpc_for_static_fini(ptr noundef nonnull align 8 dereferenceable(24) @[[GLOB1]], i32 [[TMP0]])
106 ; TUNIT-NEXT: call void @llvm.lifetime.end.p0(i64 noundef 4, ptr nocapture nofree noundef nonnull align 4 dereferenceable(4) [[DOTOMP_IS_LAST]])
107 ; TUNIT-NEXT: call void @llvm.lifetime.end.p0(i64 noundef 4, ptr nocapture nofree noundef nonnull align 4 dereferenceable(4) [[DOTOMP_STRIDE]])
108 ; TUNIT-NEXT: call void @llvm.lifetime.end.p0(i64 noundef 4, ptr nocapture nofree noundef nonnull align 4 dereferenceable(4) [[DOTOMP_UB]])
109 ; TUNIT-NEXT: call void @llvm.lifetime.end.p0(i64 noundef 4, ptr nocapture nofree noundef nonnull align 4 dereferenceable(4) [[DOTOMP_LB]])
110 ; TUNIT-NEXT: br label [[OMP_PRECOND_END:%.*]]
111 ; TUNIT: omp.precond.end:
112 ; TUNIT-NEXT: ret void
114 ; CGSCC: Function Attrs: alwaysinline nofree norecurse nounwind uwtable
115 ; CGSCC-LABEL: define {{[^@]+}}@.omp_outlined.
116 ; CGSCC-SAME: (ptr noalias nocapture nofree readonly [[DOTGLOBAL_TID_:%.*]], ptr noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]], ptr noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[N:%.*]], ptr noalias nocapture nofree noundef nonnull readonly align 8 dereferenceable(8) [[A:%.*]], ptr noalias nocapture nofree noundef nonnull readonly align 8 dereferenceable(8) [[B:%.*]]) #[[ATTR1:[0-9]+]] {
118 ; CGSCC-NEXT: [[DOTOMP_LB:%.*]] = alloca i32, align 4
119 ; CGSCC-NEXT: [[DOTOMP_UB:%.*]] = alloca i32, align 4
120 ; CGSCC-NEXT: [[DOTOMP_STRIDE:%.*]] = alloca i32, align 4
121 ; CGSCC-NEXT: [[DOTOMP_IS_LAST:%.*]] = alloca i32, align 4
122 ; CGSCC-NEXT: [[TMP0:%.*]] = load i32, ptr [[N]], align 4
123 ; CGSCC-NEXT: [[SUB2:%.*]] = add nsw i32 [[TMP0]], -2
124 ; CGSCC-NEXT: [[CMP:%.*]] = icmp sgt i32 [[TMP0]], 1
125 ; CGSCC-NEXT: br i1 [[CMP]], label [[OMP_PRECOND_THEN:%.*]], label [[OMP_PRECOND_END:%.*]]
126 ; CGSCC: omp.precond.then:
127 ; CGSCC-NEXT: call void @llvm.lifetime.start.p0(i64 noundef 4, ptr nocapture nofree noundef nonnull align 4 dereferenceable(4) [[DOTOMP_LB]]) #[[ATTR3:[0-9]+]]
128 ; CGSCC-NEXT: store i32 0, ptr [[DOTOMP_LB]], align 4
129 ; CGSCC-NEXT: call void @llvm.lifetime.start.p0(i64 noundef 4, ptr nocapture nofree noundef nonnull align 4 dereferenceable(4) [[DOTOMP_UB]]) #[[ATTR3]]
130 ; CGSCC-NEXT: store i32 [[SUB2]], ptr [[DOTOMP_UB]], align 4
131 ; CGSCC-NEXT: call void @llvm.lifetime.start.p0(i64 noundef 4, ptr nocapture nofree noundef nonnull align 4 dereferenceable(4) [[DOTOMP_STRIDE]]) #[[ATTR3]]
132 ; CGSCC-NEXT: store i32 1, ptr [[DOTOMP_STRIDE]], align 4
133 ; CGSCC-NEXT: call void @llvm.lifetime.start.p0(i64 noundef 4, ptr nocapture nofree noundef nonnull align 4 dereferenceable(4) [[DOTOMP_IS_LAST]]) #[[ATTR3]]
134 ; CGSCC-NEXT: store i32 0, ptr [[DOTOMP_IS_LAST]], align 4
135 ; CGSCC-NEXT: [[TMP1:%.*]] = load i32, ptr [[DOTGLOBAL_TID_]], align 4
136 ; CGSCC-NEXT: call void @__kmpc_for_static_init_4(ptr noundef nonnull align 8 dereferenceable(24) @[[GLOB1]], i32 [[TMP1]], i32 noundef 34, ptr noundef nonnull align 4 dereferenceable(4) [[DOTOMP_IS_LAST]], ptr noundef nonnull align 4 dereferenceable(4) [[DOTOMP_LB]], ptr noundef nonnull align 4 dereferenceable(4) [[DOTOMP_UB]], ptr noundef nonnull align 4 dereferenceable(4) [[DOTOMP_STRIDE]], i32 noundef 1, i32 noundef 1)
137 ; CGSCC-NEXT: [[TMP2:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4
138 ; CGSCC-NEXT: [[CMP4:%.*]] = icmp sgt i32 [[TMP2]], [[SUB2]]
139 ; CGSCC-NEXT: [[COND:%.*]] = select i1 [[CMP4]], i32 [[SUB2]], i32 [[TMP2]]
140 ; CGSCC-NEXT: store i32 [[COND]], ptr [[DOTOMP_UB]], align 4
141 ; CGSCC-NEXT: [[TMP3:%.*]] = load i32, ptr [[DOTOMP_LB]], align 4
142 ; CGSCC-NEXT: [[CMP513:%.*]] = icmp sgt i32 [[TMP3]], [[COND]]
143 ; CGSCC-NEXT: br i1 [[CMP513]], label [[OMP_LOOP_EXIT:%.*]], label [[OMP_INNER_FOR_BODY_LR_PH:%.*]]
144 ; CGSCC: omp.inner.for.body.lr.ph:
145 ; CGSCC-NEXT: [[TMP4:%.*]] = load ptr, ptr [[B]], align 8
146 ; CGSCC-NEXT: [[TMP5:%.*]] = load ptr, ptr [[A]], align 8
147 ; CGSCC-NEXT: [[TMP6:%.*]] = sext i32 [[TMP3]] to i64
148 ; CGSCC-NEXT: [[TMP7:%.*]] = sext i32 [[COND]] to i64
149 ; CGSCC-NEXT: br label [[OMP_INNER_FOR_BODY:%.*]]
150 ; CGSCC: omp.inner.for.body:
151 ; CGSCC-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[OMP_INNER_FOR_BODY]] ], [ [[TMP6]], [[OMP_INNER_FOR_BODY_LR_PH]] ]
152 ; CGSCC-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
153 ; CGSCC-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds float, ptr [[TMP4]], i64 [[INDVARS_IV_NEXT]]
154 ; CGSCC-NEXT: [[TMP8:%.*]] = load float, ptr [[ARRAYIDX]], align 4
155 ; CGSCC-NEXT: [[CONV7:%.*]] = fadd float [[TMP8]], 1.000000e+00
156 ; CGSCC-NEXT: [[ARRAYIDX9:%.*]] = getelementptr inbounds float, ptr [[TMP5]], i64 [[INDVARS_IV_NEXT]]
157 ; CGSCC-NEXT: store float [[CONV7]], ptr [[ARRAYIDX9]], align 4
158 ; CGSCC-NEXT: [[CMP5:%.*]] = icmp slt i64 [[INDVARS_IV]], [[TMP7]]
159 ; CGSCC-NEXT: br i1 [[CMP5]], label [[OMP_INNER_FOR_BODY]], label [[OMP_LOOP_EXIT]]
160 ; CGSCC: omp.loop.exit:
161 ; CGSCC-NEXT: call void @__kmpc_for_static_fini(ptr noundef nonnull align 8 dereferenceable(24) @[[GLOB1]], i32 [[TMP1]])
162 ; CGSCC-NEXT: call void @llvm.lifetime.end.p0(i64 noundef 4, ptr nocapture nofree noundef nonnull align 4 dereferenceable(4) [[DOTOMP_IS_LAST]])
163 ; CGSCC-NEXT: call void @llvm.lifetime.end.p0(i64 noundef 4, ptr nocapture nofree noundef nonnull align 4 dereferenceable(4) [[DOTOMP_STRIDE]])
164 ; CGSCC-NEXT: call void @llvm.lifetime.end.p0(i64 noundef 4, ptr nocapture nofree noundef nonnull align 4 dereferenceable(4) [[DOTOMP_UB]])
165 ; CGSCC-NEXT: call void @llvm.lifetime.end.p0(i64 noundef 4, ptr nocapture nofree noundef nonnull align 4 dereferenceable(4) [[DOTOMP_LB]])
166 ; CGSCC-NEXT: br label [[OMP_PRECOND_END]]
167 ; CGSCC: omp.precond.end:
168 ; CGSCC-NEXT: ret void
171 %.omp.lb = alloca i32, align 4
172 %.omp.ub = alloca i32, align 4
173 %.omp.stride = alloca i32, align 4
174 %.omp.is_last = alloca i32, align 4
175 %0 = load i32, ptr %N, align 4
176 %sub2 = add nsw i32 %0, -2
177 %cmp = icmp sgt i32 %0, 1
178 br i1 %cmp, label %omp.precond.then, label %omp.precond.end
180 omp.precond.then: ; preds = %entry
181 call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %.omp.lb) #3
182 store i32 0, ptr %.omp.lb, align 4
183 call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %.omp.ub) #3
184 store i32 %sub2, ptr %.omp.ub, align 4
185 call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %.omp.stride) #3
186 store i32 1, ptr %.omp.stride, align 4
187 call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %.omp.is_last) #3
188 store i32 0, ptr %.omp.is_last, align 4
189 %1 = load i32, ptr %.global_tid., align 4
190 call void @__kmpc_for_static_init_4(ptr nonnull @1, i32 %1, i32 34, ptr nonnull %.omp.is_last, ptr nonnull %.omp.lb, ptr nonnull %.omp.ub, ptr nonnull %.omp.stride, i32 1, i32 1) #3
191 %2 = load i32, ptr %.omp.ub, align 4
192 %cmp4 = icmp sgt i32 %2, %sub2
193 %cond = select i1 %cmp4, i32 %sub2, i32 %2
194 store i32 %cond, ptr %.omp.ub, align 4
195 %3 = load i32, ptr %.omp.lb, align 4
196 %cmp513 = icmp sgt i32 %3, %cond
197 br i1 %cmp513, label %omp.loop.exit, label %omp.inner.for.body.lr.ph
199 omp.inner.for.body.lr.ph: ; preds = %omp.precond.then
200 %4 = load ptr, ptr %b, align 8
201 %5 = load ptr, ptr %a, align 8
202 %6 = sext i32 %3 to i64
203 %7 = sext i32 %cond to i64
204 br label %omp.inner.for.body
206 omp.inner.for.body: ; preds = %omp.inner.for.body, %omp.inner.for.body.lr.ph
207 %indvars.iv = phi i64 [ %indvars.iv.next, %omp.inner.for.body ], [ %6, %omp.inner.for.body.lr.ph ]
208 %indvars.iv.next = add nsw i64 %indvars.iv, 1
209 %arrayidx = getelementptr inbounds float, ptr %4, i64 %indvars.iv.next
210 %8 = load float, ptr %arrayidx, align 4
211 %conv7 = fadd float %8, 1.000000e+00
212 %arrayidx9 = getelementptr inbounds float, ptr %5, i64 %indvars.iv.next
213 store float %conv7, ptr %arrayidx9, align 4
214 %cmp5 = icmp slt i64 %indvars.iv, %7
215 br i1 %cmp5, label %omp.inner.for.body, label %omp.loop.exit
217 omp.loop.exit: ; preds = %omp.inner.for.body, %omp.precond.then
218 call void @__kmpc_for_static_fini(ptr nonnull @1, i32 %1)
219 call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %.omp.is_last) #3
220 call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %.omp.stride) #3
221 call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %.omp.ub) #3
222 call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %.omp.lb) #3
223 br label %omp.precond.end
225 omp.precond.end: ; preds = %omp.loop.exit, %entry
229 ; Function Attrs: argmemonly nounwind willreturn
230 declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #2
232 ; Function Attrs: argmemonly nounwind willreturn
233 declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) #2
235 declare dso_local void @__kmpc_for_static_init_4(ptr, i32, i32, ptr, ptr, ptr, ptr, i32, i32) local_unnamed_addr
237 ; Function Attrs: nounwind
238 declare void @__kmpc_for_static_fini(ptr, i32) local_unnamed_addr #3
240 ; Function Attrs: nounwind
241 declare !callback !1 void @__kmpc_fork_call(ptr, i32, ptr, ...) local_unnamed_addr #3
243 attributes #0 = { nounwind uwtable }
244 attributes #1 = { alwaysinline nofree norecurse nounwind uwtable }
245 attributes #2 = { nounwind }
247 !llvm.module.flags = !{!0}
249 !0 = !{i32 7, !"openmp", i32 50}
251 !2 = !{i64 2, i64 -1, i64 -1, i1 true}
253 ; CHECK: attributes #[[ATTR0:[0-9]+]] = { nounwind uwtable }
254 ; CHECK: attributes #[[ATTR1:[0-9]+]] = { alwaysinline nofree norecurse nounwind uwtable }
255 ; CHECK: attributes #[[ATTR2:[0-9]+]] = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }
256 ; CHECK: attributes #[[ATTR3:[0-9]+]] = { memory(readwrite) }
258 ; CHECK: [[META0:![0-9]+]] = !{i32 7, !"openmp", i32 50}
259 ; CHECK: [[META1:![0-9]+]] = !{!2}
260 ; CHECK: [[META2:![0-9]+]] = !{i64 2, i64 -1, i64 -1, i1 true}
262 ;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line: