1; RUN: opt -basic-aa -print-memoryssa -verify-memoryssa -analyze < %s 2>&1 | FileCheck %s
2; RUN: opt -aa-pipeline=basic-aa -passes='print<memoryssa>,verify<memoryssa>' -disable-output < %s 2>&1 | FileCheck %s
3;
4; Ensures that atomic loads count as MemoryDefs
5
6; CHECK-LABEL: define i32 @foo
7define i32 @foo(i32* %a, i32* %b) {
8; CHECK: 1 = MemoryDef(liveOnEntry)
9; CHECK-NEXT: store i32 4
10  store i32 4, i32* %a, align 4
11; CHECK: 2 = MemoryDef(1)
12; CHECK-NEXT: %1 = load atomic i32
13  %1 = load atomic i32, i32* %b acquire, align 4
14; CHECK: MemoryUse(2)
15; CHECK-NEXT: %2 = load i32
16  %2 = load i32, i32* %a, align 4
17  %3 = add i32 %1, %2
18  ret i32 %3
19}
20
21; CHECK-LABEL: define void @bar
22define void @bar(i32* %a) {
23; CHECK: MemoryUse(liveOnEntry)
24; CHECK-NEXT: load atomic i32, i32* %a unordered, align 4
25  load atomic i32, i32* %a unordered, align 4
26; CHECK: 1 = MemoryDef(liveOnEntry)
27; CHECK-NEXT: load atomic i32, i32* %a monotonic, align 4
28  load atomic i32, i32* %a monotonic, align 4
29; CHECK: 2 = MemoryDef(1)
30; CHECK-NEXT: load atomic i32, i32* %a acquire, align 4
31  load atomic i32, i32* %a acquire, align 4
32; CHECK: 3 = MemoryDef(2)
33; CHECK-NEXT: load atomic i32, i32* %a seq_cst, align 4
34  load atomic i32, i32* %a seq_cst, align 4
35  ret void
36}
37
38; CHECK-LABEL: define void @baz
39define void @baz(i32* %a) {
40; CHECK: 1 = MemoryDef(liveOnEntry)
41; CHECK-NEXT: %1 = load atomic i32
42  %1 = load atomic i32, i32* %a acquire, align 4
43; CHECK: MemoryUse(1)
44; CHECK-NEXT: %2 = load atomic i32, i32* %a unordered, align 4
45  %2 = load atomic i32, i32* %a unordered, align 4
46; CHECK: 2 = MemoryDef(1)
47; CHECK-NEXT: %3 = load atomic i32, i32* %a monotonic, align 4
48  %3 = load atomic i32, i32* %a monotonic, align 4
49  ret void
50}
51
52; CHECK-LABEL: define void @fences
53define void @fences(i32* %a) {
54; CHECK: 1 = MemoryDef(liveOnEntry)
55; CHECK-NEXT: fence acquire
56  fence acquire
57; CHECK: MemoryUse(1)
58; CHECK-NEXT: %1 = load i32, i32* %a
59  %1 = load i32, i32* %a
60
61; CHECK: 2 = MemoryDef(1)
62; CHECK-NEXT: fence release
63  fence release
64; CHECK: MemoryUse(2)
65; CHECK-NEXT: %2 = load i32, i32* %a
66  %2 = load i32, i32* %a
67
68; CHECK: 3 = MemoryDef(2)
69; CHECK-NEXT: fence acq_rel
70  fence acq_rel
71; CHECK: MemoryUse(3)
72; CHECK-NEXT: %3 = load i32, i32* %a
73  %3 = load i32, i32* %a
74
75; CHECK: 4 = MemoryDef(3)
76; CHECK-NEXT: fence seq_cst
77  fence seq_cst
78; CHECK: MemoryUse(4)
79; CHECK-NEXT: %4 = load i32, i32* %a
80  %4 = load i32, i32* %a
81  ret void
82}
83
84; CHECK-LABEL: define void @seq_cst_clobber
85define void @seq_cst_clobber(i32* noalias %a, i32* noalias %b) {
86; CHECK: 1 = MemoryDef(liveOnEntry)
87; CHECK-NEXT: %1 = load atomic i32, i32* %a monotonic, align 4
88  load atomic i32, i32* %a monotonic, align 4
89
90; CHECK: 2 = MemoryDef(1)
91; CHECK-NEXT: %2 = load atomic i32, i32* %a seq_cst, align 4
92  load atomic i32, i32* %a seq_cst, align 4
93
94; CHECK: 3 = MemoryDef(2)
95; CHECK-NEXT: load atomic i32, i32* %a monotonic, align 4
96  load atomic i32, i32* %a monotonic, align 4
97
98  ret void
99}
100
101; Ensure that AA hands us MRI_Mod on unreorderable atomic ops.
102;
103; This test is a bit implementation-specific. In particular, it depends on that
104; we pass cmpxchg-load queries to AA, without trying to reason about them on
105; our own.
106;
107; If AA gets more aggressive, we can find another way.
108;
109; CHECK-LABEL: define void @check_aa_is_sane
110define void @check_aa_is_sane(i32* noalias %a, i32* noalias %b) {
111; CHECK: 1 = MemoryDef(liveOnEntry)
112; CHECK-NEXT: cmpxchg i32* %a, i32 0, i32 1 acquire acquire
113  cmpxchg i32* %a, i32 0, i32 1 acquire acquire
114; CHECK: MemoryUse(1)
115; CHECK-NEXT: load i32, i32* %b, align 4
116  load i32, i32* %b, align 4
117
118  ret void
119}
120