mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-26 04:32:44 +01:00
[NFCI][SimpleLoopUnswitch] Adjust CostKind query
When getUserCost was transitioned to use an explicit CostKind, TCK_CodeSize was used even though the original kind was implicitly SizeAndLatency so restore this behaviour. We now only query for CodeSize when optimising for minsize. I expect this to not change anything as, I think all, targets will currently return the same value for CodeSize and SizeLatency. Indeed I see no changes in the test suite for Arm, AArch64 and X86. Differential Revision: https://reviews.llvm.org/D85829
This commit is contained in:
parent
85a0582465
commit
4451edd54d
@ -2692,6 +2692,10 @@ unswitchBestCondition(Loop &L, DominatorTree &DT, LoopInfo &LI,
|
||||
// (convergent, noduplicate, or cross-basic-block tokens).
|
||||
// FIXME: We might be able to safely handle some of these in non-duplicated
|
||||
// regions.
|
||||
TargetTransformInfo::TargetCostKind CostKind =
|
||||
L.getHeader()->getParent()->hasMinSize()
|
||||
? TargetTransformInfo::TCK_CodeSize
|
||||
: TargetTransformInfo::TCK_SizeAndLatency;
|
||||
int LoopCost = 0;
|
||||
for (auto *BB : L.blocks()) {
|
||||
int Cost = 0;
|
||||
@ -2705,7 +2709,7 @@ unswitchBestCondition(Loop &L, DominatorTree &DT, LoopInfo &LI,
|
||||
if (CB->isConvergent() || CB->cannotDuplicate())
|
||||
return false;
|
||||
|
||||
Cost += TTI.getUserCost(&I, TargetTransformInfo::TCK_CodeSize);
|
||||
Cost += TTI.getUserCost(&I, CostKind);
|
||||
}
|
||||
assert(Cost >= 0 && "Must not have negative costs!");
|
||||
LoopCost += Cost;
|
||||
|
2
test/Transforms/SimpleLoopUnswitch/ARM/lit.local.cfg
Normal file
2
test/Transforms/SimpleLoopUnswitch/ARM/lit.local.cfg
Normal file
@ -0,0 +1,2 @@
|
||||
if not 'ARM' in config.root.targets:
|
||||
config.unsupported = True
|
@ -0,0 +1,723 @@
|
||||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt -mtriple=thumbv8m.main -simple-loop-unswitch -enable-nontrivial-unswitch -unswitch-threshold=5 -S -o - %s | FileCheck %s
|
||||
|
||||
declare void @a()
|
||||
declare void @b()
|
||||
declare void @x()
|
||||
|
||||
define void @test_no_unswitch(i1* %ptr, i1 %cond) {
|
||||
; CHECK-LABEL: @test_no_unswitch(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]
|
||||
; CHECK: loop_begin:
|
||||
; CHECK-NEXT: call void @x()
|
||||
; CHECK-NEXT: call void @x()
|
||||
; CHECK-NEXT: call void @x()
|
||||
; CHECK-NEXT: call void @x()
|
||||
; CHECK-NEXT: br i1 [[COND:%.*]], label [[LOOP_A:%.*]], label [[LOOP_B:%.*]]
|
||||
; CHECK: loop_a:
|
||||
; CHECK-NEXT: call void @a()
|
||||
; CHECK-NEXT: br label [[LOOP_LATCH:%.*]]
|
||||
; CHECK: loop_b:
|
||||
; CHECK-NEXT: call void @b()
|
||||
; CHECK-NEXT: br label [[LOOP_LATCH]]
|
||||
; CHECK: loop_latch:
|
||||
; CHECK-NEXT: [[V:%.*]] = load i1, i1* [[PTR:%.*]], align 1
|
||||
; CHECK-NEXT: br i1 [[V]], label [[LOOP_BEGIN]], label [[LOOP_EXIT:%.*]]
|
||||
; CHECK: loop_exit:
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
entry:
|
||||
br label %loop_begin
|
||||
loop_begin:
|
||||
call void @x()
|
||||
call void @x()
|
||||
call void @x()
|
||||
call void @x()
|
||||
br i1 %cond, label %loop_a, label %loop_b
|
||||
|
||||
loop_a:
|
||||
call void @a()
|
||||
br label %loop_latch
|
||||
|
||||
loop_b:
|
||||
call void @b()
|
||||
br label %loop_latch
|
||||
|
||||
loop_latch:
|
||||
%v = load i1, i1* %ptr
|
||||
br i1 %v, label %loop_begin, label %loop_exit
|
||||
|
||||
loop_exit:
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @test_unswitch(i1* %ptr, i1 %cond) {
|
||||
; CHECK-LABEL: @test_unswitch(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: br i1 [[COND:%.*]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
|
||||
; CHECK: entry.split.us:
|
||||
; CHECK-NEXT: br label [[LOOP_BEGIN_US:%.*]]
|
||||
; CHECK: loop_begin.us:
|
||||
; CHECK-NEXT: call void @x()
|
||||
; CHECK-NEXT: br label [[LOOP_A_US:%.*]]
|
||||
; CHECK: loop_a.us:
|
||||
; CHECK-NEXT: call void @a()
|
||||
; CHECK-NEXT: br label [[LOOP_LATCH_US:%.*]]
|
||||
; CHECK: loop_latch.us:
|
||||
; CHECK-NEXT: [[V_US:%.*]] = load i1, i1* [[PTR:%.*]], align 1
|
||||
; CHECK-NEXT: br i1 [[V_US]], label [[LOOP_BEGIN_US]], label [[LOOP_EXIT_SPLIT_US:%.*]]
|
||||
; CHECK: loop_exit.split.us:
|
||||
; CHECK-NEXT: br label [[LOOP_EXIT:%.*]]
|
||||
; CHECK: entry.split:
|
||||
; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]
|
||||
; CHECK: loop_begin:
|
||||
; CHECK-NEXT: call void @x()
|
||||
; CHECK-NEXT: br label [[LOOP_B:%.*]]
|
||||
; CHECK: loop_b:
|
||||
; CHECK-NEXT: call void @b()
|
||||
; CHECK-NEXT: br label [[LOOP_LATCH:%.*]]
|
||||
; CHECK: loop_latch:
|
||||
; CHECK-NEXT: [[V:%.*]] = load i1, i1* [[PTR]], align 1
|
||||
; CHECK-NEXT: br i1 [[V]], label [[LOOP_BEGIN]], label [[LOOP_EXIT_SPLIT:%.*]]
|
||||
; CHECK: loop_exit.split:
|
||||
; CHECK-NEXT: br label [[LOOP_EXIT]]
|
||||
; CHECK: loop_exit:
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
entry:
|
||||
br label %loop_begin
|
||||
|
||||
loop_begin:
|
||||
call void @x()
|
||||
br i1 %cond, label %loop_a, label %loop_b
|
||||
|
||||
loop_a:
|
||||
call void @a()
|
||||
br label %loop_latch
|
||||
|
||||
loop_b:
|
||||
call void @b()
|
||||
br label %loop_latch
|
||||
|
||||
loop_latch:
|
||||
%v = load i1, i1* %ptr
|
||||
br i1 %v, label %loop_begin, label %loop_exit
|
||||
|
||||
loop_exit:
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @test_unswitch_minsize(i1* %ptr, i1 %cond) #0 {
|
||||
; CHECK-LABEL: @test_unswitch_minsize(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: br i1 [[COND:%.*]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
|
||||
; CHECK: entry.split.us:
|
||||
; CHECK-NEXT: br label [[LOOP_BEGIN_US:%.*]]
|
||||
; CHECK: loop_begin.us:
|
||||
; CHECK-NEXT: call void @x()
|
||||
; CHECK-NEXT: br label [[LOOP_A_US:%.*]]
|
||||
; CHECK: loop_a.us:
|
||||
; CHECK-NEXT: call void @a()
|
||||
; CHECK-NEXT: br label [[LOOP_LATCH_US:%.*]]
|
||||
; CHECK: loop_latch.us:
|
||||
; CHECK-NEXT: [[V_US:%.*]] = load i1, i1* [[PTR:%.*]], align 1
|
||||
; CHECK-NEXT: br i1 [[V_US]], label [[LOOP_BEGIN_US]], label [[LOOP_EXIT_SPLIT_US:%.*]]
|
||||
; CHECK: loop_exit.split.us:
|
||||
; CHECK-NEXT: br label [[LOOP_EXIT:%.*]]
|
||||
; CHECK: entry.split:
|
||||
; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]
|
||||
; CHECK: loop_begin:
|
||||
; CHECK-NEXT: call void @x()
|
||||
; CHECK-NEXT: br label [[LOOP_B:%.*]]
|
||||
; CHECK: loop_b:
|
||||
; CHECK-NEXT: call void @b()
|
||||
; CHECK-NEXT: br label [[LOOP_LATCH:%.*]]
|
||||
; CHECK: loop_latch:
|
||||
; CHECK-NEXT: [[V:%.*]] = load i1, i1* [[PTR]], align 1
|
||||
; CHECK-NEXT: br i1 [[V]], label [[LOOP_BEGIN]], label [[LOOP_EXIT_SPLIT:%.*]]
|
||||
; CHECK: loop_exit.split:
|
||||
; CHECK-NEXT: br label [[LOOP_EXIT]]
|
||||
; CHECK: loop_exit:
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
entry:
|
||||
br label %loop_begin
|
||||
|
||||
loop_begin:
|
||||
call void @x()
|
||||
br i1 %cond, label %loop_a, label %loop_b
|
||||
|
||||
loop_a:
|
||||
call void @a()
|
||||
br label %loop_latch
|
||||
|
||||
loop_b:
|
||||
call void @b()
|
||||
br label %loop_latch
|
||||
|
||||
loop_latch:
|
||||
%v = load i1, i1* %ptr
|
||||
br i1 %v, label %loop_begin, label %loop_exit
|
||||
|
||||
loop_exit:
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @test_unswitch_non_dup_code(i1* %ptr, i1 %cond) {
|
||||
; CHECK-LABEL: @test_unswitch_non_dup_code(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: br i1 [[COND:%.*]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
|
||||
; CHECK: entry.split.us:
|
||||
; CHECK-NEXT: br label [[LOOP_BEGIN_US:%.*]]
|
||||
; CHECK: loop_begin.us:
|
||||
; CHECK-NEXT: call void @x()
|
||||
; CHECK-NEXT: br label [[LOOP_A_US:%.*]]
|
||||
; CHECK: loop_a.us:
|
||||
; CHECK-NEXT: call void @a()
|
||||
; CHECK-NEXT: call void @a()
|
||||
; CHECK-NEXT: call void @a()
|
||||
; CHECK-NEXT: call void @a()
|
||||
; CHECK-NEXT: br label [[LOOP_LATCH_US:%.*]]
|
||||
; CHECK: loop_latch.us:
|
||||
; CHECK-NEXT: [[V_US:%.*]] = load i1, i1* [[PTR:%.*]], align 1
|
||||
; CHECK-NEXT: br i1 [[V_US]], label [[LOOP_BEGIN_US]], label [[LOOP_EXIT_SPLIT_US:%.*]]
|
||||
; CHECK: loop_exit.split.us:
|
||||
; CHECK-NEXT: br label [[LOOP_EXIT:%.*]]
|
||||
; CHECK: entry.split:
|
||||
; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]
|
||||
; CHECK: loop_begin:
|
||||
; CHECK-NEXT: call void @x()
|
||||
; CHECK-NEXT: br label [[LOOP_B:%.*]]
|
||||
; CHECK: loop_b:
|
||||
; CHECK-NEXT: call void @b()
|
||||
; CHECK-NEXT: call void @b()
|
||||
; CHECK-NEXT: call void @b()
|
||||
; CHECK-NEXT: call void @b()
|
||||
; CHECK-NEXT: br label [[LOOP_LATCH:%.*]]
|
||||
; CHECK: loop_latch:
|
||||
; CHECK-NEXT: [[V:%.*]] = load i1, i1* [[PTR]], align 1
|
||||
; CHECK-NEXT: br i1 [[V]], label [[LOOP_BEGIN]], label [[LOOP_EXIT_SPLIT:%.*]]
|
||||
; CHECK: loop_exit.split:
|
||||
; CHECK-NEXT: br label [[LOOP_EXIT]]
|
||||
; CHECK: loop_exit:
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
entry:
|
||||
br label %loop_begin
|
||||
|
||||
loop_begin:
|
||||
call void @x()
|
||||
br i1 %cond, label %loop_a, label %loop_b
|
||||
|
||||
loop_a:
|
||||
call void @a()
|
||||
call void @a()
|
||||
call void @a()
|
||||
call void @a()
|
||||
br label %loop_latch
|
||||
|
||||
loop_b:
|
||||
call void @b()
|
||||
call void @b()
|
||||
call void @b()
|
||||
call void @b()
|
||||
br label %loop_latch
|
||||
|
||||
loop_latch:
|
||||
%v = load i1, i1* %ptr
|
||||
br i1 %v, label %loop_begin, label %loop_exit
|
||||
|
||||
loop_exit:
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @test_unswitch_non_dup_code_minsize(i1* %ptr, i1 %cond) #0 {
|
||||
; CHECK-LABEL: @test_unswitch_non_dup_code_minsize(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: br i1 [[COND:%.*]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
|
||||
; CHECK: entry.split.us:
|
||||
; CHECK-NEXT: br label [[LOOP_BEGIN_US:%.*]]
|
||||
; CHECK: loop_begin.us:
|
||||
; CHECK-NEXT: call void @x()
|
||||
; CHECK-NEXT: br label [[LOOP_A_US:%.*]]
|
||||
; CHECK: loop_a.us:
|
||||
; CHECK-NEXT: call void @a()
|
||||
; CHECK-NEXT: call void @a()
|
||||
; CHECK-NEXT: call void @a()
|
||||
; CHECK-NEXT: call void @a()
|
||||
; CHECK-NEXT: br label [[LOOP_LATCH_US:%.*]]
|
||||
; CHECK: loop_latch.us:
|
||||
; CHECK-NEXT: [[V_US:%.*]] = load i1, i1* [[PTR:%.*]], align 1
|
||||
; CHECK-NEXT: br i1 [[V_US]], label [[LOOP_BEGIN_US]], label [[LOOP_EXIT_SPLIT_US:%.*]]
|
||||
; CHECK: loop_exit.split.us:
|
||||
; CHECK-NEXT: br label [[LOOP_EXIT:%.*]]
|
||||
; CHECK: entry.split:
|
||||
; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]
|
||||
; CHECK: loop_begin:
|
||||
; CHECK-NEXT: call void @x()
|
||||
; CHECK-NEXT: br label [[LOOP_B:%.*]]
|
||||
; CHECK: loop_b:
|
||||
; CHECK-NEXT: call void @b()
|
||||
; CHECK-NEXT: call void @b()
|
||||
; CHECK-NEXT: call void @b()
|
||||
; CHECK-NEXT: call void @b()
|
||||
; CHECK-NEXT: br label [[LOOP_LATCH:%.*]]
|
||||
; CHECK: loop_latch:
|
||||
; CHECK-NEXT: [[V:%.*]] = load i1, i1* [[PTR]], align 1
|
||||
; CHECK-NEXT: br i1 [[V]], label [[LOOP_BEGIN]], label [[LOOP_EXIT_SPLIT:%.*]]
|
||||
; CHECK: loop_exit.split:
|
||||
; CHECK-NEXT: br label [[LOOP_EXIT]]
|
||||
; CHECK: loop_exit:
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
entry:
|
||||
br label %loop_begin
|
||||
|
||||
loop_begin:
|
||||
call void @x()
|
||||
br i1 %cond, label %loop_a, label %loop_b
|
||||
|
||||
loop_a:
|
||||
call void @a()
|
||||
call void @a()
|
||||
call void @a()
|
||||
call void @a()
|
||||
br label %loop_latch
|
||||
|
||||
loop_b:
|
||||
call void @b()
|
||||
call void @b()
|
||||
call void @b()
|
||||
call void @b()
|
||||
br label %loop_latch
|
||||
|
||||
loop_latch:
|
||||
%v = load i1, i1* %ptr
|
||||
br i1 %v, label %loop_begin, label %loop_exit
|
||||
|
||||
loop_exit:
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @test_unswitch_non_dup_code_in_cfg(i1* %ptr, i1 %cond) {
|
||||
; CHECK-LABEL: @test_unswitch_non_dup_code_in_cfg(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: br i1 [[COND:%.*]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
|
||||
; CHECK: entry.split.us:
|
||||
; CHECK-NEXT: br label [[LOOP_BEGIN_US:%.*]]
|
||||
; CHECK: loop_begin.us:
|
||||
; CHECK-NEXT: call void @x()
|
||||
; CHECK-NEXT: br label [[LOOP_A_US:%.*]]
|
||||
; CHECK: loop_a.us:
|
||||
; CHECK-NEXT: [[V1_US:%.*]] = load i1, i1* [[PTR:%.*]], align 1
|
||||
; CHECK-NEXT: br i1 [[V1_US]], label [[LOOP_A_A_US:%.*]], label [[LOOP_A_B_US:%.*]]
|
||||
; CHECK: loop_a_b.us:
|
||||
; CHECK-NEXT: call void @a()
|
||||
; CHECK-NEXT: br label [[LOOP_LATCH_US:%.*]]
|
||||
; CHECK: loop_a_a.us:
|
||||
; CHECK-NEXT: call void @a()
|
||||
; CHECK-NEXT: br label [[LOOP_LATCH_US]]
|
||||
; CHECK: loop_latch.us:
|
||||
; CHECK-NEXT: [[V3_US:%.*]] = load i1, i1* [[PTR]], align 1
|
||||
; CHECK-NEXT: br i1 [[V3_US]], label [[LOOP_BEGIN_US]], label [[LOOP_EXIT_SPLIT_US:%.*]]
|
||||
; CHECK: loop_exit.split.us:
|
||||
; CHECK-NEXT: br label [[LOOP_EXIT:%.*]]
|
||||
; CHECK: entry.split:
|
||||
; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]
|
||||
; CHECK: loop_begin:
|
||||
; CHECK-NEXT: call void @x()
|
||||
; CHECK-NEXT: br label [[LOOP_B:%.*]]
|
||||
; CHECK: loop_b:
|
||||
; CHECK-NEXT: [[V2:%.*]] = load i1, i1* [[PTR]], align 1
|
||||
; CHECK-NEXT: br i1 [[V2]], label [[LOOP_B_A:%.*]], label [[LOOP_B_B:%.*]]
|
||||
; CHECK: loop_b_a:
|
||||
; CHECK-NEXT: call void @b()
|
||||
; CHECK-NEXT: br label [[LOOP_LATCH:%.*]]
|
||||
; CHECK: loop_b_b:
|
||||
; CHECK-NEXT: call void @b()
|
||||
; CHECK-NEXT: br label [[LOOP_LATCH]]
|
||||
; CHECK: loop_latch:
|
||||
; CHECK-NEXT: [[V3:%.*]] = load i1, i1* [[PTR]], align 1
|
||||
; CHECK-NEXT: br i1 [[V3]], label [[LOOP_BEGIN]], label [[LOOP_EXIT_SPLIT:%.*]]
|
||||
; CHECK: loop_exit.split:
|
||||
; CHECK-NEXT: br label [[LOOP_EXIT]]
|
||||
; CHECK: loop_exit:
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
entry:
|
||||
br label %loop_begin
|
||||
|
||||
loop_begin:
|
||||
call void @x()
|
||||
br i1 %cond, label %loop_a, label %loop_b
|
||||
|
||||
loop_a:
|
||||
%v1 = load i1, i1* %ptr
|
||||
br i1 %v1, label %loop_a_a, label %loop_a_b
|
||||
|
||||
loop_a_a:
|
||||
call void @a()
|
||||
br label %loop_latch
|
||||
|
||||
loop_a_b:
|
||||
call void @a()
|
||||
br label %loop_latch
|
||||
|
||||
loop_b:
|
||||
%v2 = load i1, i1* %ptr
|
||||
br i1 %v2, label %loop_b_a, label %loop_b_b
|
||||
|
||||
loop_b_a:
|
||||
call void @b()
|
||||
br label %loop_latch
|
||||
|
||||
loop_b_b:
|
||||
call void @b()
|
||||
br label %loop_latch
|
||||
|
||||
loop_latch:
|
||||
%v3 = load i1, i1* %ptr
|
||||
br i1 %v3, label %loop_begin, label %loop_exit
|
||||
|
||||
loop_exit:
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @test_unswitch_non_dup_code_in_cfg_minsize(i1* %ptr, i1 %cond) #0 {
|
||||
; CHECK-LABEL: @test_unswitch_non_dup_code_in_cfg_minsize(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: br i1 [[COND:%.*]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
|
||||
; CHECK: entry.split.us:
|
||||
; CHECK-NEXT: br label [[LOOP_BEGIN_US:%.*]]
|
||||
; CHECK: loop_begin.us:
|
||||
; CHECK-NEXT: call void @x()
|
||||
; CHECK-NEXT: br label [[LOOP_A_US:%.*]]
|
||||
; CHECK: loop_a.us:
|
||||
; CHECK-NEXT: [[V1_US:%.*]] = load i1, i1* [[PTR:%.*]], align 1
|
||||
; CHECK-NEXT: br i1 [[V1_US]], label [[LOOP_A_A_US:%.*]], label [[LOOP_A_B_US:%.*]]
|
||||
; CHECK: loop_a_b.us:
|
||||
; CHECK-NEXT: call void @a()
|
||||
; CHECK-NEXT: br label [[LOOP_LATCH_US:%.*]]
|
||||
; CHECK: loop_a_a.us:
|
||||
; CHECK-NEXT: call void @a()
|
||||
; CHECK-NEXT: br label [[LOOP_LATCH_US]]
|
||||
; CHECK: loop_latch.us:
|
||||
; CHECK-NEXT: [[V3_US:%.*]] = load i1, i1* [[PTR]], align 1
|
||||
; CHECK-NEXT: br i1 [[V3_US]], label [[LOOP_BEGIN_US]], label [[LOOP_EXIT_SPLIT_US:%.*]]
|
||||
; CHECK: loop_exit.split.us:
|
||||
; CHECK-NEXT: br label [[LOOP_EXIT:%.*]]
|
||||
; CHECK: entry.split:
|
||||
; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]
|
||||
; CHECK: loop_begin:
|
||||
; CHECK-NEXT: call void @x()
|
||||
; CHECK-NEXT: br label [[LOOP_B:%.*]]
|
||||
; CHECK: loop_b:
|
||||
; CHECK-NEXT: [[V2:%.*]] = load i1, i1* [[PTR]], align 1
|
||||
; CHECK-NEXT: br i1 [[V2]], label [[LOOP_B_A:%.*]], label [[LOOP_B_B:%.*]]
|
||||
; CHECK: loop_b_a:
|
||||
; CHECK-NEXT: call void @b()
|
||||
; CHECK-NEXT: br label [[LOOP_LATCH:%.*]]
|
||||
; CHECK: loop_b_b:
|
||||
; CHECK-NEXT: call void @b()
|
||||
; CHECK-NEXT: br label [[LOOP_LATCH]]
|
||||
; CHECK: loop_latch:
|
||||
; CHECK-NEXT: [[V3:%.*]] = load i1, i1* [[PTR]], align 1
|
||||
; CHECK-NEXT: br i1 [[V3]], label [[LOOP_BEGIN]], label [[LOOP_EXIT_SPLIT:%.*]]
|
||||
; CHECK: loop_exit.split:
|
||||
; CHECK-NEXT: br label [[LOOP_EXIT]]
|
||||
; CHECK: loop_exit:
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
entry:
|
||||
br label %loop_begin
|
||||
|
||||
loop_begin:
|
||||
call void @x()
|
||||
br i1 %cond, label %loop_a, label %loop_b
|
||||
|
||||
loop_a:
|
||||
%v1 = load i1, i1* %ptr
|
||||
br i1 %v1, label %loop_a_a, label %loop_a_b
|
||||
|
||||
loop_a_a:
|
||||
call void @a()
|
||||
br label %loop_latch
|
||||
|
||||
loop_a_b:
|
||||
call void @a()
|
||||
br label %loop_latch
|
||||
|
||||
loop_b:
|
||||
%v2 = load i1, i1* %ptr
|
||||
br i1 %v2, label %loop_b_a, label %loop_b_b
|
||||
|
||||
loop_b_a:
|
||||
call void @b()
|
||||
br label %loop_latch
|
||||
|
||||
loop_b_b:
|
||||
call void @b()
|
||||
br label %loop_latch
|
||||
|
||||
loop_latch:
|
||||
%v3 = load i1, i1* %ptr
|
||||
br i1 %v3, label %loop_begin, label %loop_exit
|
||||
|
||||
loop_exit:
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @test_no_unswitch_non_dup_code(i1* %ptr, i1 %cond) {
|
||||
; CHECK-LABEL: @test_no_unswitch_non_dup_code(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]
|
||||
; CHECK: loop_begin:
|
||||
; CHECK-NEXT: call void @x()
|
||||
; CHECK-NEXT: br i1 [[COND:%.*]], label [[LOOP_A:%.*]], label [[LOOP_B:%.*]]
|
||||
; CHECK: loop_a:
|
||||
; CHECK-NEXT: [[V1:%.*]] = load i1, i1* [[PTR:%.*]], align 1
|
||||
; CHECK-NEXT: br i1 [[V1]], label [[LOOP_A_A:%.*]], label [[LOOP_A_B:%.*]]
|
||||
; CHECK: loop_a_a:
|
||||
; CHECK-NEXT: call void @a()
|
||||
; CHECK-NEXT: br label [[LOOP_LATCH:%.*]]
|
||||
; CHECK: loop_a_b:
|
||||
; CHECK-NEXT: call void @a()
|
||||
; CHECK-NEXT: br label [[LOOP_LATCH]]
|
||||
; CHECK: loop_b:
|
||||
; CHECK-NEXT: [[V2:%.*]] = load i1, i1* [[PTR]], align 1
|
||||
; CHECK-NEXT: br i1 [[V2]], label [[LOOP_B_A:%.*]], label [[LOOP_B_B:%.*]]
|
||||
; CHECK: loop_b_a:
|
||||
; CHECK-NEXT: call void @b()
|
||||
; CHECK-NEXT: br label [[LOOP_LATCH]]
|
||||
; CHECK: loop_b_b:
|
||||
; CHECK-NEXT: call void @b()
|
||||
; CHECK-NEXT: br label [[LOOP_LATCH]]
|
||||
; CHECK: loop_latch:
|
||||
; CHECK-NEXT: call void @x()
|
||||
; CHECK-NEXT: call void @x()
|
||||
; CHECK-NEXT: [[V:%.*]] = load i1, i1* [[PTR]], align 1
|
||||
; CHECK-NEXT: br i1 [[V]], label [[LOOP_BEGIN]], label [[LOOP_EXIT:%.*]]
|
||||
; CHECK: loop_exit:
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
entry:
|
||||
br label %loop_begin
|
||||
|
||||
loop_begin:
|
||||
call void @x()
|
||||
br i1 %cond, label %loop_a, label %loop_b
|
||||
|
||||
loop_a:
|
||||
%v1 = load i1, i1* %ptr
|
||||
br i1 %v1, label %loop_a_a, label %loop_a_b
|
||||
|
||||
loop_a_a:
|
||||
call void @a()
|
||||
br label %loop_latch
|
||||
|
||||
loop_a_b:
|
||||
call void @a()
|
||||
br label %loop_latch
|
||||
|
||||
loop_b:
|
||||
%v2 = load i1, i1* %ptr
|
||||
br i1 %v2, label %loop_b_a, label %loop_b_b
|
||||
|
||||
loop_b_a:
|
||||
call void @b()
|
||||
br label %loop_latch
|
||||
|
||||
loop_b_b:
|
||||
call void @b()
|
||||
br label %loop_latch
|
||||
|
||||
loop_latch:
|
||||
call void @x()
|
||||
call void @x()
|
||||
%v = load i1, i1* %ptr
|
||||
br i1 %v, label %loop_begin, label %loop_exit
|
||||
|
||||
loop_exit:
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @test_unswitch_large_exit(i1* %ptr, i1 %cond) {
|
||||
; CHECK-LABEL: @test_unswitch_large_exit(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: br i1 [[COND:%.*]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
|
||||
; CHECK: entry.split.us:
|
||||
; CHECK-NEXT: br label [[LOOP_BEGIN_US:%.*]]
|
||||
; CHECK: loop_begin.us:
|
||||
; CHECK-NEXT: call void @x()
|
||||
; CHECK-NEXT: br label [[LOOP_A_US:%.*]]
|
||||
; CHECK: loop_a.us:
|
||||
; CHECK-NEXT: call void @a()
|
||||
; CHECK-NEXT: br label [[LOOP_LATCH_US:%.*]]
|
||||
; CHECK: loop_latch.us:
|
||||
; CHECK-NEXT: [[V_US:%.*]] = load i1, i1* [[PTR:%.*]], align 1
|
||||
; CHECK-NEXT: br i1 [[V_US]], label [[LOOP_BEGIN_US]], label [[LOOP_EXIT_SPLIT_US:%.*]]
|
||||
; CHECK: loop_exit.split.us:
|
||||
; CHECK-NEXT: br label [[LOOP_EXIT:%.*]]
|
||||
; CHECK: entry.split:
|
||||
; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]
|
||||
; CHECK: loop_begin:
|
||||
; CHECK-NEXT: call void @x()
|
||||
; CHECK-NEXT: br label [[LOOP_B:%.*]]
|
||||
; CHECK: loop_b:
|
||||
; CHECK-NEXT: call void @b()
|
||||
; CHECK-NEXT: br label [[LOOP_LATCH:%.*]]
|
||||
; CHECK: loop_latch:
|
||||
; CHECK-NEXT: [[V:%.*]] = load i1, i1* [[PTR]], align 1
|
||||
; CHECK-NEXT: br i1 [[V]], label [[LOOP_BEGIN]], label [[LOOP_EXIT_SPLIT:%.*]]
|
||||
; CHECK: loop_exit.split:
|
||||
; CHECK-NEXT: br label [[LOOP_EXIT]]
|
||||
; CHECK: loop_exit:
|
||||
; CHECK-NEXT: call void @x()
|
||||
; CHECK-NEXT: call void @x()
|
||||
; CHECK-NEXT: call void @x()
|
||||
; CHECK-NEXT: call void @x()
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
entry:
|
||||
br label %loop_begin
|
||||
|
||||
loop_begin:
|
||||
call void @x()
|
||||
br i1 %cond, label %loop_a, label %loop_b
|
||||
|
||||
loop_a:
|
||||
call void @a()
|
||||
br label %loop_latch
|
||||
|
||||
loop_b:
|
||||
call void @b()
|
||||
br label %loop_latch
|
||||
|
||||
loop_latch:
|
||||
%v = load i1, i1* %ptr
|
||||
br i1 %v, label %loop_begin, label %loop_exit
|
||||
|
||||
loop_exit:
|
||||
call void @x()
|
||||
call void @x()
|
||||
call void @x()
|
||||
call void @x()
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @test_unswitch_dedicated_exiting(i1* %ptr, i1 %cond) {
|
||||
; CHECK-LABEL: @test_unswitch_dedicated_exiting(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: br i1 [[COND:%.*]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
|
||||
; CHECK: entry.split.us:
|
||||
; CHECK-NEXT: br label [[LOOP_BEGIN_US:%.*]]
|
||||
; CHECK: loop_begin.us:
|
||||
; CHECK-NEXT: call void @x()
|
||||
; CHECK-NEXT: br label [[LOOP_A_US:%.*]]
|
||||
; CHECK: loop_a.us:
|
||||
; CHECK-NEXT: call void @a()
|
||||
; CHECK-NEXT: br label [[LOOP_LATCH_US:%.*]]
|
||||
; CHECK: loop_latch.us:
|
||||
; CHECK-NEXT: [[V_US:%.*]] = load i1, i1* [[PTR:%.*]], align 1
|
||||
; CHECK-NEXT: br i1 [[V_US]], label [[LOOP_BEGIN_US]], label [[LOOP_EXIT_SPLIT_US:%.*]]
|
||||
; CHECK: loop_exit.split.us:
|
||||
; CHECK-NEXT: br label [[LOOP_EXIT:%.*]]
|
||||
; CHECK: entry.split:
|
||||
; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]
|
||||
; CHECK: loop_begin:
|
||||
; CHECK-NEXT: call void @x()
|
||||
; CHECK-NEXT: br label [[LOOP_B_EXIT:%.*]]
|
||||
; CHECK: loop_b_exit:
|
||||
; CHECK-NEXT: call void @b()
|
||||
; CHECK-NEXT: call void @b()
|
||||
; CHECK-NEXT: call void @b()
|
||||
; CHECK-NEXT: call void @b()
|
||||
; CHECK-NEXT: ret void
|
||||
; CHECK: loop_exit:
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
entry:
|
||||
br label %loop_begin
|
||||
|
||||
loop_begin:
|
||||
call void @x()
|
||||
br i1 %cond, label %loop_a, label %loop_b_exit
|
||||
|
||||
loop_a:
|
||||
call void @a()
|
||||
br label %loop_latch
|
||||
|
||||
loop_b_exit:
|
||||
call void @b()
|
||||
call void @b()
|
||||
call void @b()
|
||||
call void @b()
|
||||
ret void
|
||||
|
||||
loop_latch:
|
||||
%v = load i1, i1* %ptr
|
||||
br i1 %v, label %loop_begin, label %loop_exit
|
||||
|
||||
loop_exit:
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @test_unswitch_dedicated_exiting_minsize(i1* %ptr, i1 %cond) #0 {
|
||||
; CHECK-LABEL: @test_unswitch_dedicated_exiting_minsize(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: br i1 [[COND:%.*]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
|
||||
; CHECK: entry.split.us:
|
||||
; CHECK-NEXT: br label [[LOOP_BEGIN_US:%.*]]
|
||||
; CHECK: loop_begin.us:
|
||||
; CHECK-NEXT: call void @x()
|
||||
; CHECK-NEXT: br label [[LOOP_A_US:%.*]]
|
||||
; CHECK: loop_a.us:
|
||||
; CHECK-NEXT: call void @a()
|
||||
; CHECK-NEXT: br label [[LOOP_LATCH_US:%.*]]
|
||||
; CHECK: loop_latch.us:
|
||||
; CHECK-NEXT: [[V_US:%.*]] = load i1, i1* [[PTR:%.*]], align 1
|
||||
; CHECK-NEXT: br i1 [[V_US]], label [[LOOP_BEGIN_US]], label [[LOOP_EXIT_SPLIT_US:%.*]]
|
||||
; CHECK: loop_exit.split.us:
|
||||
; CHECK-NEXT: br label [[LOOP_EXIT:%.*]]
|
||||
; CHECK: entry.split:
|
||||
; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]
|
||||
; CHECK: loop_begin:
|
||||
; CHECK-NEXT: call void @x()
|
||||
; CHECK-NEXT: br label [[LOOP_B_EXIT:%.*]]
|
||||
; CHECK: loop_b_exit:
|
||||
; CHECK-NEXT: call void @b()
|
||||
; CHECK-NEXT: call void @b()
|
||||
; CHECK-NEXT: call void @b()
|
||||
; CHECK-NEXT: call void @b()
|
||||
; CHECK-NEXT: ret void
|
||||
; CHECK: loop_exit:
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
entry:
|
||||
br label %loop_begin
|
||||
|
||||
loop_begin:
|
||||
call void @x()
|
||||
br i1 %cond, label %loop_a, label %loop_b_exit
|
||||
|
||||
loop_a:
|
||||
call void @a()
|
||||
br label %loop_latch
|
||||
|
||||
loop_b_exit:
|
||||
call void @b()
|
||||
call void @b()
|
||||
call void @b()
|
||||
call void @b()
|
||||
ret void
|
||||
|
||||
loop_latch:
|
||||
%v = load i1, i1* %ptr
|
||||
br i1 %v, label %loop_begin, label %loop_exit
|
||||
|
||||
loop_exit:
|
||||
ret void
|
||||
}
|
||||
|
||||
attributes #0 = { minsize optsize }
|
Loading…
Reference in New Issue
Block a user