1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -dse -S %s | FileCheck %s
4 ; TODO: Both the stores in %then and %else can be eliminated by translating %p
6 define void @memoryphi_translate_1(i1 %c) {
7 ; CHECK-LABEL: @memoryphi_translate_1(
9 ; CHECK-NEXT: [[A_1:%.*]] = alloca i8, align 1
10 ; CHECK-NEXT: [[A_2:%.*]] = alloca i8, align 1
11 ; CHECK-NEXT: br i1 [[C:%.*]], label [[THEN:%.*]], label [[ELSE:%.*]]
13 ; CHECK-NEXT: store i8 0, i8* [[A_1]], align 1
14 ; CHECK-NEXT: br label [[END:%.*]]
16 ; CHECK-NEXT: store i8 9, i8* [[A_2]], align 1
17 ; CHECK-NEXT: br label [[END]]
19 ; CHECK-NEXT: [[P:%.*]] = phi i8* [ [[A_1]], [[THEN]] ], [ [[A_2]], [[ELSE]] ]
20 ; CHECK-NEXT: store i8 10, i8* [[P]], align 1
21 ; CHECK-NEXT: ret void
26 br i1 %c, label %then, label %else
37 %p = phi i8* [ %a.1, %then ], [ %a.2, %else ]
42 ; TODO: The store in %else can be eliminated by translating %p through the phi.
43 ; The store in %then cannot be eliminated, because %a.1 is read before the final
45 define i8 @memoryphi_translate_2(i1 %c) {
46 ; CHECK-LABEL: @memoryphi_translate_2(
48 ; CHECK-NEXT: [[A_1:%.*]] = alloca i8, align 1
49 ; CHECK-NEXT: [[A_2:%.*]] = alloca i8, align 1
50 ; CHECK-NEXT: br i1 [[C:%.*]], label [[THEN:%.*]], label [[ELSE:%.*]]
52 ; CHECK-NEXT: store i8 0, i8* [[A_1]], align 1
53 ; CHECK-NEXT: br label [[END:%.*]]
55 ; CHECK-NEXT: store i8 9, i8* [[A_2]], align 1
56 ; CHECK-NEXT: br label [[END]]
58 ; CHECK-NEXT: [[P:%.*]] = phi i8* [ [[A_1]], [[THEN]] ], [ [[A_2]], [[ELSE]] ]
59 ; CHECK-NEXT: [[L:%.*]] = load i8, i8* [[A_1]], align 1
60 ; CHECK-NEXT: store i8 10, i8* [[P]], align 1
61 ; CHECK-NEXT: ret i8 [[L]]
66 br i1 %c, label %then, label %else
77 %p = phi i8* [ %a.1, %then ], [ %a.2, %else ]
78 %l = load i8, i8* %a.1
83 ; TODO: The store in %then can be eliminated by translating %p through the phi.
84 ; The store in %else cannot be eliminated, because %a.2 is read before the final
86 define i8 @memoryphi_translate_3(i1 %c) {
87 ; CHECK-LABEL: @memoryphi_translate_3(
89 ; CHECK-NEXT: [[A_1:%.*]] = alloca i8, align 1
90 ; CHECK-NEXT: [[A_2:%.*]] = alloca i8, align 1
91 ; CHECK-NEXT: br i1 [[C:%.*]], label [[THEN:%.*]], label [[ELSE:%.*]]
93 ; CHECK-NEXT: store i8 0, i8* [[A_1]], align 1
94 ; CHECK-NEXT: br label [[END:%.*]]
96 ; CHECK-NEXT: store i8 9, i8* [[A_2]], align 1
97 ; CHECK-NEXT: br label [[END]]
99 ; CHECK-NEXT: [[P:%.*]] = phi i8* [ [[A_1]], [[THEN]] ], [ [[A_2]], [[ELSE]] ]
100 ; CHECK-NEXT: [[L:%.*]] = load i8, i8* [[A_2]], align 1
101 ; CHECK-NEXT: store i8 10, i8* [[P]], align 1
102 ; CHECK-NEXT: ret i8 [[L]]
107 br i1 %c, label %then, label %else
118 %p = phi i8* [ %a.1, %then ], [ %a.2, %else ]
119 %l = load i8, i8* %a.2
124 ; No stores can be eliminated, because there's a load from the phi.
125 define i8 @memoryphi_translate_4(i1 %c) {
126 ; CHECK-LABEL: @memoryphi_translate_4(
128 ; CHECK-NEXT: [[A_1:%.*]] = alloca i8, align 1
129 ; CHECK-NEXT: [[A_2:%.*]] = alloca i8, align 1
130 ; CHECK-NEXT: br i1 [[C:%.*]], label [[THEN:%.*]], label [[ELSE:%.*]]
132 ; CHECK-NEXT: store i8 0, i8* [[A_1]], align 1
133 ; CHECK-NEXT: br label [[END:%.*]]
135 ; CHECK-NEXT: store i8 9, i8* [[A_2]], align 1
136 ; CHECK-NEXT: br label [[END]]
138 ; CHECK-NEXT: [[P:%.*]] = phi i8* [ [[A_1]], [[THEN]] ], [ [[A_2]], [[ELSE]] ]
139 ; CHECK-NEXT: [[L:%.*]] = load i8, i8* [[P]], align 1
140 ; CHECK-NEXT: store i8 10, i8* [[P]], align 1
141 ; CHECK-NEXT: ret i8 [[L]]
146 br i1 %c, label %then, label %else
157 %p = phi i8* [ %a.1, %then ], [ %a.2, %else ]
163 ; TODO: The store in %entry can be removed by translating %p through the phi.
164 define void @memoryphi_translate_5(i1 %cond) {
165 ; CHECK-LABEL: @memoryphi_translate_5(
167 ; CHECK-NEXT: [[A:%.*]] = alloca i8, align 1
168 ; CHECK-NEXT: [[B:%.*]] = alloca i8, align 1
169 ; CHECK-NEXT: [[C:%.*]] = alloca i8, align 1
170 ; CHECK-NEXT: store i8 0, i8* [[A]], align 1
171 ; CHECK-NEXT: br i1 [[COND:%.*]], label [[COND_TRUE:%.*]], label [[COND_END:%.*]]
173 ; CHECK-NEXT: store i8 0, i8* [[C]], align 1
174 ; CHECK-NEXT: br label [[COND_END]]
176 ; CHECK-NEXT: [[P:%.*]] = phi i8* [ [[B]], [[COND_TRUE]] ], [ [[A]], [[ENTRY:%.*]] ]
177 ; CHECK-NEXT: store i8 0, i8* [[P]], align 1
178 ; CHECK-NEXT: call void @use(i8* [[P]])
179 ; CHECK-NEXT: ret void
186 br i1 %cond, label %cond.true, label %cond.end
193 %p = phi i8* [ %b, %cond.true ], [ %a, %entry ]
195 call void @use(i8* %p)
199 ; TODO: The store in %entry can be removed by translating %p through the phi.
200 ; Same as @memoryphi_translate_5, but without stores in %cond.true, so there
202 define void @translate_without_memoryphi_1(i1 %cond) {
203 ; CHECK-LABEL: @translate_without_memoryphi_1(
205 ; CHECK-NEXT: [[A:%.*]] = alloca i8, align 1
206 ; CHECK-NEXT: [[B:%.*]] = alloca i8, align 1
207 ; CHECK-NEXT: store i8 0, i8* [[A]], align 1
208 ; CHECK-NEXT: br i1 [[COND:%.*]], label [[COND_TRUE:%.*]], label [[COND_END:%.*]]
210 ; CHECK-NEXT: br label [[COND_END]]
212 ; CHECK-NEXT: [[P:%.*]] = phi i8* [ [[B]], [[COND_TRUE]] ], [ [[A]], [[ENTRY:%.*]] ]
213 ; CHECK-NEXT: store i8 0, i8* [[P]], align 1
214 ; CHECK-NEXT: call void @use(i8* [[P]])
215 ; CHECK-NEXT: ret void
221 br i1 %cond, label %cond.true, label %cond.end
227 %p = phi i8* [ %b, %cond.true ], [ %a, %entry ]
229 call void @use(i8* %p)
233 ; In the test, translating through the phi results in a null address. Make sure
234 ; this does not cause a crash.
235 define void @test_trans_null(i1 %c, i16* %ptr) {
236 ; CHECK-LABEL: @test_trans_null(
238 ; CHECK-NEXT: br i1 [[C:%.*]], label [[THEN:%.*]], label [[ELSE:%.*]]
240 ; CHECK-NEXT: br label [[EXIT:%.*]]
242 ; CHECK-NEXT: call void @fn()
243 ; CHECK-NEXT: [[BC:%.*]] = bitcast i8* undef to i16*
244 ; CHECK-NEXT: [[GEP_1:%.*]] = getelementptr inbounds i16, i16* [[BC]], i64 2
245 ; CHECK-NEXT: store i16 8, i16* [[GEP_1]], align 2
246 ; CHECK-NEXT: br label [[EXIT]]
248 ; CHECK-NEXT: [[P:%.*]] = phi i16* [ [[PTR:%.*]], [[THEN]] ], [ [[BC]], [[ELSE]] ]
249 ; CHECK-NEXT: [[GEP_2:%.*]] = getelementptr inbounds i16, i16* [[P]], i64 2
250 ; CHECK-NEXT: store i16 8, i16* [[GEP_2]], align 2
251 ; CHECK-NEXT: ret void
254 br i1 %c, label %then, label %else
261 %bc = bitcast i8* undef to i16*
262 %gep.1 = getelementptr inbounds i16, i16* %bc, i64 2
263 store i16 8, i16* %gep.1, align 2
267 %p = phi i16* [ %ptr, %then ], [ %bc, %else ]
268 %gep.2 = getelementptr inbounds i16, i16* %p, i64 2
269 store i16 8, i16* %gep.2, align 2
274 declare void @use(i8*)