-
Notifications
You must be signed in to change notification settings - Fork 12.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Inline][Cloning] Reliably remove unreachable blocks during cloning (…
…PR53206) The pruning cloner already tries to remove unreachable blocks. The original cloning process will simplify instructions and constant terminators, and only clone blocks that are reachable at that point. However, phi nodes can only be simplified after everything has been cloned. For that reason, additional blocks may become unreachable after phi simplification. The code does try to handle this as well, but only removes blocks that don't have predecessors. It misses unreachable cycles. This can cause issues if SEH exception handling code is part of an unreachable cycle, as the inliner is not prepared to deal with that. This patch instead performs an explicit scan for reachable blocks, and drops everything else. Fixes #53206. Differential Revision: https://reviews.llvm.org/D118449
- Loading branch information
Showing
2 changed files
with
78 additions
and
26 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py | ||
; RUN: opt -S -inline < %s | FileCheck %s | ||
|
||
; Check that the exception handling code is fully pruned, and does not | ||
; leave behind invalid IR. | ||
|
||
define internal void @foo() personality i32 (...)* undef { | ||
entry: | ||
br i1 false, label %join, label %split | ||
|
||
split: | ||
br label %join | ||
|
||
join: | ||
%phi = phi i64 [ 1, %split ], [ 0, %entry ] | ||
%cmp = icmp ugt i64 1, %phi | ||
br i1 %cmp, label %invoke1, label %exit | ||
|
||
invoke1: | ||
invoke void undef() | ||
to label %exit unwind label %cleanup1 | ||
|
||
cleanup1: | ||
%pad1 = cleanuppad within none [] | ||
br label %cleanup1.cont | ||
|
||
cleanup1.cont: | ||
br i1 undef, label %cleanupret, label %invoke2 | ||
|
||
invoke2: | ||
invoke void undef() [ "funclet"(token %pad1) ] | ||
to label %cleanup1.cont unwind label %cleanup2 | ||
|
||
cleanup2: | ||
%pad2 = cleanuppad within %pad1 [] | ||
unreachable | ||
|
||
cleanupret: | ||
unreachable | ||
|
||
exit: | ||
ret void | ||
} | ||
|
||
define void @test() personality i32 (...)* undef { | ||
; CHECK-LABEL: @test( | ||
; CHECK-NEXT: ret void | ||
; | ||
call void @foo() | ||
ret void | ||
} |