1 ; RUN: opt -S -basicaa -gvn < %s | FileCheck %s
3 @a = external constant i32
4 ; We can value forward across the fence since we can (semantically)
5 ; reorder the following load before the fence.
6 define i32 @test(i32* %addr.i) {
12 store i32 5, i32* %addr.i, align 4
14 %a = load i32, i32* %addr.i, align 4
19 define i32 @test2(i32* %addr.i) {
24 %a = load i32, i32* %addr.i, align 4
26 %a2 = load i32, i32* %addr.i, align 4
27 %res = sub i32 %a, %a2
31 ; We can not value forward across an acquire barrier since we might
32 ; be syncronizing with another thread storing to the same variable
33 ; followed by a release fence. This is not so much enforcing an
34 ; ordering property (though it is that too), but a liveness
35 ; property. We expect to eventually see the value of store by
36 ; another thread when spinning on that location.
37 define i32 @test3(i32* noalias %addr.i, i32* noalias %otheraddr) {
43 ; the following code is intented to model the unrolling of
44 ; two iterations in a spin loop of the form:
45 ; do { fence acquire: tmp = *%addr.i; ) while (!tmp);
46 ; It's hopefully clear that allowing PRE to turn this into:
47 ; if (!*%addr.i) while(true) {} would be unfortunate
49 %a = load i32, i32* %addr.i, align 4
51 %a2 = load i32, i32* %addr.i, align 4
52 %res = sub i32 %a, %a2
56 ; We can forward the value forward the load
57 ; across both the fences, because the load is from
58 ; a constant memory location.
59 define i32 @test4(i32* %addr) {
62 ; CHECK: fence release
64 ; CHECK: fence seq_cst
66 %var = load i32, i32* @a
68 store i32 42, i32* %addr, align 8
70 %var2 = load i32, i32* @a
71 %var3 = sub i32 %var, %var2
75 ; Another example of why forwarding across an acquire fence is problematic
76 ; can be seen in a normal locking operation. Say we had:
77 ; *p = 5; unlock(l); lock(l); use(p);
78 ; forwarding the store to p would be invalid. A reasonable implementation
79 ; of unlock and lock might be:
80 ; unlock() { atomicrmw sub %l, 1 unordered; fence release }
83 ; %res = cmpxchg %p, 0, 1, monotonic monotonic
84 ; } while(!%res.success)
87 ; Given we chose to forward across the release fence, we clearly can't forward
88 ; across the acquire fence as well.