1 ; RUN: opt -basicaa -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
4 %struct.hoge = type { i32, %struct.widget }
5 %struct.widget = type { i64 }
7 define hidden void @quux(%struct.hoge *%f) align 2 {
8 %tmp = getelementptr inbounds %struct.hoge, %struct.hoge* %f, i64 0, i32 1, i32 0
9 %tmp24 = getelementptr inbounds %struct.hoge, %struct.hoge* %f, i64 0, i32 1
10 %tmp25 = bitcast %struct.widget* %tmp24 to i64**
13 bb26: ; preds = %bb77, %0
14 ; CHECK: 3 = MemoryPhi({%0,liveOnEntry},{bb77,2})
15 ; CHECK-NEXT: br i1 undef, label %bb68, label %bb77
16 br i1 undef, label %bb68, label %bb77
19 ; CHECK: MemoryUse(liveOnEntry)
20 ; CHECK-NEXT: %tmp69 = load i64, i64* null, align 8
21 %tmp69 = load i64, i64* null, align 8
22 ; CHECK: 1 = MemoryDef(3)
23 ; CHECK-NEXT: store i64 %tmp69, i64* %tmp, align 8
24 store i64 %tmp69, i64* %tmp, align 8
27 bb77: ; preds = %bb68, %bb26
28 ; CHECK: 2 = MemoryPhi({bb26,3},{bb68,1})
30 ; CHECK-NEXT: %tmp78 = load i64*, i64** %tmp25, align 8
31 %tmp78 = load i64*, i64** %tmp25, align 8
32 %tmp79 = getelementptr inbounds i64, i64* %tmp78, i64 undef
36 define hidden void @quux_no_null_opt(%struct.hoge *%f) align 2 #0 {
37 ; CHECK-LABEL: quux_no_null_opt(
38 %tmp = getelementptr inbounds %struct.hoge, %struct.hoge* %f, i64 0, i32 1, i32 0
39 %tmp24 = getelementptr inbounds %struct.hoge, %struct.hoge* %f, i64 0, i32 1
40 %tmp25 = bitcast %struct.widget* %tmp24 to i64**
43 bb26: ; preds = %bb77, %0
44 ; CHECK: 3 = MemoryPhi({%0,liveOnEntry},{bb77,2})
45 ; CHECK-NEXT: br i1 undef, label %bb68, label %bb77
46 br i1 undef, label %bb68, label %bb77
50 ; CHECK-NEXT: %tmp69 = load i64, i64* null, align 8
51 %tmp69 = load i64, i64* null, align 8
52 ; CHECK: 1 = MemoryDef(3)
53 ; CHECK-NEXT: store i64 %tmp69, i64* %tmp, align 8
54 store i64 %tmp69, i64* %tmp, align 8
57 bb77: ; preds = %bb68, %bb26
58 ; CHECK: 2 = MemoryPhi({bb26,3},{bb68,1})
60 ; CHECK-NEXT: %tmp78 = load i64*, i64** %tmp25, align 8
61 %tmp78 = load i64*, i64** %tmp25, align 8
62 %tmp79 = getelementptr inbounds i64, i64* %tmp78, i64 undef
66 ; CHECK-LABEL: define void @quux_skip
67 define void @quux_skip(%struct.hoge* noalias %f, i64* noalias %g) align 2 {
68 %tmp = getelementptr inbounds %struct.hoge, %struct.hoge* %f, i64 0, i32 1, i32 0
69 %tmp24 = getelementptr inbounds %struct.hoge, %struct.hoge* %f, i64 0, i32 1
70 %tmp25 = bitcast %struct.widget* %tmp24 to i64**
73 bb26: ; preds = %bb77, %0
74 ; CHECK: 3 = MemoryPhi({%0,liveOnEntry},{bb77,2})
75 ; CHECK-NEXT: br i1 undef, label %bb68, label %bb77
76 br i1 undef, label %bb68, label %bb77
80 ; CHECK-NEXT: %tmp69 = load i64, i64* %g, align 8
81 %tmp69 = load i64, i64* %g, align 8
82 ; CHECK: 1 = MemoryDef(3)
83 ; CHECK-NEXT: store i64 %tmp69, i64* %g, align 8
84 store i64 %tmp69, i64* %g, align 8
87 bb77: ; preds = %bb68, %bb26
88 ; CHECK: 2 = MemoryPhi({bb26,3},{bb68,1})
89 ; CHECK: MemoryUse(liveOnEntry)
90 ; CHECK-NEXT: %tmp78 = load i64*, i64** %tmp25, align 8
91 %tmp78 = load i64*, i64** %tmp25, align 8
95 ; CHECK-LABEL: define void @quux_dominated
96 define void @quux_dominated(%struct.hoge* noalias %f, i64* noalias %g) align 2 {
97 %tmp = getelementptr inbounds %struct.hoge, %struct.hoge* %f, i64 0, i32 1, i32 0
98 %tmp24 = getelementptr inbounds %struct.hoge, %struct.hoge* %f, i64 0, i32 1
99 %tmp25 = bitcast %struct.widget* %tmp24 to i64**
102 bb26: ; preds = %bb77, %0
103 ; CHECK: 3 = MemoryPhi({%0,liveOnEntry},{bb77,2})
104 ; CHECK: MemoryUse(3)
105 ; CHECK-NEXT: load i64*, i64** %tmp25, align 8
106 load i64*, i64** %tmp25, align 8
107 br i1 undef, label %bb68, label %bb77
109 bb68: ; preds = %bb26
110 ; CHECK: MemoryUse(3)
111 ; CHECK-NEXT: %tmp69 = load i64, i64* %g, align 8
112 %tmp69 = load i64, i64* %g, align 8
113 ; CHECK: 1 = MemoryDef(3)
114 ; CHECK-NEXT: store i64 %tmp69, i64* %g, align 8
115 store i64 %tmp69, i64* %g, align 8
118 bb77: ; preds = %bb68, %bb26
119 ; CHECK: 4 = MemoryPhi({bb26,3},{bb68,1})
120 ; CHECK: 2 = MemoryDef(4)
121 ; CHECK-NEXT: store i64* null, i64** %tmp25, align 8
122 store i64* null, i64** %tmp25, align 8
126 ; CHECK-LABEL: define void @quux_nodominate
127 define void @quux_nodominate(%struct.hoge* noalias %f, i64* noalias %g) align 2 {
128 %tmp = getelementptr inbounds %struct.hoge, %struct.hoge* %f, i64 0, i32 1, i32 0
129 %tmp24 = getelementptr inbounds %struct.hoge, %struct.hoge* %f, i64 0, i32 1
130 %tmp25 = bitcast %struct.widget* %tmp24 to i64**
133 bb26: ; preds = %bb77, %0
134 ; CHECK: 3 = MemoryPhi({%0,liveOnEntry},{bb77,2})
135 ; CHECK: MemoryUse(liveOnEntry)
136 ; CHECK-NEXT: load i64*, i64** %tmp25, align 8
137 load i64*, i64** %tmp25, align 8
138 br i1 undef, label %bb68, label %bb77
140 bb68: ; preds = %bb26
141 ; CHECK: MemoryUse(3)
142 ; CHECK-NEXT: %tmp69 = load i64, i64* %g, align 8
143 %tmp69 = load i64, i64* %g, align 8
144 ; CHECK: 1 = MemoryDef(3)
145 ; CHECK-NEXT: store i64 %tmp69, i64* %g, align 8
146 store i64 %tmp69, i64* %g, align 8
149 bb77: ; preds = %bb68, %bb26
150 ; CHECK: 2 = MemoryPhi({bb26,3},{bb68,1})
151 ; CHECK-NEXT: br label %bb26
155 attributes #0 = { "null-pointer-is-valid"="true" }