forked from OSchip/llvm-project
[SimpleLoopUnswitch] Add trivial unswitching tests with selects.
Add tests with selects that match both logical AND and logical OR. Note that some of the tests get miscompiled at the moment. Also moves a related test to the newly added test file.
This commit is contained in:
parent
4059770af5
commit
51be0925b4
|
@ -0,0 +1,264 @@
|
|||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt -passes='loop-mssa(simple-loop-unswitch)' -S %s | FileCheck %s
|
||||
|
||||
; Test cases for trivial unswitching with selects that matches both a logical and & or.
|
||||
|
||||
declare void @some_func()
|
||||
|
||||
define void @test_select_logical_and_or_with_and_1(i1 noundef %cond1, i1 noundef %cond2) {
|
||||
; CHECK-LABEL: @test_select_logical_and_or_with_and_1(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[TMP0:%.*]] = or i1 [[COND2:%.*]], [[COND1:%.*]]
|
||||
; CHECK-NEXT: br i1 [[TMP0]], label [[EXIT_SPLIT:%.*]], label [[ENTRY_SPLIT:%.*]]
|
||||
; CHECK: entry.split:
|
||||
; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
|
||||
; CHECK: loop.header:
|
||||
; CHECK-NEXT: [[COND_AND1:%.*]] = and i1 false, false
|
||||
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND_AND1]], i1 true, i1 false
|
||||
; CHECK-NEXT: br i1 [[SEL]], label [[EXIT:%.*]], label [[LOOP_LATCH:%.*]]
|
||||
; CHECK: loop.latch:
|
||||
; CHECK-NEXT: call void @some_func()
|
||||
; CHECK-NEXT: br label [[LOOP_HEADER]]
|
||||
; CHECK: exit:
|
||||
; CHECK-NEXT: br label [[EXIT_SPLIT]]
|
||||
; CHECK: exit.split:
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
entry:
|
||||
br label %loop.header
|
||||
|
||||
loop.header:
|
||||
%cond_and1 = and i1 %cond2, %cond1
|
||||
%sel = select i1 %cond_and1, i1 true, i1 false
|
||||
br i1 %sel, label %exit, label %loop.latch
|
||||
|
||||
loop.latch:
|
||||
call void @some_func()
|
||||
br label %loop.header
|
||||
|
||||
exit:
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @test_select_logical_and_or_with_and_2(i1 noundef %cond1, i1 noundef %cond2) {
|
||||
; CHECK-LABEL: @test_select_logical_and_or_with_and_2(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[TMP0:%.*]] = and i1 [[COND2:%.*]], [[COND1:%.*]]
|
||||
; CHECK-NEXT: br i1 [[TMP0]], label [[ENTRY_SPLIT:%.*]], label [[EXIT_SPLIT:%.*]]
|
||||
; CHECK: entry.split:
|
||||
; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
|
||||
; CHECK: loop.header:
|
||||
; CHECK-NEXT: [[COND_AND1:%.*]] = and i1 true, true
|
||||
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND_AND1]], i1 true, i1 false
|
||||
; CHECK-NEXT: br i1 [[SEL]], label [[LOOP_LATCH:%.*]], label [[EXIT:%.*]]
|
||||
; CHECK: loop.latch:
|
||||
; CHECK-NEXT: call void @some_func()
|
||||
; CHECK-NEXT: br label [[LOOP_HEADER]]
|
||||
; CHECK: exit:
|
||||
; CHECK-NEXT: br label [[EXIT_SPLIT]]
|
||||
; CHECK: exit.split:
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
entry:
|
||||
br label %loop.header
|
||||
|
||||
loop.header:
|
||||
%cond_and1 = and i1 %cond2, %cond1
|
||||
%sel = select i1 %cond_and1, i1 true, i1 false
|
||||
br i1 %sel, label %loop.latch, label %exit
|
||||
|
||||
loop.latch:
|
||||
call void @some_func()
|
||||
br label %loop.header
|
||||
|
||||
exit:
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @test_select_logical_and_or_with_or_1(i1 noundef %cond1, i1 noundef %cond2) {
|
||||
; CHECK-LABEL: @test_select_logical_and_or_with_or_1(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[TMP0:%.*]] = or i1 [[COND2:%.*]], [[COND1:%.*]]
|
||||
; CHECK-NEXT: br i1 [[TMP0]], label [[EXIT_SPLIT:%.*]], label [[ENTRY_SPLIT:%.*]]
|
||||
; CHECK: entry.split:
|
||||
; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
|
||||
; CHECK: loop.header:
|
||||
; CHECK-NEXT: [[COND_AND1:%.*]] = or i1 false, false
|
||||
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND_AND1]], i1 true, i1 false
|
||||
; CHECK-NEXT: br i1 [[SEL]], label [[EXIT:%.*]], label [[LOOP_LATCH:%.*]]
|
||||
; CHECK: loop.latch:
|
||||
; CHECK-NEXT: call void @some_func()
|
||||
; CHECK-NEXT: br label [[LOOP_HEADER]]
|
||||
; CHECK: exit:
|
||||
; CHECK-NEXT: br label [[EXIT_SPLIT]]
|
||||
; CHECK: exit.split:
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
entry:
|
||||
br label %loop.header
|
||||
|
||||
loop.header:
|
||||
%cond_and1 = or i1 %cond2, %cond1
|
||||
%sel = select i1 %cond_and1, i1 true, i1 false
|
||||
br i1 %sel, label %exit, label %loop.latch
|
||||
|
||||
loop.latch:
|
||||
call void @some_func()
|
||||
br label %loop.header
|
||||
|
||||
exit:
|
||||
ret void
|
||||
}
|
||||
|
||||
|
||||
define void @test_select_logical_and_or_with_or_2(i1 noundef %cond1, i1 noundef %cond2) {
|
||||
; CHECK-LABEL: @test_select_logical_and_or_with_or_2(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[TMP0:%.*]] = and i1 [[COND2:%.*]], [[COND1:%.*]]
|
||||
; CHECK-NEXT: br i1 [[TMP0]], label [[ENTRY_SPLIT:%.*]], label [[EXIT_SPLIT:%.*]]
|
||||
; CHECK: entry.split:
|
||||
; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
|
||||
; CHECK: loop.header:
|
||||
; CHECK-NEXT: [[COND_AND1:%.*]] = or i1 true, true
|
||||
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND_AND1]], i1 true, i1 false
|
||||
; CHECK-NEXT: br i1 [[SEL]], label [[LOOP_LATCH:%.*]], label [[EXIT:%.*]]
|
||||
; CHECK: loop.latch:
|
||||
; CHECK-NEXT: call void @some_func()
|
||||
; CHECK-NEXT: br label [[LOOP_HEADER]]
|
||||
; CHECK: exit:
|
||||
; CHECK-NEXT: br label [[EXIT_SPLIT]]
|
||||
; CHECK: exit.split:
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
entry:
|
||||
br label %loop.header
|
||||
|
||||
loop.header:
|
||||
%cond_and1 = or i1 %cond2, %cond1
|
||||
%sel = select i1 %cond_and1, i1 true, i1 false
|
||||
br i1 %sel, label %loop.latch, label %exit
|
||||
|
||||
loop.latch:
|
||||
call void @some_func()
|
||||
br label %loop.header
|
||||
|
||||
exit:
|
||||
ret void
|
||||
}
|
||||
|
||||
; Check that loop unswitch looks through a combination of or and select instructions.
|
||||
; Note that cond6 can be unswitched because `select i1 %cond_or5, i1 true, i1 false` is
|
||||
; both logical-or and logical-and.
|
||||
define i32 @test_partial_condition_unswitch_or_select(i32* %var, i1 %cond1, i1 %cond2, i1 %cond3, i1 %cond4, i1 %cond5, i1 %cond6) {
|
||||
; CHECK-LABEL: @test_partial_condition_unswitch_or_select(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[TMP0:%.*]] = or i1 [[COND4:%.*]], [[COND2:%.*]]
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = or i1 [[TMP0]], [[COND3:%.*]]
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = or i1 [[TMP1]], [[COND1:%.*]]
|
||||
; CHECK-NEXT: br i1 [[TMP2]], label [[LOOP_EXIT_SPLIT:%.*]], label [[ENTRY_SPLIT:%.*]]
|
||||
; CHECK: entry.split:
|
||||
; CHECK-NEXT: br i1 [[COND6:%.*]], label [[LOOP_EXIT_SPLIT1:%.*]], label [[ENTRY_SPLIT_SPLIT:%.*]]
|
||||
; CHECK: entry.split.split:
|
||||
; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]
|
||||
; CHECK: loop_begin:
|
||||
; CHECK-NEXT: [[VAR_VAL:%.*]] = load i32, i32* [[VAR:%.*]], align 4
|
||||
; CHECK-NEXT: [[VAR_COND:%.*]] = trunc i32 [[VAR_VAL]] to i1
|
||||
; CHECK-NEXT: [[COND_OR1:%.*]] = or i1 [[VAR_COND]], false
|
||||
; CHECK-NEXT: [[COND_OR2:%.*]] = or i1 false, false
|
||||
; CHECK-NEXT: [[COND_OR3:%.*]] = or i1 [[COND_OR1]], [[COND_OR2]]
|
||||
; CHECK-NEXT: [[COND_XOR1:%.*]] = xor i1 [[COND5:%.*]], [[VAR_COND]]
|
||||
; CHECK-NEXT: [[COND_AND1:%.*]] = and i1 false, [[VAR_COND]]
|
||||
; CHECK-NEXT: [[COND_OR4:%.*]] = or i1 [[COND_XOR1]], [[COND_AND1]]
|
||||
; CHECK-NEXT: [[COND_OR5:%.*]] = select i1 [[COND_OR3]], i1 true, i1 [[COND_OR4]]
|
||||
; CHECK-NEXT: [[COND_OR6:%.*]] = select i1 [[COND_OR5]], i1 true, i1 false
|
||||
; CHECK-NEXT: br i1 [[COND_OR6]], label [[LOOP_EXIT:%.*]], label [[DO_SOMETHING:%.*]]
|
||||
; CHECK: do_something:
|
||||
; CHECK-NEXT: call void @some_func() #[[ATTR0:[0-9]+]]
|
||||
; CHECK-NEXT: br label [[LOOP_BEGIN]]
|
||||
; CHECK: loop_exit:
|
||||
; CHECK-NEXT: br label [[LOOP_EXIT_SPLIT1]]
|
||||
; CHECK: loop_exit.split1:
|
||||
; CHECK-NEXT: br label [[LOOP_EXIT_SPLIT]]
|
||||
; CHECK: loop_exit.split:
|
||||
; CHECK-NEXT: ret i32 0
|
||||
;
|
||||
entry:
|
||||
br label %loop_begin
|
||||
|
||||
loop_begin:
|
||||
%var_val = load i32, i32* %var
|
||||
%var_cond = trunc i32 %var_val to i1
|
||||
%cond_or1 = or i1 %var_cond, %cond1
|
||||
%cond_or2 = or i1 %cond2, %cond3
|
||||
%cond_or3 = or i1 %cond_or1, %cond_or2
|
||||
%cond_xor1 = xor i1 %cond5, %var_cond
|
||||
%cond_and1 = and i1 %cond6, %var_cond
|
||||
%cond_or4 = or i1 %cond_xor1, %cond_and1
|
||||
%cond_or5 = select i1 %cond_or3, i1 true, i1 %cond_or4
|
||||
%cond_or6 = select i1 %cond_or5, i1 true, i1 %cond4
|
||||
br i1 %cond_or6, label %loop_exit, label %do_something
|
||||
|
||||
do_something:
|
||||
call void @some_func() noreturn nounwind
|
||||
br label %loop_begin
|
||||
|
||||
loop_exit:
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
define i32 @test_partial_condition_unswitch_or_select_noundef(i32* noundef %var, i1 noundef %cond1, i1 noundef %cond2, i1 noundef %cond3, i1 noundef %cond4, i1 noundef %cond5, i1 noundef %cond6) {
|
||||
; CHECK-LABEL: @test_partial_condition_unswitch_or_select_noundef(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[TMP0:%.*]] = or i1 [[COND4:%.*]], [[COND2:%.*]]
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = or i1 [[TMP0]], [[COND3:%.*]]
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = or i1 [[TMP1]], [[COND1:%.*]]
|
||||
; CHECK-NEXT: br i1 [[TMP2]], label [[LOOP_EXIT_SPLIT:%.*]], label [[ENTRY_SPLIT:%.*]]
|
||||
; CHECK: entry.split:
|
||||
; CHECK-NEXT: br i1 [[COND6:%.*]], label [[LOOP_EXIT_SPLIT1:%.*]], label [[ENTRY_SPLIT_SPLIT:%.*]]
|
||||
; CHECK: entry.split.split:
|
||||
; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]
|
||||
; CHECK: loop_begin:
|
||||
; CHECK-NEXT: [[VAR_VAL:%.*]] = load i32, i32* [[VAR:%.*]], align 4
|
||||
; CHECK-NEXT: [[VAR_COND:%.*]] = trunc i32 [[VAR_VAL]] to i1
|
||||
; CHECK-NEXT: [[COND_OR1:%.*]] = or i1 [[VAR_COND]], false
|
||||
; CHECK-NEXT: [[COND_OR2:%.*]] = or i1 false, false
|
||||
; CHECK-NEXT: [[COND_OR3:%.*]] = or i1 [[COND_OR1]], [[COND_OR2]]
|
||||
; CHECK-NEXT: [[COND_XOR1:%.*]] = xor i1 [[COND5:%.*]], [[VAR_COND]]
|
||||
; CHECK-NEXT: [[COND_AND1:%.*]] = and i1 false, [[VAR_COND]]
|
||||
; CHECK-NEXT: [[COND_OR4:%.*]] = or i1 [[COND_XOR1]], [[COND_AND1]]
|
||||
; CHECK-NEXT: [[COND_OR5:%.*]] = select i1 [[COND_OR3]], i1 true, i1 [[COND_OR4]]
|
||||
; CHECK-NEXT: [[COND_OR6:%.*]] = select i1 [[COND_OR5]], i1 true, i1 false
|
||||
; CHECK-NEXT: br i1 [[COND_OR6]], label [[LOOP_EXIT:%.*]], label [[DO_SOMETHING:%.*]]
|
||||
; CHECK: do_something:
|
||||
; CHECK-NEXT: call void @some_func() #[[ATTR0]]
|
||||
; CHECK-NEXT: br label [[LOOP_BEGIN]]
|
||||
; CHECK: loop_exit:
|
||||
; CHECK-NEXT: br label [[LOOP_EXIT_SPLIT1]]
|
||||
; CHECK: loop_exit.split1:
|
||||
; CHECK-NEXT: br label [[LOOP_EXIT_SPLIT]]
|
||||
; CHECK: loop_exit.split:
|
||||
; CHECK-NEXT: ret i32 0
|
||||
;
|
||||
entry:
|
||||
br label %loop_begin
|
||||
|
||||
loop_begin:
|
||||
%var_val = load i32, i32* %var
|
||||
%var_cond = trunc i32 %var_val to i1
|
||||
%cond_or1 = or i1 %var_cond, %cond1
|
||||
%cond_or2 = or i1 %cond2, %cond3
|
||||
%cond_or3 = or i1 %cond_or1, %cond_or2
|
||||
%cond_xor1 = xor i1 %cond5, %var_cond
|
||||
%cond_and1 = and i1 %cond6, %var_cond
|
||||
%cond_or4 = or i1 %cond_xor1, %cond_and1
|
||||
%cond_or5 = select i1 %cond_or3, i1 true, i1 %cond_or4
|
||||
%cond_or6 = select i1 %cond_or5, i1 true, i1 %cond4
|
||||
br i1 %cond_or6, label %loop_exit, label %do_something
|
||||
|
||||
do_something:
|
||||
call void @some_func() noreturn nounwind
|
||||
br label %loop_begin
|
||||
|
||||
loop_exit:
|
||||
ret i32 0
|
||||
}
|
|
@ -634,63 +634,6 @@ loop_exit:
|
|||
; CHECK-NEXT: ret
|
||||
}
|
||||
|
||||
; Check that loop unswitch looks through a combination of or and select instructions.
|
||||
; Note that cond6 can be unswitched because `select i1 %cond_or5, i1 true, i1 false` is
|
||||
; both logical-or and logical-and.
|
||||
define i32 @test_partial_condition_unswitch_or_select(i32* %var, i1 %cond1, i1 %cond2, i1 %cond3, i1 %cond4, i1 %cond5, i1 %cond6) {
|
||||
; CHECK-LABEL: @test_partial_condition_unswitch_or_select(
|
||||
entry:
|
||||
br label %loop_begin
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: %[[INV_OR1:.*]] = or i1 %cond4, %cond2
|
||||
; CHECK-NEXT: %[[INV_OR2:.*]] = or i1 %[[INV_OR1]], %cond3
|
||||
; CHECK-NEXT: %[[INV_OR3:.*]] = or i1 %[[INV_OR2]], %cond1
|
||||
; CHECK-NEXT: br i1 %[[INV_OR3]], label %loop_exit.split, label %entry.split
|
||||
;
|
||||
; CHECK: entry.split:
|
||||
; CHECK-NEXT: br i1 %cond6, label %loop_exit.split1, label %entry.split.split
|
||||
;
|
||||
; CHECK: entry.split.split:
|
||||
; CHECK-NEXT: br label %loop_begin
|
||||
|
||||
loop_begin:
|
||||
%var_val = load i32, i32* %var
|
||||
%var_cond = trunc i32 %var_val to i1
|
||||
%cond_or1 = or i1 %var_cond, %cond1
|
||||
%cond_or2 = or i1 %cond2, %cond3
|
||||
%cond_or3 = or i1 %cond_or1, %cond_or2
|
||||
%cond_xor1 = xor i1 %cond5, %var_cond
|
||||
%cond_and1 = and i1 %cond6, %var_cond
|
||||
%cond_or4 = or i1 %cond_xor1, %cond_and1
|
||||
%cond_or5 = select i1 %cond_or3, i1 true, i1 %cond_or4
|
||||
%cond_or6 = select i1 %cond_or5, i1 true, i1 %cond4
|
||||
br i1 %cond_or6, label %loop_exit, label %do_something
|
||||
; CHECK: loop_begin:
|
||||
; CHECK-NEXT: %[[VAR:.*]] = load i32
|
||||
; CHECK-NEXT: %[[VAR_COND:.*]] = trunc i32 %[[VAR]] to i1
|
||||
; CHECK-NEXT: %[[COND_OR1:.*]] = or i1 %[[VAR_COND]], false
|
||||
; CHECK-NEXT: %[[COND_OR2:.*]] = or i1 false, false
|
||||
; CHECK-NEXT: %[[COND_OR3:.*]] = or i1 %[[COND_OR1]], %[[COND_OR2]]
|
||||
; CHECK-NEXT: %[[COND_XOR:.*]] = xor i1 %cond5, %[[VAR_COND]]
|
||||
; CHECK-NEXT: %[[COND_AND:.*]] = and i1 false, %[[VAR_COND]]
|
||||
; CHECK-NEXT: %[[COND_OR4:.*]] = or i1 %[[COND_XOR]], %[[COND_AND]]
|
||||
; CHECK-NEXT: %[[COND_OR5:.*]] = select i1 %[[COND_OR3]], i1 true, i1 %[[COND_OR4]]
|
||||
; CHECK-NEXT: %[[COND_OR6:.*]] = select i1 %[[COND_OR5]], i1 true, i1 false
|
||||
; CHECK-NEXT: br i1 %[[COND_OR6]], label %loop_exit, label %do_something
|
||||
|
||||
do_something:
|
||||
call void @some_func() noreturn nounwind
|
||||
br label %loop_begin
|
||||
; CHECK: do_something:
|
||||
; CHECK-NEXT: call
|
||||
; CHECK-NEXT: br label %loop_begin
|
||||
|
||||
loop_exit:
|
||||
ret i32 0
|
||||
; CHECK: loop_exit.split:
|
||||
; CHECK-NEXT: ret
|
||||
}
|
||||
|
||||
define i32 @test_partial_condition_unswitch_with_lcssa_phi1(i32* %var, i1 %cond, i32 %x) {
|
||||
; CHECK-LABEL: @test_partial_condition_unswitch_with_lcssa_phi1(
|
||||
entry:
|
||||
|
|
Loading…
Reference in New Issue