[llvm] 51be092 - [SimpleLoopUnswitch] Add trivial unswitching tests with selects.

Florian Hahn via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 27 06:06:56 PDT 2022


Author: Florian Hahn
Date: 2022-04-27T14:06:36+01:00
New Revision: 51be0925b42e089241de5815a79fcce68b02aa01

URL: https://github.com/llvm/llvm-project/commit/51be0925b42e089241de5815a79fcce68b02aa01
DIFF: https://github.com/llvm/llvm-project/commit/51be0925b42e089241de5815a79fcce68b02aa01.diff

LOG: [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.

Added: 
    llvm/test/Transforms/SimpleLoopUnswitch/trivial-unswitch-logical-and-or.ll

Modified: 
    llvm/test/Transforms/SimpleLoopUnswitch/trivial-unswitch.ll

Removed: 
    


################################################################################
diff  --git a/llvm/test/Transforms/SimpleLoopUnswitch/trivial-unswitch-logical-and-or.ll b/llvm/test/Transforms/SimpleLoopUnswitch/trivial-unswitch-logical-and-or.ll
new file mode 100644
index 000000000000..c13dd5594595
--- /dev/null
+++ b/llvm/test/Transforms/SimpleLoopUnswitch/trivial-unswitch-logical-and-or.ll
@@ -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
+}

diff  --git a/llvm/test/Transforms/SimpleLoopUnswitch/trivial-unswitch.ll b/llvm/test/Transforms/SimpleLoopUnswitch/trivial-unswitch.ll
index 9b460101ecb4..57bc34b0f0a1 100644
--- a/llvm/test/Transforms/SimpleLoopUnswitch/trivial-unswitch.ll
+++ b/llvm/test/Transforms/SimpleLoopUnswitch/trivial-unswitch.ll
@@ -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:


        


More information about the llvm-commits mailing list