[DAG] TransformFPLoadStorePair - early out if we're not loading a simple type
[llvm-project.git] / llvm / test / Transforms / GVN / assume-equal.ll
blob2ca8f3384e8133b7073c2550c566d948f49c8ff4
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) {
13 entry:
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
23   
24   ; CHECK: call i32 @_ZN1A3fooEv(
25   %call2 = tail call i32 %0(ptr %call) #1
26   
27   br label %if.end
29 if.else:                                          ; preds = %entry
30   %vfn47 = getelementptr inbounds ptr, ptr %vtable, i64 1
31   
32   ; CHECK: call i32 @_ZN1A3barEv(
33   %1 = load ptr, ptr %vfn47, align 8
34   
35   %call5 = tail call i32 %1(ptr %call) #1
36   br label %if.end
38 if.end:                                           ; preds = %if.else, %if.then
39   ret void
42 ; Check integration with invariant.group handling
43 ; CHECK-LABEL: define void @invariantGroupHandling(i1 zeroext %p) {
44 define void @invariantGroupHandling(i1 zeroext %p) {
45 entry:
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
55   
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
62   
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
67   
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
72   
73   br label %if.end
75 if.else:                                          ; preds = %entry
76   %vfn47 = getelementptr inbounds ptr, ptr %vtable, i64 1
77   
78   ; CHECK: call i32 @_ZN1A3barEv(
79   %1 = load ptr, ptr %vfn47, align 8
80   
81   %call5 = tail call i32 %1(ptr %call) #1
82   br label %if.end
84 if.end:                                           ; preds = %if.else, %if.then
85   ret void
89 ; Checking const propagation in the same BB
90 ; CHECK-LABEL: define i32 @main()
92 define i32 @main() {
93 entry:
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)
99   
100   ; CHECK: call i32 @_ZN1A3fooEv(
101   %0 = load ptr, ptr %vtable, align 8
102   
103   %call2 = tail call i32 %0(ptr %call)
104   ret i32 0
107 ; This tests checks const propatation with fcmp instruction.
108 ; CHECK-LABEL: define float @_Z1gf(float %p)
110 define float @_Z1gf(float %p) {
111 entry:
112   %p.addr = alloca float, align 4
113   %f = alloca float, align 4
114   store float %p, ptr %p.addr, align 4
115   
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)
121   
122   ; CHECK: ret float 3.000000e+00
123   ret float %0
126 ; CHECK-LABEL: define float @_Z1hf(float %p)
128 define float @_Z1hf(float %p) {
129 entry:
130   %p.addr = alloca float, align 4
131   store float %p, ptr %p.addr, align 4
132   
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)
136   
137   ; CHECK: ret float 3.000000e+00
138   ret float %0
141 ; CHECK-LABEL: define float @_Z1if(float %p)
142 define float @_Z1if(float %p) {
143 entry:
144   %p.addr = alloca float, align 4
145   store float %p, ptr %p.addr, align 4
146   
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)
150   
151   ; CHECK-NOT: ret float 3.000000e+00
152   ret float %0
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) {
158 entry:
159   %cmp = icmp eq i32 %p, 42
160   call void @llvm.assume(i1 %cmp)
161   
162   ; CHECK: br i1 true, label %bb2, label %bb2
163   br i1 %cmp, label %bb2, label %bb2
164 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
168   
169   ; CHECK: ret i32 42
170   ret i32 %p
173 ; CHECK-LABEL: define i32 @_Z1ij(i32 %p)
174 define i32 @_Z1ij(i32 %p) {
175 entry:
176   %cmp = icmp eq i32 %p, 42
177   call void @llvm.assume(i1 %cmp)
178   
179   ; CHECK: br i1 true, label %bb2, label %bb2
180   br i1 %cmp, label %bb2, label %bb2
181 bb2:
182    ; CHECK-NOT: %cmp2 = 
183   %cmp2 = icmp eq i32 %p, 42
184   ; CHECK-NOT: call void @llvm.assume(
185   call void @llvm.assume(i1 %cmp2)
186   
187   ; CHECK: br i1 true, label %bb2, label %bb2
188   br i1 %cmp, label %bb2, label %bb2
189   
190   ; CHECK: ret i32 42
191   ret i32 %p
194 ; CHECK-LABEL: define i32 @_Z1ik(i32 %p)
195 define i32 @_Z1ik(i32 %p) {
196 entry:
197   %cmp = icmp eq i32 %p, 42
198   call void @llvm.assume(i1 %cmp)
199   
200   ; CHECK: br i1 true, label %bb2, label %bb3
201   br i1 %cmp, label %bb2, label %bb3
202 bb2:
203   ; CHECK-NOT: %cmp3 = 
204   %cmp3 = icmp eq i32 %p, 43
205   ; CHECK: store i8 poison, ptr null
206   call void @llvm.assume(i1 %cmp3)
207   ret i32 15
208 bb3:
209   ret i32 17
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) {
218   br label %next
220 next:
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
228 meh:
229   ret i32 0 
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
240 next:
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)
245   br label %meh
247 meh:
248 ; CHECK: ret i1 %k
249   ret 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)
258 !0 = !{!"struct A"}