1 ; RUN: opt < %s -passes=gvn -S | FileCheck %s
3 %struct.A = type { ptr }
4 @_ZTV1A = available_externally unnamed_addr constant [4 x ptr] [ptr null, ptr @_ZTI1A, ptr @_ZN1A3fooEv, ptr @_ZN1A3barEv], align 8
5 @_ZTI1A = external constant ptr
7 ; Checks if indirect calls can be replaced with direct
8 ; assuming that %vtable == @_ZTV1A (with alignment).
9 ; Checking const propagation across other BBs
10 ; CHECK-LABEL: define void @_Z1gb(
12 define void @_Z1gb(i1 zeroext %p) {
14 %call = tail call noalias ptr @_Znwm(i64 8) #4
15 tail call void @_ZN1AC1Ev(ptr %call) #1
16 %vtable = load ptr, ptr %call, align 8
17 %cmp.vtables = icmp eq ptr %vtable, getelementptr inbounds ([4 x ptr], ptr @_ZTV1A, i64 0, i64 2)
18 tail call void @llvm.assume(i1 %cmp.vtables)
19 br i1 %p, label %if.then, label %if.else
21 if.then: ; preds = %entry
22 %0 = load ptr, ptr %vtable, align 8
24 ; CHECK: call i32 @_ZN1A3fooEv(
25 %call2 = tail call i32 %0(ptr %call) #1
29 if.else: ; preds = %entry
30 %vfn47 = getelementptr inbounds ptr, ptr %vtable, i64 1
32 ; CHECK: call i32 @_ZN1A3barEv(
33 %1 = load ptr, ptr %vfn47, align 8
35 %call5 = tail call i32 %1(ptr %call) #1
38 if.end: ; preds = %if.else, %if.then
42 ; Check integration with invariant.group handling
43 ; CHECK-LABEL: define void @invariantGroupHandling(i1 zeroext %p) {
44 define void @invariantGroupHandling(i1 zeroext %p) {
46 %call = tail call noalias ptr @_Znwm(i64 8) #4
47 tail call void @_ZN1AC1Ev(ptr %call) #1
48 %vtable = load ptr, ptr %call, align 8, !invariant.group !0
49 %cmp.vtables = icmp eq ptr %vtable, getelementptr inbounds ([4 x ptr], ptr @_ZTV1A, i64 0, i64 2)
50 tail call void @llvm.assume(i1 %cmp.vtables)
51 br i1 %p, label %if.then, label %if.else
53 if.then: ; preds = %entry
54 %0 = load ptr, ptr %vtable, align 8
56 ; CHECK: call i32 @_ZN1A3fooEv(
57 %call2 = tail call i32 %0(ptr %call) #1
58 %vtable1 = load ptr, ptr %call, align 8, !invariant.group !0
59 %call1 = load ptr, ptr %vtable1, align 8
60 ; CHECK: call i32 @_ZN1A3fooEv(
61 %callx = tail call i32 %call1(ptr %call) #1
63 %vtable2 = load ptr, ptr %call, align 8, !invariant.group !0
64 %call4 = load ptr, ptr %vtable2, align 8
65 ; CHECK: call i32 @_ZN1A3fooEv(
66 %cally = tail call i32 %call4(ptr %call) #1
68 %vtable3 = load ptr, ptr %call, align 8, !invariant.group !0
69 %vfun = load ptr, ptr %vtable3, align 8
70 ; CHECK: call i32 @_ZN1A3fooEv(
71 %unknown = tail call i32 %vfun(ptr %call) #1
75 if.else: ; preds = %entry
76 %vfn47 = getelementptr inbounds ptr, ptr %vtable, i64 1
78 ; CHECK: call i32 @_ZN1A3barEv(
79 %1 = load ptr, ptr %vfn47, align 8
81 %call5 = tail call i32 %1(ptr %call) #1
84 if.end: ; preds = %if.else, %if.then
89 ; Checking const propagation in the same BB
90 ; CHECK-LABEL: define i32 @main()
94 %call = tail call noalias ptr @_Znwm(i64 8)
95 tail call void @_ZN1AC1Ev(ptr %call)
96 %vtable = load ptr, ptr %call, align 8
97 %cmp.vtables = icmp eq ptr %vtable, getelementptr inbounds ([4 x ptr], ptr @_ZTV1A, i64 0, i64 2)
98 tail call void @llvm.assume(i1 %cmp.vtables)
100 ; CHECK: call i32 @_ZN1A3fooEv(
101 %0 = load ptr, ptr %vtable, align 8
103 %call2 = tail call i32 %0(ptr %call)
107 ; This tests checks const propatation with fcmp instruction.
108 ; CHECK-LABEL: define float @_Z1gf(float %p)
110 define float @_Z1gf(float %p) {
112 %p.addr = alloca float, align 4
113 %f = alloca float, align 4
114 store float %p, ptr %p.addr, align 4
116 store float 3.000000e+00, ptr %f, align 4
117 %0 = load float, ptr %p.addr, align 4
118 %1 = load float, ptr %f, align 4
119 %cmp = fcmp oeq float %1, %0 ; note const on lhs
120 call void @llvm.assume(i1 %cmp)
122 ; CHECK: ret float 3.000000e+00
126 ; CHECK-LABEL: define float @_Z1hf(float %p)
128 define float @_Z1hf(float %p) {
130 %p.addr = alloca float, align 4
131 store float %p, ptr %p.addr, align 4
133 %0 = load float, ptr %p.addr, align 4
134 %cmp = fcmp nnan ueq float %0, 3.000000e+00
135 call void @llvm.assume(i1 %cmp)
137 ; CHECK: ret float 3.000000e+00
141 ; CHECK-LABEL: define float @_Z1if(float %p)
142 define float @_Z1if(float %p) {
144 %p.addr = alloca float, align 4
145 store float %p, ptr %p.addr, align 4
147 %0 = load float, ptr %p.addr, align 4
148 %cmp = fcmp ueq float %0, 3.000000e+00 ; no nnan flag - can't propagate
149 call void @llvm.assume(i1 %cmp)
151 ; CHECK-NOT: ret float 3.000000e+00
155 ; This test checks if constant propagation works for multiple node edges
156 ; CHECK-LABEL: define i32 @_Z1ii(i32 %p)
157 define i32 @_Z1ii(i32 %p) {
159 %cmp = icmp eq i32 %p, 42
160 call void @llvm.assume(i1 %cmp)
162 ; CHECK: br i1 true, label %bb2, label %bb2
163 br i1 %cmp, label %bb2, label %bb2
165 call void @llvm.assume(i1 true)
166 ; CHECK: br i1 true, label %bb2, label %bb2
167 br i1 %cmp, label %bb2, label %bb2
173 ; CHECK-LABEL: define i32 @_Z1ij(i32 %p)
174 define i32 @_Z1ij(i32 %p) {
176 %cmp = icmp eq i32 %p, 42
177 call void @llvm.assume(i1 %cmp)
179 ; CHECK: br i1 true, label %bb2, label %bb2
180 br i1 %cmp, label %bb2, label %bb2
183 %cmp2 = icmp eq i32 %p, 42
184 ; CHECK-NOT: call void @llvm.assume(
185 call void @llvm.assume(i1 %cmp2)
187 ; CHECK: br i1 true, label %bb2, label %bb2
188 br i1 %cmp, label %bb2, label %bb2
194 ; CHECK-LABEL: define i32 @_Z1ik(i32 %p)
195 define i32 @_Z1ik(i32 %p) {
197 %cmp = icmp eq i32 %p, 42
198 call void @llvm.assume(i1 %cmp)
200 ; CHECK: br i1 true, label %bb2, label %bb3
201 br i1 %cmp, label %bb2, label %bb3
204 %cmp3 = icmp eq i32 %p, 43
205 ; CHECK: store i8 poison, ptr null
206 call void @llvm.assume(i1 %cmp3)
212 ; This test checks if GVN can do the constant propagation correctly
213 ; when there are multiple uses of the same assume value in the
214 ; basic block that has a loop back-edge pointing to itself.
216 ; CHECK-LABEL: define i32 @_Z1il(i32 %val, i1 %k)
217 define i32 @_Z1il(i32 %val, i1 %k) {
221 ; CHECK: tail call void @llvm.assume(i1 %k)
222 ; CHECK-NEXT: %cmp = icmp eq i32 %val, 50
223 tail call void @llvm.assume(i1 %k)
224 tail call void @llvm.assume(i1 %k)
225 %cmp = icmp eq i32 %val, 50
226 br i1 %cmp, label %next, label %meh
232 ; This test checks if GVN can prevent the constant propagation correctly
233 ; in the successor blocks that are not dominated by the basic block
234 ; with the assume instruction.
236 ; CHECK-LABEL: define i1 @_z1im(i32 %val, i1 %k, i1 %j)
237 define i1 @_z1im(i32 %val, i1 %k, i1 %j) {
238 br i1 %j, label %next, label %meh
241 ; CHECK: tail call void @llvm.assume(i1 %k)
242 ; CHECK-NEXT: br label %meh
243 tail call void @llvm.assume(i1 %k)
244 tail call void @llvm.assume(i1 %k)
252 declare noalias ptr @_Znwm(i64)
253 declare void @_ZN1AC1Ev(ptr)
254 declare void @llvm.assume(i1)
255 declare i32 @_ZN1A3fooEv(ptr)
256 declare i32 @_ZN1A3barEv(ptr)