Bump version to 19.1.0-rc3
[llvm-project.git] / llvm / test / Transforms / GVN / PRE / volatile.ll
blob532019119fdb705b790d8843379a682d29640fab
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; Tests that check our handling of volatile instructions encountered
3 ; when scanning for dependencies
4 ; RUN: opt -passes=gvn -enable-split-backedge-in-load-pre -S < %s | FileCheck %s
6 ; Check that we can bypass a volatile load when searching
7 ; for dependencies of a non-volatile load
8 define i32 @test1(ptr nocapture %p, ptr nocapture %q) {
9 ; CHECK-LABEL: @test1(
10 ; CHECK-NEXT:  entry:
11 ; CHECK-NEXT:    [[TMP0:%.*]] = load volatile i32, ptr [[Q:%.*]], align 4
12 ; CHECK-NEXT:    ret i32 0
14 entry:
15   %x = load i32, ptr %p
16   load volatile i32, ptr %q
17   %y = load i32, ptr %p
18   %add = sub i32 %y, %x
19   ret i32 %add
22 ; We can not value forward if the query instruction is
23 ; volatile, this would be (in effect) removing the volatile load
24 define i32 @test2(ptr nocapture %p, ptr nocapture %q) {
25 ; CHECK-LABEL: @test2(
26 ; CHECK-NEXT:  entry:
27 ; CHECK-NEXT:    [[X:%.*]] = load i32, ptr [[P:%.*]], align 4
28 ; CHECK-NEXT:    [[Y:%.*]] = load volatile i32, ptr [[P]], align 4
29 ; CHECK-NEXT:    [[ADD:%.*]] = sub i32 [[Y]], [[X]]
30 ; CHECK-NEXT:    ret i32 [[ADD]]
32 entry:
33   %x = load i32, ptr %p
34   %y = load volatile i32, ptr %p
35   %add = sub i32 %y, %x
36   ret i32 %add
39 ; If the query instruction is itself volatile, we *cannot*
40 ; reorder it even if p and q are noalias
41 define i32 @test3(ptr noalias nocapture %p, ptr noalias nocapture %q) {
42 ; CHECK-LABEL: @test3(
43 ; CHECK-NEXT:  entry:
44 ; CHECK-NEXT:    [[X:%.*]] = load i32, ptr [[P:%.*]], align 4
45 ; CHECK-NEXT:    [[TMP0:%.*]] = load volatile i32, ptr [[Q:%.*]], align 4
46 ; CHECK-NEXT:    [[Y:%.*]] = load volatile i32, ptr [[P]], align 4
47 ; CHECK-NEXT:    [[ADD:%.*]] = sub i32 [[Y]], [[X]]
48 ; CHECK-NEXT:    ret i32 [[ADD]]
50 entry:
51   %x = load i32, ptr %p
52   load volatile i32, ptr %q
53   %y = load volatile i32, ptr %p
54   %add = sub i32 %y, %x
55   ret i32 %add
58 ; If an encountered instruction is both volatile and ordered,
59 ; we need to use the strictest ordering of either.  In this
60 ; case, the ordering prevents forwarding.
61 define i32 @test4(ptr noalias nocapture %p, ptr noalias nocapture %q) {
62 ; CHECK-LABEL: @test4(
63 ; CHECK-NEXT:  entry:
64 ; CHECK-NEXT:    [[X:%.*]] = load i32, ptr [[P:%.*]], align 4
65 ; CHECK-NEXT:    [[TMP0:%.*]] = load atomic volatile i32, ptr [[Q:%.*]] seq_cst, align 4
66 ; CHECK-NEXT:    [[Y:%.*]] = load atomic i32, ptr [[P]] seq_cst, align 4
67 ; CHECK-NEXT:    [[ADD:%.*]] = sub i32 [[Y]], [[X]]
68 ; CHECK-NEXT:    ret i32 [[ADD]]
70 entry:
71   %x = load i32, ptr %p
72   load atomic volatile i32, ptr %q seq_cst, align 4
73   %y = load atomic i32, ptr %p seq_cst, align 4
74   %add = sub i32 %y, %x
75   ret i32 %add
78 ; Value forwarding from a volatile load is perfectly legal
79 define i32 @test5(ptr nocapture %p, ptr nocapture %q) {
80 ; CHECK-LABEL: @test5(
81 ; CHECK-NEXT:  entry:
82 ; CHECK-NEXT:    [[X:%.*]] = load volatile i32, ptr [[P:%.*]], align 4
83 ; CHECK-NEXT:    ret i32 0
85 entry:
86   %x = load volatile i32, ptr %p
87   %y = load i32, ptr %p
88   %add = sub i32 %y, %x
89   ret i32 %add
92 ; Does cross block redundancy elimination work with volatiles?
93 define i32 @test6(ptr noalias nocapture %p, ptr noalias nocapture %q) {
94 ; CHECK-LABEL: @test6(
95 ; CHECK-NEXT:  entry:
96 ; CHECK-NEXT:    [[Y1:%.*]] = load i32, ptr [[P:%.*]], align 4
97 ; CHECK-NEXT:    call void @use(i32 [[Y1]])
98 ; CHECK-NEXT:    br label [[HEADER:%.*]]
99 ; CHECK:       header:
100 ; CHECK-NEXT:    [[X:%.*]] = load volatile i32, ptr [[Q:%.*]], align 4
101 ; CHECK-NEXT:    [[ADD:%.*]] = sub i32 [[Y1]], [[X]]
102 ; CHECK-NEXT:    [[CND:%.*]] = icmp eq i32 [[ADD]], 0
103 ; CHECK-NEXT:    br i1 [[CND]], label [[EXIT:%.*]], label [[HEADER]]
104 ; CHECK:       exit:
105 ; CHECK-NEXT:    ret i32 0
107 entry:
108   %y1 = load i32, ptr %p
109   call void @use(i32 %y1)
110   br label %header
111 header:
112   %x = load volatile i32, ptr %q
113   %y = load i32, ptr %p
114   %add = sub i32 %y, %x
115   %cnd = icmp eq i32 %add, 0
116   br i1 %cnd, label %exit, label %header
117 exit:
118   ret i32 %add
121 ; Does cross block PRE work with volatiles?
122 define i32 @test7(i1 %c, ptr noalias nocapture %p, ptr noalias nocapture %q) {
123 ; CHECK-LABEL: @test7(
124 ; CHECK-NEXT:  entry:
125 ; CHECK-NEXT:    [[Y_PRE:%.*]] = load i32, ptr [[P:%.*]], align 4
126 ; CHECK-NEXT:    br i1 [[C:%.*]], label [[HEADER:%.*]], label [[SKIP:%.*]]
127 ; CHECK:       skip:
128 ; CHECK-NEXT:    call void @use(i32 [[Y_PRE]])
129 ; CHECK-NEXT:    br label [[HEADER]]
130 ; CHECK:       header:
131 ; CHECK-NEXT:    [[X:%.*]] = load volatile i32, ptr [[Q:%.*]], align 4
132 ; CHECK-NEXT:    [[ADD:%.*]] = sub i32 [[Y_PRE]], [[X]]
133 ; CHECK-NEXT:    [[CND:%.*]] = icmp eq i32 [[ADD]], 0
134 ; CHECK-NEXT:    br i1 [[CND]], label [[EXIT:%.*]], label [[HEADER]]
135 ; CHECK:       exit:
136 ; CHECK-NEXT:    ret i32 0
138 entry:
139   br i1 %c, label %header, label %skip
140 skip:
141   %y1 = load i32, ptr %p
142   call void @use(i32 %y1)
143   br label %header
144 header:
145   %x = load volatile i32, ptr %q
146   %y = load i32, ptr %p
147   %add = sub i32 %y, %x
148   %cnd = icmp eq i32 %add, 0
149   br i1 %cnd, label %exit, label %header
150 exit:
151   ret i32 %add
154 ; Another volatile PRE case - two paths through a loop
155 ; load in preheader, one path read only, one not
156 define i32 @test8(i1 %b, i1 %c, ptr noalias %p, ptr noalias %q) {
157 ; CHECK-LABEL: @test8(
158 ; CHECK-NEXT:  entry:
159 ; CHECK-NEXT:    [[Y1:%.*]] = load i32, ptr [[P:%.*]], align 4
160 ; CHECK-NEXT:    call void @use(i32 [[Y1]])
161 ; CHECK-NEXT:    br label [[HEADER:%.*]]
162 ; CHECK:       header:
163 ; CHECK-NEXT:    [[Y:%.*]] = phi i32 [ [[Y_PRE:%.*]], [[SKIP_HEADER_CRIT_EDGE:%.*]] ], [ [[Y]], [[HEADER]] ], [ [[Y1]], [[ENTRY:%.*]] ]
164 ; CHECK-NEXT:    [[X:%.*]] = load volatile i32, ptr [[Q:%.*]], align 4
165 ; CHECK-NEXT:    call void @use(i32 [[Y]])
166 ; CHECK-NEXT:    br i1 [[B:%.*]], label [[SKIP:%.*]], label [[HEADER]]
167 ; CHECK:       skip:
168 ; CHECK-NEXT:    call void @clobber(ptr [[P]], ptr [[Q]])
169 ; CHECK-NEXT:    br i1 [[C:%.*]], label [[SKIP_HEADER_CRIT_EDGE]], label [[EXIT:%.*]]
170 ; CHECK:       skip.header_crit_edge:
171 ; CHECK-NEXT:    [[Y_PRE]] = load i32, ptr [[P]], align 4
172 ; CHECK-NEXT:    br label [[HEADER]]
173 ; CHECK:       exit:
174 ; CHECK-NEXT:    [[ADD:%.*]] = sub i32 [[Y]], [[X]]
175 ; CHECK-NEXT:    ret i32 [[ADD]]
177 entry:
178   %y1 = load i32, ptr %p
179   call void @use(i32 %y1)
180   br label %header
181 header:
182   %x = load volatile i32, ptr %q
183   %y = load i32, ptr %p
184   call void @use(i32 %y)
185   br i1 %b, label %skip, label %header
186 skip:
187   ; escaping the arguments is explicitly required since we marked
188   ; them noalias
189   call void @clobber(ptr %p, ptr %q)
190   br i1 %c, label %header, label %exit
191 exit:
192   %add = sub i32 %y, %x
193   ret i32 %add
196 ; This test checks that we don't optimize away instructions that are
197 ; simplified by SimplifyInstruction(), but are not trivially dead.
199 define i32 @test9(ptr %V) {
200 ; CHECK-LABEL: @test9(
201 ; CHECK-NEXT:  entry:
202 ; CHECK-NEXT:    [[LOAD:%.*]] = call i32 undef()
203 ; CHECK-NEXT:    ret i32 poison
205 entry:
206   %load = call i32 undef()
207   ret i32 %load
210 declare void @use(i32) readonly
211 declare void @clobber(ptr %p, ptr %q)
213 !0 = !{ i32 0, i32 1 }