llvm.org GIT mirror llvm / 49ccc8d
[EarlyCSE] Remove guards with conditions known to be true If a condition is calculated only once, and there are multiple guards on this condition, we should be able to remove all guards dominated by the first of them. This patch allows EarlyCSE to try to find the condition of a guard among the known values, and if it is true, remove the guard. Otherwise we keep the guard and mark its condition as 'true' for future consideration. Reviewers: sanjoy, reames, apilipenko, skatkov, anna, dberlin Reviewed By: reames, sanjoy Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D32476 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@301623 91177308-0d34-0410-b5e6-96231b3b80d8 Max Kazantsev 2 years ago
2 changed file(s) with 174 addition(s) and 3 deletion(s). Raw diff Collapse all Expand all
657657 if (match(Inst, m_Intrinsic())) {
658658 if (auto *CondI =
659659 dyn_cast(cast(Inst)->getArgOperand(0))) {
660 // The condition we're on guarding here is true for all dominated
661 // locations.
662 if (SimpleValue::canHandle(CondI))
660 if (SimpleValue::canHandle(CondI)) {
661 // Do we already know the actual value of this condition?
662 if (auto *KnownCond = AvailableValues.lookup(CondI)) {
663 // Is the condition known to be true?
664 if (isa(KnownCond) &&
665 cast(KnownCond)->isOneValue()) {
666 DEBUG(dbgs() << "EarlyCSE removing guard: " << *Inst << '\n');
667 removeMSSA(Inst);
668 Inst->eraseFromParent();
669 Changed = true;
670 continue;
671 } else
672 // Use the known value if it wasn't true.
673 cast(Inst)->setArgOperand(0, KnownCond);
674 }
675 // The condition we're on guarding here is true for all dominated
676 // locations.
663677 AvailableValues.insert(CondI, ConstantInt::getTrue(BB->getContext()));
678 }
664679 }
665680
666681 // Guard intrinsics read all memory, but don't write any memory.
179179 store i32 600, i32* %ptr
180180 ret void
181181 }
182
183 define void @test07(i32 %a, i32 %b) {
184 ; Check that we are able to remove the guards on the same condition even if the
185 ; condition is not being recalculated.
186
187 ; CHECK-LABEL: @test07(
188 ; CHECK-NEXT: %cmp = icmp eq i32 %a, %b
189 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
190 ; CHECK-NEXT: ret void
191
192 %cmp = icmp eq i32 %a, %b
193 call void (i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
194 call void (i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
195 call void (i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
196 ret void
197 }
198
199 define void @test08(i32 %a, i32 %b, i32* %ptr) {
200 ; Check that we deal correctly with stores when removing guards in the same
201 ; block in case when the condition is not recalculated.
202
203 ; CHECK-LABEL: @test08(
204 ; CHECK-NEXT: %cmp = icmp eq i32 %a, %b
205 ; CHECK-NEXT: store i32 100, i32* %ptr
206 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
207 ; CHECK-NEXT: store i32 400, i32* %ptr
208 ; CHECK-NEXT: ret void
209
210 %cmp = icmp eq i32 %a, %b
211 store i32 100, i32* %ptr
212 call void (i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
213 store i32 200, i32* %ptr
214 call void (i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
215 store i32 300, i32* %ptr
216 call void (i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
217 store i32 400, i32* %ptr
218 ret void
219 }
220
221 define void @test09(i32 %a, i32 %b, i1 %c, i32* %ptr) {
222 ; Similar to test08, but with more control flow.
223 ; TODO: Can we get rid of the store in the end of entry given that it is
224 ; post-dominated by other stores?
225
226 ; CHECK-LABEL: @test09(
227 ; CHECK: entry:
228 ; CHECK-NEXT: %cmp = icmp eq i32 %a, %b
229 ; CHECK-NEXT: store i32 100, i32* %ptr
230 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
231 ; CHECK-NEXT: store i32 400, i32* %ptr
232 ; CHECK-NEXT: br i1 %c, label %if.true, label %if.false
233 ; CHECK: if.true:
234 ; CHECK-NEXT: store i32 500, i32* %ptr
235 ; CHECK-NEXT: br label %merge
236 ; CHECK: if.false:
237 ; CHECK-NEXT: store i32 600, i32* %ptr
238 ; CHECK-NEXT: br label %merge
239 ; CHECK: merge:
240 ; CHECK-NEXT: ret void
241
242 entry:
243 %cmp = icmp eq i32 %a, %b
244 store i32 100, i32* %ptr
245 call void (i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
246 store i32 200, i32* %ptr
247 call void (i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
248 store i32 300, i32* %ptr
249 call void (i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
250 store i32 400, i32* %ptr
251 br i1 %c, label %if.true, label %if.false
252
253 if.true:
254 call void (i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
255 store i32 500, i32* %ptr
256 br label %merge
257
258 if.false:
259 call void (i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
260 store i32 600, i32* %ptr
261 br label %merge
262
263 merge:
264 ret void
265 }
266
267 define void @test10(i32 %a, i32 %b, i1 %c, i32* %ptr) {
268 ; Make sure that non-dominating guards do not cause other guards removal.
269
270 ; CHECK-LABEL: @test10(
271 ; CHECK: entry:
272 ; CHECK-NEXT: %cmp = icmp eq i32 %a, %b
273 ; CHECK-NEXT: br i1 %c, label %if.true, label %if.false
274 ; CHECK: if.true:
275 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
276 ; CHECK-NEXT: store i32 100, i32* %ptr
277 ; CHECK-NEXT: br label %merge
278 ; CHECK: if.false:
279 ; CHECK-NEXT: store i32 200, i32* %ptr
280 ; CHECK-NEXT: br label %merge
281 ; CHECK: merge:
282 ; CHECK-NEXT: store i32 300, i32* %ptr
283 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
284 ; CHECK-NEXT: store i32 400, i32* %ptr
285 ; CHECK-NEXT: ret void
286
287 entry:
288 %cmp = icmp eq i32 %a, %b
289 br i1 %c, label %if.true, label %if.false
290
291 if.true:
292 call void (i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
293 store i32 100, i32* %ptr
294 call void (i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
295 br label %merge
296
297 if.false:
298 store i32 200, i32* %ptr
299 br label %merge
300
301 merge:
302 store i32 300, i32* %ptr
303 call void (i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
304 store i32 400, i32* %ptr
305 ret void
306 }
307
308 define void @test11(i32 %a, i32 %b, i32* %ptr) {
309 ; Make sure that branching condition is applied to guards.
310
311 ; CHECK-LABEL: @test11(
312 ; CHECK: entry:
313 ; CHECK-NEXT: %cmp = icmp eq i32 %a, %b
314 ; CHECK-NEXT: br i1 %cmp, label %if.true, label %if.false
315 ; CHECK: if.true:
316 ; CHECK-NEXT: br label %merge
317 ; CHECK: if.false:
318 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 false) [ "deopt"() ]
319 ; CHECK-NEXT: br label %merge
320 ; CHECK: merge:
321 ; CHECK-NEXT: ret void
322
323 entry:
324 %cmp = icmp eq i32 %a, %b
325 br i1 %cmp, label %if.true, label %if.false
326
327 if.true:
328 call void (i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
329 br label %merge
330
331 if.false:
332 call void (i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
333 br label %merge
334
335 merge:
336 ret void
337 }