1; RUN: opt < %s -function-attrs -S | FileCheck %s 2; RUN: opt < %s -passes=function-attrs -S | FileCheck %s 3 4; CHECK: define void @nouses-argworn-funrn(i32* nocapture readnone %.aaa) #0 { 5define void @nouses-argworn-funrn(i32* writeonly %.aaa) { 6nouses-argworn-funrn_entry: 7 ret void 8} 9 10; CHECK: define void @nouses-argworn-funro(i32* nocapture readnone %.aaa, i32* nocapture readonly %.bbb) #1 { 11define void @nouses-argworn-funro(i32* writeonly %.aaa, i32* %.bbb) { 12nouses-argworn-funro_entry: 13 %val = load i32 , i32* %.bbb 14 ret void 15} 16 17%_type_of_d-ccc = type <{ i8*, i8, i8, i8, i8 }> 18 19@d-ccc = internal global %_type_of_d-ccc <{ i8* null, i8 1, i8 13, i8 0, i8 -127 }>, align 8 20 21; CHECK: define void @nouses-argworn-funwo(i32* nocapture readnone %.aaa) #2 { 22define void @nouses-argworn-funwo(i32* writeonly %.aaa) { 23nouses-argworn-funwo_entry: 24 store i8 0, i8* getelementptr inbounds (%_type_of_d-ccc, %_type_of_d-ccc* @d-ccc, i32 0, i32 3) 25 ret void 26} 27 28; CHECK: define void @test_store(i8* nocapture writeonly %p) 29define void @test_store(i8* %p) { 30 store i8 0, i8* %p 31 ret void 32} 33 34@G = external global i8* 35; CHECK: define i8 @test_store_capture(i8* %p) 36define i8 @test_store_capture(i8* %p) { 37 store i8* %p, i8** @G 38 %p2 = load i8*, i8** @G 39 %v = load i8, i8* %p2 40 ret i8 %v 41} 42 43; CHECK: define void @test_addressing(i8* nocapture writeonly %p) 44define void @test_addressing(i8* %p) { 45 %gep = getelementptr i8, i8* %p, i64 8 46 %bitcast = bitcast i8* %gep to i32* 47 store i32 0, i32* %bitcast 48 ret void 49} 50 51; CHECK: define void @test_readwrite(i8* nocapture %p) 52define void @test_readwrite(i8* %p) { 53 %v = load i8, i8* %p 54 store i8 %v, i8* %p 55 ret void 56} 57 58; CHECK: define void @test_volatile(i8* %p) 59define void @test_volatile(i8* %p) { 60 store volatile i8 0, i8* %p 61 ret void 62} 63 64; CHECK: define void @test_atomicrmw(i8* nocapture %p) 65define void @test_atomicrmw(i8* %p) { 66 atomicrmw add i8* %p, i8 0 seq_cst 67 ret void 68} 69 70 71declare void @direct1_callee(i8* %p) 72 73; CHECK: define void @direct1(i8* %p) 74define void @direct1(i8* %p) { 75 call void @direct1_callee(i8* %p) 76 ret void 77} 78 79declare void @direct2_callee(i8* %p) writeonly 80 81; writeonly w/o nocapture is not enough 82; CHECK: define void @direct2(i8* %p) 83define void @direct2(i8* %p) { 84 call void @direct2_callee(i8* %p) 85 ; read back from global, read through pointer... 86 ret void 87} 88 89; CHECK: define void @direct2b(i8* nocapture writeonly %p) 90define void @direct2b(i8* %p) { 91 call void @direct2_callee(i8* nocapture %p) 92 ret void 93} 94 95declare void @direct3_callee(i8* nocapture writeonly %p) 96 97; CHECK: define void @direct3(i8* nocapture writeonly %p) 98define void @direct3(i8* %p) { 99 call void @direct3_callee(i8* %p) 100 ret void 101} 102 103; CHECK: define void @direct3b(i8* %p) 104define void @direct3b(i8* %p) { 105 call void @direct3_callee(i8* %p) ["may-read-and-capture"(i8* %p)] 106 ret void 107} 108 109; CHECK: define void @fptr_test1(i8* %p, void (i8*)* nocapture readonly %f) 110define void @fptr_test1(i8* %p, void (i8*)* %f) { 111 call void %f(i8* %p) 112 ret void 113} 114 115; CHECK: define void @fptr_test2(i8* nocapture writeonly %p, void (i8*)* nocapture readonly %f) 116define void @fptr_test2(i8* %p, void (i8*)* %f) { 117 call void %f(i8* nocapture writeonly %p) 118 ret void 119} 120 121; CHECK: define void @fptr_test3(i8* nocapture writeonly %p, void (i8*)* nocapture readonly %f) 122define void @fptr_test3(i8* %p, void (i8*)* %f) { 123 call void %f(i8* nocapture %p) writeonly 124 ret void 125} 126 127; CHECK: attributes #0 = { {{.*}}readnone{{.*}} } 128; CHECK: attributes #1 = { {{.*}}readonly{{.*}} } 129; CHECK: attributes #2 = { {{.*}}writeonly{{.*}} } 130