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 volatile stores/loads count as MemoryDefs
5
6; CHECK-LABEL: define i32 @foo
7define i32 @foo() {
8  %1 = alloca i32, align 4
9; CHECK: 1 = MemoryDef(liveOnEntry)
10; CHECK-NEXT: store volatile i32 4
11  store volatile i32 4, i32* %1, align 4
12; CHECK: 2 = MemoryDef(1)
13; CHECK-NEXT: store volatile i32 8
14  store volatile i32 8, i32* %1, align 4
15; CHECK: 3 = MemoryDef(2)
16; CHECK-NEXT: %2 = load volatile i32
17  %2 = load volatile i32, i32* %1, align 4
18; CHECK: 4 = MemoryDef(3)
19; CHECK-NEXT: %3 = load volatile i32
20  %3 = load volatile i32, i32* %1, align 4
21  %4 = add i32 %3, %2
22  ret i32 %4
23}
24
25; Ensuring we allow hoisting nonvolatile loads around volatile loads.
26; CHECK-LABEL: define void @volatile_only
27define void @volatile_only(i32* %arg1, i32* %arg2) {
28  ; Trivially NoAlias/MustAlias
29  %a = alloca i32
30  %b = alloca i32
31
32; CHECK: 1 = MemoryDef(liveOnEntry)
33; CHECK-NEXT: load volatile i32, i32* %a
34  load volatile i32, i32* %a
35; CHECK: MemoryUse(liveOnEntry)
36; CHECK-NEXT: load i32, i32* %b
37  load i32, i32* %b
38; CHECK: MemoryUse(liveOnEntry)
39; CHECK-NEXT: load i32, i32* %a
40  load i32, i32* %a
41
42  ; MayAlias
43; CHECK: 2 = MemoryDef(1)
44; CHECK-NEXT: load volatile i32, i32* %arg1
45  load volatile i32, i32* %arg1
46; CHECK: MemoryUse(liveOnEntry)
47; CHECK-NEXT: load i32, i32* %arg2
48  load i32, i32* %arg2
49
50  ret void
51}
52
53; Ensuring that volatile atomic operations work properly.
54; CHECK-LABEL: define void @volatile_atomics
55define void @volatile_atomics(i32* %arg1, i32* %arg2) {
56  %a = alloca i32
57  %b = alloca i32
58
59 ; Trivially NoAlias/MustAlias
60
61; CHECK: 1 = MemoryDef(liveOnEntry)
62; CHECK-NEXT: load atomic volatile i32, i32* %a acquire, align 4
63  load atomic volatile i32, i32* %a acquire, align 4
64; CHECK: MemoryUse(1)
65; CHECK-NEXT: load i32, i32* %b
66  load i32, i32* %b
67
68; CHECK: 2 = MemoryDef(1)
69; CHECK-NEXT: load atomic volatile i32, i32* %a monotonic, align 4
70  load atomic volatile i32, i32* %a monotonic, align 4
71; CHECK: MemoryUse(1)
72; CHECK-NEXT: load i32, i32* %b
73  load i32, i32* %b
74; CHECK: MemoryUse(1)
75; CHECK-NEXT: load atomic i32, i32* %b unordered, align 4
76  load atomic i32, i32* %b unordered, align 4
77; CHECK: MemoryUse(1)
78; CHECK-NEXT: load atomic i32, i32* %a unordered, align 4
79  load atomic i32, i32* %a unordered, align 4
80; CHECK: MemoryUse(1)
81; CHECK-NEXT: load i32, i32* %a
82  load i32, i32* %a
83
84  ; MayAlias
85; CHECK: 3 = MemoryDef(2)
86; CHECK-NEXT: load atomic volatile i32, i32* %arg1 monotonic, align 4
87  load atomic volatile i32, i32* %arg1 monotonic, align 4
88; CHECK: MemoryUse(1)
89; CHECK-NEXT: load i32, i32* %arg2
90  load i32, i32* %arg2
91
92  ret void
93}
94