forked from OSchip/llvm-project
277 lines
9.7 KiB
LLVM
277 lines
9.7 KiB
LLVM
; 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: br label [[LOOP_HEADER:%.*]]
|
|
; CHECK: loop.header:
|
|
; CHECK-NEXT: [[COND_AND1:%.*]] = and i1 [[COND2:%.*]], [[COND1:%.*]]
|
|
; 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: 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: br label [[LOOP_HEADER:%.*]]
|
|
; CHECK: loop.header:
|
|
; CHECK-NEXT: [[COND_AND1:%.*]] = or i1 [[COND2:%.*]], [[COND1:%.*]]
|
|
; 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: 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.
|
|
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: [[COND4_FR:%.*]] = freeze i1 [[COND4:%.*]]
|
|
; CHECK-NEXT: [[COND2_FR:%.*]] = freeze i1 [[COND2:%.*]]
|
|
; CHECK-NEXT: [[COND3_FR:%.*]] = freeze i1 [[COND3:%.*]]
|
|
; CHECK-NEXT: [[COND1_FR:%.*]] = freeze i1 [[COND1:%.*]]
|
|
; CHECK-NEXT: [[TMP0:%.*]] = or i1 [[COND4_FR]], [[COND2_FR]]
|
|
; CHECK-NEXT: [[TMP1:%.*]] = or i1 [[TMP0]], [[COND3_FR]]
|
|
; CHECK-NEXT: [[TMP2:%.*]] = or i1 [[TMP1]], [[COND1_FR]]
|
|
; CHECK-NEXT: br i1 [[TMP2]], label [[LOOP_EXIT_SPLIT:%.*]], label [[ENTRY_SPLIT:%.*]]
|
|
; CHECK: entry.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 [[COND6:%.*]], [[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_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
|
|
}
|
|
|
|
; Same as test_partial_condition_unswitch_or_select, but with arguments marked
|
|
; as noundef.
|
|
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 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 [[COND6:%.*]], [[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_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
|
|
}
|
|
|
|
; Test case for PR55526.
|
|
define void @test_pr55526(i16 %a) {
|
|
; CHECK-LABEL: @test_pr55526(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne i16 [[A:%.*]], 0
|
|
; CHECK-NEXT: br i1 [[TOBOOL]], label [[ENTRY_SPLIT:%.*]], label [[EXIT:%.*]]
|
|
; CHECK: entry.split:
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[SEL:%.*]] = select i1 true, i1 true, i1 false
|
|
; CHECK-NEXT: br label [[LOOP]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
%tobool = icmp ne i16 %a, 0
|
|
br label %loop
|
|
|
|
loop:
|
|
%sel = select i1 %tobool, i1 true, i1 false
|
|
br i1 %sel, label %loop, label %exit
|
|
|
|
exit:
|
|
ret void
|
|
}
|