xref: /aosp_15_r20/external/llvm/test/Transforms/GVN/volatile.ll (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker; Tests that check our handling of volatile instructions encountered
2*9880d681SAndroid Build Coastguard Worker; when scanning for dependencies
3*9880d681SAndroid Build Coastguard Worker; RUN: opt -basicaa -gvn -S < %s | FileCheck %s
4*9880d681SAndroid Build Coastguard Worker
5*9880d681SAndroid Build Coastguard Worker; Check that we can bypass a volatile load when searching
6*9880d681SAndroid Build Coastguard Worker; for dependencies of a non-volatile load
7*9880d681SAndroid Build Coastguard Workerdefine i32 @test1(i32* nocapture %p, i32* nocapture %q) {
8*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: test1
9*9880d681SAndroid Build Coastguard Worker; CHECK:      %0 = load volatile i32, i32* %q
10*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: ret i32 0
11*9880d681SAndroid Build Coastguard Workerentry:
12*9880d681SAndroid Build Coastguard Worker  %x = load i32, i32* %p
13*9880d681SAndroid Build Coastguard Worker  load volatile i32, i32* %q
14*9880d681SAndroid Build Coastguard Worker  %y = load i32, i32* %p
15*9880d681SAndroid Build Coastguard Worker  %add = sub i32 %y, %x
16*9880d681SAndroid Build Coastguard Worker  ret i32 %add
17*9880d681SAndroid Build Coastguard Worker}
18*9880d681SAndroid Build Coastguard Worker
19*9880d681SAndroid Build Coastguard Worker; We can not value forward if the query instruction is
20*9880d681SAndroid Build Coastguard Worker; volatile, this would be (in effect) removing the volatile load
21*9880d681SAndroid Build Coastguard Workerdefine i32 @test2(i32* nocapture %p, i32* nocapture %q) {
22*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: test2
23*9880d681SAndroid Build Coastguard Worker; CHECK:      %x = load i32, i32* %p
24*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %y = load volatile i32, i32* %p
25*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %add = sub i32 %y, %x
26*9880d681SAndroid Build Coastguard Workerentry:
27*9880d681SAndroid Build Coastguard Worker  %x = load i32, i32* %p
28*9880d681SAndroid Build Coastguard Worker  %y = load volatile i32, i32* %p
29*9880d681SAndroid Build Coastguard Worker  %add = sub i32 %y, %x
30*9880d681SAndroid Build Coastguard Worker  ret i32 %add
31*9880d681SAndroid Build Coastguard Worker}
32*9880d681SAndroid Build Coastguard Worker
33*9880d681SAndroid Build Coastguard Worker; If the query instruction is itself volatile, we *cannot*
34*9880d681SAndroid Build Coastguard Worker; reorder it even if p and q are noalias
35*9880d681SAndroid Build Coastguard Workerdefine i32 @test3(i32* noalias nocapture %p, i32* noalias nocapture %q) {
36*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: test3
37*9880d681SAndroid Build Coastguard Worker; CHECK:      %x = load i32, i32* %p
38*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %0 = load volatile i32, i32* %q
39*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %y = load volatile i32, i32* %p
40*9880d681SAndroid Build Coastguard Workerentry:
41*9880d681SAndroid Build Coastguard Worker  %x = load i32, i32* %p
42*9880d681SAndroid Build Coastguard Worker  load volatile i32, i32* %q
43*9880d681SAndroid Build Coastguard Worker  %y = load volatile i32, i32* %p
44*9880d681SAndroid Build Coastguard Worker  %add = sub i32 %y, %x
45*9880d681SAndroid Build Coastguard Worker  ret i32 %add
46*9880d681SAndroid Build Coastguard Worker}
47*9880d681SAndroid Build Coastguard Worker
48*9880d681SAndroid Build Coastguard Worker; If an encountered instruction is both volatile and ordered,
49*9880d681SAndroid Build Coastguard Worker; we need to use the strictest ordering of either.  In this
50*9880d681SAndroid Build Coastguard Worker; case, the ordering prevents forwarding.
51*9880d681SAndroid Build Coastguard Workerdefine i32 @test4(i32* noalias nocapture %p, i32* noalias nocapture %q) {
52*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: test4
53*9880d681SAndroid Build Coastguard Worker; CHECK:      %x = load i32, i32* %p
54*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %0 = load atomic volatile i32, i32* %q seq_cst
55*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %y = load atomic i32, i32* %p seq_cst
56*9880d681SAndroid Build Coastguard Workerentry:
57*9880d681SAndroid Build Coastguard Worker  %x = load i32, i32* %p
58*9880d681SAndroid Build Coastguard Worker  load atomic volatile i32, i32* %q seq_cst, align 4
59*9880d681SAndroid Build Coastguard Worker  %y = load atomic i32, i32* %p seq_cst, align 4
60*9880d681SAndroid Build Coastguard Worker  %add = sub i32 %y, %x
61*9880d681SAndroid Build Coastguard Worker  ret i32 %add
62*9880d681SAndroid Build Coastguard Worker}
63*9880d681SAndroid Build Coastguard Worker
64*9880d681SAndroid Build Coastguard Worker; Value forwarding from a volatile load is perfectly legal
65*9880d681SAndroid Build Coastguard Workerdefine i32 @test5(i32* nocapture %p, i32* nocapture %q) {
66*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: test5
67*9880d681SAndroid Build Coastguard Worker; CHECK:      %x = load volatile i32, i32* %p
68*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: ret i32 0
69*9880d681SAndroid Build Coastguard Workerentry:
70*9880d681SAndroid Build Coastguard Worker  %x = load volatile i32, i32* %p
71*9880d681SAndroid Build Coastguard Worker  %y = load i32, i32* %p
72*9880d681SAndroid Build Coastguard Worker  %add = sub i32 %y, %x
73*9880d681SAndroid Build Coastguard Worker  ret i32 %add
74*9880d681SAndroid Build Coastguard Worker}
75*9880d681SAndroid Build Coastguard Worker
76*9880d681SAndroid Build Coastguard Worker; Does cross block redundancy elimination work with volatiles?
77*9880d681SAndroid Build Coastguard Workerdefine i32 @test6(i32* noalias nocapture %p, i32* noalias nocapture %q) {
78*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: test6
79*9880d681SAndroid Build Coastguard Worker; CHECK:      %y1 = load i32, i32* %p
80*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: header
81*9880d681SAndroid Build Coastguard Worker; CHECK:      %x = load volatile i32, i32* %q
82*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %add = sub i32 %y1, %x
83*9880d681SAndroid Build Coastguard Workerentry:
84*9880d681SAndroid Build Coastguard Worker  %y1 = load i32, i32* %p
85*9880d681SAndroid Build Coastguard Worker  call void @use(i32 %y1)
86*9880d681SAndroid Build Coastguard Worker  br label %header
87*9880d681SAndroid Build Coastguard Workerheader:
88*9880d681SAndroid Build Coastguard Worker  %x = load volatile i32, i32* %q
89*9880d681SAndroid Build Coastguard Worker  %y = load i32, i32* %p
90*9880d681SAndroid Build Coastguard Worker  %add = sub i32 %y, %x
91*9880d681SAndroid Build Coastguard Worker  %cnd = icmp eq i32 %add, 0
92*9880d681SAndroid Build Coastguard Worker  br i1 %cnd, label %exit, label %header
93*9880d681SAndroid Build Coastguard Workerexit:
94*9880d681SAndroid Build Coastguard Worker  ret i32 %add
95*9880d681SAndroid Build Coastguard Worker}
96*9880d681SAndroid Build Coastguard Worker
97*9880d681SAndroid Build Coastguard Worker; Does cross block PRE work with volatiles?
98*9880d681SAndroid Build Coastguard Workerdefine i32 @test7(i1 %c, i32* noalias nocapture %p, i32* noalias nocapture %q) {
99*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: test7
100*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: entry.header_crit_edge:
101*9880d681SAndroid Build Coastguard Worker; CHECK:       %y.pre = load i32, i32* %p
102*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: skip:
103*9880d681SAndroid Build Coastguard Worker; CHECK:       %y1 = load i32, i32* %p
104*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: header:
105*9880d681SAndroid Build Coastguard Worker; CHECK:      %y = phi i32
106*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %x = load volatile i32, i32* %q
107*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %add = sub i32 %y, %x
108*9880d681SAndroid Build Coastguard Workerentry:
109*9880d681SAndroid Build Coastguard Worker  br i1 %c, label %header, label %skip
110*9880d681SAndroid Build Coastguard Workerskip:
111*9880d681SAndroid Build Coastguard Worker  %y1 = load i32, i32* %p
112*9880d681SAndroid Build Coastguard Worker  call void @use(i32 %y1)
113*9880d681SAndroid Build Coastguard Worker  br label %header
114*9880d681SAndroid Build Coastguard Workerheader:
115*9880d681SAndroid Build Coastguard Worker  %x = load volatile i32, i32* %q
116*9880d681SAndroid Build Coastguard Worker  %y = load i32, i32* %p
117*9880d681SAndroid Build Coastguard Worker  %add = sub i32 %y, %x
118*9880d681SAndroid Build Coastguard Worker  %cnd = icmp eq i32 %add, 0
119*9880d681SAndroid Build Coastguard Worker  br i1 %cnd, label %exit, label %header
120*9880d681SAndroid Build Coastguard Workerexit:
121*9880d681SAndroid Build Coastguard Worker  ret i32 %add
122*9880d681SAndroid Build Coastguard Worker}
123*9880d681SAndroid Build Coastguard Worker
124*9880d681SAndroid Build Coastguard Worker; Another volatile PRE case - two paths through a loop
125*9880d681SAndroid Build Coastguard Worker; load in preheader, one path read only, one not
126*9880d681SAndroid Build Coastguard Workerdefine i32 @test8(i1 %b, i1 %c, i32* noalias %p, i32* noalias %q) {
127*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: test8
128*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: entry
129*9880d681SAndroid Build Coastguard Worker; CHECK:       %y1 = load i32, i32* %p
130*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: header:
131*9880d681SAndroid Build Coastguard Worker; CHECK:      %y = phi i32
132*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %x = load volatile i32, i32* %q
133*9880d681SAndroid Build Coastguard Worker; CHECK-NOT:  load
134*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: skip.header_crit_edge:
135*9880d681SAndroid Build Coastguard Worker; CHECK:       %y.pre = load i32, i32* %p
136*9880d681SAndroid Build Coastguard Workerentry:
137*9880d681SAndroid Build Coastguard Worker  %y1 = load i32, i32* %p
138*9880d681SAndroid Build Coastguard Worker  call void @use(i32 %y1)
139*9880d681SAndroid Build Coastguard Worker  br label %header
140*9880d681SAndroid Build Coastguard Workerheader:
141*9880d681SAndroid Build Coastguard Worker  %x = load volatile i32, i32* %q
142*9880d681SAndroid Build Coastguard Worker  %y = load i32, i32* %p
143*9880d681SAndroid Build Coastguard Worker  call void @use(i32 %y)
144*9880d681SAndroid Build Coastguard Worker  br i1 %b, label %skip, label %header
145*9880d681SAndroid Build Coastguard Workerskip:
146*9880d681SAndroid Build Coastguard Worker  ; escaping the arguments is explicitly required since we marked
147*9880d681SAndroid Build Coastguard Worker  ; them noalias
148*9880d681SAndroid Build Coastguard Worker  call void @clobber(i32* %p, i32* %q)
149*9880d681SAndroid Build Coastguard Worker  br i1 %c, label %header, label %exit
150*9880d681SAndroid Build Coastguard Workerexit:
151*9880d681SAndroid Build Coastguard Worker  %add = sub i32 %y, %x
152*9880d681SAndroid Build Coastguard Worker  ret i32 %add
153*9880d681SAndroid Build Coastguard Worker}
154*9880d681SAndroid Build Coastguard Worker
155*9880d681SAndroid Build Coastguard Workerdefine i32 @test9(i32* %V) {
156*9880d681SAndroid Build Coastguard Workerentry:
157*9880d681SAndroid Build Coastguard Worker  %load = load volatile i32, i32* %V, !range !0
158*9880d681SAndroid Build Coastguard Worker  ret i32 %load
159*9880d681SAndroid Build Coastguard Worker}
160*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: test9
161*9880d681SAndroid Build Coastguard Worker; CHECK: load volatile
162*9880d681SAndroid Build Coastguard Worker; CHECK: ret i32 0
163*9880d681SAndroid Build Coastguard Worker
164*9880d681SAndroid Build Coastguard Workerdeclare void @use(i32) readonly
165*9880d681SAndroid Build Coastguard Workerdeclare void @clobber(i32* %p, i32* %q)
166*9880d681SAndroid Build Coastguard Worker
167*9880d681SAndroid Build Coastguard Worker!0 = !{ i32 0, i32 1 }
168