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