[rtsan] Add fork/execve interceptors (#117198)
[llvm-project.git] / llvm / test / Transforms / DeadStoreElimination / phi-translation.ll
blob65e6332b1e47d3283f282d2e2a182b08eb0cd174
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -passes=dse -S %s | FileCheck %s
4 ; 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:    br label [[END:%.*]]
14 ; CHECK:       else:
15 ; CHECK-NEXT:    br label [[END]]
16 ; CHECK:       end:
17 ; CHECK-NEXT:    [[P:%.*]] = phi ptr [ [[A_1]], [[THEN]] ], [ [[A_2]], [[ELSE]] ]
18 ; CHECK-NEXT:    store i8 10, ptr [[P]], align 1
19 ; CHECK-NEXT:    ret void
21 entry:
22   %a.1 = alloca i8
23   %a.2 = alloca i8
24   br i1 %c, label %then, label %else
26 then:
27   store i8 0, ptr %a.1
28   br label %end
30 else:
31   store i8 9, ptr %a.2
32   br label %end
34 end:
35   %p = phi ptr [ %a.1, %then ], [ %a.2, %else ]
36   store i8 10, ptr %p
37   ret void
40 ; The store in %else can be eliminated by translating %p through the phi.
41 ; The store in %then cannot be eliminated, because %a.1 is read before the final
42 ; store.
43 define i8 @memoryphi_translate_2(i1 %c) {
44 ; CHECK-LABEL: @memoryphi_translate_2(
45 ; CHECK-NEXT:  entry:
46 ; CHECK-NEXT:    [[A_1:%.*]] = alloca i8, align 1
47 ; CHECK-NEXT:    [[A_2:%.*]] = alloca i8, align 1
48 ; CHECK-NEXT:    br i1 [[C:%.*]], label [[THEN:%.*]], label [[ELSE:%.*]]
49 ; CHECK:       then:
50 ; CHECK-NEXT:    store i8 0, ptr [[A_1]], align 1
51 ; CHECK-NEXT:    br label [[END:%.*]]
52 ; CHECK:       else:
53 ; CHECK-NEXT:    br label [[END]]
54 ; CHECK:       end:
55 ; CHECK-NEXT:    [[P:%.*]] = phi ptr [ [[A_1]], [[THEN]] ], [ [[A_2]], [[ELSE]] ]
56 ; CHECK-NEXT:    [[L:%.*]] = load i8, ptr [[A_1]], align 1
57 ; CHECK-NEXT:    store i8 10, ptr [[P]], align 1
58 ; CHECK-NEXT:    ret i8 [[L]]
60 entry:
61   %a.1 = alloca i8
62   %a.2 = alloca i8
63   br i1 %c, label %then, label %else
65 then:
66   store i8 0, ptr %a.1
67   br label %end
69 else:
70   store i8 9, ptr %a.2
71   br label %end
73 end:
74   %p = phi ptr [ %a.1, %then ], [ %a.2, %else ]
75   %l = load i8, ptr %a.1
76   store i8 10, ptr %p
77   ret i8 %l
80 ; The store in %then can be eliminated by translating %p through the phi.
81 ; The store in %else cannot be eliminated, because %a.2 is read before the final
82 ; store.
83 define i8 @memoryphi_translate_3(i1 %c) {
84 ; CHECK-LABEL: @memoryphi_translate_3(
85 ; CHECK-NEXT:  entry:
86 ; CHECK-NEXT:    [[A_1:%.*]] = alloca i8, align 1
87 ; CHECK-NEXT:    [[A_2:%.*]] = alloca i8, align 1
88 ; CHECK-NEXT:    br i1 [[C:%.*]], label [[THEN:%.*]], label [[ELSE:%.*]]
89 ; CHECK:       then:
90 ; CHECK-NEXT:    br label [[END:%.*]]
91 ; CHECK:       else:
92 ; CHECK-NEXT:    store i8 9, ptr [[A_2]], align 1
93 ; CHECK-NEXT:    br label [[END]]
94 ; CHECK:       end:
95 ; CHECK-NEXT:    [[P:%.*]] = phi ptr [ [[A_1]], [[THEN]] ], [ [[A_2]], [[ELSE]] ]
96 ; CHECK-NEXT:    [[L:%.*]] = load i8, ptr [[A_2]], align 1
97 ; CHECK-NEXT:    store i8 10, ptr [[P]], align 1
98 ; CHECK-NEXT:    ret i8 [[L]]
100 entry:
101   %a.1 = alloca i8
102   %a.2 = alloca i8
103   br i1 %c, label %then, label %else
105 then:
106   store i8 0, ptr %a.1
107   br label %end
109 else:
110   store i8 9, ptr %a.2
111   br label %end
113 end:
114   %p = phi ptr [ %a.1, %then ], [ %a.2, %else ]
115   %l = load i8, ptr %a.2
116   store i8 10, ptr %p
117   ret i8 %l
120 ; No stores can be eliminated, because there's a load from the phi.
121 define i8 @memoryphi_translate_4(i1 %c) {
122 ; CHECK-LABEL: @memoryphi_translate_4(
123 ; CHECK-NEXT:  entry:
124 ; CHECK-NEXT:    [[A_1:%.*]] = alloca i8, align 1
125 ; CHECK-NEXT:    [[A_2:%.*]] = alloca i8, align 1
126 ; CHECK-NEXT:    br i1 [[C:%.*]], label [[THEN:%.*]], label [[ELSE:%.*]]
127 ; CHECK:       then:
128 ; CHECK-NEXT:    store i8 0, ptr [[A_1]], align 1
129 ; CHECK-NEXT:    br label [[END:%.*]]
130 ; CHECK:       else:
131 ; CHECK-NEXT:    store i8 9, ptr [[A_2]], align 1
132 ; CHECK-NEXT:    br label [[END]]
133 ; CHECK:       end:
134 ; CHECK-NEXT:    [[P:%.*]] = phi ptr [ [[A_1]], [[THEN]] ], [ [[A_2]], [[ELSE]] ]
135 ; CHECK-NEXT:    [[L:%.*]] = load i8, ptr [[P]], align 1
136 ; CHECK-NEXT:    store i8 10, ptr [[P]], align 1
137 ; CHECK-NEXT:    ret i8 [[L]]
139 entry:
140   %a.1 = alloca i8
141   %a.2 = alloca i8
142   br i1 %c, label %then, label %else
144 then:
145   store i8 0, ptr %a.1
146   br label %end
148 else:
149   store i8 9, ptr %a.2
150   br label %end
152 end:
153   %p = phi ptr [ %a.1, %then ], [ %a.2, %else ]
154   %l = load i8, ptr %p
155   store i8 10, ptr %p
156   ret i8 %l
159 ; TODO: The store in %entry can be removed by translating %p through the phi.
160 define void @memoryphi_translate_5(i1 %cond) {
161 ; CHECK-LABEL: @memoryphi_translate_5(
162 ; CHECK-NEXT:  entry:
163 ; CHECK-NEXT:    [[A:%.*]] = alloca i8, align 1
164 ; CHECK-NEXT:    [[B:%.*]] = alloca i8, align 1
165 ; CHECK-NEXT:    store i8 0, ptr [[A]], align 1
166 ; CHECK-NEXT:    br i1 [[COND:%.*]], label [[COND_TRUE:%.*]], label [[COND_END:%.*]]
167 ; CHECK:       cond.true:
168 ; CHECK-NEXT:    br label [[COND_END]]
169 ; CHECK:       cond.end:
170 ; CHECK-NEXT:    [[P:%.*]] = phi ptr [ [[B]], [[COND_TRUE]] ], [ [[A]], [[ENTRY:%.*]] ]
171 ; CHECK-NEXT:    store i8 0, ptr [[P]], align 1
172 ; CHECK-NEXT:    call void @use(ptr [[P]])
173 ; CHECK-NEXT:    ret void
175 entry:
176   %a = alloca i8
177   %b = alloca i8
178   %c = alloca i8
179   store i8 0, ptr %a
180   br i1 %cond, label %cond.true, label %cond.end
182 cond.true:
183   store i8 0, ptr %c
184   br label %cond.end
186 cond.end:
187   %p = phi ptr [ %b, %cond.true ], [ %a, %entry ]
188   store i8 0, ptr %p
189   call void @use(ptr %p)
190   ret void
193 ; TODO: The store in %entry can be removed by translating %p through the phi.
194 ; Same as @memoryphi_translate_5, but without stores in %cond.true, so there
195 ; is no MemoryPhi.
196 define void @translate_without_memoryphi_1(i1 %cond) {
197 ; CHECK-LABEL: @translate_without_memoryphi_1(
198 ; CHECK-NEXT:  entry:
199 ; CHECK-NEXT:    [[A:%.*]] = alloca i8, align 1
200 ; CHECK-NEXT:    [[B:%.*]] = alloca i8, align 1
201 ; CHECK-NEXT:    store i8 0, ptr [[A]], align 1
202 ; CHECK-NEXT:    br i1 [[COND:%.*]], label [[COND_TRUE:%.*]], label [[COND_END:%.*]]
203 ; CHECK:       cond.true:
204 ; CHECK-NEXT:    br label [[COND_END]]
205 ; CHECK:       cond.end:
206 ; CHECK-NEXT:    [[P:%.*]] = phi ptr [ [[B]], [[COND_TRUE]] ], [ [[A]], [[ENTRY:%.*]] ]
207 ; CHECK-NEXT:    store i8 0, ptr [[P]], align 1
208 ; CHECK-NEXT:    call void @use(ptr [[P]])
209 ; CHECK-NEXT:    ret void
211 entry:
212   %a = alloca i8
213   %b = alloca i8
214   store i8 0, ptr %a
215   br i1 %cond, label %cond.true, label %cond.end
217 cond.true:
218   br label %cond.end
220 cond.end:
221   %p = phi ptr [ %b, %cond.true ], [ %a, %entry ]
222   store i8 0, ptr %p
223   call void @use(ptr %p)
224   ret void
227 ; In the test, translating through the phi results in a null address. Make sure
228 ; this does not cause a crash.
229 define void @test_trans_null(i1 %c, ptr %ptr) {
230 ; CHECK-LABEL: @test_trans_null(
231 ; CHECK-NEXT:  entry:
232 ; CHECK-NEXT:    br i1 [[C:%.*]], label [[THEN:%.*]], label [[ELSE:%.*]]
233 ; CHECK:       then:
234 ; CHECK-NEXT:    br label [[EXIT:%.*]]
235 ; CHECK:       else:
236 ; CHECK-NEXT:    call void @fn()
237 ; CHECK-NEXT:    [[GEP_1:%.*]] = getelementptr inbounds i16, ptr undef, i64 2
238 ; CHECK-NEXT:    store i16 8, ptr [[GEP_1]], align 2
239 ; CHECK-NEXT:    br label [[EXIT]]
240 ; CHECK:       exit:
241 ; CHECK-NEXT:    [[P:%.*]] = phi ptr [ [[PTR:%.*]], [[THEN]] ], [ undef, [[ELSE]] ]
242 ; CHECK-NEXT:    [[GEP_2:%.*]] = getelementptr inbounds i16, ptr [[P]], i64 2
243 ; CHECK-NEXT:    store i16 8, ptr [[GEP_2]], align 2
244 ; CHECK-NEXT:    ret void
246 entry:
247   br i1 %c, label %then, label %else
249 then:
250   br label %exit
252 else:
253   call void @fn()
254   %gep.1 = getelementptr inbounds i16, ptr undef, i64 2
255   store i16 8, ptr %gep.1, align 2
256   br label %exit
258 exit:
259   %p = phi ptr [ %ptr, %then ], [ undef, %else ]
260   %gep.2 = getelementptr inbounds i16, ptr %p, i64 2
261   store i16 8, ptr %gep.2, align 2
262   ret void
266 declare void @use(ptr)
267 declare void @fn()