1; RUN: opt -S -basicaa -gvn < %s | FileCheck %s
2
3; We can value forward across the fence since we can (semantically)
4; reorder the following load before the fence.
5define i32 @test(i32* %addr.i) {
6; CHECK-LABEL: @test
7; CHECK: store
8; CHECK: fence
9; CHECK-NOT: load
10; CHECK: ret
11  store i32 5, i32* %addr.i, align 4
12  fence release
13  %a = load i32, i32* %addr.i, align 4
14  ret i32 %a
15}
16
17; Same as above
18define i32 @test2(i32* %addr.i) {
19; CHECK-LABEL: @test2
20; CHECK-NEXT: fence
21; CHECK-NOT: load
22; CHECK: ret
23  %a = load i32, i32* %addr.i, align 4
24  fence release
25  %a2 = load i32, i32* %addr.i, align 4
26  %res = sub i32 %a, %a2
27  ret i32 %res
28}
29
30; We can not value forward across an acquire barrier since we might
31; be syncronizing with another thread storing to the same variable
32; followed by a release fence.  This is not so much enforcing an
33; ordering property (though it is that too), but a liveness
34; property.  We expect to eventually see the value of store by
35; another thread when spinning on that location.
36define i32 @test3(i32* noalias %addr.i, i32* noalias %otheraddr) {
37; CHECK-LABEL: @test3
38; CHECK: load
39; CHECK: fence
40; CHECK: load
41; CHECK: ret i32 %res
42  ; the following code is intented to model the unrolling of
43  ; two iterations in a spin loop of the form:
44  ;   do { fence acquire: tmp = *%addr.i; ) while (!tmp);
45  ; It's hopefully clear that allowing PRE to turn this into:
46  ;   if (!*%addr.i) while(true) {} would be unfortunate
47  fence acquire
48  %a = load i32, i32* %addr.i, align 4
49  fence acquire
50  %a2 = load i32, i32* %addr.i, align 4
51  %res = sub i32 %a, %a2
52  ret i32 %res
53}
54
55; Another example of why forwarding across an acquire fence is problematic
56; can be seen in a normal locking operation.  Say we had:
57; *p = 5; unlock(l); lock(l); use(p);
58; forwarding the store to p would be invalid.  A reasonable implementation
59; of unlock and lock might be:
60; unlock() { atomicrmw sub %l, 1 unordered; fence release }
61; lock() {
62;   do {
63;     %res = cmpxchg %p, 0, 1, monotonic monotonic
64;   } while(!%res.success)
65;   fence acquire;
66; }
67; Given we chose to forward across the release fence, we clearly can't forward
68; across the acquire fence as well.
69
70