[DAGCombiner] Add target hook function to decide folding (mul (add x, c1), c2)
[llvm-project.git] / llvm / test / Transforms / DeadStoreElimination / phi-translation.ll
blob9f764bdb0d0b14dc4e91f6938e12b1275ed3f8b4
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
5 ; through the phi.
6 define void @memoryphi_translate_1(i1 %c) {
7 ; CHECK-LABEL: @memoryphi_translate_1(
8 ; CHECK-NEXT:  entry:
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:%.*]]
12 ; CHECK:       then:
13 ; CHECK-NEXT:    store i8 0, i8* [[A_1]], align 1
14 ; CHECK-NEXT:    br label [[END:%.*]]
15 ; CHECK:       else:
16 ; CHECK-NEXT:    store i8 9, i8* [[A_2]], align 1
17 ; CHECK-NEXT:    br label [[END]]
18 ; CHECK:       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
23 entry:
24   %a.1 = alloca i8
25   %a.2 = alloca i8
26   br i1 %c, label %then, label %else
28 then:
29   store i8 0, i8* %a.1
30   br label %end
32 else:
33   store i8 9, i8* %a.2
34   br label %end
36 end:
37   %p = phi i8* [ %a.1, %then ], [ %a.2, %else ]
38   store i8 10, i8* %p
39   ret void
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
44 ; store.
45 define i8 @memoryphi_translate_2(i1 %c) {
46 ; CHECK-LABEL: @memoryphi_translate_2(
47 ; CHECK-NEXT:  entry:
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:%.*]]
51 ; CHECK:       then:
52 ; CHECK-NEXT:    store i8 0, i8* [[A_1]], align 1
53 ; CHECK-NEXT:    br label [[END:%.*]]
54 ; CHECK:       else:
55 ; CHECK-NEXT:    store i8 9, i8* [[A_2]], align 1
56 ; CHECK-NEXT:    br label [[END]]
57 ; CHECK:       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]]
63 entry:
64   %a.1 = alloca i8
65   %a.2 = alloca i8
66   br i1 %c, label %then, label %else
68 then:
69   store i8 0, i8* %a.1
70   br label %end
72 else:
73   store i8 9, i8* %a.2
74   br label %end
76 end:
77   %p = phi i8* [ %a.1, %then ], [ %a.2, %else ]
78   %l = load i8, i8* %a.1
79   store i8 10, i8* %p
80   ret i8 %l
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
85 ; store.
86 define i8 @memoryphi_translate_3(i1 %c) {
87 ; CHECK-LABEL: @memoryphi_translate_3(
88 ; CHECK-NEXT:  entry:
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:%.*]]
92 ; CHECK:       then:
93 ; CHECK-NEXT:    store i8 0, i8* [[A_1]], align 1
94 ; CHECK-NEXT:    br label [[END:%.*]]
95 ; CHECK:       else:
96 ; CHECK-NEXT:    store i8 9, i8* [[A_2]], align 1
97 ; CHECK-NEXT:    br label [[END]]
98 ; CHECK:       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]]
104 entry:
105   %a.1 = alloca i8
106   %a.2 = alloca i8
107   br i1 %c, label %then, label %else
109 then:
110   store i8 0, i8* %a.1
111   br label %end
113 else:
114   store i8 9, i8* %a.2
115   br label %end
117 end:
118   %p = phi i8* [ %a.1, %then ], [ %a.2, %else ]
119   %l = load i8, i8* %a.2
120   store i8 10, i8* %p
121   ret i8 %l
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(
127 ; CHECK-NEXT:  entry:
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:%.*]]
131 ; CHECK:       then:
132 ; CHECK-NEXT:    store i8 0, i8* [[A_1]], align 1
133 ; CHECK-NEXT:    br label [[END:%.*]]
134 ; CHECK:       else:
135 ; CHECK-NEXT:    store i8 9, i8* [[A_2]], align 1
136 ; CHECK-NEXT:    br label [[END]]
137 ; CHECK:       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]]
143 entry:
144   %a.1 = alloca i8
145   %a.2 = alloca i8
146   br i1 %c, label %then, label %else
148 then:
149   store i8 0, i8* %a.1
150   br label %end
152 else:
153   store i8 9, i8* %a.2
154   br label %end
156 end:
157   %p = phi i8* [ %a.1, %then ], [ %a.2, %else ]
158   %l = load i8, i8* %p
159   store i8 10, i8* %p
160   ret i8 %l
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(
166 ; CHECK-NEXT:  entry:
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:%.*]]
172 ; CHECK:       cond.true:
173 ; CHECK-NEXT:    store i8 0, i8* [[C]], align 1
174 ; CHECK-NEXT:    br label [[COND_END]]
175 ; CHECK:       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
181 entry:
182   %a = alloca i8
183   %b = alloca i8
184   %c = alloca i8
185   store i8 0, i8* %a
186   br i1 %cond, label %cond.true, label %cond.end
188 cond.true:
189   store i8 0, i8* %c
190   br label %cond.end
192 cond.end:
193   %p = phi i8* [ %b, %cond.true ], [ %a, %entry ]
194   store i8 0, i8* %p
195   call void @use(i8* %p)
196   ret void
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
201 ; is no MemoryPhi.
202 define void @translate_without_memoryphi_1(i1 %cond) {
203 ; CHECK-LABEL: @translate_without_memoryphi_1(
204 ; CHECK-NEXT:  entry:
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:%.*]]
209 ; CHECK:       cond.true:
210 ; CHECK-NEXT:    br label [[COND_END]]
211 ; CHECK:       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
217 entry:
218   %a = alloca i8
219   %b = alloca i8
220   store i8 0, i8* %a
221   br i1 %cond, label %cond.true, label %cond.end
223 cond.true:
224   br label %cond.end
226 cond.end:
227   %p = phi i8* [ %b, %cond.true ], [ %a, %entry ]
228   store i8 0, i8* %p
229   call void @use(i8* %p)
230   ret void
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(
237 ; CHECK-NEXT:  entry:
238 ; CHECK-NEXT:    br i1 [[C:%.*]], label [[THEN:%.*]], label [[ELSE:%.*]]
239 ; CHECK:       then:
240 ; CHECK-NEXT:    br label [[EXIT:%.*]]
241 ; CHECK:       else:
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]]
247 ; CHECK:       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
253 entry:
254   br i1 %c, label %then, label %else
256 then:
257   br label %exit
259 else:
260   call void @fn()
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
264   br label %exit
266 exit:
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
270   ret void
274 declare void @use(i8*)
275 declare void @fn()