Joshua Cao 5cfb9aa428 [SimpleLoopUnswitch][reland 2] unswitch selects
The old LoopUnswitch pass unswitched selects, but the changes were
never ported to the new SimpleLoopUnswitch.

We unswitch by turning:

``` S = select %cond, %a, %b ```

into:

``` head: br %cond, label %then, label %tail

then: br label %tail

tail: S = phi [ %a, %then ], [ %b, %head ] ```

Unswitch selects are always nontrivial, since the successors do not
exit the loop and the loop body always needs to be cloned.

Unswitch selects always need to freeze the conditional if the
conditional could be poison or undef. Selects don't propagate
poison/undef, and branches on poison/undef causes UB.

Reland 1 - Fix the insertion of freeze instructions. The original
implementation inserts a dead freeze instruction that is not used by the
unswitched branch.

Reland 2 - Include https://reviews.llvm.org/D149560 in the same patch,
which was originally reverted along with this patch. The patch prevents
unswitching of selects with a vector conditional. This could have been
caught in SimpleLoopUnswitch/crash.ll if it included tests for
nontrivial unswitching. This reland also adds a run for the test file
with nontrivial unswitching.

Reviewed By: nikic, kachkov98, vitalybuka

Differential Revision: https://reviews.llvm.org/D138526
2023-05-11 22:19:05 -07:00

68 lines
2.5 KiB
LLVM

; RUN: opt < %s -passes=simple-loop-unswitch -verify-memoryssa -disable-output
; RUN: opt < %s -passes='simple-loop-unswitch<nontrivial>' -verify-memoryssa -disable-output
define void @test1(ptr %S2) {
entry:
br i1 false, label %list_Length.exit, label %cond_true.i
cond_true.i: ; preds = %entry
ret void
list_Length.exit: ; preds = %entry
br i1 false, label %list_Length.exit9, label %cond_true.i5
cond_true.i5: ; preds = %list_Length.exit
ret void
list_Length.exit9: ; preds = %list_Length.exit
br i1 false, label %bb78, label %return
bb44: ; preds = %bb78, %cond_next68
br i1 %tmp49.not, label %bb62, label %bb62.loopexit
bb62.loopexit: ; preds = %bb44
br label %bb62
bb62: ; preds = %bb62.loopexit, %bb44
br i1 false, label %return.loopexit, label %cond_next68
cond_next68: ; preds = %bb62
br i1 false, label %return.loopexit, label %bb44
bb78: ; preds = %list_Length.exit9
%tmp49.not = icmp eq ptr %S2, null ; <i1> [#uses=1]
br label %bb44
return.loopexit: ; preds = %cond_next68, %bb62
%retval.0.ph = phi i32 [ 1, %cond_next68 ], [ 0, %bb62 ] ; <i32> [#uses=1]
br label %return
return: ; preds = %return.loopexit, %list_Length.exit9
%retval.0 = phi i32 [ 0, %list_Length.exit9 ], [ %retval.0.ph, %return.loopexit ] ; <i32> [#uses=0]
ret void
}
define void @test2() nounwind {
entry:
br label %bb.nph
bb.nph: ; preds = %entry
%and.i13521 = and <4 x i1> undef, undef ; <<4 x i1>> [#uses=1]
br label %for.body
for.body: ; preds = %for.body, %bb.nph
%or.i = select <4 x i1> %and.i13521, <4 x i32> undef, <4 x i32> undef ; <<4 x i32>> [#uses=0]
br i1 false, label %for.body, label %for.end
for.end: ; preds = %for.body, %entry
ret void
}
; PR6879
define ptr @test3(ptr %p_45, i16 zeroext %p_46, i64 %p_47, i64 %p_48, i16 signext %p_49) nounwind {
entry:
br label %for.cond
for.cond: ; preds = %for.cond4, %entry
br i1 false, label %for.cond4, label %for.end88
for.cond4: ; preds = %for.cond
%conv46 = trunc i32 0 to i8 ; <i8> [#uses=2]
%cmp60 = icmp sgt i8 %conv46, 124 ; <i1> [#uses=1]
%or.cond = and i1 undef, %cmp60 ; <i1> [#uses=1]
%cond = select i1 %or.cond, i8 %conv46, i8 undef ; <i8> [#uses=0]
br label %for.cond
for.end88: ; preds = %for.cond
ret ptr undef
}