1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes
2; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=2 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM
3; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-disable=false -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=2 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM
4; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-disable=false -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM
5; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal -attributor-disable=false -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_OPM,IS__CGSCC____,IS________NPM,IS__CGSCC_NPM
6target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
7
8; Test cases designed for the nosync function attribute.
9; FIXME's are used to indicate problems and missing attributes.
10
11; struct RT {
12;   char A;
13;   int B[10][20];
14;   char C;
15; };
16; struct ST {
17;   int X;
18;   double Y;
19;   struct RT Z;
20; };
21;
22; int *foo(struct ST *s) {
23;   return &s[1].Z.B[5][13];
24; }
25
26; TEST 1
27; non-convergent and readnone implies nosync
28%struct.RT = type { i8, [10 x [20 x i32]], i8 }
29%struct.ST = type { i32, double, %struct.RT }
30
31; IS__TUNIT____: Function Attrs: nofree nosync nounwind optsize readnone ssp uwtable
32; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind optsize readnone ssp uwtable
33define i32* @foo(%struct.ST* %s) nounwind uwtable readnone optsize ssp {
34; CHECK-LABEL: define {{[^@]+}}@foo
35; CHECK-SAME: (%struct.ST* nofree readnone "no-capture-maybe-returned" [[S:%.*]])
36; CHECK-NEXT:  entry:
37; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_ST:%.*]], %struct.ST* [[S]], i64 1, i32 2, i32 1, i64 5, i64 13
38; CHECK-NEXT:    ret i32* [[ARRAYIDX]]
39;
40entry:
41  %arrayidx = getelementptr inbounds %struct.ST, %struct.ST* %s, i64 1, i32 2, i32 1, i64 5, i64 13
42  ret i32* %arrayidx
43}
44
45; TEST 2
46; atomic load with monotonic ordering
47; int load_monotonic(_Atomic int *num) {
48;   int n = atomic_load_explicit(num, memory_order_relaxed);
49;   return n;
50; }
51
52; IS__TUNIT____: Function Attrs: argmemonly nofree norecurse nosync nounwind uwtable
53; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind uwtable
54define i32 @load_monotonic(i32* nocapture readonly %0) norecurse nounwind uwtable {
55; CHECK-LABEL: define {{[^@]+}}@load_monotonic
56; CHECK-SAME: (i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[TMP0:%.*]])
57; CHECK-NEXT:    [[TMP2:%.*]] = load atomic i32, i32* [[TMP0]] monotonic, align 4
58; CHECK-NEXT:    ret i32 [[TMP2]]
59;
60  %2 = load atomic i32, i32* %0 monotonic, align 4
61  ret i32 %2
62}
63
64
65; TEST 3
66; atomic store with monotonic ordering.
67; void store_monotonic(_Atomic int *num) {
68;   atomic_load_explicit(num, memory_order_relaxed);
69; }
70
71; IS__TUNIT____: Function Attrs: argmemonly nofree norecurse nosync nounwind uwtable
72; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind uwtable
73define void @store_monotonic(i32* nocapture %0) norecurse nounwind uwtable {
74; CHECK-LABEL: define {{[^@]+}}@store_monotonic
75; CHECK-SAME: (i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[TMP0:%.*]])
76; CHECK-NEXT:    store atomic i32 10, i32* [[TMP0]] monotonic, align 4
77; CHECK-NEXT:    ret void
78;
79  store atomic i32 10, i32* %0 monotonic, align 4
80  ret void
81}
82
83; TEST 4 - negative, should not deduce nosync
84; atomic load with acquire ordering.
85; int load_acquire(_Atomic int *num) {
86;   int n = atomic_load_explicit(num, memory_order_acquire);
87;   return n;
88; }
89
90; IS__TUNIT____: Function Attrs: argmemonly nofree norecurse nounwind uwtable
91; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nounwind uwtable
92; CHECK-NOT: nosync
93define i32 @load_acquire(i32* nocapture readonly %0) norecurse nounwind uwtable {
94; CHECK-LABEL: define {{[^@]+}}@load_acquire
95; CHECK-SAME: (i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[TMP0:%.*]])
96; CHECK-NEXT:    [[TMP2:%.*]] = load atomic i32, i32* [[TMP0]] acquire, align 4
97; CHECK-NEXT:    ret i32 [[TMP2]]
98;
99  %2 = load atomic i32, i32* %0 acquire, align 4
100  ret i32 %2
101}
102
103; TEST 5 - negative, should not deduce nosync
104; atomic load with release ordering
105; void load_release(_Atomic int *num) {
106;   atomic_store_explicit(num, 10, memory_order_release);
107; }
108
109; IS__TUNIT____: Function Attrs: argmemonly nofree norecurse nounwind uwtable
110; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nounwind uwtable
111; CHECK-NOT: nosync
112define void @load_release(i32* nocapture %0) norecurse nounwind uwtable {
113; CHECK-LABEL: define {{[^@]+}}@load_release
114; CHECK-SAME: (i32* nocapture nofree writeonly align 4 [[TMP0:%.*]])
115; CHECK-NEXT:    store atomic volatile i32 10, i32* [[TMP0]] release, align 4
116; CHECK-NEXT:    ret void
117;
118  store atomic volatile i32 10, i32* %0 release, align 4
119  ret void
120}
121
122; TEST 6 - negative volatile, relaxed atomic
123
124; IS__TUNIT____: Function Attrs: argmemonly nofree norecurse nounwind uwtable
125; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nounwind uwtable
126; CHECK-NOT: nosync
127define void @load_volatile_release(i32* nocapture %0) norecurse nounwind uwtable {
128; CHECK-LABEL: define {{[^@]+}}@load_volatile_release
129; CHECK-SAME: (i32* nocapture nofree writeonly align 4 [[TMP0:%.*]])
130; CHECK-NEXT:    store atomic volatile i32 10, i32* [[TMP0]] release, align 4
131; CHECK-NEXT:    ret void
132;
133  store atomic volatile i32 10, i32* %0 release, align 4
134  ret void
135}
136
137; TEST 7 - negative, should not deduce nosync
138; volatile store.
139; void volatile_store(volatile int *num) {
140;   *num = 14;
141; }
142
143; IS__TUNIT____: Function Attrs: argmemonly nofree norecurse nounwind uwtable
144; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nounwind uwtable
145; CHECK-NOT: nosync
146define void @volatile_store(i32* %0) norecurse nounwind uwtable {
147; CHECK-LABEL: define {{[^@]+}}@volatile_store
148; CHECK-SAME: (i32* nofree align 4 [[TMP0:%.*]])
149; CHECK-NEXT:    store volatile i32 14, i32* [[TMP0]], align 4
150; CHECK-NEXT:    ret void
151;
152  store volatile i32 14, i32* %0, align 4
153  ret void
154}
155
156; TEST 8 - negative, should not deduce nosync
157; volatile load.
158; int volatile_load(volatile int *num) {
159;   int n = *num;
160;   return n;
161; }
162
163; IS__TUNIT____: Function Attrs: argmemonly nofree norecurse nounwind uwtable
164; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nounwind uwtable
165; CHECK-NOT: nosync
166define i32 @volatile_load(i32* %0) norecurse nounwind uwtable {
167; CHECK-LABEL: define {{[^@]+}}@volatile_load
168; CHECK-SAME: (i32* nofree align 4 [[TMP0:%.*]])
169; CHECK-NEXT:    [[TMP2:%.*]] = load volatile i32, i32* [[TMP0]], align 4
170; CHECK-NEXT:    ret i32 [[TMP2]]
171;
172  %2 = load volatile i32, i32* %0, align 4
173  ret i32 %2
174}
175
176; TEST 9
177
178; CHECK: Function Attrs: noinline nosync nounwind uwtable
179; CHECK-NEXT: declare void @nosync_function()
180declare void @nosync_function() noinline nounwind uwtable nosync
181
182; IS__TUNIT____: Function Attrs: noinline nosync nounwind uwtable
183; IS__CGSCC____: Function Attrs: noinline nosync nounwind uwtable
184define void @call_nosync_function() nounwind uwtable noinline {
185; CHECK-LABEL: define {{[^@]+}}@call_nosync_function()
186; CHECK-NEXT:    tail call void @nosync_function()
187; CHECK-NEXT:    ret void
188;
189  tail call void @nosync_function() noinline nounwind uwtable
190  ret void
191}
192
193; TEST 10 - negative, should not deduce nosync
194
195; CHECK: Function Attrs: noinline nounwind uwtable
196; CHECK-NEXT: declare void @might_sync()
197declare void @might_sync() noinline nounwind uwtable
198
199; IS__TUNIT____: Function Attrs: noinline nounwind uwtable
200; IS__CGSCC____: Function Attrs: noinline nounwind uwtable
201; CHECK-NOT: nosync
202define void @call_might_sync() nounwind uwtable noinline {
203; CHECK-LABEL: define {{[^@]+}}@call_might_sync()
204; CHECK-NEXT:    tail call void @might_sync()
205; CHECK-NEXT:    ret void
206;
207  tail call void @might_sync() noinline nounwind uwtable
208  ret void
209}
210
211; TEST 11 - positive, should deduce nosync
212; volatile operation in same scc but dead. Call volatile_load defined in TEST 8.
213
214; IS__TUNIT____: Function Attrs: nofree noinline noreturn nosync nounwind readnone uwtable
215; IS__CGSCC_OPM: Function Attrs: nofree noinline noreturn nosync nounwind readnone uwtable
216; IS__CGSCC_NPM: Function Attrs: nofree noinline norecurse noreturn nosync nounwind readnone uwtable
217define i32 @scc1(i32* %0) noinline nounwind uwtable {
218; CHECK-LABEL: define {{[^@]+}}@scc1
219; CHECK-SAME: (i32* nocapture nofree readnone [[TMP0:%.*]])
220; CHECK-NEXT:    unreachable
221;
222  tail call void @scc2(i32* %0);
223  %val = tail call i32 @volatile_load(i32* %0);
224  ret i32 %val;
225}
226
227; IS__TUNIT____: Function Attrs: nofree noinline noreturn nosync nounwind readnone uwtable
228; IS__CGSCC_OPM: Function Attrs: nofree noinline noreturn nosync nounwind readnone uwtable
229; IS__CGSCC_NPM: Function Attrs: nofree noinline norecurse noreturn nosync nounwind readnone uwtable
230define void @scc2(i32* %0) noinline nounwind uwtable {
231; CHECK-LABEL: define {{[^@]+}}@scc2
232; CHECK-SAME: (i32* nocapture nofree readnone [[TMP0:%.*]])
233; CHECK-NEXT:    unreachable
234;
235  tail call i32 @scc1(i32* %0);
236  ret void;
237}
238
239; TEST 12 - fences, negative
240;
241; void foo1(int *a, std::atomic<bool> flag){
242;   *a = 100;
243;   atomic_thread_fence(std::memory_order_release);
244;   flag.store(true, std::memory_order_relaxed);
245; }
246;
247; void bar(int *a, std::atomic<bool> flag){
248;   while(!flag.load(std::memory_order_relaxed))
249;     ;
250;
251;   atomic_thread_fence(std::memory_order_acquire);
252;   int b = *a;
253; }
254
255%"struct.std::atomic" = type { %"struct.std::__atomic_base" }
256%"struct.std::__atomic_base" = type { i8 }
257
258; CHECK-NOT: nosync
259define void @foo1(i32* %0, %"struct.std::atomic"* %1) {
260; CHECK-LABEL: define {{[^@]+}}@foo1
261; CHECK-SAME: (i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[TMP0:%.*]], %"struct.std::atomic"* nocapture nofree nonnull writeonly dereferenceable(1) [[TMP1:%.*]])
262; CHECK-NEXT:    store i32 100, i32* [[TMP0]], align 4
263; CHECK-NEXT:    fence release
264; CHECK-NEXT:    [[TMP3:%.*]] = getelementptr inbounds %"struct.std::atomic", %"struct.std::atomic"* [[TMP1]], i64 0, i32 0, i32 0
265; CHECK-NEXT:    store atomic i8 1, i8* [[TMP3]] monotonic, align 1
266; CHECK-NEXT:    ret void
267;
268  store i32 100, i32* %0, align 4
269  fence release
270  %3 = getelementptr inbounds %"struct.std::atomic", %"struct.std::atomic"* %1, i64 0, i32 0, i32 0
271  store atomic i8 1, i8* %3 monotonic, align 1
272  ret void
273}
274
275; CHECK-NOT: nosync
276define void @bar(i32* %0, %"struct.std::atomic"* %1) {
277; CHECK-LABEL: define {{[^@]+}}@bar
278; CHECK-SAME: (i32* nocapture nofree readnone [[TMP0:%.*]], %"struct.std::atomic"* nocapture nofree nonnull readonly dereferenceable(1) [[TMP1:%.*]])
279; CHECK-NEXT:    [[TMP3:%.*]] = getelementptr inbounds %"struct.std::atomic", %"struct.std::atomic"* [[TMP1]], i64 0, i32 0, i32 0
280; CHECK-NEXT:    br label [[TMP4:%.*]]
281; CHECK:       4:
282; CHECK-NEXT:    [[TMP5:%.*]] = load atomic i8, i8* [[TMP3]] monotonic, align 1
283; CHECK-NEXT:    [[TMP6:%.*]] = and i8 [[TMP5]], 1
284; CHECK-NEXT:    [[TMP7:%.*]] = icmp eq i8 [[TMP6]], 0
285; CHECK-NEXT:    br i1 [[TMP7]], label [[TMP4]], label [[TMP8:%.*]]
286; CHECK:       8:
287; CHECK-NEXT:    fence acquire
288; CHECK-NEXT:    ret void
289;
290  %3 = getelementptr inbounds %"struct.std::atomic", %"struct.std::atomic"* %1, i64 0, i32 0, i32 0
291  br label %4
292
2934:                                                ; preds = %4, %2
294  %5 = load atomic i8, i8* %3  monotonic, align 1
295  %6 = and i8 %5, 1
296  %7 = icmp eq i8 %6, 0
297  br i1 %7, label %4, label %8
298
2998:                                                ; preds = %4
300  fence acquire
301  ret void
302}
303
304; TEST 13 - Fence syncscope("singlethread") seq_cst
305; IS__TUNIT____: Function Attrs: nofree nosync nounwind willreturn
306; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind willreturn
307define void @foo1_singlethread(i32* %0, %"struct.std::atomic"* %1) {
308; CHECK-LABEL: define {{[^@]+}}@foo1_singlethread
309; CHECK-SAME: (i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[TMP0:%.*]], %"struct.std::atomic"* nocapture nofree nonnull writeonly dereferenceable(1) [[TMP1:%.*]])
310; CHECK-NEXT:    store i32 100, i32* [[TMP0]], align 4
311; CHECK-NEXT:    fence syncscope("singlethread") release
312; CHECK-NEXT:    [[TMP3:%.*]] = getelementptr inbounds %"struct.std::atomic", %"struct.std::atomic"* [[TMP1]], i64 0, i32 0, i32 0
313; CHECK-NEXT:    store atomic i8 1, i8* [[TMP3]] monotonic, align 1
314; CHECK-NEXT:    ret void
315;
316  store i32 100, i32* %0, align 4
317  fence syncscope("singlethread") release
318  %3 = getelementptr inbounds %"struct.std::atomic", %"struct.std::atomic"* %1, i64 0, i32 0, i32 0
319  store atomic i8 1, i8* %3 monotonic, align 1
320  ret void
321}
322
323; IS__TUNIT____: Function Attrs: nofree nosync nounwind
324; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind
325define void @bar_singlethread(i32* %0, %"struct.std::atomic"* %1) {
326; CHECK-LABEL: define {{[^@]+}}@bar_singlethread
327; CHECK-SAME: (i32* nocapture nofree readnone [[TMP0:%.*]], %"struct.std::atomic"* nocapture nofree nonnull readonly dereferenceable(1) [[TMP1:%.*]])
328; CHECK-NEXT:    [[TMP3:%.*]] = getelementptr inbounds %"struct.std::atomic", %"struct.std::atomic"* [[TMP1]], i64 0, i32 0, i32 0
329; CHECK-NEXT:    br label [[TMP4:%.*]]
330; CHECK:       4:
331; CHECK-NEXT:    [[TMP5:%.*]] = load atomic i8, i8* [[TMP3]] monotonic, align 1
332; CHECK-NEXT:    [[TMP6:%.*]] = and i8 [[TMP5]], 1
333; CHECK-NEXT:    [[TMP7:%.*]] = icmp eq i8 [[TMP6]], 0
334; CHECK-NEXT:    br i1 [[TMP7]], label [[TMP4]], label [[TMP8:%.*]]
335; CHECK:       8:
336; CHECK-NEXT:    fence syncscope("singlethread") acquire
337; CHECK-NEXT:    ret void
338;
339  %3 = getelementptr inbounds %"struct.std::atomic", %"struct.std::atomic"* %1, i64 0, i32 0, i32 0
340  br label %4
341
3424:                                                ; preds = %4, %2
343  %5 = load atomic i8, i8* %3  monotonic, align 1
344  %6 = and i8 %5, 1
345  %7 = icmp eq i8 %6, 0
346  br i1 %7, label %4, label %8
347
3488:                                                ; preds = %4
349  fence syncscope("singlethread") acquire
350  ret void
351}
352
353declare void @llvm.memcpy(i8* %dest, i8* %src, i32 %len, i1 %isvolatile)
354declare void @llvm.memset(i8* %dest, i8 %val, i32 %len, i1 %isvolatile)
355
356; TEST 14 - negative, checking volatile intrinsics.
357
358; It is odd to add nocapture but a result of the llvm.memcpy nocapture.
359;
360; IS__TUNIT____: Function Attrs: argmemonly nounwind
361; IS__CGSCC____: Function Attrs: argmemonly nounwind
362; CHECK-NOT: nosync
363define i32 @memcpy_volatile(i8* %ptr1, i8* %ptr2) {
364; CHECK-LABEL: define {{[^@]+}}@memcpy_volatile
365; CHECK-SAME: (i8* nocapture writeonly [[PTR1:%.*]], i8* nocapture readonly [[PTR2:%.*]])
366; CHECK-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i32(i8* noalias nocapture writeonly [[PTR1]], i8* noalias nocapture readonly [[PTR2]], i32 8, i1 true)
367; CHECK-NEXT:    ret i32 4
368;
369  call void @llvm.memcpy(i8* %ptr1, i8* %ptr2, i32 8, i1 1)
370  ret i32 4
371}
372
373; TEST 15 - positive, non-volatile intrinsic.
374
375; It is odd to add nocapture but a result of the llvm.memset nocapture.
376;
377; IS__TUNIT____: Function Attrs: argmemonly nosync
378; IS__CGSCC____: Function Attrs: argmemonly nosync
379define i32 @memset_non_volatile(i8* %ptr1, i8 %val) {
380; CHECK-LABEL: define {{[^@]+}}@memset_non_volatile
381; CHECK-SAME: (i8* nocapture writeonly [[PTR1:%.*]], i8 [[VAL:%.*]])
382; CHECK-NEXT:    call void @llvm.memset.p0i8.i32(i8* nocapture writeonly [[PTR1]], i8 [[VAL]], i32 8, i1 false)
383; CHECK-NEXT:    ret i32 4
384;
385  call void @llvm.memset(i8* %ptr1, i8 %val, i32 8, i1 0)
386  ret i32 4
387}
388
389; TEST 16 - negative, inline assembly.
390
391define i32 @inline_asm_test(i32 %x) {
392; CHECK-LABEL: define {{[^@]+}}@inline_asm_test
393; CHECK-SAME: (i32 [[X:%.*]])
394; CHECK-NEXT:    [[TMP1:%.*]] = call i32 asm "bswap $0", "=r,r"(i32 [[X]])
395; CHECK-NEXT:    ret i32 4
396;
397  call i32 asm "bswap $0", "=r,r"(i32 %x)
398  ret i32 4
399}
400
401declare void @readnone_test() convergent readnone
402
403; TEST 17 - negative. Convergent
404define void @convergent_readnone(){
405; CHECK-LABEL: define {{[^@]+}}@convergent_readnone()
406; CHECK-NEXT:    call void @readnone_test()
407; CHECK-NEXT:    ret void
408;
409  call void @readnone_test()
410  ret void
411}
412
413; CHECK: Function Attrs: nounwind
414; CHECK-NEXT: declare void @llvm.x86.sse2.clflush(i8*)
415declare void @llvm.x86.sse2.clflush(i8*)
416@a = common global i32 0, align 4
417
418; TEST 18 - negative. Synchronizing intrinsic
419
420; IS__TUNIT____: Function Attrs: nounwind
421; IS__CGSCC____: Function Attrs: nounwind
422; CHECK-NOT: nosync
423define void @i_totally_sync() {
424; CHECK-LABEL: define {{[^@]+}}@i_totally_sync()
425; CHECK-NEXT:    tail call void @llvm.x86.sse2.clflush(i8* nonnull align 4 dereferenceable(4) bitcast (i32* @a to i8*))
426; CHECK-NEXT:    ret void
427;
428  tail call void @llvm.x86.sse2.clflush(i8* bitcast (i32* @a to i8*))
429  ret void
430}
431
432declare float @llvm.cos(float %val) readnone
433
434; TEST 19 - positive, readnone & non-convergent intrinsic.
435
436; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn
437; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
438define i32 @cos_test(float %x) {
439; CHECK-LABEL: define {{[^@]+}}@cos_test
440; CHECK-SAME: (float [[X:%.*]])
441; CHECK-NEXT:    ret i32 4
442;
443  call float @llvm.cos(float %x)
444  ret i32 4
445}
446
447; IS__TUNIT____: Function Attrs: nosync nounwind
448; IS__CGSCC____: Function Attrs: nosync nounwind
449define float @cos_test2(float %x) {
450; CHECK-LABEL: define {{[^@]+}}@cos_test2
451; CHECK-SAME: (float [[X:%.*]])
452; CHECK-NEXT:    [[C:%.*]] = call float @llvm.cos.f32(float [[X]])
453; CHECK-NEXT:    ret float [[C]]
454;
455  %c = call float @llvm.cos(float %x)
456  ret float %c
457}
458