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 -basic-aa -gvn -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(i32* nocapture %p, i32* nocapture %q) {
11 ; CHECK-NEXT: [[TMP0:%.*]] = load volatile i32, i32* [[Q:%.*]], align 4
12 ; CHECK-NEXT: ret i32 0
15 %x = load i32, i32* %p
16 load volatile i32, i32* %q
17 %y = load i32, i32* %p
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(i32* nocapture %p, i32* nocapture %q) {
25 ; CHECK-LABEL: @test2(
27 ; CHECK-NEXT: [[X:%.*]] = load i32, i32* [[P:%.*]], align 4
28 ; CHECK-NEXT: [[Y:%.*]] = load volatile i32, i32* [[P]], align 4
29 ; CHECK-NEXT: [[ADD:%.*]] = sub i32 [[Y]], [[X]]
30 ; CHECK-NEXT: ret i32 [[ADD]]
33 %x = load i32, i32* %p
34 %y = load volatile i32, i32* %p
39 ; If the query instruction is itself volatile, we *cannot*
40 ; reorder it even if p and q are noalias
41 define i32 @test3(i32* noalias nocapture %p, i32* noalias nocapture %q) {
42 ; CHECK-LABEL: @test3(
44 ; CHECK-NEXT: [[X:%.*]] = load i32, i32* [[P:%.*]], align 4
45 ; CHECK-NEXT: [[TMP0:%.*]] = load volatile i32, i32* [[Q:%.*]], align 4
46 ; CHECK-NEXT: [[Y:%.*]] = load volatile i32, i32* [[P]], align 4
47 ; CHECK-NEXT: [[ADD:%.*]] = sub i32 [[Y]], [[X]]
48 ; CHECK-NEXT: ret i32 [[ADD]]
51 %x = load i32, i32* %p
52 load volatile i32, i32* %q
53 %y = load volatile i32, i32* %p
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(i32* noalias nocapture %p, i32* noalias nocapture %q) {
62 ; CHECK-LABEL: @test4(
64 ; CHECK-NEXT: [[X:%.*]] = load i32, i32* [[P:%.*]], align 4
65 ; CHECK-NEXT: [[TMP0:%.*]] = load atomic volatile i32, i32* [[Q:%.*]] seq_cst, align 4
66 ; CHECK-NEXT: [[Y:%.*]] = load atomic i32, i32* [[P]] seq_cst, align 4
67 ; CHECK-NEXT: [[ADD:%.*]] = sub i32 [[Y]], [[X]]
68 ; CHECK-NEXT: ret i32 [[ADD]]
71 %x = load i32, i32* %p
72 load atomic volatile i32, i32* %q seq_cst, align 4
73 %y = load atomic i32, i32* %p seq_cst, align 4
78 ; Value forwarding from a volatile load is perfectly legal
79 define i32 @test5(i32* nocapture %p, i32* nocapture %q) {
80 ; CHECK-LABEL: @test5(
82 ; CHECK-NEXT: [[X:%.*]] = load volatile i32, i32* [[P:%.*]], align 4
83 ; CHECK-NEXT: ret i32 0
86 %x = load volatile i32, i32* %p
87 %y = load i32, i32* %p
92 ; Does cross block redundancy elimination work with volatiles?
93 define i32 @test6(i32* noalias nocapture %p, i32* noalias nocapture %q) {
94 ; CHECK-LABEL: @test6(
96 ; CHECK-NEXT: [[Y1:%.*]] = load i32, i32* [[P:%.*]], align 4
97 ; CHECK-NEXT: call void @use(i32 [[Y1]])
98 ; CHECK-NEXT: br label [[HEADER:%.*]]
100 ; CHECK-NEXT: [[X:%.*]] = load volatile i32, i32* [[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]]
105 ; CHECK-NEXT: ret i32 0
108 %y1 = load i32, i32* %p
109 call void @use(i32 %y1)
112 %x = load volatile i32, i32* %q
113 %y = load i32, i32* %p
114 %add = sub i32 %y, %x
115 %cnd = icmp eq i32 %add, 0
116 br i1 %cnd, label %exit, label %header
121 ; Does cross block PRE work with volatiles?
122 define i32 @test7(i1 %c, i32* noalias nocapture %p, i32* noalias nocapture %q) {
123 ; CHECK-LABEL: @test7(
125 ; CHECK-NEXT: br i1 [[C:%.*]], label [[ENTRY_HEADER_CRIT_EDGE:%.*]], label [[SKIP:%.*]]
126 ; CHECK: entry.header_crit_edge:
127 ; CHECK-NEXT: [[Y_PRE:%.*]] = load i32, i32* [[P:%.*]], align 4
128 ; CHECK-NEXT: br label [[HEADER:%.*]]
130 ; CHECK-NEXT: [[Y1:%.*]] = load i32, i32* [[P]], align 4
131 ; CHECK-NEXT: call void @use(i32 [[Y1]])
132 ; CHECK-NEXT: br label [[HEADER]]
134 ; CHECK-NEXT: [[Y:%.*]] = phi i32 [ [[Y_PRE]], [[ENTRY_HEADER_CRIT_EDGE]] ], [ [[Y]], [[HEADER]] ], [ [[Y1]], [[SKIP]] ]
135 ; CHECK-NEXT: [[X:%.*]] = load volatile i32, i32* [[Q:%.*]], align 4
136 ; CHECK-NEXT: [[ADD:%.*]] = sub i32 [[Y]], [[X]]
137 ; CHECK-NEXT: [[CND:%.*]] = icmp eq i32 [[ADD]], 0
138 ; CHECK-NEXT: br i1 [[CND]], label [[EXIT:%.*]], label [[HEADER]]
140 ; CHECK-NEXT: ret i32 0
143 br i1 %c, label %header, label %skip
145 %y1 = load i32, i32* %p
146 call void @use(i32 %y1)
149 %x = load volatile i32, i32* %q
150 %y = load i32, i32* %p
151 %add = sub i32 %y, %x
152 %cnd = icmp eq i32 %add, 0
153 br i1 %cnd, label %exit, label %header
158 ; Another volatile PRE case - two paths through a loop
159 ; load in preheader, one path read only, one not
160 define i32 @test8(i1 %b, i1 %c, i32* noalias %p, i32* noalias %q) {
161 ; CHECK-LABEL: @test8(
163 ; CHECK-NEXT: [[Y1:%.*]] = load i32, i32* [[P:%.*]], align 4
164 ; CHECK-NEXT: call void @use(i32 [[Y1]])
165 ; CHECK-NEXT: br label [[HEADER:%.*]]
167 ; CHECK-NEXT: [[Y:%.*]] = phi i32 [ [[Y_PRE:%.*]], [[SKIP_HEADER_CRIT_EDGE:%.*]] ], [ [[Y]], [[HEADER]] ], [ [[Y1]], [[ENTRY:%.*]] ]
168 ; CHECK-NEXT: [[X:%.*]] = load volatile i32, i32* [[Q:%.*]], align 4
169 ; CHECK-NEXT: call void @use(i32 [[Y]])
170 ; CHECK-NEXT: br i1 [[B:%.*]], label [[SKIP:%.*]], label [[HEADER]]
172 ; CHECK-NEXT: call void @clobber(i32* [[P]], i32* [[Q]])
173 ; CHECK-NEXT: br i1 [[C:%.*]], label [[SKIP_HEADER_CRIT_EDGE]], label [[EXIT:%.*]]
174 ; CHECK: skip.header_crit_edge:
175 ; CHECK-NEXT: [[Y_PRE]] = load i32, i32* [[P]], align 4
176 ; CHECK-NEXT: br label [[HEADER]]
178 ; CHECK-NEXT: [[ADD:%.*]] = sub i32 [[Y]], [[X]]
179 ; CHECK-NEXT: ret i32 [[ADD]]
182 %y1 = load i32, i32* %p
183 call void @use(i32 %y1)
186 %x = load volatile i32, i32* %q
187 %y = load i32, i32* %p
188 call void @use(i32 %y)
189 br i1 %b, label %skip, label %header
191 ; escaping the arguments is explicitly required since we marked
193 call void @clobber(i32* %p, i32* %q)
194 br i1 %c, label %header, label %exit
196 %add = sub i32 %y, %x
200 ; This test checks that we don't optimize away instructions that are
201 ; simplified by SimplifyInstruction(), but are not trivially dead.
203 define i32 @test9(i32* %V) {
204 ; CHECK-LABEL: @test9(
206 ; CHECK-NEXT: [[LOAD:%.*]] = call i32 undef()
207 ; CHECK-NEXT: ret i32 poison
210 %load = call i32 undef()
214 declare void @use(i32) readonly
215 declare void @clobber(i32* %p, i32* %q)
217 !0 = !{ i32 0, i32 1 }