1; RUN: opt -S -early-cse < %s | FileCheck %s
2; NOTE: This file is testing the current implementation.  Some of
3; the transforms used as negative tests below would be legal, but
4; only if reached through a chain of logic which EarlyCSE is incapable
5; of performing.  To say it differently, this file tests a conservative
6; version of the memory model.  If we want to extend EarlyCSE to be more
7; aggressive in the future, we may need to relax some of the negative tests.
8
9; We can value forward across the fence since we can (semantically)
10; reorder the following load before the fence.
11define i32 @test(i32* %addr.i) {
12; CHECK-LABEL: @test
13; CHECK: store
14; CHECK: fence
15; CHECK-NOT: load
16; CHECK: ret
17  store i32 5, i32* %addr.i, align 4
18  fence release
19  %a = load i32, i32* %addr.i, align 4
20  ret i32 %a
21}
22
23; Same as above
24define i32 @test2(i32* noalias %addr.i, i32* noalias %otheraddr) {
25; CHECK-LABEL: @test2
26; CHECK: load
27; CHECK: fence
28; CHECK-NOT: load
29; CHECK: ret
30  %a = load i32, i32* %addr.i, align 4
31  fence release
32  %a2 = load i32, i32* %addr.i, align 4
33  %res = sub i32 %a, %a2
34  ret i32 %a
35}
36
37; We can not value forward across an acquire barrier since we might
38; be syncronizing with another thread storing to the same variable
39; followed by a release fence.  If this thread observed the release
40; had happened, we must present a consistent view of memory at the
41; fence.  Note that it would be legal to reorder '%a' after the fence
42; and then remove '%a2'.  The current implementation doesn't know how
43; to do this, but if it learned, this test will need revised.
44define i32 @test3(i32* noalias %addr.i, i32* noalias %otheraddr) {
45; CHECK-LABEL: @test3
46; CHECK: load
47; CHECK: fence
48; CHECK: load
49; CHECK: sub
50; CHECK: ret
51  %a = load i32, i32* %addr.i, align 4
52  fence acquire
53  %a2 = load i32, i32* %addr.i, align 4
54  %res = sub i32 %a, %a2
55  ret i32 %res
56}
57
58; We can not dead store eliminate accross the fence.  We could in
59; principal reorder the second store above the fence and then DSE either
60; store, but this is beyond the simple last-store DSE which EarlyCSE
61; implements.
62define void @test4(i32* %addr.i) {
63; CHECK-LABEL: @test4
64; CHECK: store
65; CHECK: fence
66; CHECK: store
67; CHECK: ret
68  store i32 5, i32* %addr.i, align 4
69  fence release
70  store i32 5, i32* %addr.i, align 4
71  ret void
72}
73
74; We *could* DSE across this fence, but don't.  No other thread can
75; observe the order of the acquire fence and the store.
76define void @test5(i32* %addr.i) {
77; CHECK-LABEL: @test5
78; CHECK: store
79; CHECK: fence
80; CHECK: store
81; CHECK: ret
82  store i32 5, i32* %addr.i, align 4
83  fence acquire
84  store i32 5, i32* %addr.i, align 4
85  ret void
86}
87