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. 5 define 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 18 define 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. 36 define 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