blob: ea2bec2cee3fea38367ea20366047d3910f23149 [file] [log] [blame]
Eric Christophercee313d2019-04-17 04:52:47 +00001; RUN: opt < %s -inline -S | FileCheck %s
2; RUN: opt < %s -passes='cgscc(inline)' -S | FileCheck %s
3
4; The verifier does catch problems with inlining of byval arguments that has a
5; different address space compared to the alloca. But running instcombine
6; after inline used to trigger asserts unless we disallow such inlining.
7; RUN: opt < %s -inline -instcombine -disable-output 2>/dev/null
8
9target datalayout = "p:32:32-p1:64:64-p2:16:16-n16:32:64"
10
11; Inlining a byval struct should cause an explicit copy into an alloca.
12
13 %struct.ss = type { i32, i64 }
14@.str = internal constant [10 x i8] c"%d, %lld\0A\00" ; <[10 x i8]*> [#uses=1]
15
16define internal void @f(%struct.ss* byval %b) nounwind {
17entry:
18 %tmp = getelementptr %struct.ss, %struct.ss* %b, i32 0, i32 0 ; <i32*> [#uses=2]
19 %tmp1 = load i32, i32* %tmp, align 4 ; <i32> [#uses=1]
20 %tmp2 = add i32 %tmp1, 1 ; <i32> [#uses=1]
21 store i32 %tmp2, i32* %tmp, align 4
22 ret void
23}
24
25declare i32 @printf(i8*, ...) nounwind
26
27define i32 @test1() nounwind {
28entry:
29 %S = alloca %struct.ss ; <%struct.ss*> [#uses=4]
30 %tmp1 = getelementptr %struct.ss, %struct.ss* %S, i32 0, i32 0 ; <i32*> [#uses=1]
31 store i32 1, i32* %tmp1, align 8
32 %tmp4 = getelementptr %struct.ss, %struct.ss* %S, i32 0, i32 1 ; <i64*> [#uses=1]
33 store i64 2, i64* %tmp4, align 4
34 call void @f( %struct.ss* byval %S ) nounwind
35 ret i32 0
36; CHECK: @test1()
37; CHECK: %S1 = alloca %struct.ss
38; CHECK: %S = alloca %struct.ss
39; CHECK: call void @llvm.memcpy
40; CHECK: ret i32 0
41}
42
43; Inlining a byval struct should NOT cause an explicit copy
44; into an alloca if the function is readonly
45
46define internal i32 @f2(%struct.ss* byval %b) nounwind readonly {
47entry:
48 %tmp = getelementptr %struct.ss, %struct.ss* %b, i32 0, i32 0 ; <i32*> [#uses=2]
49 %tmp1 = load i32, i32* %tmp, align 4 ; <i32> [#uses=1]
50 %tmp2 = add i32 %tmp1, 1 ; <i32> [#uses=1]
51 ret i32 %tmp2
52}
53
54define i32 @test2() nounwind {
55entry:
56 %S = alloca %struct.ss ; <%struct.ss*> [#uses=4]
57 %tmp1 = getelementptr %struct.ss, %struct.ss* %S, i32 0, i32 0 ; <i32*> [#uses=1]
58 store i32 1, i32* %tmp1, align 8
59 %tmp4 = getelementptr %struct.ss, %struct.ss* %S, i32 0, i32 1 ; <i64*> [#uses=1]
60 store i64 2, i64* %tmp4, align 4
61 %X = call i32 @f2( %struct.ss* byval %S ) nounwind
62 ret i32 %X
63; CHECK: @test2()
64; CHECK: %S = alloca %struct.ss
65; CHECK-NOT: call void @llvm.memcpy
66; CHECK: ret i32
67}
68
69
70; Inlining a byval with an explicit alignment needs to use *at least* that
71; alignment on the generated alloca.
72; PR8769
73declare void @g3(%struct.ss* %p)
74
75define internal void @f3(%struct.ss* byval align 64 %b) nounwind {
76 call void @g3(%struct.ss* %b) ;; Could make alignment assumptions!
77 ret void
78}
79
80define void @test3() nounwind {
81entry:
82 %S = alloca %struct.ss, align 1 ;; May not be aligned.
83 call void @f3( %struct.ss* byval align 64 %S) nounwind
84 ret void
85; CHECK: @test3()
86; CHECK: %S1 = alloca %struct.ss, align 64
87; CHECK: %S = alloca %struct.ss
88; CHECK: call void @llvm.memcpy
89; CHECK: call void @g3(%struct.ss* %S1)
90; CHECK: ret void
91}
92
93
94; Inlining a byval struct should NOT cause an explicit copy
95; into an alloca if the function is readonly, but should increase an alloca's
96; alignment to satisfy an explicit alignment request.
97
98define internal i32 @f4(%struct.ss* byval align 64 %b) nounwind readonly {
99 call void @g3(%struct.ss* %b)
100 ret i32 4
101}
102
103define i32 @test4() nounwind {
104entry:
105 %S = alloca %struct.ss, align 2 ; <%struct.ss*> [#uses=4]
106 %X = call i32 @f4( %struct.ss* byval align 64 %S ) nounwind
107 ret i32 %X
108; CHECK: @test4()
109; CHECK: %S = alloca %struct.ss, align 64
110; CHECK-NOT: call void @llvm.memcpy
111; CHECK: call void @g3
112; CHECK: ret i32 4
113}
114
115%struct.S0 = type { i32 }
116
117@b = global %struct.S0 { i32 1 }, align 4
118@a = common global i32 0, align 4
119
120define internal void @f5(%struct.S0* byval nocapture readonly align 4 %p) {
121entry:
122 store i32 0, i32* getelementptr inbounds (%struct.S0, %struct.S0* @b, i64 0, i32 0), align 4
123 %f2 = getelementptr inbounds %struct.S0, %struct.S0* %p, i64 0, i32 0
124 %0 = load i32, i32* %f2, align 4
125 store i32 %0, i32* @a, align 4
126 ret void
127}
128
129define i32 @test5() {
130entry:
131 tail call void @f5(%struct.S0* byval align 4 @b)
132 %0 = load i32, i32* @a, align 4
133 ret i32 %0
134; CHECK: @test5()
135; CHECK: store i32 0, i32* getelementptr inbounds (%struct.S0, %struct.S0* @b, i64 0, i32 0), align 4
136; CHECK-NOT: load i32, i32* getelementptr inbounds (%struct.S0, %struct.S0* @b, i64 0, i32 0), align 4
137}
138
139; Inlining a byval struct that is in a different address space compared to the
140; alloca address space is at the moment not expected. That would need
141; adjustments inside the inlined function since the address space attribute of
142; the inlined argument changes.
143
144%struct.S1 = type { i32 }
145
146@d = addrspace(1) global %struct.S1 { i32 1 }, align 4
147@c = common addrspace(1) global i32 0, align 4
148
149define internal void @f5_as1(%struct.S1 addrspace(1)* byval nocapture readonly align 4 %p) {
150entry:
151 store i32 0, i32 addrspace(1)* getelementptr inbounds (%struct.S1, %struct.S1 addrspace(1)* @d, i64 0, i32 0), align 4
152 %f2 = getelementptr inbounds %struct.S1, %struct.S1 addrspace(1)* %p, i64 0, i32 0
153 %0 = load i32, i32 addrspace(1)* %f2, align 4
154 store i32 %0, i32 addrspace(1)* @c, align 4
155 ret void
156}
157
158define i32 @test5_as1() {
159entry:
160 tail call void @f5_as1(%struct.S1 addrspace(1)* byval align 4 @d)
161 %0 = load i32, i32 addrspace(1)* @c, align 4
162 ret i32 %0
163; CHECK: @test5_as1()
164; CHECK: call void @f5_as1
165}