1 ; RUN: opt -aa-pipeline=basic-aa -passes='print<memoryssa>,verify<memoryssa>' -disable-output < %s 2>&1 | FileCheck %s
3 %struct.hoge = type { i32, %struct.widget }
4 %struct.widget = type { i64 }
6 define hidden void @quux(%struct.hoge *%f) align 2 {
7 %tmp = getelementptr inbounds %struct.hoge, %struct.hoge* %f, i64 0, i32 1, i32 0
8 %tmp24 = getelementptr inbounds %struct.hoge, %struct.hoge* %f, i64 0, i32 1
9 %tmp25 = bitcast %struct.widget* %tmp24 to i64**
12 bb26: ; preds = %bb77, %0
13 ; CHECK: 3 = MemoryPhi({%0,liveOnEntry},{bb77,2})
14 ; CHECK-NEXT: br i1 undef, label %bb68, label %bb77
15 br i1 undef, label %bb68, label %bb77
18 ; CHECK: MemoryUse(liveOnEntry)
19 ; CHECK-NEXT: %tmp69 = load i64, i64* null, align 8
20 %tmp69 = load i64, i64* null, align 8
21 ; CHECK: 1 = MemoryDef(3)
22 ; CHECK-NEXT: store i64 %tmp69, i64* %tmp, align 8
23 store i64 %tmp69, i64* %tmp, align 8
26 bb77: ; preds = %bb68, %bb26
27 ; CHECK: 2 = MemoryPhi({bb26,3},{bb68,1})
29 ; CHECK-NEXT: %tmp78 = load i64*, i64** %tmp25, align 8
30 %tmp78 = load i64*, i64** %tmp25, align 8
31 %tmp79 = getelementptr inbounds i64, i64* %tmp78, i64 undef
35 define hidden void @quux_no_null_opt(%struct.hoge *%f) align 2 #0 {
36 ; CHECK-LABEL: quux_no_null_opt(
37 %tmp = getelementptr inbounds %struct.hoge, %struct.hoge* %f, i64 0, i32 1, i32 0
38 %tmp24 = getelementptr inbounds %struct.hoge, %struct.hoge* %f, i64 0, i32 1
39 %tmp25 = bitcast %struct.widget* %tmp24 to i64**
42 bb26: ; preds = %bb77, %0
43 ; CHECK: 3 = MemoryPhi({%0,liveOnEntry},{bb77,2})
44 ; CHECK-NEXT: br i1 undef, label %bb68, label %bb77
45 br i1 undef, label %bb68, label %bb77
49 ; CHECK-NEXT: %tmp69 = load i64, i64* null, align 8
50 %tmp69 = load i64, i64* null, align 8
51 ; CHECK: 1 = MemoryDef(3)
52 ; CHECK-NEXT: store i64 %tmp69, i64* %tmp, align 8
53 store i64 %tmp69, i64* %tmp, align 8
56 bb77: ; preds = %bb68, %bb26
57 ; CHECK: 2 = MemoryPhi({bb26,3},{bb68,1})
59 ; CHECK-NEXT: %tmp78 = load i64*, i64** %tmp25, align 8
60 %tmp78 = load i64*, i64** %tmp25, align 8
61 %tmp79 = getelementptr inbounds i64, i64* %tmp78, i64 undef
65 ; CHECK-LABEL: define void @quux_skip
66 define void @quux_skip(%struct.hoge* noalias %f, i64* noalias %g) align 2 {
67 %tmp = getelementptr inbounds %struct.hoge, %struct.hoge* %f, i64 0, i32 1, i32 0
68 %tmp24 = getelementptr inbounds %struct.hoge, %struct.hoge* %f, i64 0, i32 1
69 %tmp25 = bitcast %struct.widget* %tmp24 to i64**
72 bb26: ; preds = %bb77, %0
73 ; CHECK: 3 = MemoryPhi({%0,liveOnEntry},{bb77,2})
74 ; CHECK-NEXT: br i1 undef, label %bb68, label %bb77
75 br i1 undef, label %bb68, label %bb77
79 ; CHECK-NEXT: %tmp69 = load i64, i64* %g, align 8
80 %tmp69 = load i64, i64* %g, align 8
81 ; CHECK: 1 = MemoryDef(3)
82 ; CHECK-NEXT: store i64 %tmp69, i64* %g, align 8
83 store i64 %tmp69, i64* %g, align 8
86 bb77: ; preds = %bb68, %bb26
87 ; CHECK: 2 = MemoryPhi({bb26,3},{bb68,1})
88 ; CHECK: MemoryUse(liveOnEntry)
89 ; CHECK-NEXT: %tmp78 = load i64*, i64** %tmp25, align 8
90 %tmp78 = load i64*, i64** %tmp25, align 8
94 ; CHECK-LABEL: define void @quux_dominated
95 define void @quux_dominated(%struct.hoge* noalias %f, i64* noalias %g) align 2 {
96 %tmp = getelementptr inbounds %struct.hoge, %struct.hoge* %f, i64 0, i32 1, i32 0
97 %tmp24 = getelementptr inbounds %struct.hoge, %struct.hoge* %f, i64 0, i32 1
98 %tmp25 = bitcast %struct.widget* %tmp24 to i64**
101 bb26: ; preds = %bb77, %0
102 ; CHECK: 3 = MemoryPhi({%0,liveOnEntry},{bb77,2})
103 ; CHECK: MemoryUse(3)
104 ; CHECK-NEXT: load i64*, i64** %tmp25, align 8
105 load i64*, i64** %tmp25, align 8
106 br i1 undef, label %bb68, label %bb77
108 bb68: ; preds = %bb26
109 ; CHECK: MemoryUse(3)
110 ; CHECK-NEXT: %tmp69 = load i64, i64* %g, align 8
111 %tmp69 = load i64, i64* %g, align 8
112 ; CHECK: 1 = MemoryDef(3)
113 ; CHECK-NEXT: store i64 %tmp69, i64* %g, align 8
114 store i64 %tmp69, i64* %g, align 8
117 bb77: ; preds = %bb68, %bb26
118 ; CHECK: 4 = MemoryPhi({bb26,3},{bb68,1})
119 ; CHECK: 2 = MemoryDef(4)
120 ; CHECK-NEXT: store i64* null, i64** %tmp25, align 8
121 store i64* null, i64** %tmp25, align 8
125 ; CHECK-LABEL: define void @quux_nodominate
126 define void @quux_nodominate(%struct.hoge* noalias %f, i64* noalias %g) align 2 {
127 %tmp = getelementptr inbounds %struct.hoge, %struct.hoge* %f, i64 0, i32 1, i32 0
128 %tmp24 = getelementptr inbounds %struct.hoge, %struct.hoge* %f, i64 0, i32 1
129 %tmp25 = bitcast %struct.widget* %tmp24 to i64**
132 bb26: ; preds = %bb77, %0
133 ; CHECK: 3 = MemoryPhi({%0,liveOnEntry},{bb77,2})
134 ; CHECK: MemoryUse(liveOnEntry)
135 ; CHECK-NEXT: load i64*, i64** %tmp25, align 8
136 load i64*, i64** %tmp25, align 8
137 br i1 undef, label %bb68, label %bb77
139 bb68: ; preds = %bb26
140 ; CHECK: MemoryUse(3)
141 ; CHECK-NEXT: %tmp69 = load i64, i64* %g, align 8
142 %tmp69 = load i64, i64* %g, align 8
143 ; CHECK: 1 = MemoryDef(3)
144 ; CHECK-NEXT: store i64 %tmp69, i64* %g, align 8
145 store i64 %tmp69, i64* %g, align 8
148 bb77: ; preds = %bb68, %bb26
149 ; CHECK: 2 = MemoryPhi({bb26,3},{bb68,1})
150 ; CHECK-NEXT: br label %bb26
154 attributes #0 = { null_pointer_is_valid }