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) {
11 ; CHECK-NEXT: [[TMP0:%.*]] = load volatile i32, ptr [[Q:%.*]], align 4
12 ; CHECK-NEXT: ret i32 0
16 load volatile i32, ptr %q
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(
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]]
34 %y = load volatile i32, ptr %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(ptr noalias nocapture %p, ptr noalias nocapture %q) {
42 ; CHECK-LABEL: @test3(
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]]
52 load volatile i32, ptr %q
53 %y = load volatile i32, ptr %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(ptr noalias nocapture %p, ptr noalias nocapture %q) {
62 ; CHECK-LABEL: @test4(
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]]
72 load atomic volatile i32, ptr %q seq_cst, align 4
73 %y = load atomic i32, ptr %p seq_cst, align 4
78 ; Value forwarding from a volatile load is perfectly legal
79 define i32 @test5(ptr nocapture %p, ptr nocapture %q) {
80 ; CHECK-LABEL: @test5(
82 ; CHECK-NEXT: [[X:%.*]] = load volatile i32, ptr [[P:%.*]], align 4
83 ; CHECK-NEXT: ret i32 0
86 %x = load volatile i32, ptr %p
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(
96 ; CHECK-NEXT: [[Y1:%.*]] = load i32, ptr [[P:%.*]], align 4
97 ; CHECK-NEXT: call void @use(i32 [[Y1]])
98 ; CHECK-NEXT: br label [[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]]
105 ; CHECK-NEXT: ret i32 0
108 %y1 = load i32, ptr %p
109 call void @use(i32 %y1)
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
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(
125 ; CHECK-NEXT: [[Y_PRE:%.*]] = load i32, ptr [[P:%.*]], align 4
126 ; CHECK-NEXT: br i1 [[C:%.*]], label [[HEADER:%.*]], label [[SKIP:%.*]]
128 ; CHECK-NEXT: call void @use(i32 [[Y_PRE]])
129 ; CHECK-NEXT: br label [[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]]
136 ; CHECK-NEXT: ret i32 0
139 br i1 %c, label %header, label %skip
141 %y1 = load i32, ptr %p
142 call void @use(i32 %y1)
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
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(
159 ; CHECK-NEXT: [[Y1:%.*]] = load i32, ptr [[P:%.*]], align 4
160 ; CHECK-NEXT: call void @use(i32 [[Y1]])
161 ; CHECK-NEXT: br label [[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]]
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]]
174 ; CHECK-NEXT: [[ADD:%.*]] = sub i32 [[Y]], [[X]]
175 ; CHECK-NEXT: ret i32 [[ADD]]
178 %y1 = load i32, ptr %p
179 call void @use(i32 %y1)
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
187 ; escaping the arguments is explicitly required since we marked
189 call void @clobber(ptr %p, ptr %q)
190 br i1 %c, label %header, label %exit
192 %add = sub i32 %y, %x
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(
202 ; CHECK-NEXT: [[LOAD:%.*]] = call i32 undef()
203 ; CHECK-NEXT: ret i32 poison
206 %load = call i32 undef()
210 declare void @use(i32) readonly
211 declare void @clobber(ptr %p, ptr %q)
213 !0 = !{ i32 0, i32 1 }