• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; XFAIL: *
2; RUN: opt < %s -newgvn -S | FileCheck %s
3
4%struct.A = type { i32 (...)** }
5@_ZTV1A = available_externally unnamed_addr constant [4 x i8*] [i8* null, i8* bitcast (i8** @_ZTI1A to i8*), i8* bitcast (i32 (%struct.A*)* @_ZN1A3fooEv to i8*), i8* bitcast (i32 (%struct.A*)* @_ZN1A3barEv to i8*)], align 8
6@_ZTI1A = external constant i8*
7
8; Checks if indirect calls can be replaced with direct
9; assuming that %vtable == @_ZTV1A (with alignment).
10; Checking const propagation across other BBs
11; CHECK-LABEL: define void @_Z1gb(
12
13define void @_Z1gb(i1 zeroext %p) {
14entry:
15  %call = tail call noalias i8* @_Znwm(i64 8) #4
16  %0 = bitcast i8* %call to %struct.A*
17  tail call void @_ZN1AC1Ev(%struct.A* %0) #1
18  %1 = bitcast i8* %call to i8***
19  %vtable = load i8**, i8*** %1, align 8
20  %cmp.vtables = icmp eq i8** %vtable, getelementptr inbounds ([4 x i8*], [4 x i8*]* @_ZTV1A, i64 0, i64 2)
21  tail call void @llvm.assume(i1 %cmp.vtables)
22  br i1 %p, label %if.then, label %if.else
23
24if.then:                                          ; preds = %entry
25  %vtable1.cast = bitcast i8** %vtable to i32 (%struct.A*)**
26  %2 = load i32 (%struct.A*)*, i32 (%struct.A*)** %vtable1.cast, align 8
27
28  ; CHECK: call i32 @_ZN1A3fooEv(
29  %call2 = tail call i32 %2(%struct.A* %0) #1
30
31  br label %if.end
32
33if.else:                                          ; preds = %entry
34  %vfn47 = getelementptr inbounds i8*, i8** %vtable, i64 1
35  %vfn4 = bitcast i8** %vfn47 to i32 (%struct.A*)**
36
37  ; CHECK: call i32 @_ZN1A3barEv(
38  %3 = load i32 (%struct.A*)*, i32 (%struct.A*)** %vfn4, align 8
39
40  %call5 = tail call i32 %3(%struct.A* %0) #1
41  br label %if.end
42
43if.end:                                           ; preds = %if.else, %if.then
44  ret void
45}
46
47; Check integration with invariant.group handling
48; CHECK-LABEL: define void @invariantGroupHandling(i1 zeroext %p) {
49define void @invariantGroupHandling(i1 zeroext %p) {
50entry:
51  %call = tail call noalias i8* @_Znwm(i64 8) #4
52  %0 = bitcast i8* %call to %struct.A*
53  tail call void @_ZN1AC1Ev(%struct.A* %0) #1
54  %1 = bitcast i8* %call to i8***
55  %vtable = load i8**, i8*** %1, align 8, !invariant.group !0
56  %cmp.vtables = icmp eq i8** %vtable, getelementptr inbounds ([4 x i8*], [4 x i8*]* @_ZTV1A, i64 0, i64 2)
57  tail call void @llvm.assume(i1 %cmp.vtables)
58  br i1 %p, label %if.then, label %if.else
59
60if.then:                                          ; preds = %entry
61  %vtable1.cast = bitcast i8** %vtable to i32 (%struct.A*)**
62  %2 = load i32 (%struct.A*)*, i32 (%struct.A*)** %vtable1.cast, align 8
63
64; CHECK: call i32 @_ZN1A3fooEv(
65  %call2 = tail call i32 %2(%struct.A* %0) #1
66  %vtable1 = load i8**, i8*** %1, align 8, !invariant.group !0
67  %vtable2.cast = bitcast i8** %vtable1 to i32 (%struct.A*)**
68  %call1 = load i32 (%struct.A*)*, i32 (%struct.A*)** %vtable2.cast, align 8
69; CHECK: call i32 @_ZN1A3fooEv(
70  %callx = tail call i32 %call1(%struct.A* %0) #1
71
72  %vtable2 = load i8**, i8*** %1, align 8, !invariant.group !0
73  %vtable3.cast = bitcast i8** %vtable2 to i32 (%struct.A*)**
74  %call4 = load i32 (%struct.A*)*, i32 (%struct.A*)** %vtable3.cast, align 8
75; CHECK: call i32 @_ZN1A3fooEv(
76  %cally = tail call i32 %call4(%struct.A* %0) #1
77
78  %b = bitcast i8* %call to %struct.A**
79  %vtable3 = load %struct.A*, %struct.A** %b, align 8, !invariant.group !0
80  %vtable4.cast = bitcast %struct.A* %vtable3 to i32 (%struct.A*)**
81  %vfun = load i32 (%struct.A*)*, i32 (%struct.A*)** %vtable4.cast, align 8
82; CHECK: call i32 @_ZN1A3fooEv(
83  %unknown = tail call i32 %vfun(%struct.A* %0) #1
84
85  br label %if.end
86
87if.else:                                          ; preds = %entry
88  %vfn47 = getelementptr inbounds i8*, i8** %vtable, i64 1
89  %vfn4 = bitcast i8** %vfn47 to i32 (%struct.A*)**
90
91  ; CHECK: call i32 @_ZN1A3barEv(
92  %3 = load i32 (%struct.A*)*, i32 (%struct.A*)** %vfn4, align 8
93
94  %call5 = tail call i32 %3(%struct.A* %0) #1
95  br label %if.end
96
97if.end:                                           ; preds = %if.else, %if.then
98  ret void
99}
100
101
102; Checking const propagation in the same BB
103; CHECK-LABEL: define i32 @main()
104
105define i32 @main() {
106entry:
107  %call = tail call noalias i8* @_Znwm(i64 8)
108  %0 = bitcast i8* %call to %struct.A*
109  tail call void @_ZN1AC1Ev(%struct.A* %0)
110  %1 = bitcast i8* %call to i8***
111  %vtable = load i8**, i8*** %1, align 8
112  %cmp.vtables = icmp eq i8** %vtable, getelementptr inbounds ([4 x i8*], [4 x i8*]* @_ZTV1A, i64 0, i64 2)
113  tail call void @llvm.assume(i1 %cmp.vtables)
114  %vtable1.cast = bitcast i8** %vtable to i32 (%struct.A*)**
115
116  ; CHECK: call i32 @_ZN1A3fooEv(
117  %2 = load i32 (%struct.A*)*, i32 (%struct.A*)** %vtable1.cast, align 8
118
119  %call2 = tail call i32 %2(%struct.A* %0)
120  ret i32 0
121}
122
123; This tests checks const propatation with fcmp instruction.
124; CHECK-LABEL: define float @_Z1gf(float %p)
125
126define float @_Z1gf(float %p) {
127entry:
128  %p.addr = alloca float, align 4
129  %f = alloca float, align 4
130  store float %p, float* %p.addr, align 4
131
132  store float 3.000000e+00, float* %f, align 4
133  %0 = load float, float* %p.addr, align 4
134  %1 = load float, float* %f, align 4
135  %cmp = fcmp oeq float %1, %0 ; note const on lhs
136  call void @llvm.assume(i1 %cmp)
137
138  ; CHECK: ret float 3.000000e+00
139  ret float %0
140}
141
142; CHECK-LABEL: define float @_Z1hf(float %p)
143
144define float @_Z1hf(float %p) {
145entry:
146  %p.addr = alloca float, align 4
147  store float %p, float* %p.addr, align 4
148
149  %0 = load float, float* %p.addr, align 4
150  %cmp = fcmp nnan ueq float %0, 3.000000e+00
151  call void @llvm.assume(i1 %cmp)
152
153  ; CHECK: ret float 3.000000e+00
154  ret float %0
155}
156
157; CHECK-LABEL: define float @_Z1if(float %p)
158define float @_Z1if(float %p) {
159entry:
160  %p.addr = alloca float, align 4
161  store float %p, float* %p.addr, align 4
162
163  %0 = load float, float* %p.addr, align 4
164  %cmp = fcmp ueq float %0, 3.000000e+00 ; no nnan flag - can't propagate
165  call void @llvm.assume(i1 %cmp)
166
167  ; CHECK-NOT: ret float 3.000000e+00
168  ret float %0
169}
170
171; This test checks if constant propagation works for multiple node edges
172; CHECK-LABEL: define i32 @_Z1ii(i32 %p)
173define i32 @_Z1ii(i32 %p) {
174entry:
175  %cmp = icmp eq i32 %p, 42
176  call void @llvm.assume(i1 %cmp)
177
178  ; CHECK: br i1 true, label %bb2, label %bb2
179  br i1 %cmp, label %bb2, label %bb2
180bb2:
181  call void @llvm.assume(i1 true)
182  ; CHECK: br i1 true, label %bb2, label %bb2
183  br i1 %cmp, label %bb2, label %bb2
184
185  ; CHECK: ret i32 42
186  ret i32 %p
187}
188
189; CHECK-LABEL: define i32 @_Z1ij(i32 %p)
190define i32 @_Z1ij(i32 %p) {
191entry:
192  %cmp = icmp eq i32 %p, 42
193  call void @llvm.assume(i1 %cmp)
194
195  ; CHECK: br i1 true, label %bb2, label %bb2
196  br i1 %cmp, label %bb2, label %bb2
197bb2:
198   ; CHECK-NOT: %cmp2 =
199  %cmp2 = icmp eq i32 %p, 42
200  ; CHECK-NOT: call void @llvm.assume(
201  call void @llvm.assume(i1 %cmp2)
202
203  ; CHECK: br i1 true, label %bb2, label %bb2
204  br i1 %cmp, label %bb2, label %bb2
205
206  ; CHECK: ret i32 42
207  ret i32 %p
208}
209
210; CHECK-LABEL: define i32 @_Z1ik(i32 %p)
211define i32 @_Z1ik(i32 %p) {
212entry:
213  %cmp = icmp eq i32 %p, 42
214  call void @llvm.assume(i1 %cmp)
215
216  ; CHECK: br i1 true, label %bb2, label %bb3
217  br i1 %cmp, label %bb2, label %bb3
218bb2:
219  ; CHECK-NOT: %cmp3 =
220  %cmp3 = icmp eq i32 %p, 43
221  ; CHECK: store i8 undef, i8* null
222  call void @llvm.assume(i1 %cmp3)
223  ret i32 15
224bb3:
225  ret i32 17
226}
227
228; This test checks if GVN can do the constant propagation correctly
229; when there are multiple uses of the same assume value in the
230; basic block that has a loop back-edge pointing to itself.
231;
232; CHECK-LABEL: define i32 @_Z1il(i32 %val, i1 %k)
233define i32 @_Z1il(i32 %val, i1 %k) {
234  br label %next
235
236next:
237; CHECK: tail call void @llvm.assume(i1 %k)
238; CHECK-NEXT: %cmp = icmp eq i32 %val, 50
239  tail call void @llvm.assume(i1 %k)
240  tail call void @llvm.assume(i1 %k)
241  %cmp = icmp eq i32 %val, 50
242  br i1 %cmp, label %next, label %meh
243
244meh:
245  ret i32 0
246}
247
248; This test checks if GVN can prevent the constant propagation correctly
249; in the successor blocks that are not dominated by the basic block
250; with the assume instruction.
251;
252; CHECK-LABEL: define i1 @_z1im(i32 %val, i1 %k, i1 %j)
253define i1 @_z1im(i32 %val, i1 %k, i1 %j) {
254  br i1 %j, label %next, label %meh
255
256next:
257; CHECK: tail call void @llvm.assume(i1 %k)
258; CHECK-NEXT: br label %meh
259  tail call void @llvm.assume(i1 %k)
260  tail call void @llvm.assume(i1 %k)
261  br label %meh
262
263meh:
264; CHECK: ret i1 %k
265  ret i1 %k
266}
267
268declare noalias i8* @_Znwm(i64)
269declare void @_ZN1AC1Ev(%struct.A*)
270declare void @llvm.assume(i1)
271declare i32 @_ZN1A3fooEv(%struct.A*)
272declare i32 @_ZN1A3barEv(%struct.A*)
273
274!0 = !{!"struct A"}
275