| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py |
| ; RUN: opt -passes='simple-loop-unswitch<nontrivial>' -S < %s | FileCheck %s |
| |
| ; If we try to replace uses of `true` outside of `@foo`, we'll see it here. |
| define i1 @bar() { |
| ; CHECK-LABEL: @bar( |
| ; CHECK-NEXT: ret i1 true |
| ; |
| ret i1 true |
| } |
| |
| ; We shouldn't unswitch this loop. |
| define void @foo() { |
| ; CHECK-LABEL: @foo( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: br label [[HEADER:%.*]] |
| ; CHECK: header: |
| ; CHECK-NEXT: [[VAL:%.*]] = select i1 true, i1 true, i1 false |
| ; CHECK-NEXT: br i1 [[VAL]], label [[EXIT:%.*]], label [[HEADER]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br label %header |
| |
| header: |
| %val = select i1 true, i1 true, i1 false |
| br i1 %val, label %exit, label %header |
| |
| exit: |
| ret void |
| } |
| |
| define void @unswitch_trivial_select(i1 %c.1, i1 %c.2, i8 %a) { |
| ; CHECK-LABEL: @unswitch_trivial_select( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: br i1 [[C_1:%.*]], label [[PH_1:%.*]], label [[EXIT:%.*]] |
| ; CHECK: ph.1: |
| ; CHECK-NEXT: br i1 [[C_2:%.*]], label [[PH_2:%.*]], label [[EXIT]] |
| ; CHECK: ph.2: |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[A:%.*]], 30 |
| ; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i1 true, i1 false |
| ; CHECK-NEXT: [[CMP_FR:%.*]] = freeze i1 [[CMP]] |
| ; CHECK-NEXT: br i1 [[CMP_FR]], label [[PH_2_SPLIT_US:%.*]], label [[PH_2_SPLIT:%.*]] |
| ; CHECK: ph.2.split.us: |
| ; CHECK-NEXT: br label [[LOOP_US:%.*]] |
| ; CHECK: loop.us: |
| ; CHECK-NEXT: call void @foo() |
| ; CHECK-NEXT: br label [[EXIT_LOOPEXIT_SPLIT_US:%.*]] |
| ; CHECK: exit.loopexit.split.us: |
| ; CHECK-NEXT: br label [[EXIT_LOOPEXIT:%.*]] |
| ; CHECK: ph.2.split: |
| ; CHECK-NEXT: br label [[LOOP:%.*]] |
| ; CHECK: loop: |
| ; CHECK-NEXT: call void @foo() |
| ; CHECK-NEXT: br label [[LOOP_LATCH:%.*]] |
| ; CHECK: loop.latch: |
| ; CHECK-NEXT: br label [[LOOP]] |
| ; CHECK: exit.loopexit: |
| ; CHECK-NEXT: br label [[EXIT]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br i1 %c.1, label %ph.1, label %exit |
| |
| ph.1: |
| br i1 %c.2, label %ph.2, label %exit |
| |
| ph.2: |
| %cmp = icmp eq i8 %a, 30 |
| %sel = select i1 %cmp, i1 true, i1 false |
| br label %loop |
| |
| loop: |
| call void @foo() |
| br i1 %sel, label %exit, label %loop.latch |
| |
| loop.latch: |
| br label %loop |
| |
| exit: |
| ret void |
| } |
| |
| ; Test case for PR55697. |
| define i32 @unswitch_trivial_select_cmp_outside(i32 %x) { |
| ; CHECK-LABEL: @unswitch_trivial_select_cmp_outside( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[X:%.*]], 100 |
| ; CHECK-NEXT: br i1 [[C]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]] |
| ; CHECK: entry.split.us: |
| ; CHECK-NEXT: br label [[LOOP_US:%.*]] |
| ; CHECK: loop.us: |
| ; CHECK-NEXT: [[P_US:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT_US]] ], [ 35, [[LOOP_US]] ] |
| ; CHECK-NEXT: br label [[LOOP_US]] |
| ; CHECK: entry.split: |
| ; CHECK-NEXT: br label [[LOOP:%.*]] |
| ; CHECK: loop: |
| ; CHECK-NEXT: [[P:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT]] ] |
| ; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 false, i1 true, i1 false |
| ; CHECK-NEXT: br label [[EXIT:%.*]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: [[LCSSA:%.*]] = phi i32 [ [[P]], [[LOOP]] ] |
| ; CHECK-NEXT: ret i32 [[LCSSA]] |
| ; |
| entry: |
| %c = icmp ult i32 %x, 100 |
| br label %loop |
| |
| loop: |
| %p = phi i32 [ 0, %entry ], [ 35, %loop ] |
| %spec.select = select i1 %c, i1 true, i1 false |
| br i1 %spec.select, label %loop, label %exit |
| |
| exit: |
| %lcssa = phi i32 [ %p, %loop ] |
| ret i32 %lcssa |
| } |