Re-land [openmp] Fix warnings when building on Windows with latest MSVC or Clang...
[llvm-project.git] / llvm / test / Transforms / EarlyCSE / memoryssa.ll
blob942b6f87011bf4b892ea29dcd46789e89b1101a2
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -S -passes='early-cse' -earlycse-debug-hash | FileCheck %s --check-prefix=CHECK-NOMEMSSA
3 ; RUN: opt < %s -S -passes='early-cse<memssa>' | FileCheck %s
4 ; RUN: opt < %s -S -passes='early-cse' | FileCheck %s --check-prefix=CHECK-NOMEMSSA
5 ; RUN: opt < %s -S -aa-pipeline=basic-aa -passes='early-cse<memssa>' | FileCheck %s
7 @G1 = global i32 zeroinitializer
8 @G2 = global i32 zeroinitializer
9 @G3 = global i32 zeroinitializer
11 ;; Simple load value numbering across non-clobbering store.
12 define i32 @test1() {
13 ; CHECK-NOMEMSSA-LABEL: @test1(
14 ; CHECK-NOMEMSSA-NEXT:    [[V1:%.*]] = load i32, ptr @G1, align 4
15 ; CHECK-NOMEMSSA-NEXT:    store i32 0, ptr @G2, align 4
16 ; CHECK-NOMEMSSA-NEXT:    [[V2:%.*]] = load i32, ptr @G1, align 4
17 ; CHECK-NOMEMSSA-NEXT:    [[DIFF:%.*]] = sub i32 [[V1]], [[V2]]
18 ; CHECK-NOMEMSSA-NEXT:    ret i32 [[DIFF]]
20 ; CHECK-LABEL: @test1(
21 ; CHECK-NEXT:    [[V1:%.*]] = load i32, ptr @G1, align 4
22 ; CHECK-NEXT:    store i32 0, ptr @G2, align 4
23 ; CHECK-NEXT:    ret i32 0
25   %V1 = load i32, ptr @G1
26   store i32 0, ptr @G2
27   %V2 = load i32, ptr @G1
28   %Diff = sub i32 %V1, %V2
29   ret i32 %Diff
32 ;; Simple dead store elimination across non-clobbering store.
33 define void @test2() {
34 ; CHECK-NOMEMSSA-LABEL: @test2(
35 ; CHECK-NOMEMSSA-NEXT:  entry:
36 ; CHECK-NOMEMSSA-NEXT:    [[V1:%.*]] = load i32, ptr @G1, align 4
37 ; CHECK-NOMEMSSA-NEXT:    store i32 0, ptr @G2, align 4
38 ; CHECK-NOMEMSSA-NEXT:    store i32 [[V1]], ptr @G1, align 4
39 ; CHECK-NOMEMSSA-NEXT:    ret void
41 ; CHECK-LABEL: @test2(
42 ; CHECK-NEXT:  entry:
43 ; CHECK-NEXT:    [[V1:%.*]] = load i32, ptr @G1, align 4
44 ; CHECK-NEXT:    store i32 0, ptr @G2, align 4
45 ; CHECK-NEXT:    ret void
47 entry:
48   %V1 = load i32, ptr @G1
49   store i32 0, ptr @G2
50   store i32 %V1, ptr @G1
51   ret void
54 ;; Check that memoryphi optimization happens during EarlyCSE, enabling
55 ;; more load CSE opportunities.
56 define void @test_memphiopt(i1 %c, ptr %p) {
57 ; CHECK-NOMEMSSA-LABEL: @test_memphiopt(
58 ; CHECK-NOMEMSSA-NEXT:  entry:
59 ; CHECK-NOMEMSSA-NEXT:    [[V1:%.*]] = load i32, ptr @G1, align 4
60 ; CHECK-NOMEMSSA-NEXT:    br i1 [[C:%.*]], label [[THEN:%.*]], label [[END:%.*]]
61 ; CHECK-NOMEMSSA:       then:
62 ; CHECK-NOMEMSSA-NEXT:    [[PV:%.*]] = load i32, ptr [[P:%.*]], align 4
63 ; CHECK-NOMEMSSA-NEXT:    br label [[END]]
64 ; CHECK-NOMEMSSA:       end:
65 ; CHECK-NOMEMSSA-NEXT:    [[V2:%.*]] = load i32, ptr @G1, align 4
66 ; CHECK-NOMEMSSA-NEXT:    [[SUM:%.*]] = add i32 [[V1]], [[V2]]
67 ; CHECK-NOMEMSSA-NEXT:    store i32 [[SUM]], ptr @G2, align 4
68 ; CHECK-NOMEMSSA-NEXT:    ret void
70 ; CHECK-LABEL: @test_memphiopt(
71 ; CHECK-NEXT:  entry:
72 ; CHECK-NEXT:    [[V1:%.*]] = load i32, ptr @G1, align 4
73 ; CHECK-NEXT:    br i1 [[C:%.*]], label [[THEN:%.*]], label [[END:%.*]]
74 ; CHECK:       then:
75 ; CHECK-NEXT:    [[PV:%.*]] = load i32, ptr [[P:%.*]], align 4
76 ; CHECK-NEXT:    br label [[END]]
77 ; CHECK:       end:
78 ; CHECK-NEXT:    [[SUM:%.*]] = add i32 [[V1]], [[V1]]
79 ; CHECK-NEXT:    store i32 [[SUM]], ptr @G2, align 4
80 ; CHECK-NEXT:    ret void
82 entry:
83   %v1 = load i32, ptr @G1
84   br i1 %c, label %then, label %end
86 then:
87   %pv = load i32, ptr %p
88   store i32 %pv, ptr %p
89   br label %end
91 end:
92   %v2 = load i32, ptr @G1
93   %sum = add i32 %v1, %v2
94   store i32 %sum, ptr @G2
95   ret void
99 ;; Check that MemoryPhi optimization and MemoryUse re-optimization
100 ;; happens during EarlyCSE, enabling more load CSE opportunities.
101 define void @test_memphiopt2(i1 %c, ptr %p) {
102 ; CHECK-NOMEMSSA-LABEL: @test_memphiopt2(
103 ; CHECK-NOMEMSSA-NEXT:  entry:
104 ; CHECK-NOMEMSSA-NEXT:    [[V1:%.*]] = load i32, ptr @G1, align 4
105 ; CHECK-NOMEMSSA-NEXT:    store i32 [[V1]], ptr @G2, align 4
106 ; CHECK-NOMEMSSA-NEXT:    br i1 [[C:%.*]], label [[THEN:%.*]], label [[END:%.*]]
107 ; CHECK-NOMEMSSA:       then:
108 ; CHECK-NOMEMSSA-NEXT:    [[PV:%.*]] = load i32, ptr [[P:%.*]], align 4
109 ; CHECK-NOMEMSSA-NEXT:    br label [[END]]
110 ; CHECK-NOMEMSSA:       end:
111 ; CHECK-NOMEMSSA-NEXT:    [[V2:%.*]] = load i32, ptr @G1, align 4
112 ; CHECK-NOMEMSSA-NEXT:    store i32 [[V2]], ptr @G3, align 4
113 ; CHECK-NOMEMSSA-NEXT:    ret void
115 ; CHECK-LABEL: @test_memphiopt2(
116 ; CHECK-NEXT:  entry:
117 ; CHECK-NEXT:    [[V1:%.*]] = load i32, ptr @G1, align 4
118 ; CHECK-NEXT:    store i32 [[V1]], ptr @G2, align 4
119 ; CHECK-NEXT:    br i1 [[C:%.*]], label [[THEN:%.*]], label [[END:%.*]]
120 ; CHECK:       then:
121 ; CHECK-NEXT:    [[PV:%.*]] = load i32, ptr [[P:%.*]], align 4
122 ; CHECK-NEXT:    br label [[END]]
123 ; CHECK:       end:
124 ; CHECK-NEXT:    store i32 [[V1]], ptr @G3, align 4
125 ; CHECK-NEXT:    ret void
127 entry:
128   %v1 = load i32, ptr @G1
129   store i32 %v1, ptr @G2
130   br i1 %c, label %then, label %end
132 then:
133   %pv = load i32, ptr %p
134   store i32 %pv, ptr %p
135   br label %end
137 end:
138   %v2 = load i32, ptr @G1
139   store i32 %v2, ptr @G3
140   ret void
143 ;; Check that we respect lifetime.start/lifetime.end intrinsics when deleting
144 ;; stores that, without the lifetime calls, would be writebacks.
145 define void @test_writeback_lifetimes(ptr %p) {
146 ; CHECK-NOMEMSSA-LABEL: @test_writeback_lifetimes(
147 ; CHECK-NOMEMSSA-NEXT:  entry:
148 ; CHECK-NOMEMSSA-NEXT:    [[Q:%.*]] = getelementptr i32, ptr [[P:%.*]], i64 1
149 ; CHECK-NOMEMSSA-NEXT:    [[PV:%.*]] = load i32, ptr [[P]], align 4
150 ; CHECK-NOMEMSSA-NEXT:    [[QV:%.*]] = load i32, ptr [[Q]], align 4
151 ; CHECK-NOMEMSSA-NEXT:    call void @llvm.lifetime.end.p0(i64 8, ptr [[P]])
152 ; CHECK-NOMEMSSA-NEXT:    call void @llvm.lifetime.start.p0(i64 8, ptr [[P]])
153 ; CHECK-NOMEMSSA-NEXT:    store i32 [[PV]], ptr [[P]], align 4
154 ; CHECK-NOMEMSSA-NEXT:    store i32 [[QV]], ptr [[Q]], align 4
155 ; CHECK-NOMEMSSA-NEXT:    ret void
157 ; CHECK-LABEL: @test_writeback_lifetimes(
158 ; CHECK-NEXT:  entry:
159 ; CHECK-NEXT:    [[Q:%.*]] = getelementptr i32, ptr [[P:%.*]], i64 1
160 ; CHECK-NEXT:    [[PV:%.*]] = load i32, ptr [[P]], align 4
161 ; CHECK-NEXT:    [[QV:%.*]] = load i32, ptr [[Q]], align 4
162 ; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 8, ptr [[P]])
163 ; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 8, ptr [[P]])
164 ; CHECK-NEXT:    store i32 [[PV]], ptr [[P]], align 4
165 ; CHECK-NEXT:    store i32 [[QV]], ptr [[Q]], align 4
166 ; CHECK-NEXT:    ret void
168 entry:
169   %q = getelementptr i32, ptr %p, i64 1
170   %pv = load i32, ptr %p
171   %qv = load i32, ptr %q
172   call void @llvm.lifetime.end.p0(i64 8, ptr %p)
173   call void @llvm.lifetime.start.p0(i64 8, ptr %p)
174   store i32 %pv, ptr %p
175   store i32 %qv, ptr %q
176   ret void
179 ;; Check that we respect lifetime.start/lifetime.end intrinsics when deleting
180 ;; stores that, without the lifetime calls, would be writebacks.
181 define void @test_writeback_lifetimes_multi_arg(ptr %p, ptr %q) {
182 ; CHECK-NOMEMSSA-LABEL: @test_writeback_lifetimes_multi_arg(
183 ; CHECK-NOMEMSSA-NEXT:  entry:
184 ; CHECK-NOMEMSSA-NEXT:    [[PV:%.*]] = load i32, ptr [[P:%.*]], align 4
185 ; CHECK-NOMEMSSA-NEXT:    [[QV:%.*]] = load i32, ptr [[Q:%.*]], align 4
186 ; CHECK-NOMEMSSA-NEXT:    call void @llvm.lifetime.end.p0(i64 8, ptr [[P]])
187 ; CHECK-NOMEMSSA-NEXT:    call void @llvm.lifetime.start.p0(i64 8, ptr [[P]])
188 ; CHECK-NOMEMSSA-NEXT:    store i32 [[PV]], ptr [[P]], align 4
189 ; CHECK-NOMEMSSA-NEXT:    store i32 [[QV]], ptr [[Q]], align 4
190 ; CHECK-NOMEMSSA-NEXT:    ret void
192 ; CHECK-LABEL: @test_writeback_lifetimes_multi_arg(
193 ; CHECK-NEXT:  entry:
194 ; CHECK-NEXT:    [[PV:%.*]] = load i32, ptr [[P:%.*]], align 4
195 ; CHECK-NEXT:    [[QV:%.*]] = load i32, ptr [[Q:%.*]], align 4
196 ; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 8, ptr [[P]])
197 ; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 8, ptr [[P]])
198 ; CHECK-NEXT:    store i32 [[PV]], ptr [[P]], align 4
199 ; CHECK-NEXT:    store i32 [[QV]], ptr [[Q]], align 4
200 ; CHECK-NEXT:    ret void
202 entry:
203   %pv = load i32, ptr %p
204   %qv = load i32, ptr %q
205   call void @llvm.lifetime.end.p0(i64 8, ptr %p)
206   call void @llvm.lifetime.start.p0(i64 8, ptr %p)
207   store i32 %pv, ptr %p
208   store i32 %qv, ptr %q
209   ret void
212 declare void @llvm.lifetime.end.p0(i64, ptr)
213 declare void @llvm.lifetime.start.p0(i64, ptr)