diff options
author | Shawn Landden <shawn@git.icu> | 2019-06-13 05:26:17 +0000 |
---|---|---|
committer | Shawn Landden <shawn@git.icu> | 2019-06-13 05:26:17 +0000 |
commit | 8b142bcc3f21f279303e28ea2e060acc79a3cbe4 (patch) | |
tree | 223dc3f95fcdbf4d4a93d42a4a563d26459114dc /llvm/test/Transforms/SimplifyCFG | |
parent | 2bf25681509add1d9987ca7dada2fffeb95da4c1 (diff) | |
download | bcm5719-llvm-8b142bcc3f21f279303e28ea2e060acc79a3cbe4.tar.gz bcm5719-llvm-8b142bcc3f21f279303e28ea2e060acc79a3cbe4.zip |
[SimplifyCFG] reverting preliminary Switch patches again
This reverts 363226 and 363227, both NFC intended
I swear I fixed the test case that is failing, and ran
the tests, but I will look into it again.
llvm-svn: 363229
Diffstat (limited to 'llvm/test/Transforms/SimplifyCFG')
19 files changed, 1422 insertions, 2582 deletions
diff --git a/llvm/test/Transforms/SimplifyCFG/ARM/cttz-ctlz.ll b/llvm/test/Transforms/SimplifyCFG/ARM/cttz-ctlz.ll index 22f5e9f3cc1..ffcf2175091 100644 --- a/llvm/test/Transforms/SimplifyCFG/ARM/cttz-ctlz.ll +++ b/llvm/test/Transforms/SimplifyCFG/ARM/cttz-ctlz.ll @@ -1,14 +1,11 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt -S -simplifycfg -mtriple=arm -mattr=+v6t2 < %s | FileCheck %s define i32 @ctlz(i32 %A) { ; CHECK-LABEL: @ctlz( -; CHECK-NEXT: entry: -; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[A:%.*]], 0 -; CHECK-NEXT: [[TMP0:%.*]] = tail call i32 @llvm.ctlz.i32(i32 [[A]], i1 true) -; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[TOBOOL]], i32 32, i32 [[TMP0]] -; CHECK-NEXT: ret i32 [[SPEC_SELECT]] -; +; CHECK: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i32 %A, 0 +; CHECK-NEXT: [[CTZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.ctlz.i32(i32 %A, i1 true) +; CHECK-NEXT: [[SEL:%[A-Za-z0-9.]+]] = select i1 [[ICMP]], i32 32, i32 [[CTZ]] +; CHECK-NEXT: ret i32 [[SEL]] entry: %tobool = icmp eq i32 %A, 0 br i1 %tobool, label %cond.end, label %cond.true @@ -24,12 +21,10 @@ cond.end: define i32 @cttz(i32 %A) { ; CHECK-LABEL: @cttz( -; CHECK-NEXT: entry: -; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[A:%.*]], 0 -; CHECK-NEXT: [[TMP0:%.*]] = tail call i32 @llvm.cttz.i32(i32 [[A]], i1 true) -; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[TOBOOL]], i32 32, i32 [[TMP0]] -; CHECK-NEXT: ret i32 [[SPEC_SELECT]] -; +; CHECK: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i32 %A, 0 +; CHECK-NEXT: [[CTZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.cttz.i32(i32 %A, i1 true) +; CHECK-NEXT: [[SEL:%[A-Za-z0-9.]+]] = select i1 [[ICMP]], i32 32, i32 [[CTZ]] +; CHECK-NEXT: ret i32 [[SEL]] entry: %tobool = icmp eq i32 %A, 0 br i1 %tobool, label %cond.end, label %cond.true diff --git a/llvm/test/Transforms/SimplifyCFG/ARM/select-trunc-i64.ll b/llvm/test/Transforms/SimplifyCFG/ARM/select-trunc-i64.ll index 9218ee185b1..9484de77db4 100644 --- a/llvm/test/Transforms/SimplifyCFG/ARM/select-trunc-i64.ll +++ b/llvm/test/Transforms/SimplifyCFG/ARM/select-trunc-i64.ll @@ -1,20 +1,11 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ;RUN: opt -S -simplifycfg -mtriple=arm < %s | FileCheck %s target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64" +; CHECK-LABEL: select_trunc_i64 +; CHECK-NOT: br +; CHECK: select +; CHECK: select define arm_aapcscc i32 @select_trunc_i64(i32 %a, i32 %b) { -; CHECK-LABEL: @select_trunc_i64( -; CHECK-NEXT: entry: -; CHECK-NEXT: [[CONV:%.*]] = sext i32 [[A:%.*]] to i64 -; CHECK-NEXT: [[CONV1:%.*]] = sext i32 [[B:%.*]] to i64 -; CHECK-NEXT: [[ADD:%.*]] = add nsw i64 [[CONV1]], [[CONV]] -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i64 [[ADD]], 2147483647 -; CHECK-NEXT: [[TMP0:%.*]] = icmp sgt i64 [[ADD]], -2147483648 -; CHECK-NEXT: [[COND:%.*]] = select i1 [[TMP0]], i64 [[ADD]], i64 -2147483648 -; CHECK-NEXT: [[EXTRACT_T:%.*]] = trunc i64 [[COND]] to i32 -; CHECK-NEXT: [[COND8_OFF0:%.*]] = select i1 [[CMP]], i32 2147483647, i32 [[EXTRACT_T]] -; CHECK-NEXT: ret i32 [[COND8_OFF0]] -; entry: %conv = sext i32 %a to i64 %conv1 = sext i32 %b to i64 diff --git a/llvm/test/Transforms/SimplifyCFG/ARM/switch-to-lookup-table-constant-expr.ll b/llvm/test/Transforms/SimplifyCFG/ARM/switch-to-lookup-table-constant-expr.ll index f6773717342..453a7686403 100644 --- a/llvm/test/Transforms/SimplifyCFG/ARM/switch-to-lookup-table-constant-expr.ll +++ b/llvm/test/Transforms/SimplifyCFG/ARM/switch-to-lookup-table-constant-expr.ll @@ -1,4 +1,3 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt -S -simplifycfg < %s | FileCheck %s target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64" @@ -16,28 +15,11 @@ target triple = "armv7a--none-eabi" @g4 = external thread_local global i32, align 4 define i32* @test3(i32 %n) { -; CHECK-LABEL: @test3( -; CHECK-NEXT: entry: -; CHECK-NEXT: switch i32 [[N:%.*]], label [[SW_DEFAULT:%.*]] [ -; CHECK-NEXT: i32 0, label [[RETURN:%.*]] -; CHECK-NEXT: i32 1, label [[SW_BB1:%.*]] -; CHECK-NEXT: i32 2, label [[SW_BB2:%.*]] -; CHECK-NEXT: ] -; CHECK: sw.bb1: -; CHECK-NEXT: br label [[RETURN]] -; CHECK: sw.bb2: -; CHECK-NEXT: br label [[RETURN]] -; CHECK: sw.default: -; CHECK-NEXT: br label [[RETURN]] -; CHECK: return: -; CHECK-NEXT: [[RETVAL_0:%.*]] = phi i32* [ @g4, [[SW_DEFAULT]] ], [ getelementptr inbounds (i32, i32* inttoptr (i32 mul (i32 ptrtoint (i32* @g3 to i32), i32 2) to i32*), i32 1), [[SW_BB2]] ], [ @g2, [[SW_BB1]] ], [ @g1, [[ENTRY:%.*]] ] -; CHECK-NEXT: ret i32* [[RETVAL_0]] -; entry: switch i32 %n, label %sw.default [ - i32 0, label %sw.bb - i32 1, label %sw.bb1 - i32 2, label %sw.bb2 + i32 0, label %sw.bb + i32 1, label %sw.bb1 + i32 2, label %sw.bb2 ] sw.bb: diff --git a/llvm/test/Transforms/SimplifyCFG/ARM/switch-to-lookup-table.ll b/llvm/test/Transforms/SimplifyCFG/ARM/switch-to-lookup-table.ll index 08dbb31a84b..501bc31bd0d 100644 --- a/llvm/test/Transforms/SimplifyCFG/ARM/switch-to-lookup-table.ll +++ b/llvm/test/Transforms/SimplifyCFG/ARM/switch-to-lookup-table.ll @@ -1,4 +1,3 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt -S -simplifycfg -switch-to-lookup -mtriple=arm -relocation-model=static < %s | FileCheck %s --check-prefix=CHECK --check-prefix=ENABLE ; RUN: opt -S -simplifycfg -switch-to-lookup -mtriple=arm -relocation-model=pic < %s | FileCheck %s --check-prefix=CHECK --check-prefix=ENABLE ; RUN: opt -S -simplifycfg -switch-to-lookup -mtriple=arm -relocation-model=ropi < %s | FileCheck %s --check-prefix=CHECK --check-prefix=DISABLE @@ -23,28 +22,11 @@ target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64" target triple = "armv7a--none-eabi" define i32 @test1(i32 %n) { -; CHECK-LABEL: @test1( -; CHECK-NEXT: entry: -; CHECK-NEXT: switch i32 [[N:%.*]], label [[SW_DEFAULT:%.*]] [ -; CHECK-NEXT: i32 0, label [[RETURN:%.*]] -; CHECK-NEXT: i32 1, label [[SW_BB1:%.*]] -; CHECK-NEXT: i32 2, label [[SW_BB2:%.*]] -; CHECK-NEXT: ] -; CHECK: sw.bb1: -; CHECK-NEXT: br label [[RETURN]] -; CHECK: sw.bb2: -; CHECK-NEXT: br label [[RETURN]] -; CHECK: sw.default: -; CHECK-NEXT: br label [[RETURN]] -; CHECK: return: -; CHECK-NEXT: [[RETVAL_0:%.*]] = phi i32 [ 15498, [[SW_DEFAULT]] ], [ 15532, [[SW_BB2]] ], [ 5678, [[SW_BB1]] ], [ 1234, [[ENTRY:%.*]] ] -; CHECK-NEXT: ret i32 [[RETVAL_0]] -; entry: switch i32 %n, label %sw.default [ - i32 0, label %sw.bb - i32 1, label %sw.bb1 - i32 2, label %sw.bb2 + i32 0, label %sw.bb + i32 1, label %sw.bb1 + i32 2, label %sw.bb2 ] sw.bb: @@ -71,28 +53,11 @@ return: define i32* @test2(i32 %n) { -; CHECK-LABEL: @test2( -; CHECK-NEXT: entry: -; CHECK-NEXT: switch i32 [[N:%.*]], label [[SW_DEFAULT:%.*]] [ -; CHECK-NEXT: i32 0, label [[RETURN:%.*]] -; CHECK-NEXT: i32 1, label [[SW_BB1:%.*]] -; CHECK-NEXT: i32 2, label [[SW_BB2:%.*]] -; CHECK-NEXT: ] -; CHECK: sw.bb1: -; CHECK-NEXT: br label [[RETURN]] -; CHECK: sw.bb2: -; CHECK-NEXT: br label [[RETURN]] -; CHECK: sw.default: -; CHECK-NEXT: br label [[RETURN]] -; CHECK: return: -; CHECK-NEXT: [[RETVAL_0:%.*]] = phi i32* [ @c4, [[SW_DEFAULT]] ], [ @c3, [[SW_BB2]] ], [ @c2, [[SW_BB1]] ], [ @c1, [[ENTRY:%.*]] ] -; CHECK-NEXT: ret i32* [[RETVAL_0]] -; entry: switch i32 %n, label %sw.default [ - i32 0, label %sw.bb - i32 1, label %sw.bb1 - i32 2, label %sw.bb2 + i32 0, label %sw.bb + i32 1, label %sw.bb1 + i32 2, label %sw.bb2 ] sw.bb: @@ -118,28 +83,11 @@ return: @g4 = external global i32, align 4 define i32* @test3(i32 %n) { -; CHECK-LABEL: @test3( -; CHECK-NEXT: entry: -; CHECK-NEXT: switch i32 [[N:%.*]], label [[SW_DEFAULT:%.*]] [ -; CHECK-NEXT: i32 0, label [[RETURN:%.*]] -; CHECK-NEXT: i32 1, label [[SW_BB1:%.*]] -; CHECK-NEXT: i32 2, label [[SW_BB2:%.*]] -; CHECK-NEXT: ] -; CHECK: sw.bb1: -; CHECK-NEXT: br label [[RETURN]] -; CHECK: sw.bb2: -; CHECK-NEXT: br label [[RETURN]] -; CHECK: sw.default: -; CHECK-NEXT: br label [[RETURN]] -; CHECK: return: -; CHECK-NEXT: [[RETVAL_0:%.*]] = phi i32* [ @g4, [[SW_DEFAULT]] ], [ @g3, [[SW_BB2]] ], [ @g2, [[SW_BB1]] ], [ @g1, [[ENTRY:%.*]] ] -; CHECK-NEXT: ret i32* [[RETVAL_0]] -; entry: switch i32 %n, label %sw.default [ - i32 0, label %sw.bb - i32 1, label %sw.bb1 - i32 2, label %sw.bb2 + i32 0, label %sw.bb + i32 1, label %sw.bb1 + i32 2, label %sw.bb2 ] sw.bb: @@ -166,26 +114,6 @@ declare i32 @f4(i32, i32) declare i32 @f5(i32, i32) define i32 @test4(i32 %a, i32 %b, i32 %c) { -; CHECK-LABEL: @test4( -; CHECK-NEXT: entry: -; CHECK-NEXT: switch i32 [[A:%.*]], label [[COND_FALSE6:%.*]] [ -; CHECK-NEXT: i32 1, label [[COND_END11:%.*]] -; CHECK-NEXT: i32 2, label [[COND_END11_FOLD_SPLIT:%.*]] -; CHECK-NEXT: i32 3, label [[COND_END11_FOLD_SPLIT1:%.*]] -; CHECK-NEXT: ] -; CHECK: cond.false6: -; CHECK-NEXT: [[CMP7:%.*]] = icmp eq i32 [[A]], 4 -; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP7]], i32 (i32, i32)* @f4, i32 (i32, i32)* @f5 -; CHECK-NEXT: br label [[COND_END11]] -; CHECK: cond.end11.fold.split: -; CHECK-NEXT: br label [[COND_END11]] -; CHECK: cond.end11.fold.split1: -; CHECK-NEXT: br label [[COND_END11]] -; CHECK: cond.end11: -; CHECK-NEXT: [[COND12:%.*]] = phi i32 (i32, i32)* [ @f1, [[ENTRY:%.*]] ], [ [[COND]], [[COND_FALSE6]] ], [ @f2, [[COND_END11_FOLD_SPLIT]] ], [ @f3, [[COND_END11_FOLD_SPLIT1]] ] -; CHECK-NEXT: [[CALL:%.*]] = call i32 [[COND12]](i32 [[B:%.*]], i32 [[C:%.*]]) -; CHECK-NEXT: ret i32 [[CALL]] -; entry: %cmp = icmp eq i32 %a, 1 br i1 %cmp, label %cond.end11, label %cond.false diff --git a/llvm/test/Transforms/SimplifyCFG/CoveredLookupTable.ll b/llvm/test/Transforms/SimplifyCFG/CoveredLookupTable.ll index e3a3b3fc58c..e558956d502 100644 --- a/llvm/test/Transforms/SimplifyCFG/CoveredLookupTable.ll +++ b/llvm/test/Transforms/SimplifyCFG/CoveredLookupTable.ll @@ -1,4 +1,3 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt -simplifycfg -switch-to-lookup -S %s | FileCheck %s ; RUN: opt -passes='simplify-cfg<switch-to-lookup>' -S %s | FileCheck %s ; rdar://15268442 @@ -6,24 +5,24 @@ target datalayout = "e-p:64:64:64-S128-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f16:16:16-f32:32:32-f64:64:64-f128:128:128-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" target triple = "x86_64-apple-darwin12.0.0" +; CHECK-LABEL: define i3 @coveredswitch_test( +; CHECK: entry: +; CHECK-NEXT: sub i3 %input, -4 +; CHECK-NEXT: zext i3 %switch.tableidx to i24 +; CHECK-NEXT: mul i24 %switch.cast, 3 +; CHECK-NEXT: lshr i24 7507338, %switch.shiftamt +; CHECK-NEXT: trunc i24 %switch.downshift to i3 +; CHECK-NEXT: ret i3 %switch.masked + define i3 @coveredswitch_test(i3 %input) { -; CHECK-LABEL: @coveredswitch_test( -; CHECK-NEXT: entry: -; CHECK-NEXT: [[SWITCH_TABLEIDX:%.*]] = sub i3 [[INPUT:%.*]], -4 -; CHECK-NEXT: [[SWITCH_CAST:%.*]] = zext i3 [[SWITCH_TABLEIDX]] to i24 -; CHECK-NEXT: [[SWITCH_SHIFTAMT:%.*]] = mul i24 [[SWITCH_CAST]], 3 -; CHECK-NEXT: [[SWITCH_DOWNSHIFT:%.*]] = lshr i24 7507338, [[SWITCH_SHIFTAMT]] -; CHECK-NEXT: [[SWITCH_MASKED:%.*]] = trunc i24 [[SWITCH_DOWNSHIFT]] to i3 -; CHECK-NEXT: ret i3 [[SWITCH_MASKED]] -; entry: switch i3 %input, label %bb8 [ - i3 0, label %bb7 - i3 1, label %bb - i3 2, label %bb3 - i3 3, label %bb4 - i3 4, label %bb5 - i3 5, label %bb6 + i3 0, label %bb7 + i3 1, label %bb + i3 2, label %bb3 + i3 3, label %bb4 + i3 4, label %bb5 + i3 5, label %bb6 ] bb: ; preds = %entry diff --git a/llvm/test/Transforms/SimplifyCFG/X86/disable-lookup-table.ll b/llvm/test/Transforms/SimplifyCFG/X86/disable-lookup-table.ll index 423d9462433..a8758a789ec 100644 --- a/llvm/test/Transforms/SimplifyCFG/X86/disable-lookup-table.ll +++ b/llvm/test/Transforms/SimplifyCFG/X86/disable-lookup-table.ll @@ -1,36 +1,19 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt < %s -simplifycfg -switch-to-lookup -S -mtriple=x86_64-unknown-linux-gnu | FileCheck %s ; RUN: opt < %s -passes='simplify-cfg<switch-to-lookup>' -S -mtriple=x86_64-unknown-linux-gnu | FileCheck %s ; In the presence of "-no-jump-tables"="true", simplifycfg should not convert switches to lookup tables. +; CHECK: @switch.table.bar = private unnamed_addr constant [4 x i32] [i32 55, i32 123, i32 0, i32 -1] +; CHECK-LABEL: foo +; CHECK-NOT: @switch.table.foo = private unnamed_addr constant [4 x i32] [i32 55, i32 123, i32 0, i32 -1] + define i32 @foo(i32 %c) "no-jump-tables"="true" { -; CHECK-LABEL: @foo( -; CHECK-NEXT: entry: -; CHECK-NEXT: switch i32 [[C:%.*]], label [[SW_DEFAULT:%.*]] [ -; CHECK-NEXT: i32 42, label [[RETURN:%.*]] -; CHECK-NEXT: i32 43, label [[SW_BB1:%.*]] -; CHECK-NEXT: i32 44, label [[SW_BB2:%.*]] -; CHECK-NEXT: i32 45, label [[SW_BB3:%.*]] -; CHECK-NEXT: ] -; CHECK: sw.bb1: -; CHECK-NEXT: br label [[RETURN]] -; CHECK: sw.bb2: -; CHECK-NEXT: br label [[RETURN]] -; CHECK: sw.bb3: -; CHECK-NEXT: br label [[RETURN]] -; CHECK: sw.default: -; CHECK-NEXT: br label [[RETURN]] -; CHECK: return: -; CHECK-NEXT: [[RETVAL_0:%.*]] = phi i32 [ 15, [[SW_DEFAULT]] ], [ -1, [[SW_BB3]] ], [ 0, [[SW_BB2]] ], [ 123, [[SW_BB1]] ], [ 55, [[ENTRY:%.*]] ] -; CHECK-NEXT: ret i32 [[RETVAL_0]] -; entry: switch i32 %c, label %sw.default [ - i32 42, label %return - i32 43, label %sw.bb1 - i32 44, label %sw.bb2 - i32 45, label %sw.bb3 + i32 42, label %return + i32 43, label %sw.bb1 + i32 44, label %sw.bb2 + i32 45, label %sw.bb3 ] sw.bb1: br label %return @@ -44,24 +27,12 @@ return: define i32 @bar(i32 %c) { -; CHECK-LABEL: @bar( -; CHECK-NEXT: entry: -; CHECK-NEXT: [[SWITCH_TABLEIDX:%.*]] = sub i32 [[C:%.*]], 42 -; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i32 [[SWITCH_TABLEIDX]], 4 -; CHECK-NEXT: br i1 [[TMP0]], label [[SWITCH_LOOKUP:%.*]], label [[RETURN:%.*]] -; CHECK: switch.lookup: -; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [4 x i32], [4 x i32]* @switch.table.bar, i32 0, i32 [[SWITCH_TABLEIDX]] -; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i32, i32* [[SWITCH_GEP]] -; CHECK-NEXT: ret i32 [[SWITCH_LOAD]] -; CHECK: return: -; CHECK-NEXT: ret i32 15 -; entry: switch i32 %c, label %sw.default [ - i32 42, label %return - i32 43, label %sw.bb1 - i32 44, label %sw.bb2 - i32 45, label %sw.bb3 + i32 42, label %return + i32 43, label %sw.bb1 + i32 44, label %sw.bb2 + i32 45, label %sw.bb3 ] sw.bb1: br label %return diff --git a/llvm/test/Transforms/SimplifyCFG/X86/speculate-cttz-ctlz.ll b/llvm/test/Transforms/SimplifyCFG/X86/speculate-cttz-ctlz.ll index 11ba3984f35..bee80e6acce 100644 --- a/llvm/test/Transforms/SimplifyCFG/X86/speculate-cttz-ctlz.ll +++ b/llvm/test/Transforms/SimplifyCFG/X86/speculate-cttz-ctlz.ll @@ -1,31 +1,14 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt -S -simplifycfg -mtriple=x86_64-unknown-unknown -mattr=+bmi < %s | FileCheck %s --check-prefix=ALL --check-prefix=BMI ; RUN: opt -S -simplifycfg -mtriple=x86_64-unknown-unknown -mattr=+lzcnt < %s | FileCheck %s --check-prefix=ALL --check-prefix=LZCNT ; RUN: opt -S -simplifycfg -mtriple=x86_64-unknown-unknown < %s | FileCheck %s --check-prefix=ALL --check-prefix=GENERIC define i64 @test1(i64 %A) { -; BMI-LABEL: @test1( -; BMI-NEXT: entry: -; BMI-NEXT: [[TOBOOL:%.*]] = icmp eq i64 [[A:%.*]], 0 -; BMI-NEXT: [[TMP0:%.*]] = tail call i64 @llvm.ctlz.i64(i64 [[A]], i1 true) -; BMI-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i64 64, i64 [[TMP0]] -; BMI-NEXT: ret i64 [[COND]] -; -; LZCNT-LABEL: @test1( -; LZCNT-NEXT: entry: -; LZCNT-NEXT: [[TOBOOL:%.*]] = icmp eq i64 [[A:%.*]], 0 -; LZCNT-NEXT: [[TMP0:%.*]] = tail call i64 @llvm.ctlz.i64(i64 [[A]], i1 true) -; LZCNT-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[TOBOOL]], i64 64, i64 [[TMP0]] -; LZCNT-NEXT: ret i64 [[SPEC_SELECT]] -; -; GENERIC-LABEL: @test1( -; GENERIC-NEXT: entry: -; GENERIC-NEXT: [[TOBOOL:%.*]] = icmp eq i64 [[A:%.*]], 0 -; GENERIC-NEXT: [[TMP0:%.*]] = tail call i64 @llvm.ctlz.i64(i64 [[A]], i1 true) -; GENERIC-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i64 64, i64 [[TMP0]] -; GENERIC-NEXT: ret i64 [[COND]] -; +; ALL-LABEL: @test1( +; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i64 %A, 0 +; ALL: [[CTLZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.ctlz.i64(i64 %A, i1 true) +; ALL-NEXT: select i1 [[COND]], i64 64, i64 [[CTLZ]] +; ALL: ret entry: %tobool = icmp eq i64 %A, 0 br i1 %tobool, label %cond.end, label %cond.true @@ -40,27 +23,11 @@ cond.end: ; preds = %entry, %cond.true } define i32 @test2(i32 %A) { -; BMI-LABEL: @test2( -; BMI-NEXT: entry: -; BMI-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[A:%.*]], 0 -; BMI-NEXT: [[TMP0:%.*]] = tail call i32 @llvm.ctlz.i32(i32 [[A]], i1 true) -; BMI-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i32 32, i32 [[TMP0]] -; BMI-NEXT: ret i32 [[COND]] -; -; LZCNT-LABEL: @test2( -; LZCNT-NEXT: entry: -; LZCNT-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[A:%.*]], 0 -; LZCNT-NEXT: [[TMP0:%.*]] = tail call i32 @llvm.ctlz.i32(i32 [[A]], i1 true) -; LZCNT-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[TOBOOL]], i32 32, i32 [[TMP0]] -; LZCNT-NEXT: ret i32 [[SPEC_SELECT]] -; -; GENERIC-LABEL: @test2( -; GENERIC-NEXT: entry: -; GENERIC-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[A:%.*]], 0 -; GENERIC-NEXT: [[TMP0:%.*]] = tail call i32 @llvm.ctlz.i32(i32 [[A]], i1 true) -; GENERIC-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i32 32, i32 [[TMP0]] -; GENERIC-NEXT: ret i32 [[COND]] -; +; ALL-LABEL: @test2( +; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i32 %A, 0 +; ALL: [[CTLZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.ctlz.i32(i32 %A, i1 true) +; ALL-NEXT: select i1 [[COND]], i32 32, i32 [[CTLZ]] +; ALL: ret entry: %tobool = icmp eq i32 %A, 0 br i1 %tobool, label %cond.end, label %cond.true @@ -76,27 +43,11 @@ cond.end: ; preds = %entry, %cond.true define signext i16 @test3(i16 signext %A) { -; BMI-LABEL: @test3( -; BMI-NEXT: entry: -; BMI-NEXT: [[TOBOOL:%.*]] = icmp eq i16 [[A:%.*]], 0 -; BMI-NEXT: [[TMP0:%.*]] = tail call i16 @llvm.ctlz.i16(i16 [[A]], i1 true) -; BMI-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i16 16, i16 [[TMP0]] -; BMI-NEXT: ret i16 [[COND]] -; -; LZCNT-LABEL: @test3( -; LZCNT-NEXT: entry: -; LZCNT-NEXT: [[TOBOOL:%.*]] = icmp eq i16 [[A:%.*]], 0 -; LZCNT-NEXT: [[TMP0:%.*]] = tail call i16 @llvm.ctlz.i16(i16 [[A]], i1 true) -; LZCNT-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[TOBOOL]], i16 16, i16 [[TMP0]] -; LZCNT-NEXT: ret i16 [[SPEC_SELECT]] -; -; GENERIC-LABEL: @test3( -; GENERIC-NEXT: entry: -; GENERIC-NEXT: [[TOBOOL:%.*]] = icmp eq i16 [[A:%.*]], 0 -; GENERIC-NEXT: [[TMP0:%.*]] = tail call i16 @llvm.ctlz.i16(i16 [[A]], i1 true) -; GENERIC-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i16 16, i16 [[TMP0]] -; GENERIC-NEXT: ret i16 [[COND]] -; +; ALL-LABEL: @test3( +; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i16 %A, 0 +; ALL: [[CTLZ:%[A-Za-z0-9]+]] = tail call i16 @llvm.ctlz.i16(i16 %A, i1 true) +; ALL-NEXT: select i1 [[COND]], i16 16, i16 [[CTLZ]] +; ALL: ret entry: %tobool = icmp eq i16 %A, 0 br i1 %tobool, label %cond.end, label %cond.true @@ -112,27 +63,11 @@ cond.end: ; preds = %entry, %cond.true define i64 @test1b(i64 %A) { -; BMI-LABEL: @test1b( -; BMI-NEXT: entry: -; BMI-NEXT: [[TOBOOL:%.*]] = icmp eq i64 [[A:%.*]], 0 -; BMI-NEXT: [[TMP0:%.*]] = tail call i64 @llvm.cttz.i64(i64 [[A]], i1 true) -; BMI-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[TOBOOL]], i64 64, i64 [[TMP0]] -; BMI-NEXT: ret i64 [[SPEC_SELECT]] -; -; LZCNT-LABEL: @test1b( -; LZCNT-NEXT: entry: -; LZCNT-NEXT: [[TOBOOL:%.*]] = icmp eq i64 [[A:%.*]], 0 -; LZCNT-NEXT: [[TMP0:%.*]] = tail call i64 @llvm.cttz.i64(i64 [[A]], i1 true) -; LZCNT-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i64 64, i64 [[TMP0]] -; LZCNT-NEXT: ret i64 [[COND]] -; -; GENERIC-LABEL: @test1b( -; GENERIC-NEXT: entry: -; GENERIC-NEXT: [[TOBOOL:%.*]] = icmp eq i64 [[A:%.*]], 0 -; GENERIC-NEXT: [[TMP0:%.*]] = tail call i64 @llvm.cttz.i64(i64 [[A]], i1 true) -; GENERIC-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i64 64, i64 [[TMP0]] -; GENERIC-NEXT: ret i64 [[COND]] -; +; ALL-LABEL: @test1b( +; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i64 %A, 0 +; ALL: [[CTTZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.cttz.i64(i64 %A, i1 true) +; ALL-NEXT: select i1 [[COND]], i64 64, i64 [[CTTZ]] +; ALL: ret entry: %tobool = icmp eq i64 %A, 0 br i1 %tobool, label %cond.end, label %cond.true @@ -148,27 +83,11 @@ cond.end: ; preds = %entry, %cond.true define i32 @test2b(i32 %A) { -; BMI-LABEL: @test2b( -; BMI-NEXT: entry: -; BMI-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[A:%.*]], 0 -; BMI-NEXT: [[TMP0:%.*]] = tail call i32 @llvm.cttz.i32(i32 [[A]], i1 true) -; BMI-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[TOBOOL]], i32 32, i32 [[TMP0]] -; BMI-NEXT: ret i32 [[SPEC_SELECT]] -; -; LZCNT-LABEL: @test2b( -; LZCNT-NEXT: entry: -; LZCNT-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[A:%.*]], 0 -; LZCNT-NEXT: [[TMP0:%.*]] = tail call i32 @llvm.cttz.i32(i32 [[A]], i1 true) -; LZCNT-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i32 32, i32 [[TMP0]] -; LZCNT-NEXT: ret i32 [[COND]] -; -; GENERIC-LABEL: @test2b( -; GENERIC-NEXT: entry: -; GENERIC-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[A:%.*]], 0 -; GENERIC-NEXT: [[TMP0:%.*]] = tail call i32 @llvm.cttz.i32(i32 [[A]], i1 true) -; GENERIC-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i32 32, i32 [[TMP0]] -; GENERIC-NEXT: ret i32 [[COND]] -; +; ALL-LABEL: @test2b( +; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i32 %A, 0 +; ALL: [[CTTZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.cttz.i32(i32 %A, i1 true) +; ALL-NEXT: select i1 [[COND]], i32 32, i32 [[CTTZ]] +; ALL: ret entry: %tobool = icmp eq i32 %A, 0 br i1 %tobool, label %cond.end, label %cond.true @@ -184,27 +103,11 @@ cond.end: ; preds = %entry, %cond.true define signext i16 @test3b(i16 signext %A) { -; BMI-LABEL: @test3b( -; BMI-NEXT: entry: -; BMI-NEXT: [[TOBOOL:%.*]] = icmp eq i16 [[A:%.*]], 0 -; BMI-NEXT: [[TMP0:%.*]] = tail call i16 @llvm.cttz.i16(i16 [[A]], i1 true) -; BMI-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[TOBOOL]], i16 16, i16 [[TMP0]] -; BMI-NEXT: ret i16 [[SPEC_SELECT]] -; -; LZCNT-LABEL: @test3b( -; LZCNT-NEXT: entry: -; LZCNT-NEXT: [[TOBOOL:%.*]] = icmp eq i16 [[A:%.*]], 0 -; LZCNT-NEXT: [[TMP0:%.*]] = tail call i16 @llvm.cttz.i16(i16 [[A]], i1 true) -; LZCNT-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i16 16, i16 [[TMP0]] -; LZCNT-NEXT: ret i16 [[COND]] -; -; GENERIC-LABEL: @test3b( -; GENERIC-NEXT: entry: -; GENERIC-NEXT: [[TOBOOL:%.*]] = icmp eq i16 [[A:%.*]], 0 -; GENERIC-NEXT: [[TMP0:%.*]] = tail call i16 @llvm.cttz.i16(i16 [[A]], i1 true) -; GENERIC-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i16 16, i16 [[TMP0]] -; GENERIC-NEXT: ret i16 [[COND]] -; +; ALL-LABEL: @test3b( +; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i16 %A, 0 +; ALL: [[CTTZ:%[A-Za-z0-9]+]] = tail call i16 @llvm.cttz.i16(i16 %A, i1 true) +; ALL-NEXT: select i1 [[COND]], i16 16, i16 [[CTTZ]] +; ALL: ret entry: %tobool = icmp eq i16 %A, 0 br i1 %tobool, label %cond.end, label %cond.true @@ -223,38 +126,14 @@ cond.end: ; preds = %entry, %cond.true ; for the target. define i64 @test1e(i32 %x) { -; BMI-LABEL: @test1e( -; BMI-NEXT: entry: -; BMI-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[X:%.*]], 0 -; BMI-NEXT: [[TMP0:%.*]] = tail call i32 @llvm.cttz.i32(i32 [[X]], i1 true) -; BMI-NEXT: [[PHITMP2:%.*]] = zext i32 [[TMP0]] to i64 -; BMI-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i64 32, i64 [[PHITMP2]] -; BMI-NEXT: ret i64 [[COND]] -; -; LZCNT-LABEL: @test1e( -; LZCNT-NEXT: entry: -; LZCNT-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[X:%.*]], 0 -; LZCNT-NEXT: br i1 [[TOBOOL]], label [[COND_END:%.*]], label [[COND_TRUE:%.*]] -; LZCNT: cond.true: -; LZCNT-NEXT: [[TMP0:%.*]] = tail call i32 @llvm.cttz.i32(i32 [[X]], i1 true) -; LZCNT-NEXT: [[PHITMP2:%.*]] = zext i32 [[TMP0]] to i64 -; LZCNT-NEXT: br label [[COND_END]] -; LZCNT: cond.end: -; LZCNT-NEXT: [[COND:%.*]] = phi i64 [ [[PHITMP2]], [[COND_TRUE]] ], [ 32, [[ENTRY:%.*]] ] -; LZCNT-NEXT: ret i64 [[COND]] -; -; GENERIC-LABEL: @test1e( -; GENERIC-NEXT: entry: -; GENERIC-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[X:%.*]], 0 -; GENERIC-NEXT: br i1 [[TOBOOL]], label [[COND_END:%.*]], label [[COND_TRUE:%.*]] -; GENERIC: cond.true: -; GENERIC-NEXT: [[TMP0:%.*]] = tail call i32 @llvm.cttz.i32(i32 [[X]], i1 true) -; GENERIC-NEXT: [[PHITMP2:%.*]] = zext i32 [[TMP0]] to i64 -; GENERIC-NEXT: br label [[COND_END]] -; GENERIC: cond.end: -; GENERIC-NEXT: [[COND:%.*]] = phi i64 [ [[PHITMP2]], [[COND_TRUE]] ], [ 32, [[ENTRY:%.*]] ] -; GENERIC-NEXT: ret i64 [[COND]] -; +; ALL-LABEL: @test1e( +; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i32 %x, 0 +; ALL: [[CTTZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.cttz.i32(i32 %x, i1 true) +; ALL: [[ZEXT:%[A-Za-z0-9]+]] = zext i32 [[CTTZ]] to i64 +; BMI-NEXT: select i1 [[COND]], i64 32, i64 [[ZEXT]] +; LZCNT-NOT: select +; GENERIC-NOT: select +; ALL: ret entry: %tobool = icmp eq i32 %x, 0 br i1 %tobool, label %cond.end, label %cond.true @@ -270,38 +149,14 @@ cond.end: ; preds = %entry, %cond.true } define i32 @test2e(i64 %x) { -; BMI-LABEL: @test2e( -; BMI-NEXT: entry: -; BMI-NEXT: [[TOBOOL:%.*]] = icmp eq i64 [[X:%.*]], 0 -; BMI-NEXT: [[TMP0:%.*]] = tail call i64 @llvm.cttz.i64(i64 [[X]], i1 true) -; BMI-NEXT: [[CAST:%.*]] = trunc i64 [[TMP0]] to i32 -; BMI-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i32 64, i32 [[CAST]] -; BMI-NEXT: ret i32 [[COND]] -; -; LZCNT-LABEL: @test2e( -; LZCNT-NEXT: entry: -; LZCNT-NEXT: [[TOBOOL:%.*]] = icmp eq i64 [[X:%.*]], 0 -; LZCNT-NEXT: br i1 [[TOBOOL]], label [[COND_END:%.*]], label [[COND_TRUE:%.*]] -; LZCNT: cond.true: -; LZCNT-NEXT: [[TMP0:%.*]] = tail call i64 @llvm.cttz.i64(i64 [[X]], i1 true) -; LZCNT-NEXT: [[CAST:%.*]] = trunc i64 [[TMP0]] to i32 -; LZCNT-NEXT: br label [[COND_END]] -; LZCNT: cond.end: -; LZCNT-NEXT: [[COND:%.*]] = phi i32 [ [[CAST]], [[COND_TRUE]] ], [ 64, [[ENTRY:%.*]] ] -; LZCNT-NEXT: ret i32 [[COND]] -; -; GENERIC-LABEL: @test2e( -; GENERIC-NEXT: entry: -; GENERIC-NEXT: [[TOBOOL:%.*]] = icmp eq i64 [[X:%.*]], 0 -; GENERIC-NEXT: br i1 [[TOBOOL]], label [[COND_END:%.*]], label [[COND_TRUE:%.*]] -; GENERIC: cond.true: -; GENERIC-NEXT: [[TMP0:%.*]] = tail call i64 @llvm.cttz.i64(i64 [[X]], i1 true) -; GENERIC-NEXT: [[CAST:%.*]] = trunc i64 [[TMP0]] to i32 -; GENERIC-NEXT: br label [[COND_END]] -; GENERIC: cond.end: -; GENERIC-NEXT: [[COND:%.*]] = phi i32 [ [[CAST]], [[COND_TRUE]] ], [ 64, [[ENTRY:%.*]] ] -; GENERIC-NEXT: ret i32 [[COND]] -; +; ALL-LABEL: @test2e( +; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i64 %x, 0 +; ALL: [[CTTZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.cttz.i64(i64 %x, i1 true) +; ALL: [[TRUNC:%[A-Za-z0-9]+]] = trunc i64 [[CTTZ]] to i32 +; BMI-NEXT: select i1 [[COND]], i32 64, i32 [[TRUNC]] +; LZCNT-NOT: select +; GENERIC-NOT: select +; ALL: ret entry: %tobool = icmp eq i64 %x, 0 br i1 %tobool, label %cond.end, label %cond.true @@ -317,38 +172,14 @@ cond.end: ; preds = %entry, %cond.true } define i64 @test3e(i32 %x) { -; BMI-LABEL: @test3e( -; BMI-NEXT: entry: -; BMI-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[X:%.*]], 0 -; BMI-NEXT: br i1 [[TOBOOL]], label [[COND_END:%.*]], label [[COND_TRUE:%.*]] -; BMI: cond.true: -; BMI-NEXT: [[TMP0:%.*]] = tail call i32 @llvm.ctlz.i32(i32 [[X]], i1 true) -; BMI-NEXT: [[PHITMP2:%.*]] = zext i32 [[TMP0]] to i64 -; BMI-NEXT: br label [[COND_END]] -; BMI: cond.end: -; BMI-NEXT: [[COND:%.*]] = phi i64 [ [[PHITMP2]], [[COND_TRUE]] ], [ 32, [[ENTRY:%.*]] ] -; BMI-NEXT: ret i64 [[COND]] -; -; LZCNT-LABEL: @test3e( -; LZCNT-NEXT: entry: -; LZCNT-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[X:%.*]], 0 -; LZCNT-NEXT: [[TMP0:%.*]] = tail call i32 @llvm.ctlz.i32(i32 [[X]], i1 true) -; LZCNT-NEXT: [[PHITMP2:%.*]] = zext i32 [[TMP0]] to i64 -; LZCNT-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i64 32, i64 [[PHITMP2]] -; LZCNT-NEXT: ret i64 [[COND]] -; -; GENERIC-LABEL: @test3e( -; GENERIC-NEXT: entry: -; GENERIC-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[X:%.*]], 0 -; GENERIC-NEXT: br i1 [[TOBOOL]], label [[COND_END:%.*]], label [[COND_TRUE:%.*]] -; GENERIC: cond.true: -; GENERIC-NEXT: [[TMP0:%.*]] = tail call i32 @llvm.ctlz.i32(i32 [[X]], i1 true) -; GENERIC-NEXT: [[PHITMP2:%.*]] = zext i32 [[TMP0]] to i64 -; GENERIC-NEXT: br label [[COND_END]] -; GENERIC: cond.end: -; GENERIC-NEXT: [[COND:%.*]] = phi i64 [ [[PHITMP2]], [[COND_TRUE]] ], [ 32, [[ENTRY:%.*]] ] -; GENERIC-NEXT: ret i64 [[COND]] -; +; ALL-LABEL: @test3e( +; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i32 %x, 0 +; ALL: [[CTLZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true) +; ALL: [[ZEXT:%[A-Za-z0-9]+]] = zext i32 [[CTLZ]] to i64 +; LZCNT-NEXT: select i1 [[COND]], i64 32, i64 [[ZEXT]] +; BMI-NOT: select +; GENERIC-NOT: select +; ALL: ret entry: %tobool = icmp eq i32 %x, 0 br i1 %tobool, label %cond.end, label %cond.true @@ -364,38 +195,14 @@ cond.end: ; preds = %entry, %cond.true } define i32 @test4e(i64 %x) { -; BMI-LABEL: @test4e( -; BMI-NEXT: entry: -; BMI-NEXT: [[TOBOOL:%.*]] = icmp eq i64 [[X:%.*]], 0 -; BMI-NEXT: br i1 [[TOBOOL]], label [[COND_END:%.*]], label [[COND_TRUE:%.*]] -; BMI: cond.true: -; BMI-NEXT: [[TMP0:%.*]] = tail call i64 @llvm.ctlz.i64(i64 [[X]], i1 true) -; BMI-NEXT: [[CAST:%.*]] = trunc i64 [[TMP0]] to i32 -; BMI-NEXT: br label [[COND_END]] -; BMI: cond.end: -; BMI-NEXT: [[COND:%.*]] = phi i32 [ [[CAST]], [[COND_TRUE]] ], [ 64, [[ENTRY:%.*]] ] -; BMI-NEXT: ret i32 [[COND]] -; -; LZCNT-LABEL: @test4e( -; LZCNT-NEXT: entry: -; LZCNT-NEXT: [[TOBOOL:%.*]] = icmp eq i64 [[X:%.*]], 0 -; LZCNT-NEXT: [[TMP0:%.*]] = tail call i64 @llvm.ctlz.i64(i64 [[X]], i1 true) -; LZCNT-NEXT: [[CAST:%.*]] = trunc i64 [[TMP0]] to i32 -; LZCNT-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i32 64, i32 [[CAST]] -; LZCNT-NEXT: ret i32 [[COND]] -; -; GENERIC-LABEL: @test4e( -; GENERIC-NEXT: entry: -; GENERIC-NEXT: [[TOBOOL:%.*]] = icmp eq i64 [[X:%.*]], 0 -; GENERIC-NEXT: br i1 [[TOBOOL]], label [[COND_END:%.*]], label [[COND_TRUE:%.*]] -; GENERIC: cond.true: -; GENERIC-NEXT: [[TMP0:%.*]] = tail call i64 @llvm.ctlz.i64(i64 [[X]], i1 true) -; GENERIC-NEXT: [[CAST:%.*]] = trunc i64 [[TMP0]] to i32 -; GENERIC-NEXT: br label [[COND_END]] -; GENERIC: cond.end: -; GENERIC-NEXT: [[COND:%.*]] = phi i32 [ [[CAST]], [[COND_TRUE]] ], [ 64, [[ENTRY:%.*]] ] -; GENERIC-NEXT: ret i32 [[COND]] -; +; ALL-LABEL: @test4e( +; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i64 %x, 0 +; ALL: [[CTLZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.ctlz.i64(i64 %x, i1 true) +; ALL: [[TRUNC:%[A-Za-z0-9]+]] = trunc i64 [[CTLZ]] to i32 +; LZCNT-NEXT: select i1 [[COND]], i32 64, i32 [[TRUNC]] +; BMI-NOT: select +; GENERIC-NOT: select +; ALL: ret entry: %tobool = icmp eq i64 %x, 0 br i1 %tobool, label %cond.end, label %cond.true @@ -411,38 +218,14 @@ cond.end: ; preds = %entry, %cond.true } define i16 @test5e(i64 %x) { -; BMI-LABEL: @test5e( -; BMI-NEXT: entry: -; BMI-NEXT: [[TOBOOL:%.*]] = icmp eq i64 [[X:%.*]], 0 -; BMI-NEXT: br i1 [[TOBOOL]], label [[COND_END:%.*]], label [[COND_TRUE:%.*]] -; BMI: cond.true: -; BMI-NEXT: [[TMP0:%.*]] = tail call i64 @llvm.ctlz.i64(i64 [[X]], i1 true) -; BMI-NEXT: [[CAST:%.*]] = trunc i64 [[TMP0]] to i16 -; BMI-NEXT: br label [[COND_END]] -; BMI: cond.end: -; BMI-NEXT: [[COND:%.*]] = phi i16 [ [[CAST]], [[COND_TRUE]] ], [ 64, [[ENTRY:%.*]] ] -; BMI-NEXT: ret i16 [[COND]] -; -; LZCNT-LABEL: @test5e( -; LZCNT-NEXT: entry: -; LZCNT-NEXT: [[TOBOOL:%.*]] = icmp eq i64 [[X:%.*]], 0 -; LZCNT-NEXT: [[TMP0:%.*]] = tail call i64 @llvm.ctlz.i64(i64 [[X]], i1 true) -; LZCNT-NEXT: [[CAST:%.*]] = trunc i64 [[TMP0]] to i16 -; LZCNT-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i16 64, i16 [[CAST]] -; LZCNT-NEXT: ret i16 [[COND]] -; -; GENERIC-LABEL: @test5e( -; GENERIC-NEXT: entry: -; GENERIC-NEXT: [[TOBOOL:%.*]] = icmp eq i64 [[X:%.*]], 0 -; GENERIC-NEXT: br i1 [[TOBOOL]], label [[COND_END:%.*]], label [[COND_TRUE:%.*]] -; GENERIC: cond.true: -; GENERIC-NEXT: [[TMP0:%.*]] = tail call i64 @llvm.ctlz.i64(i64 [[X]], i1 true) -; GENERIC-NEXT: [[CAST:%.*]] = trunc i64 [[TMP0]] to i16 -; GENERIC-NEXT: br label [[COND_END]] -; GENERIC: cond.end: -; GENERIC-NEXT: [[COND:%.*]] = phi i16 [ [[CAST]], [[COND_TRUE]] ], [ 64, [[ENTRY:%.*]] ] -; GENERIC-NEXT: ret i16 [[COND]] -; +; ALL-LABEL: @test5e( +; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i64 %x, 0 +; ALL: [[CTLZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.ctlz.i64(i64 %x, i1 true) +; ALL: [[TRUNC:%[A-Za-z0-9]+]] = trunc i64 [[CTLZ]] to i16 +; LZCNT-NEXT: select i1 [[COND]], i16 64, i16 [[TRUNC]] +; BMI-NOT: select +; GENERIC-NOT: select +; ALL: ret entry: %tobool = icmp eq i64 %x, 0 br i1 %tobool, label %cond.end, label %cond.true @@ -458,38 +241,14 @@ cond.end: ; preds = %entry, %cond.true } define i16 @test6e(i32 %x) { -; BMI-LABEL: @test6e( -; BMI-NEXT: entry: -; BMI-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[X:%.*]], 0 -; BMI-NEXT: br i1 [[TOBOOL]], label [[COND_END:%.*]], label [[COND_TRUE:%.*]] -; BMI: cond.true: -; BMI-NEXT: [[TMP0:%.*]] = tail call i32 @llvm.ctlz.i32(i32 [[X]], i1 true) -; BMI-NEXT: [[CAST:%.*]] = trunc i32 [[TMP0]] to i16 -; BMI-NEXT: br label [[COND_END]] -; BMI: cond.end: -; BMI-NEXT: [[COND:%.*]] = phi i16 [ [[CAST]], [[COND_TRUE]] ], [ 32, [[ENTRY:%.*]] ] -; BMI-NEXT: ret i16 [[COND]] -; -; LZCNT-LABEL: @test6e( -; LZCNT-NEXT: entry: -; LZCNT-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[X:%.*]], 0 -; LZCNT-NEXT: [[TMP0:%.*]] = tail call i32 @llvm.ctlz.i32(i32 [[X]], i1 true) -; LZCNT-NEXT: [[CAST:%.*]] = trunc i32 [[TMP0]] to i16 -; LZCNT-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i16 32, i16 [[CAST]] -; LZCNT-NEXT: ret i16 [[COND]] -; -; GENERIC-LABEL: @test6e( -; GENERIC-NEXT: entry: -; GENERIC-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[X:%.*]], 0 -; GENERIC-NEXT: br i1 [[TOBOOL]], label [[COND_END:%.*]], label [[COND_TRUE:%.*]] -; GENERIC: cond.true: -; GENERIC-NEXT: [[TMP0:%.*]] = tail call i32 @llvm.ctlz.i32(i32 [[X]], i1 true) -; GENERIC-NEXT: [[CAST:%.*]] = trunc i32 [[TMP0]] to i16 -; GENERIC-NEXT: br label [[COND_END]] -; GENERIC: cond.end: -; GENERIC-NEXT: [[COND:%.*]] = phi i16 [ [[CAST]], [[COND_TRUE]] ], [ 32, [[ENTRY:%.*]] ] -; GENERIC-NEXT: ret i16 [[COND]] -; +; ALL-LABEL: @test6e( +; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i32 %x, 0 +; ALL: [[CTLZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true) +; ALL: [[TRUNC:%[A-Za-z0-9]+]] = trunc i32 [[CTLZ]] to i16 +; LZCNT-NEXT: select i1 [[COND]], i16 32, i16 [[TRUNC]] +; BMI-NOT: select +; GENERIC-NOT: select +; ALL: ret entry: %tobool = icmp eq i32 %x, 0 br i1 %tobool, label %cond.end, label %cond.true @@ -505,38 +264,14 @@ cond.end: ; preds = %entry, %cond.true } define i16 @test7e(i64 %x) { -; BMI-LABEL: @test7e( -; BMI-NEXT: entry: -; BMI-NEXT: [[TOBOOL:%.*]] = icmp eq i64 [[X:%.*]], 0 -; BMI-NEXT: [[TMP0:%.*]] = tail call i64 @llvm.cttz.i64(i64 [[X]], i1 true) -; BMI-NEXT: [[CAST:%.*]] = trunc i64 [[TMP0]] to i16 -; BMI-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i16 64, i16 [[CAST]] -; BMI-NEXT: ret i16 [[COND]] -; -; LZCNT-LABEL: @test7e( -; LZCNT-NEXT: entry: -; LZCNT-NEXT: [[TOBOOL:%.*]] = icmp eq i64 [[X:%.*]], 0 -; LZCNT-NEXT: br i1 [[TOBOOL]], label [[COND_END:%.*]], label [[COND_TRUE:%.*]] -; LZCNT: cond.true: -; LZCNT-NEXT: [[TMP0:%.*]] = tail call i64 @llvm.cttz.i64(i64 [[X]], i1 true) -; LZCNT-NEXT: [[CAST:%.*]] = trunc i64 [[TMP0]] to i16 -; LZCNT-NEXT: br label [[COND_END]] -; LZCNT: cond.end: -; LZCNT-NEXT: [[COND:%.*]] = phi i16 [ [[CAST]], [[COND_TRUE]] ], [ 64, [[ENTRY:%.*]] ] -; LZCNT-NEXT: ret i16 [[COND]] -; -; GENERIC-LABEL: @test7e( -; GENERIC-NEXT: entry: -; GENERIC-NEXT: [[TOBOOL:%.*]] = icmp eq i64 [[X:%.*]], 0 -; GENERIC-NEXT: br i1 [[TOBOOL]], label [[COND_END:%.*]], label [[COND_TRUE:%.*]] -; GENERIC: cond.true: -; GENERIC-NEXT: [[TMP0:%.*]] = tail call i64 @llvm.cttz.i64(i64 [[X]], i1 true) -; GENERIC-NEXT: [[CAST:%.*]] = trunc i64 [[TMP0]] to i16 -; GENERIC-NEXT: br label [[COND_END]] -; GENERIC: cond.end: -; GENERIC-NEXT: [[COND:%.*]] = phi i16 [ [[CAST]], [[COND_TRUE]] ], [ 64, [[ENTRY:%.*]] ] -; GENERIC-NEXT: ret i16 [[COND]] -; +; ALL-LABEL: @test7e( +; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i64 %x, 0 +; ALL: [[CTTZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.cttz.i64(i64 %x, i1 true) +; ALL: [[TRUNC:%[A-Za-z0-9]+]] = trunc i64 [[CTTZ]] to i16 +; BMI-NEXT: select i1 [[COND]], i16 64, i16 [[TRUNC]] +; LZCNT-NOT: select +; GENERIC-NOT: select +; ALL: ret entry: %tobool = icmp eq i64 %x, 0 br i1 %tobool, label %cond.end, label %cond.true @@ -552,38 +287,14 @@ cond.end: ; preds = %entry, %cond.true } define i16 @test8e(i32 %x) { -; BMI-LABEL: @test8e( -; BMI-NEXT: entry: -; BMI-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[X:%.*]], 0 -; BMI-NEXT: [[TMP0:%.*]] = tail call i32 @llvm.cttz.i32(i32 [[X]], i1 true) -; BMI-NEXT: [[CAST:%.*]] = trunc i32 [[TMP0]] to i16 -; BMI-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i16 32, i16 [[CAST]] -; BMI-NEXT: ret i16 [[COND]] -; -; LZCNT-LABEL: @test8e( -; LZCNT-NEXT: entry: -; LZCNT-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[X:%.*]], 0 -; LZCNT-NEXT: br i1 [[TOBOOL]], label [[COND_END:%.*]], label [[COND_TRUE:%.*]] -; LZCNT: cond.true: -; LZCNT-NEXT: [[TMP0:%.*]] = tail call i32 @llvm.cttz.i32(i32 [[X]], i1 true) -; LZCNT-NEXT: [[CAST:%.*]] = trunc i32 [[TMP0]] to i16 -; LZCNT-NEXT: br label [[COND_END]] -; LZCNT: cond.end: -; LZCNT-NEXT: [[COND:%.*]] = phi i16 [ [[CAST]], [[COND_TRUE]] ], [ 32, [[ENTRY:%.*]] ] -; LZCNT-NEXT: ret i16 [[COND]] -; -; GENERIC-LABEL: @test8e( -; GENERIC-NEXT: entry: -; GENERIC-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[X:%.*]], 0 -; GENERIC-NEXT: br i1 [[TOBOOL]], label [[COND_END:%.*]], label [[COND_TRUE:%.*]] -; GENERIC: cond.true: -; GENERIC-NEXT: [[TMP0:%.*]] = tail call i32 @llvm.cttz.i32(i32 [[X]], i1 true) -; GENERIC-NEXT: [[CAST:%.*]] = trunc i32 [[TMP0]] to i16 -; GENERIC-NEXT: br label [[COND_END]] -; GENERIC: cond.end: -; GENERIC-NEXT: [[COND:%.*]] = phi i16 [ [[CAST]], [[COND_TRUE]] ], [ 32, [[ENTRY:%.*]] ] -; GENERIC-NEXT: ret i16 [[COND]] -; +; ALL-LABEL: @test8e( +; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i32 %x, 0 +; ALL: [[CTTZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.cttz.i32(i32 %x, i1 true) +; ALL: [[TRUNC:%[A-Za-z0-9]+]] = trunc i32 [[CTTZ]] to i16 +; BMI-NEXT: select i1 [[COND]], i16 32, i16 [[TRUNC]] +; LZCNT-NOT: select +; GENERIC-NOT: select +; ALL: ret entry: %tobool = icmp eq i32 %x, 0 br i1 %tobool, label %cond.end, label %cond.true diff --git a/llvm/test/Transforms/SimplifyCFG/X86/switch-covered-bug.ll b/llvm/test/Transforms/SimplifyCFG/X86/switch-covered-bug.ll index b7bf8054a6f..c42568ffa93 100644 --- a/llvm/test/Transforms/SimplifyCFG/X86/switch-covered-bug.ll +++ b/llvm/test/Transforms/SimplifyCFG/X86/switch-covered-bug.ll @@ -1,4 +1,3 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt -S -simplifycfg -switch-to-lookup < %s -mtriple=x86_64-apple-darwin12.0.0 | FileCheck %s ; RUN: opt -S -passes='simplify-cfg<switch-to-lookup>' < %s -mtriple=x86_64-apple-darwin12.0.0 | FileCheck %s @@ -6,24 +5,25 @@ target datalayout = "e-p:64:64:64-S128-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f16:16:16-f32:32:32-f64:64:64-f128:128:128-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" target triple = "x86_64-apple-darwin12.0.0" +; When we have a covered lookup table, make sure we don't delete PHINodes that +; are cached in PHIs. +; CHECK-LABEL: @test +; CHECK: entry: +; CHECK-NEXT: sub i3 %arg, -4 +; CHECK-NEXT: zext i3 %switch.tableidx to i4 +; CHECK-NEXT: getelementptr inbounds [8 x i64], [8 x i64]* @switch.table.test, i32 0, i4 %switch.tableidx.zext +; CHECK-NEXT: load i64, i64* %switch.gep +; CHECK-NEXT: add i64 +; CHECK-NEXT: ret i64 define i64 @test(i3 %arg) { -; CHECK-LABEL: @test( -; CHECK-NEXT: entry: -; CHECK-NEXT: [[SWITCH_TABLEIDX:%.*]] = sub i3 [[ARG:%.*]], -4 -; CHECK-NEXT: [[SWITCH_TABLEIDX_ZEXT:%.*]] = zext i3 [[SWITCH_TABLEIDX]] to i4 -; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [8 x i64], [8 x i64]* @switch.table.test, i32 0, i4 [[SWITCH_TABLEIDX_ZEXT]] -; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i64, i64* [[SWITCH_GEP]] -; CHECK-NEXT: [[V3:%.*]] = add i64 [[SWITCH_LOAD]], 0 -; CHECK-NEXT: ret i64 [[V3]] -; entry: switch i3 %arg, label %Default [ - i3 -2, label %Label6 - i3 1, label %Label1 - i3 2, label %Label2 - i3 3, label %Label3 - i3 -4, label %Label4 - i3 -3, label %Label5 + i3 -2, label %Label6 + i3 1, label %Label1 + i3 2, label %Label2 + i3 3, label %Label3 + i3 -4, label %Label4 + i3 -3, label %Label5 ] Default: diff --git a/llvm/test/Transforms/SimplifyCFG/X86/switch-table-bug.ll b/llvm/test/Transforms/SimplifyCFG/X86/switch-table-bug.ll index e50a913f9e5..0b9d6ebe825 100644 --- a/llvm/test/Transforms/SimplifyCFG/X86/switch-table-bug.ll +++ b/llvm/test/Transforms/SimplifyCFG/X86/switch-table-bug.ll @@ -1,4 +1,3 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt -S -simplifycfg -switch-to-lookup < %s -mtriple=x86_64-apple-darwin12.0.0 | FileCheck %s ; RUN: opt -S -passes='simplify-cfg<switch-to-lookup>' < %s -mtriple=x86_64-apple-darwin12.0.0 | FileCheck %s @@ -6,21 +5,21 @@ target datalayout = "e-p:64:64:64-S128-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f16:16:16-f32:32:32-f64:64:64-f128:128:128-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" target triple = "x86_64-apple-darwin12.0.0" +; When tableindex can't fit into i2, we should extend the type to i3. +; CHECK-LABEL: @_TFO6reduce1E5toRawfS0_FT_Si +; CHECK: entry: +; CHECK-NEXT: sub i2 %0, -2 +; CHECK-NEXT: zext i2 %switch.tableidx to i3 +; CHECK-NEXT: getelementptr inbounds [4 x i64], [4 x i64]* @switch.table._TFO6reduce1E5toRawfS0_FT_Si, i32 0, i3 %switch.tableidx.zext +; CHECK-NEXT: load i64, i64* %switch.gep +; CHECK-NEXT: ret i64 %switch.load define i64 @_TFO6reduce1E5toRawfS0_FT_Si(i2) { -; CHECK-LABEL: @_TFO6reduce1E5toRawfS0_FT_Si( -; CHECK-NEXT: entry: -; CHECK-NEXT: [[SWITCH_TABLEIDX:%.*]] = sub i2 [[TMP0:%.*]], -2 -; CHECK-NEXT: [[SWITCH_TABLEIDX_ZEXT:%.*]] = zext i2 [[SWITCH_TABLEIDX]] to i3 -; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [4 x i64], [4 x i64]* @switch.table._TFO6reduce1E5toRawfS0_FT_Si, i32 0, i3 [[SWITCH_TABLEIDX_ZEXT]] -; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i64, i64* [[SWITCH_GEP]] -; CHECK-NEXT: ret i64 [[SWITCH_LOAD]] -; entry: switch i2 %0, label %1 [ - i2 0, label %2 - i2 1, label %3 - i2 -2, label %4 - i2 -1, label %5 + i2 0, label %2 + i2 1, label %3 + i2 -2, label %4 + i2 -1, label %5 ] ; <label>:1 ; preds = %entry diff --git a/llvm/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll b/llvm/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll index c77438974b2..3128ce4afa6 100644 --- a/llvm/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll +++ b/llvm/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll @@ -1,4 +1,3 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt < %s -simplifycfg -switch-to-lookup=true -keep-loops=false -S -mtriple=x86_64-unknown-linux-gnu | FileCheck %s ; RUN: opt < %s -passes='simplify-cfg<no-keep-loops;switch-to-lookup>' -S -mtriple=x86_64-unknown-linux-gnu | FileCheck %s target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" @@ -34,27 +33,15 @@ target triple = "x86_64-unknown-linux-gnu" ; so we return early, directly from the lookup bb. define i32 @f(i32 %c) { -; CHECK-LABEL: @f( -; CHECK-NEXT: entry: -; CHECK-NEXT: [[SWITCH_TABLEIDX:%.*]] = sub i32 [[C:%.*]], 42 -; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i32 [[SWITCH_TABLEIDX]], 7 -; CHECK-NEXT: br i1 [[TMP0]], label [[SWITCH_LOOKUP:%.*]], label [[RETURN:%.*]] -; CHECK: switch.lookup: -; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [7 x i32], [7 x i32]* @switch.table.f, i32 0, i32 [[SWITCH_TABLEIDX]] -; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i32, i32* [[SWITCH_GEP]] -; CHECK-NEXT: ret i32 [[SWITCH_LOAD]] -; CHECK: return: -; CHECK-NEXT: ret i32 15 -; entry: switch i32 %c, label %sw.default [ - i32 42, label %return - i32 43, label %sw.bb1 - i32 44, label %sw.bb2 - i32 45, label %sw.bb3 - i32 46, label %sw.bb4 - i32 47, label %sw.bb5 - i32 48, label %sw.bb6 + i32 42, label %return + i32 43, label %sw.bb1 + i32 44, label %sw.bb2 + i32 45, label %sw.bb3 + i32 46, label %sw.bb4 + i32 47, label %sw.bb5 + i32 48, label %sw.bb6 ] sw.bb1: br label %return @@ -68,34 +55,33 @@ return: %retval.0 = phi i32 [ 15, %sw.default ], [ 1, %sw.bb6 ], [ 62, %sw.bb5 ], [ 27, %sw.bb4 ], [ -1, %sw.bb3 ], [ 0, %sw.bb2 ], [ 123, %sw.bb1 ], [ 55, %entry ] ret i32 %retval.0 +; CHECK-LABEL: @f( +; CHECK: entry: +; CHECK-NEXT: %switch.tableidx = sub i32 %c, 42 +; CHECK-NEXT: %0 = icmp ult i32 %switch.tableidx, 7 +; CHECK-NEXT: br i1 %0, label %switch.lookup, label %return +; CHECK: switch.lookup: +; CHECK-NEXT: %switch.gep = getelementptr inbounds [7 x i32], [7 x i32]* @switch.table.f, i32 0, i32 %switch.tableidx +; CHECK-NEXT: %switch.load = load i32, i32* %switch.gep +; CHECK-NEXT: ret i32 %switch.load +; CHECK: return: +; CHECK-NEXT: ret i32 15 } ; Same thing, but with i8's define i8 @char(i32 %c) { -; CHECK-LABEL: @char( -; CHECK-NEXT: entry: -; CHECK-NEXT: [[SWITCH_TABLEIDX:%.*]] = sub i32 [[C:%.*]], 42 -; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i32 [[SWITCH_TABLEIDX]], 9 -; CHECK-NEXT: br i1 [[TMP0]], label [[SWITCH_LOOKUP:%.*]], label [[RETURN:%.*]] -; CHECK: switch.lookup: -; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [9 x i8], [9 x i8]* @switch.table.char, i32 0, i32 [[SWITCH_TABLEIDX]] -; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i8, i8* [[SWITCH_GEP]] -; CHECK-NEXT: ret i8 [[SWITCH_LOAD]] -; CHECK: return: -; CHECK-NEXT: ret i8 15 -; entry: switch i32 %c, label %sw.default [ - i32 42, label %return - i32 43, label %sw.bb1 - i32 44, label %sw.bb2 - i32 45, label %sw.bb3 - i32 46, label %sw.bb4 - i32 47, label %sw.bb5 - i32 48, label %sw.bb6 - i32 49, label %sw.bb7 - i32 50, label %sw.bb8 + i32 42, label %return + i32 43, label %sw.bb1 + i32 44, label %sw.bb2 + i32 45, label %sw.bb3 + i32 46, label %sw.bb4 + i32 47, label %sw.bb5 + i32 48, label %sw.bb6 + i32 49, label %sw.bb7 + i32 50, label %sw.bb8 ] sw.bb1: br label %return @@ -111,35 +97,29 @@ return: %retval.0 = phi i8 [ 15, %sw.default ], [ 84, %sw.bb8 ], [ 33, %sw.bb7 ], [ 1, %sw.bb6 ], [ 62, %sw.bb5 ], [ 27, %sw.bb4 ], [ -1, %sw.bb3 ], [ 0, %sw.bb2 ], [ 123, %sw.bb1 ], [ 55, %entry ] ret i8 %retval.0 +; CHECK-LABEL: @char( +; CHECK: entry: +; CHECK-NEXT: %switch.tableidx = sub i32 %c, 42 +; CHECK-NEXT: %0 = icmp ult i32 %switch.tableidx, 9 +; CHECK-NEXT: br i1 %0, label %switch.lookup, label %return +; CHECK: switch.lookup: +; CHECK-NEXT: %switch.gep = getelementptr inbounds [9 x i8], [9 x i8]* @switch.table.char, i32 0, i32 %switch.tableidx +; CHECK-NEXT: %switch.load = load i8, i8* %switch.gep +; CHECK-NEXT: ret i8 %switch.load +; CHECK: return: +; CHECK-NEXT: ret i8 15 } ; A switch used to initialize two variables, an i8 and a float. declare void @dummy(i8 signext, float) define void @h(i32 %x) { -; CHECK-LABEL: @h( -; CHECK-NEXT: entry: -; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i32 [[X:%.*]], 4 -; CHECK-NEXT: br i1 [[TMP0]], label [[SWITCH_LOOKUP:%.*]], label [[SW_EPILOG:%.*]] -; CHECK: switch.lookup: -; CHECK-NEXT: [[SWITCH_SHIFTAMT:%.*]] = mul i32 [[X]], 8 -; CHECK-NEXT: [[SWITCH_DOWNSHIFT:%.*]] = lshr i32 89655594, [[SWITCH_SHIFTAMT]] -; CHECK-NEXT: [[SWITCH_MASKED:%.*]] = trunc i32 [[SWITCH_DOWNSHIFT]] to i8 -; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [4 x float], [4 x float]* @switch.table.h, i32 0, i32 [[X]] -; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load float, float* [[SWITCH_GEP]] -; CHECK-NEXT: br label [[SW_EPILOG]] -; CHECK: sw.epilog: -; CHECK-NEXT: [[A_0:%.*]] = phi i8 [ [[SWITCH_MASKED]], [[SWITCH_LOOKUP]] ], [ 7, [[ENTRY:%.*]] ] -; CHECK-NEXT: [[B_0:%.*]] = phi float [ [[SWITCH_LOAD]], [[SWITCH_LOOKUP]] ], [ 0x4023FAE140000000, [[ENTRY]] ] -; CHECK-NEXT: call void @dummy(i8 signext [[A_0]], float [[B_0]]) -; CHECK-NEXT: ret void -; entry: switch i32 %x, label %sw.default [ - i32 0, label %sw.epilog - i32 1, label %sw.bb1 - i32 2, label %sw.bb2 - i32 3, label %sw.bb3 + i32 0, label %sw.epilog + i32 1, label %sw.bb1 + i32 2, label %sw.bb2 + i32 3, label %sw.bb3 ] sw.bb1: br label %sw.epilog @@ -153,6 +133,22 @@ sw.epilog: call void @dummy(i8 signext %a.0, float %b.0) ret void +; CHECK-LABEL: @h( +; CHECK: entry: +; CHECK-NEXT: %0 = icmp ult i32 %x, 4 +; CHECK-NEXT: br i1 %0, label %switch.lookup, label %sw.epilog +; CHECK: switch.lookup: +; CHECK-NEXT: %switch.shiftamt = mul i32 %x, 8 +; CHECK-NEXT: %switch.downshift = lshr i32 89655594, %switch.shiftamt +; CHECK-NEXT: %switch.masked = trunc i32 %switch.downshift to i8 +; CHECK-NEXT: %switch.gep = getelementptr inbounds [4 x float], [4 x float]* @switch.table.h, i32 0, i32 %x +; CHECK-NEXT: %switch.load = load float, float* %switch.gep +; CHECK-NEXT: br label %sw.epilog +; CHECK: sw.epilog: +; CHECK-NEXT: %a.0 = phi i8 [ %switch.masked, %switch.lookup ], [ 7, %entry ] +; CHECK-NEXT: %b.0 = phi float [ %switch.load, %switch.lookup ], [ 0x4023FAE140000000, %entry ] +; CHECK-NEXT: call void @dummy(i8 signext %a.0, float %b.0) +; CHECK-NEXT: ret void } @@ -165,23 +161,12 @@ sw.epilog: @.str4 = private unnamed_addr constant [6 x i8] c"error\00", align 1 define i8* @foostring(i32 %x) { -; CHECK-LABEL: @foostring( -; CHECK-NEXT: entry: -; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i32 [[X:%.*]], 4 -; CHECK-NEXT: br i1 [[TMP0]], label [[SWITCH_LOOKUP:%.*]], label [[RETURN:%.*]] -; CHECK: switch.lookup: -; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [4 x i8*], [4 x i8*]* @switch.table.foostring, i32 0, i32 [[X]] -; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i8*, i8** [[SWITCH_GEP]] -; CHECK-NEXT: ret i8* [[SWITCH_LOAD]] -; CHECK: return: -; CHECK-NEXT: ret i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str4, i64 0, i64 0) -; entry: switch i32 %x, label %sw.default [ - i32 0, label %return - i32 1, label %sw.bb1 - i32 2, label %sw.bb2 - i32 3, label %sw.bb3 + i32 0, label %return + i32 1, label %sw.bb1 + i32 2, label %sw.bb2 + i32 3, label %sw.bb3 ] sw.bb1: br label %return @@ -191,35 +176,32 @@ sw.default: br label %return return: %retval.0 = phi i8* [ getelementptr inbounds ([6 x i8], [6 x i8]* @.str4, i64 0, i64 0), %sw.default ], - [ getelementptr inbounds ([4 x i8], [4 x i8]* @.str3, i64 0, i64 0), %sw.bb3 ], - [ getelementptr inbounds ([4 x i8], [4 x i8]* @.str2, i64 0, i64 0), %sw.bb2 ], - [ getelementptr inbounds ([4 x i8], [4 x i8]* @.str1, i64 0, i64 0), %sw.bb1 ], - [ getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), %entry ] + [ getelementptr inbounds ([4 x i8], [4 x i8]* @.str3, i64 0, i64 0), %sw.bb3 ], + [ getelementptr inbounds ([4 x i8], [4 x i8]* @.str2, i64 0, i64 0), %sw.bb2 ], + [ getelementptr inbounds ([4 x i8], [4 x i8]* @.str1, i64 0, i64 0), %sw.bb1 ], + [ getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), %entry ] ret i8* %retval.0 +; CHECK-LABEL: @foostring( +; CHECK: entry: +; CHECK-NEXT: %0 = icmp ult i32 %x, 4 +; CHECK-NEXT: br i1 %0, label %switch.lookup, label %return +; CHECK: switch.lookup: +; CHECK-NEXT: %switch.gep = getelementptr inbounds [4 x i8*], [4 x i8*]* @switch.table.foostring, i32 0, i32 %x +; CHECK-NEXT: %switch.load = load i8*, i8** %switch.gep +; CHECK-NEXT: ret i8* %switch.load } ; Switch used to initialize two values. The first value is returned, the second ; value is not used. This used to make the transformation generate illegal code. define i32 @earlyreturncrash(i32 %x) { -; CHECK-LABEL: @earlyreturncrash( -; CHECK-NEXT: entry: -; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i32 [[X:%.*]], 4 -; CHECK-NEXT: br i1 [[TMP0]], label [[SWITCH_LOOKUP:%.*]], label [[SW_EPILOG:%.*]] -; CHECK: switch.lookup: -; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [4 x i32], [4 x i32]* @switch.table.earlyreturncrash, i32 0, i32 [[X]] -; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i32, i32* [[SWITCH_GEP]] -; CHECK-NEXT: ret i32 [[SWITCH_LOAD]] -; CHECK: sw.epilog: -; CHECK-NEXT: ret i32 7 -; entry: switch i32 %x, label %sw.default [ - i32 0, label %sw.epilog - i32 1, label %sw.bb1 - i32 2, label %sw.bb2 - i32 3, label %sw.bb3 + i32 0, label %sw.epilog + i32 1, label %sw.bb1 + i32 2, label %sw.bb2 + i32 3, label %sw.bb3 ] sw.bb1: br label %sw.epilog @@ -232,6 +214,13 @@ sw.epilog: %b.0 = phi i32 [ 10, %sw.default ], [ 5, %sw.bb3 ], [ 1, %sw.bb2 ], [ 4, %sw.bb1 ], [ 3, %entry ] ret i32 %a.0 +; CHECK-LABEL: @earlyreturncrash( +; CHECK: switch.lookup: +; CHECK-NEXT: %switch.gep = getelementptr inbounds [4 x i32], [4 x i32]* @switch.table.earlyreturncrash, i32 0, i32 %x +; CHECK-NEXT: %switch.load = load i32, i32* %switch.gep +; CHECK-NEXT: ret i32 %switch.load +; CHECK: sw.epilog: +; CHECK-NEXT: ret i32 7 } @@ -240,40 +229,21 @@ sw.epilog: ; can be packed into a bitmap. define i32 @crud(i8 zeroext %c) { -; CHECK-LABEL: @crud( -; CHECK-NEXT: entry: -; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[C:%.*]], 33 -; CHECK-NEXT: br i1 [[CMP]], label [[LOR_END:%.*]], label [[SWITCH_EARLY_TEST:%.*]] -; CHECK: switch.early.test: -; CHECK-NEXT: [[SWITCH_TABLEIDX:%.*]] = sub i8 [[C]], 34 -; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i8 [[SWITCH_TABLEIDX]], 59 -; CHECK-NEXT: br i1 [[TMP0]], label [[SWITCH_LOOKUP:%.*]], label [[LOR_END]] -; CHECK: switch.lookup: -; CHECK-NEXT: [[SWITCH_CAST:%.*]] = zext i8 [[SWITCH_TABLEIDX]] to i59 -; CHECK-NEXT: [[SWITCH_SHIFTAMT:%.*]] = mul i59 [[SWITCH_CAST]], 1 -; CHECK-NEXT: [[SWITCH_DOWNSHIFT:%.*]] = lshr i59 -288230375765830623, [[SWITCH_SHIFTAMT]] -; CHECK-NEXT: [[SWITCH_MASKED:%.*]] = trunc i59 [[SWITCH_DOWNSHIFT]] to i1 -; CHECK-NEXT: br label [[LOR_END]] -; CHECK: lor.end: -; CHECK-NEXT: [[TMP1:%.*]] = phi i1 [ true, [[ENTRY:%.*]] ], [ [[SWITCH_MASKED]], [[SWITCH_LOOKUP]] ], [ false, [[SWITCH_EARLY_TEST]] ] -; CHECK-NEXT: [[LOR_EXT:%.*]] = zext i1 [[TMP1]] to i32 -; CHECK-NEXT: ret i32 [[LOR_EXT]] -; entry: %cmp = icmp ult i8 %c, 33 br i1 %cmp, label %lor.end, label %switch.early.test switch.early.test: switch i8 %c, label %lor.rhs [ - i8 92, label %lor.end - i8 62, label %lor.end - i8 60, label %lor.end - i8 59, label %lor.end - i8 58, label %lor.end - i8 46, label %lor.end - i8 44, label %lor.end - i8 34, label %lor.end - i8 39, label %switch.edge + i8 92, label %lor.end + i8 62, label %lor.end + i8 60, label %lor.end + i8 59, label %lor.end + i8 58, label %lor.end + i8 46, label %lor.end + i8 44, label %lor.end + i8 34, label %lor.end + i8 39, label %switch.edge ] switch.edge: br label %lor.end @@ -281,49 +251,49 @@ lor.rhs: br label %lor.end lor.end: %0 = phi i1 [ true, %switch.early.test ], - [ false, %lor.rhs ], - [ true, %entry ], - [ true, %switch.early.test ], - [ true, %switch.early.test ], - [ true, %switch.early.test ], - [ true, %switch.early.test ], - [ true, %switch.early.test ], - [ true, %switch.early.test ], - [ true, %switch.early.test ], - [ true, %switch.edge ] + [ false, %lor.rhs ], + [ true, %entry ], + [ true, %switch.early.test ], + [ true, %switch.early.test ], + [ true, %switch.early.test ], + [ true, %switch.early.test ], + [ true, %switch.early.test ], + [ true, %switch.early.test ], + [ true, %switch.early.test ], + [ true, %switch.edge ] %lor.ext = zext i1 %0 to i32 ret i32 %lor.ext +; CHECK-LABEL: @crud( +; CHECK: entry: +; CHECK-NEXT: %cmp = icmp ult i8 %c, 33 +; CHECK-NEXT: br i1 %cmp, label %lor.end, label %switch.early.test +; CHECK: switch.early.test: +; CHECK-NEXT: %switch.tableidx = sub i8 %c, 34 +; CHECK-NEXT: %0 = icmp ult i8 %switch.tableidx, 59 +; CHECK-NEXT: br i1 %0, label %switch.lookup, label %lor.end +; CHECK: switch.lookup: +; CHECK-NEXT: %switch.cast = zext i8 %switch.tableidx to i59 +; CHECK-NEXT: %switch.shiftamt = mul i59 %switch.cast, 1 +; CHECK-NEXT: %switch.downshift = lshr i59 -288230375765830623, %switch.shiftamt +; CHECK-NEXT: %switch.masked = trunc i59 %switch.downshift to i1 +; CHECK-NEXT: br label %lor.end +; CHECK: lor.end: +; CHECK-NEXT: %1 = phi i1 [ true, %entry ], [ %switch.masked, %switch.lookup ], [ false, %switch.early.test ] +; CHECK-NEXT: %lor.ext = zext i1 %1 to i32 +; CHECK-NEXT: ret i32 %lor.ext } ; PR13946 define i32 @overflow(i32 %type) { -; CHECK-LABEL: @overflow( -; CHECK-NEXT: entry: -; CHECK-NEXT: switch i32 [[TYPE:%.*]], label [[IF_END:%.*]] [ -; CHECK-NEXT: i32 3, label [[SW_BB3:%.*]] -; CHECK-NEXT: i32 -2147483645, label [[SW_BB3]] -; CHECK-NEXT: i32 1, label [[SW_BB1:%.*]] -; CHECK-NEXT: i32 2, label [[SW_BB2:%.*]] -; CHECK-NEXT: ] -; CHECK: sw.bb1: -; CHECK-NEXT: br label [[IF_END]] -; CHECK: sw.bb2: -; CHECK-NEXT: br label [[IF_END]] -; CHECK: sw.bb3: -; CHECK-NEXT: br label [[IF_END]] -; CHECK: if.end: -; CHECK-NEXT: [[DIRENT_TYPE_0:%.*]] = phi i32 [ 6, [[SW_BB3]] ], [ 5, [[SW_BB2]] ], [ 0, [[SW_BB1]] ], [ 3, [[ENTRY:%.*]] ] -; CHECK-NEXT: ret i32 [[DIRENT_TYPE_0]] -; entry: switch i32 %type, label %sw.default [ - i32 -2147483648, label %sw.bb - i32 0, label %sw.bb - i32 1, label %sw.bb1 - i32 2, label %sw.bb2 - i32 -2147483645, label %sw.bb3 - i32 3, label %sw.bb3 + i32 -2147483648, label %sw.bb + i32 0, label %sw.bb + i32 1, label %sw.bb1 + i32 2, label %sw.bb2 + i32 -2147483645, label %sw.bb3 + i32 3, label %sw.bb3 ] sw.bb: br label %if.end @@ -336,29 +306,19 @@ if.else: br label %if.end if.end: %dirent_type.0 = phi i32 [ 3, %sw.default ], [ 6, %sw.bb3 ], [ 5, %sw.bb2 ], [ 0, %sw.bb1 ], [ 3, %sw.bb ], [ 0, %if.else ] ret i32 %dirent_type.0 +; CHECK-LABEL: define i32 @overflow( +; CHECK: switch +; CHECK: phi } ; PR13985 define i1 @undef(i32 %tmp) { -; CHECK-LABEL: @undef( -; CHECK-NEXT: bb: -; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i32 [[TMP:%.*]], 9 -; CHECK-NEXT: br i1 [[TMP0]], label [[SWITCH_LOOKUP:%.*]], label [[BB3:%.*]] -; CHECK: switch.lookup: -; CHECK-NEXT: [[SWITCH_CAST:%.*]] = trunc i32 [[TMP]] to i9 -; CHECK-NEXT: [[SWITCH_SHIFTAMT:%.*]] = mul i9 [[SWITCH_CAST]], 1 -; CHECK-NEXT: [[SWITCH_DOWNSHIFT:%.*]] = lshr i9 3, [[SWITCH_SHIFTAMT]] -; CHECK-NEXT: [[SWITCH_MASKED:%.*]] = trunc i9 [[SWITCH_DOWNSHIFT]] to i1 -; CHECK-NEXT: ret i1 [[SWITCH_MASKED]] -; CHECK: bb3: -; CHECK-NEXT: ret i1 undef -; bb: switch i32 %tmp, label %bb3 [ - i32 0, label %bb1 - i32 1, label %bb1 - i32 7, label %bb2 - i32 8, label %bb2 + i32 0, label %bb1 + i32 1, label %bb1 + i32 7, label %bb2 + i32 8, label %bb2 ] bb1: br label %bb3 @@ -367,27 +327,16 @@ bb2: br label %bb3 bb3: %tmp4 = phi i1 [ undef, %bb ], [ false, %bb2 ], [ true, %bb1 ] ret i1 %tmp4 +; CHECK-LABEL: define i1 @undef( +; CHECK: %switch.cast = trunc i32 %tmp to i9 +; CHECK: %switch.downshift = lshr i9 3, %switch.shiftamt } ; Also handle large switches that would be rejected by ; isValueEqualityComparison() - +; CHECK: large +; CHECK-NOT: switch i32 define i32 @large(i32 %x) { -; CHECK-LABEL: @large( -; CHECK-NEXT: entry: -; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[X:%.*]], 0 -; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[X]], -10 -; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[CMP]], i32 [[MUL]], i32 [[X]] -; CHECK-NEXT: [[SWITCH_TABLEIDX:%.*]] = sub i32 [[SPEC_SELECT]], 1 -; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i32 [[SWITCH_TABLEIDX]], 199 -; CHECK-NEXT: br i1 [[TMP0]], label [[SWITCH_LOOKUP:%.*]], label [[RETURN:%.*]] -; CHECK: switch.lookup: -; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [199 x i32], [199 x i32]* @switch.table.large, i32 0, i32 [[SWITCH_TABLEIDX]] -; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i32, i32* [[SWITCH_GEP]] -; CHECK-NEXT: ret i32 [[SWITCH_LOAD]] -; CHECK: return: -; CHECK-NEXT: ret i32 0 -; entry: %cmp = icmp slt i32 %x, 0 br i1 %cmp, label %if.then, label %if.end @@ -399,205 +348,205 @@ if.then: if.end: %x.addr.0 = phi i32 [ %mul, %if.then ], [ %x, %entry ] switch i32 %x.addr.0, label %return [ - i32 199, label %sw.bb203 - i32 1, label %sw.bb1 - i32 2, label %sw.bb2 - i32 3, label %sw.bb3 - i32 4, label %sw.bb4 - i32 5, label %sw.bb5 - i32 6, label %sw.bb6 - i32 7, label %sw.bb7 - i32 8, label %sw.bb8 - i32 9, label %sw.bb9 - i32 10, label %sw.bb10 - i32 11, label %sw.bb11 - i32 12, label %sw.bb12 - i32 13, label %sw.bb13 - i32 14, label %sw.bb14 - i32 15, label %sw.bb15 - i32 16, label %sw.bb16 - i32 17, label %sw.bb17 - i32 18, label %sw.bb18 - i32 19, label %sw.bb19 - i32 20, label %sw.bb20 - i32 21, label %sw.bb21 - i32 22, label %sw.bb22 - i32 23, label %sw.bb23 - i32 24, label %sw.bb24 - i32 25, label %sw.bb25 - i32 26, label %sw.bb26 - i32 27, label %sw.bb27 - i32 28, label %sw.bb28 - i32 29, label %sw.bb29 - i32 30, label %sw.bb30 - i32 31, label %sw.bb31 - i32 32, label %sw.bb32 - i32 33, label %sw.bb33 - i32 34, label %sw.bb34 - i32 35, label %sw.bb35 - i32 36, label %sw.bb37 - i32 37, label %sw.bb38 - i32 38, label %sw.bb39 - i32 39, label %sw.bb40 - i32 40, label %sw.bb41 - i32 41, label %sw.bb42 - i32 42, label %sw.bb43 - i32 43, label %sw.bb44 - i32 44, label %sw.bb45 - i32 45, label %sw.bb47 - i32 46, label %sw.bb48 - i32 47, label %sw.bb49 - i32 48, label %sw.bb50 - i32 49, label %sw.bb51 - i32 50, label %sw.bb52 - i32 51, label %sw.bb53 - i32 52, label %sw.bb54 - i32 53, label %sw.bb55 - i32 54, label %sw.bb56 - i32 55, label %sw.bb58 - i32 56, label %sw.bb59 - i32 57, label %sw.bb60 - i32 58, label %sw.bb61 - i32 59, label %sw.bb62 - i32 60, label %sw.bb63 - i32 61, label %sw.bb64 - i32 62, label %sw.bb65 - i32 63, label %sw.bb66 - i32 64, label %sw.bb67 - i32 65, label %sw.bb68 - i32 66, label %sw.bb69 - i32 67, label %sw.bb70 - i32 68, label %sw.bb71 - i32 69, label %sw.bb72 - i32 70, label %sw.bb73 - i32 71, label %sw.bb74 - i32 72, label %sw.bb76 - i32 73, label %sw.bb77 - i32 74, label %sw.bb78 - i32 75, label %sw.bb79 - i32 76, label %sw.bb80 - i32 77, label %sw.bb81 - i32 78, label %sw.bb82 - i32 79, label %sw.bb83 - i32 80, label %sw.bb84 - i32 81, label %sw.bb85 - i32 82, label %sw.bb86 - i32 83, label %sw.bb87 - i32 84, label %sw.bb88 - i32 85, label %sw.bb89 - i32 86, label %sw.bb90 - i32 87, label %sw.bb91 - i32 88, label %sw.bb92 - i32 89, label %sw.bb93 - i32 90, label %sw.bb94 - i32 91, label %sw.bb95 - i32 92, label %sw.bb96 - i32 93, label %sw.bb97 - i32 94, label %sw.bb98 - i32 95, label %sw.bb99 - i32 96, label %sw.bb100 - i32 97, label %sw.bb101 - i32 98, label %sw.bb102 - i32 99, label %sw.bb103 - i32 100, label %sw.bb104 - i32 101, label %sw.bb105 - i32 102, label %sw.bb106 - i32 103, label %sw.bb107 - i32 104, label %sw.bb108 - i32 105, label %sw.bb109 - i32 106, label %sw.bb110 - i32 107, label %sw.bb111 - i32 108, label %sw.bb112 - i32 109, label %sw.bb113 - i32 110, label %sw.bb114 - i32 111, label %sw.bb115 - i32 112, label %sw.bb116 - i32 113, label %sw.bb117 - i32 114, label %sw.bb118 - i32 115, label %sw.bb119 - i32 116, label %sw.bb120 - i32 117, label %sw.bb121 - i32 118, label %sw.bb122 - i32 119, label %sw.bb123 - i32 120, label %sw.bb124 - i32 121, label %sw.bb125 - i32 122, label %sw.bb126 - i32 123, label %sw.bb127 - i32 124, label %sw.bb128 - i32 125, label %sw.bb129 - i32 126, label %sw.bb130 - i32 127, label %sw.bb131 - i32 128, label %sw.bb132 - i32 129, label %sw.bb133 - i32 130, label %sw.bb134 - i32 131, label %sw.bb135 - i32 132, label %sw.bb136 - i32 133, label %sw.bb137 - i32 134, label %sw.bb138 - i32 135, label %sw.bb139 - i32 136, label %sw.bb140 - i32 137, label %sw.bb141 - i32 138, label %sw.bb142 - i32 139, label %sw.bb143 - i32 140, label %sw.bb144 - i32 141, label %sw.bb145 - i32 142, label %sw.bb146 - i32 143, label %sw.bb147 - i32 144, label %sw.bb148 - i32 145, label %sw.bb149 - i32 146, label %sw.bb150 - i32 147, label %sw.bb151 - i32 148, label %sw.bb152 - i32 149, label %sw.bb153 - i32 150, label %sw.bb154 - i32 151, label %sw.bb155 - i32 152, label %sw.bb156 - i32 153, label %sw.bb157 - i32 154, label %sw.bb158 - i32 155, label %sw.bb159 - i32 156, label %sw.bb160 - i32 157, label %sw.bb161 - i32 158, label %sw.bb162 - i32 159, label %sw.bb163 - i32 160, label %sw.bb164 - i32 161, label %sw.bb165 - i32 162, label %sw.bb166 - i32 163, label %sw.bb167 - i32 164, label %sw.bb168 - i32 165, label %sw.bb169 - i32 166, label %sw.bb170 - i32 167, label %sw.bb171 - i32 168, label %sw.bb172 - i32 169, label %sw.bb173 - i32 170, label %sw.bb174 - i32 171, label %sw.bb175 - i32 172, label %sw.bb176 - i32 173, label %sw.bb177 - i32 174, label %sw.bb178 - i32 175, label %sw.bb179 - i32 176, label %sw.bb180 - i32 177, label %sw.bb181 - i32 178, label %sw.bb182 - i32 179, label %sw.bb183 - i32 180, label %sw.bb184 - i32 181, label %sw.bb185 - i32 182, label %sw.bb186 - i32 183, label %sw.bb187 - i32 184, label %sw.bb188 - i32 185, label %sw.bb189 - i32 186, label %sw.bb190 - i32 187, label %sw.bb191 - i32 188, label %sw.bb192 - i32 189, label %sw.bb193 - i32 190, label %sw.bb194 - i32 191, label %sw.bb195 - i32 192, label %sw.bb196 - i32 193, label %sw.bb197 - i32 194, label %sw.bb198 - i32 195, label %sw.bb199 - i32 196, label %sw.bb200 - i32 197, label %sw.bb201 - i32 198, label %sw.bb202 + i32 199, label %sw.bb203 + i32 1, label %sw.bb1 + i32 2, label %sw.bb2 + i32 3, label %sw.bb3 + i32 4, label %sw.bb4 + i32 5, label %sw.bb5 + i32 6, label %sw.bb6 + i32 7, label %sw.bb7 + i32 8, label %sw.bb8 + i32 9, label %sw.bb9 + i32 10, label %sw.bb10 + i32 11, label %sw.bb11 + i32 12, label %sw.bb12 + i32 13, label %sw.bb13 + i32 14, label %sw.bb14 + i32 15, label %sw.bb15 + i32 16, label %sw.bb16 + i32 17, label %sw.bb17 + i32 18, label %sw.bb18 + i32 19, label %sw.bb19 + i32 20, label %sw.bb20 + i32 21, label %sw.bb21 + i32 22, label %sw.bb22 + i32 23, label %sw.bb23 + i32 24, label %sw.bb24 + i32 25, label %sw.bb25 + i32 26, label %sw.bb26 + i32 27, label %sw.bb27 + i32 28, label %sw.bb28 + i32 29, label %sw.bb29 + i32 30, label %sw.bb30 + i32 31, label %sw.bb31 + i32 32, label %sw.bb32 + i32 33, label %sw.bb33 + i32 34, label %sw.bb34 + i32 35, label %sw.bb35 + i32 36, label %sw.bb37 + i32 37, label %sw.bb38 + i32 38, label %sw.bb39 + i32 39, label %sw.bb40 + i32 40, label %sw.bb41 + i32 41, label %sw.bb42 + i32 42, label %sw.bb43 + i32 43, label %sw.bb44 + i32 44, label %sw.bb45 + i32 45, label %sw.bb47 + i32 46, label %sw.bb48 + i32 47, label %sw.bb49 + i32 48, label %sw.bb50 + i32 49, label %sw.bb51 + i32 50, label %sw.bb52 + i32 51, label %sw.bb53 + i32 52, label %sw.bb54 + i32 53, label %sw.bb55 + i32 54, label %sw.bb56 + i32 55, label %sw.bb58 + i32 56, label %sw.bb59 + i32 57, label %sw.bb60 + i32 58, label %sw.bb61 + i32 59, label %sw.bb62 + i32 60, label %sw.bb63 + i32 61, label %sw.bb64 + i32 62, label %sw.bb65 + i32 63, label %sw.bb66 + i32 64, label %sw.bb67 + i32 65, label %sw.bb68 + i32 66, label %sw.bb69 + i32 67, label %sw.bb70 + i32 68, label %sw.bb71 + i32 69, label %sw.bb72 + i32 70, label %sw.bb73 + i32 71, label %sw.bb74 + i32 72, label %sw.bb76 + i32 73, label %sw.bb77 + i32 74, label %sw.bb78 + i32 75, label %sw.bb79 + i32 76, label %sw.bb80 + i32 77, label %sw.bb81 + i32 78, label %sw.bb82 + i32 79, label %sw.bb83 + i32 80, label %sw.bb84 + i32 81, label %sw.bb85 + i32 82, label %sw.bb86 + i32 83, label %sw.bb87 + i32 84, label %sw.bb88 + i32 85, label %sw.bb89 + i32 86, label %sw.bb90 + i32 87, label %sw.bb91 + i32 88, label %sw.bb92 + i32 89, label %sw.bb93 + i32 90, label %sw.bb94 + i32 91, label %sw.bb95 + i32 92, label %sw.bb96 + i32 93, label %sw.bb97 + i32 94, label %sw.bb98 + i32 95, label %sw.bb99 + i32 96, label %sw.bb100 + i32 97, label %sw.bb101 + i32 98, label %sw.bb102 + i32 99, label %sw.bb103 + i32 100, label %sw.bb104 + i32 101, label %sw.bb105 + i32 102, label %sw.bb106 + i32 103, label %sw.bb107 + i32 104, label %sw.bb108 + i32 105, label %sw.bb109 + i32 106, label %sw.bb110 + i32 107, label %sw.bb111 + i32 108, label %sw.bb112 + i32 109, label %sw.bb113 + i32 110, label %sw.bb114 + i32 111, label %sw.bb115 + i32 112, label %sw.bb116 + i32 113, label %sw.bb117 + i32 114, label %sw.bb118 + i32 115, label %sw.bb119 + i32 116, label %sw.bb120 + i32 117, label %sw.bb121 + i32 118, label %sw.bb122 + i32 119, label %sw.bb123 + i32 120, label %sw.bb124 + i32 121, label %sw.bb125 + i32 122, label %sw.bb126 + i32 123, label %sw.bb127 + i32 124, label %sw.bb128 + i32 125, label %sw.bb129 + i32 126, label %sw.bb130 + i32 127, label %sw.bb131 + i32 128, label %sw.bb132 + i32 129, label %sw.bb133 + i32 130, label %sw.bb134 + i32 131, label %sw.bb135 + i32 132, label %sw.bb136 + i32 133, label %sw.bb137 + i32 134, label %sw.bb138 + i32 135, label %sw.bb139 + i32 136, label %sw.bb140 + i32 137, label %sw.bb141 + i32 138, label %sw.bb142 + i32 139, label %sw.bb143 + i32 140, label %sw.bb144 + i32 141, label %sw.bb145 + i32 142, label %sw.bb146 + i32 143, label %sw.bb147 + i32 144, label %sw.bb148 + i32 145, label %sw.bb149 + i32 146, label %sw.bb150 + i32 147, label %sw.bb151 + i32 148, label %sw.bb152 + i32 149, label %sw.bb153 + i32 150, label %sw.bb154 + i32 151, label %sw.bb155 + i32 152, label %sw.bb156 + i32 153, label %sw.bb157 + i32 154, label %sw.bb158 + i32 155, label %sw.bb159 + i32 156, label %sw.bb160 + i32 157, label %sw.bb161 + i32 158, label %sw.bb162 + i32 159, label %sw.bb163 + i32 160, label %sw.bb164 + i32 161, label %sw.bb165 + i32 162, label %sw.bb166 + i32 163, label %sw.bb167 + i32 164, label %sw.bb168 + i32 165, label %sw.bb169 + i32 166, label %sw.bb170 + i32 167, label %sw.bb171 + i32 168, label %sw.bb172 + i32 169, label %sw.bb173 + i32 170, label %sw.bb174 + i32 171, label %sw.bb175 + i32 172, label %sw.bb176 + i32 173, label %sw.bb177 + i32 174, label %sw.bb178 + i32 175, label %sw.bb179 + i32 176, label %sw.bb180 + i32 177, label %sw.bb181 + i32 178, label %sw.bb182 + i32 179, label %sw.bb183 + i32 180, label %sw.bb184 + i32 181, label %sw.bb185 + i32 182, label %sw.bb186 + i32 183, label %sw.bb187 + i32 184, label %sw.bb188 + i32 185, label %sw.bb189 + i32 186, label %sw.bb190 + i32 187, label %sw.bb191 + i32 188, label %sw.bb192 + i32 189, label %sw.bb193 + i32 190, label %sw.bb194 + i32 191, label %sw.bb195 + i32 192, label %sw.bb196 + i32 193, label %sw.bb197 + i32 194, label %sw.bb198 + i32 195, label %sw.bb199 + i32 196, label %sw.bb200 + i32 197, label %sw.bb201 + i32 198, label %sw.bb202 ] sw.bb1: br label %return @@ -806,27 +755,15 @@ return: } define i32 @cprop(i32 %x, i32 %y) { -; CHECK-LABEL: @cprop( -; CHECK-NEXT: entry: -; CHECK-NEXT: [[SWITCH_TABLEIDX:%.*]] = sub i32 [[X:%.*]], 1 -; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i32 [[SWITCH_TABLEIDX]], 7 -; CHECK-NEXT: br i1 [[TMP0]], label [[SWITCH_LOOKUP:%.*]], label [[RETURN:%.*]] -; CHECK: switch.lookup: -; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [7 x i32], [7 x i32]* @switch.table.cprop, i32 0, i32 [[SWITCH_TABLEIDX]] -; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i32, i32* [[SWITCH_GEP]] -; CHECK-NEXT: ret i32 [[SWITCH_LOAD]] -; CHECK: return: -; CHECK-NEXT: ret i32 123 -; entry: switch i32 %x, label %sw.default [ - i32 1, label %return - i32 2, label %sw.bb1 - i32 3, label %sw.bb2 - i32 4, label %sw.bb2 - i32 5, label %sw.bb2 - i32 6, label %sw.bb3 - i32 7, label %sw.bb3 + i32 1, label %return + i32 2, label %sw.bb1 + i32 3, label %sw.bb2 + i32 4, label %sw.bb2 + i32 5, label %sw.bb2 + i32 6, label %sw.bb3 + i32 7, label %sw.bb3 ] sw.bb1: br label %return @@ -853,31 +790,23 @@ return: %retval.0 = phi i32 [ 123, %sw.default ], [ %select, %sw.bb3 ], [ %sub, %sw.bb2 ], [ 42, %sw.bb1 ], [ 5, %entry ] ret i32 %retval.0 +; CHECK-LABEL: @cprop( +; CHECK: switch.lookup: +; CHECK: %switch.gep = getelementptr inbounds [7 x i32], [7 x i32]* @switch.table.cprop, i32 0, i32 %switch.tableidx } define i32 @unreachable_case(i32 %x) { -; CHECK-LABEL: @unreachable_case( -; CHECK-NEXT: entry: -; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i32 [[X:%.*]], 9 -; CHECK-NEXT: br i1 [[TMP0]], label [[SWITCH_LOOKUP:%.*]], label [[RETURN:%.*]] -; CHECK: switch.lookup: -; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [9 x i32], [9 x i32]* @switch.table.unreachable_case, i32 0, i32 [[X]] -; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i32, i32* [[SWITCH_GEP]] -; CHECK-NEXT: ret i32 [[SWITCH_LOAD]] -; CHECK: return: -; CHECK-NEXT: ret i32 2 -; entry: switch i32 %x, label %sw.default [ - i32 0, label %sw.bb - i32 1, label %sw.bb - i32 2, label %sw.bb - i32 3, label %sw.bb1 - i32 4, label %sw.bb2 - i32 5, label %sw.bb3 - i32 6, label %sw.bb3 - i32 7, label %sw.bb3 - i32 8, label %sw.bb3 + i32 0, label %sw.bb + i32 1, label %sw.bb + i32 2, label %sw.bb + i32 3, label %sw.bb1 + i32 4, label %sw.bb2 + i32 5, label %sw.bb3 + i32 6, label %sw.bb3 + i32 7, label %sw.bb3 + i32 8, label %sw.bb3 ] sw.bb: br label %return @@ -890,21 +819,18 @@ return: %retval.0 = phi i32 [ 1, %sw.bb3 ], [ -1, %sw.bb2 ], [ 0, %sw.bb ], [ 2, %sw.default ] ret i32 %retval.0 +; CHECK-LABEL: @unreachable_case( +; CHECK: switch.lookup: +; CHECK: getelementptr inbounds [9 x i32], [9 x i32]* @switch.table.unreachable_case, i32 0, i32 %x } define i32 @unreachable_default(i32 %x) { -; CHECK-LABEL: @unreachable_default( -; CHECK-NEXT: entry: -; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [4 x i32], [4 x i32]* @switch.table.unreachable_default, i32 0, i32 [[X:%.*]] -; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i32, i32* [[SWITCH_GEP]] -; CHECK-NEXT: ret i32 [[SWITCH_LOAD]] -; entry: switch i32 %x, label %default [ - i32 0, label %bb0 - i32 1, label %bb1 - i32 2, label %bb2 - i32 3, label %bb3 + i32 0, label %bb0 + i32 1, label %bb1 + i32 2, label %bb2 + i32 3, label %bb3 ] bb0: br label %return @@ -917,40 +843,24 @@ return: %retval = phi i32 [ 42, %bb0 ], [ 52, %bb1 ], [ 1, %bb2 ], [ 2, %bb3 ] ret i32 %retval +; CHECK-LABEL: @unreachable_default( +; CHECK: entry: +; CHECK-NOT: icmp +; CHECK-NOT: br 1i +; CHECK-NEXT: %switch.gep = getelementptr inbounds [4 x i32], [4 x i32]* @switch.table.unreachable_default, i32 0, i32 %x +; CHECK-NEXT: %switch.load = load i32, i32* %switch.gep +; CHECK-NEXT: ret i32 %switch.load } ; Don't create a table with illegal type define i96 @illegaltype(i32 %c) { -; CHECK-LABEL: @illegaltype( -; CHECK-NEXT: entry: -; CHECK-NEXT: switch i32 [[C:%.*]], label [[SW_DEFAULT:%.*]] [ -; CHECK-NEXT: i32 42, label [[RETURN:%.*]] -; CHECK-NEXT: i32 43, label [[SW_BB1:%.*]] -; CHECK-NEXT: i32 44, label [[SW_BB2:%.*]] -; CHECK-NEXT: i32 45, label [[SW_BB3:%.*]] -; CHECK-NEXT: i32 46, label [[SW_BB4:%.*]] -; CHECK-NEXT: ] -; CHECK: sw.bb1: -; CHECK-NEXT: br label [[RETURN]] -; CHECK: sw.bb2: -; CHECK-NEXT: br label [[RETURN]] -; CHECK: sw.bb3: -; CHECK-NEXT: br label [[RETURN]] -; CHECK: sw.bb4: -; CHECK-NEXT: br label [[RETURN]] -; CHECK: sw.default: -; CHECK-NEXT: br label [[RETURN]] -; CHECK: return: -; CHECK-NEXT: [[RETVAL_0:%.*]] = phi i96 [ 15, [[SW_DEFAULT]] ], [ 27, [[SW_BB4]] ], [ -1, [[SW_BB3]] ], [ 0, [[SW_BB2]] ], [ 123, [[SW_BB1]] ], [ 55, [[ENTRY:%.*]] ] -; CHECK-NEXT: ret i96 [[RETVAL_0]] -; entry: switch i32 %c, label %sw.default [ - i32 42, label %return - i32 43, label %sw.bb1 - i32 44, label %sw.bb2 - i32 45, label %sw.bb3 - i32 46, label %sw.bb4 + i32 42, label %return + i32 43, label %sw.bb1 + i32 44, label %sw.bb2 + i32 45, label %sw.bb3 + i32 46, label %sw.bb4 ] sw.bb1: br label %return @@ -962,106 +872,75 @@ return: %retval.0 = phi i96 [ 15, %sw.default ], [ 27, %sw.bb4 ], [ -1, %sw.bb3 ], [ 0, %sw.bb2 ], [ 123, %sw.bb1 ], [ 55, %entry ] ret i96 %retval.0 +; CHECK-LABEL: @illegaltype( +; CHECK-NOT: @switch.table +; CHECK: switch i32 %c } ; If we can build a lookup table without any holes, we don't need a default result. declare void @exit(i32) define i32 @nodefaultnoholes(i32 %c) { -; CHECK-LABEL: @nodefaultnoholes( -; CHECK-NEXT: entry: -; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i32 [[C:%.*]], 4 -; CHECK-NEXT: br i1 [[TMP0]], label [[SWITCH_LOOKUP:%.*]], label [[SW_DEFAULT:%.*]] -; CHECK: sw.default: -; CHECK-NEXT: call void @exit(i32 1) -; CHECK-NEXT: unreachable -; CHECK: switch.lookup: -; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [4 x i32], [4 x i32]* @switch.table.nodefaultnoholes, i32 0, i32 [[C]] -; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i32, i32* [[SWITCH_GEP]] -; CHECK-NEXT: ret i32 [[SWITCH_LOAD]] -; entry: switch i32 %c, label %sw.default [ - i32 0, label %return - i32 1, label %sw.bb1 - i32 2, label %sw.bb2 - i32 3, label %sw.bb3 + i32 0, label %return + i32 1, label %sw.bb1 + i32 2, label %sw.bb2 + i32 3, label %sw.bb3 ] sw.bb1: br label %return sw.bb2: br label %return sw.bb3: br label %return sw.default: call void @exit(i32 1) - unreachable + unreachable return: %x = phi i32 [ -1, %sw.bb3 ], [ 0, %sw.bb2 ], [ 123, %sw.bb1 ], [ 55, %entry ] ret i32 %x +; CHECK-LABEL: @nodefaultnoholes( +; CHECK: @switch.table +; CHECK-NOT: switch i32 } ; This lookup table will have holes, so we need to test for the holes. define i32 @nodefaultwithholes(i32 %c) { -; CHECK-LABEL: @nodefaultwithholes( -; CHECK-NEXT: entry: -; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i32 [[C:%.*]], 6 -; CHECK-NEXT: br i1 [[TMP0]], label [[SWITCH_HOLE_CHECK:%.*]], label [[SW_DEFAULT:%.*]] -; CHECK: sw.default: -; CHECK-NEXT: call void @exit(i32 1) -; CHECK-NEXT: unreachable -; CHECK: switch.hole_check: -; CHECK-NEXT: [[SWITCH_MASKINDEX:%.*]] = trunc i32 [[C]] to i8 -; CHECK-NEXT: [[SWITCH_SHIFTED:%.*]] = lshr i8 47, [[SWITCH_MASKINDEX]] -; CHECK-NEXT: [[SWITCH_LOBIT:%.*]] = trunc i8 [[SWITCH_SHIFTED]] to i1 -; CHECK-NEXT: br i1 [[SWITCH_LOBIT]], label [[SWITCH_LOOKUP:%.*]], label [[SW_DEFAULT]] -; CHECK: switch.lookup: -; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [6 x i32], [6 x i32]* @switch.table.nodefaultwithholes, i32 0, i32 [[C]] -; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i32, i32* [[SWITCH_GEP]] -; CHECK-NEXT: ret i32 [[SWITCH_LOAD]] -; entry: switch i32 %c, label %sw.default [ - i32 0, label %return - i32 1, label %sw.bb1 - i32 2, label %sw.bb2 - i32 3, label %sw.bb3 - i32 5, label %sw.bb3 + i32 0, label %return + i32 1, label %sw.bb1 + i32 2, label %sw.bb2 + i32 3, label %sw.bb3 + i32 5, label %sw.bb3 ] sw.bb1: br label %return sw.bb2: br label %return sw.bb3: br label %return sw.default: call void @exit(i32 1) - unreachable + unreachable return: %x = phi i32 [ -1, %sw.bb3 ], [ 0, %sw.bb2 ], [ 123, %sw.bb1 ], [ 55, %entry ] ret i32 %x +; CHECK-LABEL: @nodefaultwithholes( +; CHECK: entry: +; CHECK: br i1 %{{.*}}, label %switch.hole_check, label %sw.default +; CHECK: switch.hole_check: +; CHECK-NEXT: %switch.maskindex = trunc i32 %c to i8 +; CHECK-NEXT: %switch.shifted = lshr i8 47, %switch.maskindex ; The mask is binary 101111. +; CHECK-NEXT: %switch.lobit = trunc i8 %switch.shifted to i1 +; CHECK-NEXT: br i1 %switch.lobit, label %switch.lookup, label %sw.default +; CHECK-NOT: switch i32 } ; We don't build lookup tables with holes for switches with less than four cases. define i32 @threecasesholes(i32 %c) { -; CHECK-LABEL: @threecasesholes( -; CHECK-NEXT: entry: -; CHECK-NEXT: switch i32 [[C:%.*]], label [[SW_DEFAULT:%.*]] [ -; CHECK-NEXT: i32 0, label [[RETURN:%.*]] -; CHECK-NEXT: i32 1, label [[SW_BB1:%.*]] -; CHECK-NEXT: i32 3, label [[SW_BB2:%.*]] -; CHECK-NEXT: ] -; CHECK: sw.bb1: -; CHECK-NEXT: br label [[RETURN]] -; CHECK: sw.bb2: -; CHECK-NEXT: br label [[RETURN]] -; CHECK: sw.default: -; CHECK-NEXT: br label [[RETURN]] -; CHECK: return: -; CHECK-NEXT: [[X:%.*]] = phi i32 [ [[C]], [[SW_DEFAULT]] ], [ 5, [[SW_BB2]] ], [ 7, [[SW_BB1]] ], [ 9, [[ENTRY:%.*]] ] -; CHECK-NEXT: ret i32 [[X]] -; entry: switch i32 %c, label %sw.default [ - i32 0, label %return - i32 1, label %sw.bb1 - i32 3, label %sw.bb2 + i32 0, label %return + i32 1, label %sw.bb1 + i32 3, label %sw.bb2 ] sw.bb1: br label %return sw.bb2: br label %return @@ -1069,16 +948,19 @@ sw.default: br label %return return: %x = phi i32 [ %c, %sw.default ], [ 5, %sw.bb2 ], [ 7, %sw.bb1 ], [ 9, %entry ] ret i32 %x +; CHECK-LABEL: @threecasesholes( +; CHECK: switch i32 +; CHECK-NOT: @switch.table } ; We build lookup tables for switches with three or more cases. define i32 @threecases(i32 %c) { ; CHECK-LABEL: @threecases( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i32 [[C:%.*]], 3 -; CHECK-NEXT: br i1 [[TMP0]], label [[SWITCH_LOOKUP:%.*]], label [[RETURN:%.*]] +; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i32 %c, 3 +; CHECK-NEXT: br i1 [[TMP0]], label %switch.lookup, label %return ; CHECK: switch.lookup: -; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [3 x i32], [3 x i32]* @switch.table.threecases, i32 0, i32 [[C]] +; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [3 x i32], [3 x i32]* @switch.table.threecases, i32 0, i32 %c ; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i32, i32* [[SWITCH_GEP]] ; CHECK-NEXT: ret i32 [[SWITCH_LOAD]] ; CHECK: return: @@ -1105,9 +987,9 @@ return: define i32 @twocases(i32 %c) { ; CHECK-LABEL: @twocases( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[SWITCH_SELECTCMP:%.*]] = icmp eq i32 [[C:%.*]], 1 -; CHECK-NEXT: [[SWITCH_SELECT:%.*]] = select i1 [[SWITCH_SELECTCMP]], i32 7, i32 3 -; CHECK-NEXT: [[SWITCH_SELECTCMP1:%.*]] = icmp eq i32 [[C]], 0 +; CHECK-NEXT: [[SWITCH_SELECTCMP:%.*]] = icmp eq i32 %c, 1 +; CHECK-NEXT: [[SWITCH_SELECT:%.*]] = select i1 [[SWITCH_SELECTCMP:%.*]], i32 7, i32 3 +; CHECK-NEXT: [[SWITCH_SELECTCMP1:%.*]] = icmp eq i32 %c, 0 ; CHECK-NEXT: [[SWITCH_SELECT2:%.*]] = select i1 [[SWITCH_SELECTCMP1]], i32 9, i32 [[SWITCH_SELECT]] ; CHECK-NEXT: ret i32 [[SWITCH_SELECT2]] ; @@ -1131,28 +1013,11 @@ return: @tls_c = thread_local global i32 0 @tls_d = thread_local global i32 0 define i32* @tls(i32 %x) { -; CHECK-LABEL: @tls( -; CHECK-NEXT: entry: -; CHECK-NEXT: switch i32 [[X:%.*]], label [[SW_DEFAULT:%.*]] [ -; CHECK-NEXT: i32 0, label [[RETURN:%.*]] -; CHECK-NEXT: i32 1, label [[SW_BB1:%.*]] -; CHECK-NEXT: i32 2, label [[SW_BB2:%.*]] -; CHECK-NEXT: ] -; CHECK: sw.bb1: -; CHECK-NEXT: br label [[RETURN]] -; CHECK: sw.bb2: -; CHECK-NEXT: br label [[RETURN]] -; CHECK: sw.default: -; CHECK-NEXT: br label [[RETURN]] -; CHECK: return: -; CHECK-NEXT: [[RETVAL_0:%.*]] = phi i32* [ @tls_d, [[SW_DEFAULT]] ], [ @tls_c, [[SW_BB2]] ], [ @tls_b, [[SW_BB1]] ], [ @tls_a, [[ENTRY:%.*]] ] -; CHECK-NEXT: ret i32* [[RETVAL_0]] -; entry: switch i32 %x, label %sw.default [ - i32 0, label %return - i32 1, label %sw.bb1 - i32 2, label %sw.bb2 + i32 0, label %return + i32 1, label %sw.bb1 + i32 2, label %sw.bb2 ] sw.bb1: br label %return @@ -1163,6 +1028,9 @@ sw.default: return: %retval.0 = phi i32* [ @tls_d, %sw.default ], [ @tls_c, %sw.bb2 ], [ @tls_b, %sw.bb1 ], [ @tls_a, %entry ] ret i32* %retval.0 +; CHECK-LABEL: @tls( +; CHECK: switch i32 +; CHECK-NOT: @switch.table } ; Don't build tables for switches with dllimport variables. @@ -1171,28 +1039,11 @@ return: @dllimport_c = external dllimport global [3x i32] @dllimport_d = external dllimport global [3x i32] define i32* @dllimport(i32 %x) { -; CHECK-LABEL: @dllimport( -; CHECK-NEXT: entry: -; CHECK-NEXT: switch i32 [[X:%.*]], label [[SW_DEFAULT:%.*]] [ -; CHECK-NEXT: i32 0, label [[RETURN:%.*]] -; CHECK-NEXT: i32 1, label [[SW_BB1:%.*]] -; CHECK-NEXT: i32 2, label [[SW_BB2:%.*]] -; CHECK-NEXT: ] -; CHECK: sw.bb1: -; CHECK-NEXT: br label [[RETURN]] -; CHECK: sw.bb2: -; CHECK-NEXT: br label [[RETURN]] -; CHECK: sw.default: -; CHECK-NEXT: br label [[RETURN]] -; CHECK: return: -; CHECK-NEXT: [[RETVAL_0:%.*]] = phi i32* [ getelementptr inbounds ([3 x i32], [3 x i32]* @dllimport_d, i32 0, i32 0), [[SW_DEFAULT]] ], [ getelementptr inbounds ([3 x i32], [3 x i32]* @dllimport_c, i32 0, i32 0), [[SW_BB2]] ], [ getelementptr inbounds ([3 x i32], [3 x i32]* @dllimport_b, i32 0, i32 0), [[SW_BB1]] ], [ getelementptr inbounds ([3 x i32], [3 x i32]* @dllimport_a, i32 0, i32 0), [[ENTRY:%.*]] ] -; CHECK-NEXT: ret i32* [[RETVAL_0]] -; entry: switch i32 %x, label %sw.default [ - i32 0, label %return - i32 1, label %sw.bb1 - i32 2, label %sw.bb2 + i32 0, label %return + i32 1, label %sw.bb1 + i32 2, label %sw.bb2 ] sw.bb1: br label %return @@ -1202,33 +1053,23 @@ sw.default: br label %return return: %retval.0 = phi i32* [ getelementptr inbounds ([3 x i32], [3 x i32]* @dllimport_d, i32 0, i32 0), %sw.default ], - [ getelementptr inbounds ([3 x i32], [3 x i32]* @dllimport_c, i32 0, i32 0), %sw.bb2 ], - [ getelementptr inbounds ([3 x i32], [3 x i32]* @dllimport_b, i32 0, i32 0), %sw.bb1 ], - [ getelementptr inbounds ([3 x i32], [3 x i32]* @dllimport_a, i32 0, i32 0), %entry ] + [ getelementptr inbounds ([3 x i32], [3 x i32]* @dllimport_c, i32 0, i32 0), %sw.bb2 ], + [ getelementptr inbounds ([3 x i32], [3 x i32]* @dllimport_b, i32 0, i32 0), %sw.bb1 ], + [ getelementptr inbounds ([3 x i32], [3 x i32]* @dllimport_a, i32 0, i32 0), %entry ] ret i32* %retval.0 +; CHECK-LABEL: @dllimport( +; CHECK: switch i32 +; CHECK-NOT: @switch.table } ; We can use linear mapping. define i8 @linearmap1(i32 %c) { -; CHECK-LABEL: @linearmap1( -; CHECK-NEXT: entry: -; CHECK-NEXT: [[SWITCH_TABLEIDX:%.*]] = sub i32 [[C:%.*]], 10 -; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i32 [[SWITCH_TABLEIDX]], 4 -; CHECK-NEXT: br i1 [[TMP0]], label [[SWITCH_LOOKUP:%.*]], label [[RETURN:%.*]] -; CHECK: switch.lookup: -; CHECK-NEXT: [[SWITCH_IDX_CAST:%.*]] = trunc i32 [[SWITCH_TABLEIDX]] to i8 -; CHECK-NEXT: [[SWITCH_IDX_MULT:%.*]] = mul i8 [[SWITCH_IDX_CAST]], -5 -; CHECK-NEXT: [[SWITCH_OFFSET:%.*]] = add i8 [[SWITCH_IDX_MULT]], 18 -; CHECK-NEXT: ret i8 [[SWITCH_OFFSET]] -; CHECK: return: -; CHECK-NEXT: ret i8 3 -; entry: switch i32 %c, label %sw.default [ - i32 10, label %return - i32 11, label %sw.bb1 - i32 12, label %sw.bb2 - i32 13, label %sw.bb3 + i32 10, label %return + i32 11, label %sw.bb1 + i32 12, label %sw.bb2 + i32 13, label %sw.bb3 ] sw.bb1: br label %return sw.bb2: br label %return @@ -1237,28 +1078,24 @@ sw.default: br label %return return: %x = phi i8 [ 3, %sw.default ], [ 3, %sw.bb3 ], [ 8, %sw.bb2 ], [ 13, %sw.bb1 ], [ 18, %entry ] ret i8 %x +; CHECK-LABEL: @linearmap1( +; CHECK: entry: +; CHECK-NEXT: %switch.tableidx = sub i32 %c, 10 +; CHECK: switch.lookup: +; CHECK-NEXT: %switch.idx.cast = trunc i32 %switch.tableidx to i8 +; CHECK-NEXT: %switch.idx.mult = mul i8 %switch.idx.cast, -5 +; CHECK-NEXT: %switch.offset = add i8 %switch.idx.mult, 18 +; CHECK-NEXT: ret i8 %switch.offset } ; Linear mapping in a different configuration. define i32 @linearmap2(i8 %c) { -; CHECK-LABEL: @linearmap2( -; CHECK-NEXT: entry: -; CHECK-NEXT: [[SWITCH_TABLEIDX:%.*]] = sub i8 [[C:%.*]], -13 -; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i8 [[SWITCH_TABLEIDX]], 4 -; CHECK-NEXT: br i1 [[TMP0]], label [[SWITCH_LOOKUP:%.*]], label [[RETURN:%.*]] -; CHECK: switch.lookup: -; CHECK-NEXT: [[SWITCH_IDX_CAST:%.*]] = zext i8 [[SWITCH_TABLEIDX]] to i32 -; CHECK-NEXT: [[SWITCH_OFFSET:%.*]] = add i32 [[SWITCH_IDX_CAST]], 18 -; CHECK-NEXT: ret i32 [[SWITCH_OFFSET]] -; CHECK: return: -; CHECK-NEXT: ret i32 3 -; entry: switch i8 %c, label %sw.default [ - i8 -10, label %return - i8 -11, label %sw.bb1 - i8 -12, label %sw.bb2 - i8 -13, label %sw.bb3 + i8 -10, label %return + i8 -11, label %sw.bb1 + i8 -12, label %sw.bb2 + i8 -13, label %sw.bb3 ] sw.bb1: br label %return sw.bb2: br label %return @@ -1267,28 +1104,23 @@ sw.default: br label %return return: %x = phi i32 [ 3, %sw.default ], [ 18, %sw.bb3 ], [ 19, %sw.bb2 ], [ 20, %sw.bb1 ], [ 21, %entry ] ret i32 %x +; CHECK-LABEL: @linearmap2( +; CHECK: entry: +; CHECK-NEXT: %switch.tableidx = sub i8 %c, -13 +; CHECK: switch.lookup: +; CHECK-NEXT: %switch.idx.cast = zext i8 %switch.tableidx to i32 +; CHECK-NEXT: %switch.offset = add i32 %switch.idx.cast, 18 +; CHECK-NEXT: ret i32 %switch.offset } ; Linear mapping with overflows. define i8 @linearmap3(i32 %c) { -; CHECK-LABEL: @linearmap3( -; CHECK-NEXT: entry: -; CHECK-NEXT: [[SWITCH_TABLEIDX:%.*]] = sub i32 [[C:%.*]], 10 -; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i32 [[SWITCH_TABLEIDX]], 4 -; CHECK-NEXT: br i1 [[TMP0]], label [[SWITCH_LOOKUP:%.*]], label [[RETURN:%.*]] -; CHECK: switch.lookup: -; CHECK-NEXT: [[SWITCH_IDX_CAST:%.*]] = trunc i32 [[SWITCH_TABLEIDX]] to i8 -; CHECK-NEXT: [[SWITCH_IDX_MULT:%.*]] = mul i8 [[SWITCH_IDX_CAST]], 100 -; CHECK-NEXT: ret i8 [[SWITCH_IDX_MULT]] -; CHECK: return: -; CHECK-NEXT: ret i8 3 -; entry: switch i32 %c, label %sw.default [ - i32 10, label %return - i32 11, label %sw.bb1 - i32 12, label %sw.bb2 - i32 13, label %sw.bb3 + i32 10, label %return + i32 11, label %sw.bb1 + i32 12, label %sw.bb2 + i32 13, label %sw.bb3 ] sw.bb1: br label %return sw.bb2: br label %return @@ -1297,27 +1129,23 @@ sw.default: br label %return return: %x = phi i8 [ 3, %sw.default ], [ 44, %sw.bb3 ], [ -56, %sw.bb2 ], [ 100, %sw.bb1 ], [ 0, %entry ] ret i8 %x +; CHECK-LABEL: @linearmap3( +; CHECK: entry: +; CHECK-NEXT: %switch.tableidx = sub i32 %c, 10 +; CHECK: switch.lookup: +; CHECK-NEXT: %switch.idx.cast = trunc i32 %switch.tableidx to i8 +; CHECK-NEXT: %switch.idx.mult = mul i8 %switch.idx.cast, 100 +; CHECK-NEXT: ret i8 %switch.idx.mult } ; Linear mapping with with multiplier 1 and offset 0. define i8 @linearmap4(i32 %c) { -; CHECK-LABEL: @linearmap4( -; CHECK-NEXT: entry: -; CHECK-NEXT: [[SWITCH_TABLEIDX:%.*]] = sub i32 [[C:%.*]], -2 -; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i32 [[SWITCH_TABLEIDX]], 4 -; CHECK-NEXT: br i1 [[TMP0]], label [[SWITCH_LOOKUP:%.*]], label [[RETURN:%.*]] -; CHECK: switch.lookup: -; CHECK-NEXT: [[SWITCH_IDX_CAST:%.*]] = trunc i32 [[SWITCH_TABLEIDX]] to i8 -; CHECK-NEXT: ret i8 [[SWITCH_IDX_CAST]] -; CHECK: return: -; CHECK-NEXT: ret i8 3 -; entry: switch i32 %c, label %sw.default [ - i32 -2, label %return - i32 -1, label %sw.bb1 - i32 0, label %sw.bb2 - i32 1, label %sw.bb3 + i32 -2, label %return + i32 -1, label %sw.bb1 + i32 0, label %sw.bb2 + i32 1, label %sw.bb3 ] sw.bb1: br label %return sw.bb2: br label %return @@ -1326,26 +1154,22 @@ sw.default: br label %return return: %x = phi i8 [ 3, %sw.default ], [ 3, %sw.bb3 ], [ 2, %sw.bb2 ], [ 1, %sw.bb1 ], [ 0, %entry ] ret i8 %x +; CHECK-LABEL: @linearmap4( +; CHECK: entry: +; CHECK-NEXT: %switch.tableidx = sub i32 %c, -2 +; CHECK: switch.lookup: +; CHECK-NEXT: %switch.idx.cast = trunc i32 %switch.tableidx to i8 +; CHECK-NEXT: ret i8 %switch.idx.cast } ; Reuse the inverted table range compare. define i32 @reuse_cmp1(i32 %x) { -; CHECK-LABEL: @reuse_cmp1( -; CHECK-NEXT: entry: -; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i32 [[X:%.*]], 4 -; CHECK-NEXT: [[INVERTED_CMP:%.*]] = xor i1 [[TMP0]], true -; CHECK-NEXT: [[SWITCH_OFFSET:%.*]] = add i32 [[X]], 10 -; CHECK-NEXT: [[R_0:%.*]] = select i1 [[TMP0]], i32 [[SWITCH_OFFSET]], i32 0 -; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[R_0]], 0 -; CHECK-NEXT: [[DOTR_0:%.*]] = select i1 [[INVERTED_CMP]], i32 100, i32 [[R_0]] -; CHECK-NEXT: ret i32 [[DOTR_0]] -; entry: switch i32 %x, label %sw.default [ - i32 0, label %sw.bb - i32 1, label %sw.bb1 - i32 2, label %sw.bb2 - i32 3, label %sw.bb3 + i32 0, label %sw.bb + i32 1, label %sw.bb1 + i32 2, label %sw.bb2 + i32 3, label %sw.bb3 ] sw.bb: br label %sw.epilog sw.bb1: br label %sw.epilog @@ -1361,24 +1185,22 @@ if.end: br label %return return: %retval.0 = phi i32 [ 100, %if.then ], [ %r.0, %if.end ] ret i32 %retval.0 +; CHECK-LABEL: @reuse_cmp1( +; CHECK: entry: +; CHECK-NEXT: [[C:%.+]] = icmp ult i32 %x, 4 +; CHECK-NEXT: %inverted.cmp = xor i1 [[C]], true +; CHECK: [[R:%.+]] = select i1 %inverted.cmp, i32 100, i32 {{.*}} +; CHECK-NEXT: ret i32 [[R]] } ; Reuse the table range compare. define i32 @reuse_cmp2(i32 %x) { -; CHECK-LABEL: @reuse_cmp2( -; CHECK-NEXT: entry: -; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i32 [[X:%.*]], 4 -; CHECK-NEXT: [[X_:%.*]] = select i1 [[TMP0]], i32 [[X]], i32 4 -; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[X_]], 4 -; CHECK-NEXT: [[RETVAL_0:%.*]] = select i1 [[TMP0]], i32 [[X_]], i32 100 -; CHECK-NEXT: ret i32 [[RETVAL_0]] -; entry: switch i32 %x, label %sw.default [ - i32 0, label %sw.bb - i32 1, label %sw.bb1 - i32 2, label %sw.bb2 - i32 3, label %sw.bb3 + i32 0, label %sw.bb + i32 1, label %sw.bb1 + i32 2, label %sw.bb2 + i32 3, label %sw.bb3 ] sw.bb: br label %sw.epilog sw.bb1: br label %sw.epilog @@ -1394,26 +1216,24 @@ if.end: br label %return return: %retval.0 = phi i32 [ %r.0, %if.then ], [ 100, %if.end ] ret i32 %retval.0 +; CHECK-LABEL: @reuse_cmp2( +; CHECK: entry: +; CHECK-NEXT: %0 = icmp ult i32 %x, 4 +; CHECK-NEXT: %x. = select i1 %0, i32 %x, i32 4 +; CHECK-NEXT: [[C:%.+]] = icmp ne i32 %x., 4 +; CHECK: [[R:%.+]] = select i1 %0, i32 {{.*}}, i32 100 +; CHECK-NEXT: ret i32 [[R]] } ; Cannot reuse the table range compare, because the default value is the same ; as one of the case values. define i32 @no_reuse_cmp(i32 %x) { -; CHECK-LABEL: @no_reuse_cmp( -; CHECK-NEXT: entry: -; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i32 [[X:%.*]], 4 -; CHECK-NEXT: [[SWITCH_OFFSET:%.*]] = add i32 [[X]], 10 -; CHECK-NEXT: [[R_0:%.*]] = select i1 [[TMP0]], i32 [[SWITCH_OFFSET]], i32 12 -; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[R_0]], 0 -; CHECK-NEXT: [[R_0_:%.*]] = select i1 [[CMP]], i32 [[R_0]], i32 100 -; CHECK-NEXT: ret i32 [[R_0_]] -; entry: switch i32 %x, label %sw.default [ - i32 0, label %sw.bb - i32 1, label %sw.bb1 - i32 2, label %sw.bb2 - i32 3, label %sw.bb3 + i32 0, label %sw.bb + i32 1, label %sw.bb1 + i32 2, label %sw.bb2 + i32 3, label %sw.bb3 ] sw.bb: br label %sw.epilog sw.bb1: br label %sw.epilog @@ -1429,35 +1249,25 @@ if.end: br label %return return: %retval.0 = phi i32 [ %r.0, %if.then ], [ 100, %if.end ] ret i32 %retval.0 +; CHECK-LABEL: @no_reuse_cmp( +; CHECK: [[S:%.+]] = select +; CHECK-NEXT: %cmp = icmp ne i32 [[S]], 0 +; CHECK-NEXT: [[R:%.+]] = select i1 %cmp, i32 [[S]], i32 100 +; CHECK-NEXT: ret i32 [[R]] } ; Cannot reuse the table range compare, because the phi at the switch merge ; point is not dominated by the switch. define i32 @no_reuse_cmp2(i32 %x, i32 %y) { -; CHECK-LABEL: @no_reuse_cmp2( -; CHECK-NEXT: entry: -; CHECK-NEXT: [[EC:%.*]] = icmp ne i32 [[Y:%.*]], 0 -; CHECK-NEXT: br i1 [[EC]], label [[SWITCH_ENTRY:%.*]], label [[SW_EPILOG:%.*]] -; CHECK: switch.entry: -; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i32 [[X:%.*]], 4 -; CHECK-NEXT: [[SWITCH_OFFSET:%.*]] = add i32 [[X]], 10 -; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[TMP0]], i32 [[SWITCH_OFFSET]], i32 0 -; CHECK-NEXT: br label [[SW_EPILOG]] -; CHECK: sw.epilog: -; CHECK-NEXT: [[R_0:%.*]] = phi i32 [ 100, [[ENTRY:%.*]] ], [ [[SPEC_SELECT]], [[SWITCH_ENTRY]] ] -; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[R_0]], 0 -; CHECK-NEXT: [[DOTR_0:%.*]] = select i1 [[CMP]], i32 100, i32 [[R_0]] -; CHECK-NEXT: ret i32 [[DOTR_0]] -; entry: %ec = icmp ne i32 %y, 0 br i1 %ec, label %switch.entry, label %sw.epilog switch.entry: switch i32 %x, label %sw.default [ - i32 0, label %sw.bb - i32 1, label %sw.bb1 - i32 2, label %sw.bb2 - i32 3, label %sw.bb3 + i32 0, label %sw.bb + i32 1, label %sw.bb1 + i32 2, label %sw.bb2 + i32 3, label %sw.bb3 ] sw.bb: br label %sw.epilog sw.bb1: br label %sw.epilog @@ -1473,49 +1283,28 @@ if.end: br label %return return: %retval.0 = phi i32 [ 100, %if.then ], [ %r.0, %if.end ] ret i32 %retval.0 +; CHECK-LABEL: @no_reuse_cmp2( +; CHECK: %r.0 = phi +; CHECK-NEXT: %cmp = icmp eq i32 %r.0, 0 +; CHECK-NEXT: [[R:%.+]] = select i1 %cmp +; CHECK-NEXT: ret i32 [[R]] } define void @pr20210(i8 %x, i1 %y) { ; %z has uses outside of its BB or the phi it feeds into, ; so doing a table lookup and jumping directly to while.cond would ; cause %z to cease dominating all its uses. -; CHECK-LABEL: @pr20210( -; CHECK-NEXT: entry: -; CHECK-NEXT: br i1 [[Y:%.*]], label [[SW:%.*]], label [[INTERMEDIATE:%.*]] -; CHECK: sw: -; CHECK-NEXT: switch i8 [[X:%.*]], label [[END:%.*]] [ -; CHECK-NEXT: i8 7, label [[INTERMEDIATE]] -; CHECK-NEXT: i8 3, label [[INTERMEDIATE]] -; CHECK-NEXT: i8 2, label [[INTERMEDIATE]] -; CHECK-NEXT: i8 1, label [[INTERMEDIATE]] -; CHECK-NEXT: i8 0, label [[INTERMEDIATE]] -; CHECK-NEXT: ] -; CHECK: intermediate: -; CHECK-NEXT: [[Z:%.*]] = zext i8 [[X]] to i32 -; CHECK-NEXT: br label [[WHILE_COND:%.*]] -; CHECK: while.cond: -; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[Z]], [[INTERMEDIATE]] ], [ [[J:%.*]], [[WHILE_BODY:%.*]] ] -; CHECK-NEXT: [[B:%.*]] = icmp ne i32 [[I]], 7 -; CHECK-NEXT: br i1 [[B]], label [[WHILE_BODY]], label [[WHILE_END:%.*]] -; CHECK: while.body: -; CHECK-NEXT: [[J]] = add i32 [[I]], 1 -; CHECK-NEXT: br label [[WHILE_COND]] -; CHECK: while.end: -; CHECK-NEXT: call void @exit(i32 [[Z]]) -; CHECK-NEXT: unreachable -; CHECK: end: -; CHECK-NEXT: ret void -; + entry: br i1 %y, label %sw, label %intermediate sw: switch i8 %x, label %end [ - i8 7, label %intermediate - i8 3, label %intermediate - i8 2, label %intermediate - i8 1, label %intermediate - i8 0, label %intermediate + i8 7, label %intermediate + i8 3, label %intermediate + i8 2, label %intermediate + i8 1, label %intermediate + i8 0, label %intermediate ] intermediate: @@ -1537,6 +1326,8 @@ while.end: end: ret void +; CHECK-LABEL: @pr20210 +; CHECK: switch i8 %x } ; Make sure we do not crash due to trying to generate an unguarded @@ -1544,28 +1335,12 @@ end: ; values) and simultaneously trying to generate a branch to deal with ; the fact that we have holes in the range. define i32 @covered_switch_with_bit_tests(i3) { -; CHECK-LABEL: @covered_switch_with_bit_tests( -; CHECK-NEXT: entry: -; CHECK-NEXT: [[SWITCH_TABLEIDX:%.*]] = sub i3 [[TMP0:%.*]], -4 -; CHECK-NEXT: [[SWITCH_MASKINDEX:%.*]] = zext i3 [[SWITCH_TABLEIDX]] to i8 -; CHECK-NEXT: [[SWITCH_SHIFTED:%.*]] = lshr i8 -61, [[SWITCH_MASKINDEX]] -; CHECK-NEXT: [[SWITCH_LOBIT:%.*]] = trunc i8 [[SWITCH_SHIFTED]] to i1 -; CHECK-NEXT: br i1 [[SWITCH_LOBIT]], label [[SWITCH_LOOKUP:%.*]], label [[L6:%.*]] -; CHECK: switch.lookup: -; CHECK-NEXT: [[SWITCH_TABLEIDX_ZEXT:%.*]] = zext i3 [[SWITCH_TABLEIDX]] to i4 -; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [8 x i32], [8 x i32]* @switch.table.covered_switch_with_bit_tests, i32 0, i4 [[SWITCH_TABLEIDX_ZEXT]] -; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i32, i32* [[SWITCH_GEP]] -; CHECK-NEXT: br label [[L6]] -; CHECK: l6: -; CHECK-NEXT: [[R:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[SWITCH_LOAD]], [[SWITCH_LOOKUP]] ] -; CHECK-NEXT: ret i32 [[R]] -; entry: switch i3 %0, label %l6 [ - i3 -3, label %l5 - i3 -4, label %l5 - i3 3, label %l1 - i3 2, label %l1 + i3 -3, label %l5 + i3 -4, label %l5 + i3 3, label %l1 + i3 2, label %l1 ] l1: br label %l2 @@ -1579,17 +1354,18 @@ l5: br label %l2 l6: %r = phi i32 [ %x, %l2 ], [ 0, %entry ] ret i32 %r +; CHECK-LABEL: @covered_switch_with_bit_tests +; CHECK: entry +; CHECK-NEXT: switch } ; Speculation depth must be limited to avoid a zero-cost instruction cycle. -define i32 @PR26308(i1 %B, i64 %load) { ; CHECK-LABEL: @PR26308( -; CHECK-NEXT: entry: -; CHECK-NEXT: br label [[CLEANUP4:%.*]] ; CHECK: cleanup4: -; CHECK-NEXT: br label [[CLEANUP4]] -; +; CHECK-NEXT: br label %cleanup4 + +define i32 @PR26308(i1 %B, i64 %load) { entry: br label %while.body @@ -1617,32 +1393,9 @@ cleanup4: declare void @throw(i1) define void @wineh_test(i64 %val) personality i32 (...)* @__CxxFrameHandler3 { -; CHECK-LABEL: @wineh_test( -; CHECK-NEXT: entry: -; CHECK-NEXT: invoke void @throw(i1 false) -; CHECK-NEXT: to label [[UNREACHABLE:%.*]] unwind label [[CLEANUP1:%.*]] -; CHECK: unreachable: -; CHECK-NEXT: unreachable -; CHECK: cleanup1: -; CHECK-NEXT: [[CLEANUPPAD1:%.*]] = cleanuppad within none [] -; CHECK-NEXT: switch i64 [[VAL:%.*]], label [[CLEANUPDONE2:%.*]] [ -; CHECK-NEXT: i64 0, label [[CLEANUPDONE1:%.*]] -; CHECK-NEXT: i64 1, label [[CLEANUPDONE1]] -; CHECK-NEXT: i64 6, label [[CLEANUPDONE1]] -; CHECK-NEXT: ] -; CHECK: cleanupdone1: -; CHECK-NEXT: cleanupret from [[CLEANUPPAD1]] unwind label [[CLEANUP2:%.*]] -; CHECK: cleanupdone2: -; CHECK-NEXT: cleanupret from [[CLEANUPPAD1]] unwind label [[CLEANUP2]] -; CHECK: cleanup2: -; CHECK-NEXT: [[PHI:%.*]] = phi i1 [ true, [[CLEANUPDONE1]] ], [ false, [[CLEANUPDONE2]] ] -; CHECK-NEXT: [[CLEANUPPAD2:%.*]] = cleanuppad within none [] -; CHECK-NEXT: call void @throw(i1 [[PHI]]) [ "funclet"(token [[CLEANUPPAD2]]) ] -; CHECK-NEXT: unreachable -; entry: invoke void @throw(i1 false) - to label %unreachable unwind label %cleanup1 + to label %unreachable unwind label %cleanup1 unreachable: unreachable @@ -1650,9 +1403,9 @@ unreachable: cleanup1: %cleanuppad1 = cleanuppad within none [] switch i64 %val, label %cleanupdone2 [ - i64 0, label %cleanupdone1 - i64 1, label %cleanupdone1 - i64 6, label %cleanupdone1 + i64 0, label %cleanupdone1 + i64 1, label %cleanupdone1 + i64 6, label %cleanupdone1 ] cleanupdone1: @@ -1668,4 +1421,32 @@ cleanup2: unreachable } +; CHECK-LABEL: @wineh_test( +; CHECK: entry: +; CHECK: invoke void @throw(i1 false) +; CHECK: to label %[[unreachable:.*]] unwind label %[[cleanup1:.*]] + +; CHECK: [[unreachable]]: +; CHECK: unreachable + +; CHECK: [[cleanup1]]: +; CHECK: %[[cleanuppad1:.*]] = cleanuppad within none [] +; CHECK: switch i64 %val, label %[[cleanupdone2:.*]] [ +; CHECK: i64 0, label %[[cleanupdone1:.*]] +; CHECK: i64 1, label %[[cleanupdone1]] +; CHECK: i64 6, label %[[cleanupdone1]] +; CHECK: ] + +; CHECK: [[cleanupdone1]]: +; CHECK: cleanupret from %[[cleanuppad1]] unwind label %[[cleanup2:.*]] + +; CHECK: [[cleanupdone2]]: +; CHECK: cleanupret from %[[cleanuppad1]] unwind label %[[cleanup2]] + +; CHECK: [[cleanup2]]: +; CHECK: %[[phi:.*]] = phi i1 [ true, %[[cleanupdone1]] ], [ false, %[[cleanupdone2]] ] +; CHECK: %[[cleanuppad2:.*]] = cleanuppad within none [] +; CHECK: call void @throw(i1 %[[phi]]) [ "funclet"(token %[[cleanuppad2]]) ] +; CHECK: unreachable + declare i32 @__CxxFrameHandler3(...) diff --git a/llvm/test/Transforms/SimplifyCFG/switch-dead-default.ll b/llvm/test/Transforms/SimplifyCFG/switch-dead-default.ll index 7f713182fde..77d7e748c78 100644 --- a/llvm/test/Transforms/SimplifyCFG/switch-dead-default.ll +++ b/llvm/test/Transforms/SimplifyCFG/switch-dead-default.ll @@ -1,22 +1,11 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -; RUN: opt %s -S -passes='simplify-cfg<switch-to-lookup>' | FileCheck %s -target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +; RUN: opt %s -S -simplifycfg | FileCheck %s declare void @foo(i32) define void @test(i1 %a) { -; CHECK-LABEL: @test( -; CHECK-NEXT: [[A_OFF:%.*]] = add i1 [[A:%.*]], true -; CHECK-NEXT: [[SWITCH:%.*]] = icmp ult i1 [[A_OFF]], true -; CHECK-NEXT: br i1 [[SWITCH]], label [[TRUE:%.*]], label [[FALSE:%.*]] -; CHECK: true: -; CHECK-NEXT: call void @foo(i32 1) -; CHECK-NEXT: ret void -; CHECK: false: -; CHECK-NEXT: call void @foo(i32 3) -; CHECK-NEXT: ret void -; +; CHECK-LABEL: @test +; CHECK: br i1 [[IGNORE:%.*]], label %true, label %false switch i1 %a, label %default [i1 1, label %true - i1 0, label %false] + i1 0, label %false] true: call void @foo(i32 1) ret void @@ -26,35 +15,14 @@ false: default: call void @foo(i32 2) ret void -} +} define void @test2(i2 %a) { -; CHECK-LABEL: @test2( -; CHECK-NEXT: switch i2 [[A:%.*]], label [[DEFAULT1:%.*]] [ -; CHECK-NEXT: i2 0, label [[CASE0:%.*]] -; CHECK-NEXT: i2 1, label [[CASE1:%.*]] -; CHECK-NEXT: i2 -2, label [[CASE2:%.*]] -; CHECK-NEXT: i2 -1, label [[CASE3:%.*]] -; CHECK-NEXT: ] -; CHECK: case0: -; CHECK-NEXT: call void @foo(i32 0) -; CHECK-NEXT: ret void -; CHECK: case1: -; CHECK-NEXT: call void @foo(i32 1) -; CHECK-NEXT: ret void -; CHECK: case2: -; CHECK-NEXT: call void @foo(i32 2) -; CHECK-NEXT: ret void -; CHECK: case3: -; CHECK-NEXT: call void @foo(i32 3) -; CHECK-NEXT: ret void -; CHECK: default1: -; CHECK-NEXT: unreachable -; +; CHECK-LABEL: @test2 switch i2 %a, label %default [i2 0, label %case0 - i2 1, label %case1 - i2 2, label %case2 - i2 3, label %case3] + i2 1, label %case1 + i2 2, label %case2 + i2 3, label %case3] case0: call void @foo(i32 0) ret void @@ -68,35 +36,19 @@ case3: call void @foo(i32 3) ret void default: +; CHECK-LABEL: default1: +; CHECK-NEXT: unreachable call void @foo(i32 4) ret void -} +} ; This one is a negative test - we know the value of the default, ; but that's about it define void @test3(i2 %a) { -; CHECK-LABEL: @test3( -; CHECK-NEXT: switch i2 [[A:%.*]], label [[DEFAULT:%.*]] [ -; CHECK-NEXT: i2 0, label [[CASE0:%.*]] -; CHECK-NEXT: i2 1, label [[CASE1:%.*]] -; CHECK-NEXT: i2 -2, label [[CASE2:%.*]] -; CHECK-NEXT: ] -; CHECK: case0: -; CHECK-NEXT: call void @foo(i32 0) -; CHECK-NEXT: ret void -; CHECK: case1: -; CHECK-NEXT: call void @foo(i32 1) -; CHECK-NEXT: ret void -; CHECK: case2: -; CHECK-NEXT: call void @foo(i32 2) -; CHECK-NEXT: ret void -; CHECK: default: -; CHECK-NEXT: call void @foo(i32 0) -; CHECK-NEXT: ret void -; +; CHECK-LABEL: @test3 switch i2 %a, label %default [i2 0, label %case0 - i2 1, label %case1 - i2 2, label %case2] + i2 1, label %case1 + i2 2, label %case2] case0: call void @foo(i32 0) @@ -108,30 +60,18 @@ case2: call void @foo(i32 2) ret void default: +; CHECK-LABEL: default: +; CHECK-NEXT: call void @foo call void @foo(i32 0) ret void -} +} ; Negative test - check for possible overflow when computing ; number of possible cases. define void @test4(i128 %a) { -; CHECK-LABEL: @test4( -; CHECK-NEXT: switch i128 [[A:%.*]], label [[DEFAULT:%.*]] [ -; CHECK-NEXT: i128 0, label [[CASE0:%.*]] -; CHECK-NEXT: i128 1, label [[CASE1:%.*]] -; CHECK-NEXT: ] -; CHECK: case0: -; CHECK-NEXT: call void @foo(i32 0) -; CHECK-NEXT: ret void -; CHECK: case1: -; CHECK-NEXT: call void @foo(i32 1) -; CHECK-NEXT: ret void -; CHECK: default: -; CHECK-NEXT: call void @foo(i32 0) -; CHECK-NEXT: ret void -; +; CHECK-LABEL: @test4 switch i128 %a, label %default [i128 0, label %case0 - i128 1, label %case1] + i128 1, label %case1] case0: call void @foo(i32 0) @@ -140,29 +80,20 @@ case1: call void @foo(i32 1) ret void default: +; CHECK-LABEL: default: +; CHECK-NEXT: call void @foo call void @foo(i32 0) ret void -} +} ; All but one bit known zero define void @test5(i8 %a) { -; CHECK-LABEL: @test5( -; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[A:%.*]], 2 -; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]]) -; CHECK-NEXT: [[A_OFF:%.*]] = add i8 [[A]], -1 -; CHECK-NEXT: [[SWITCH:%.*]] = icmp ult i8 [[A_OFF]], 1 -; CHECK-NEXT: br i1 [[SWITCH]], label [[TRUE:%.*]], label [[FALSE:%.*]] -; CHECK: true: -; CHECK-NEXT: call void @foo(i32 1) -; CHECK-NEXT: ret void -; CHECK: false: -; CHECK-NEXT: call void @foo(i32 3) -; CHECK-NEXT: ret void -; - %cmp = icmp ult i8 %a, 2 +; CHECK-LABEL: @test5 +; CHECK: br i1 [[IGNORE:%.*]], label %true, label %false + %cmp = icmp ult i8 %a, 2 call void @llvm.assume(i1 %cmp) switch i8 %a, label %default [i8 1, label %true - i8 0, label %false] + i8 0, label %false] true: call void @foo(i32 1) ret void @@ -172,29 +103,18 @@ false: default: call void @foo(i32 2) ret void -} +} ;; All but one bit known one define void @test6(i8 %a) { -; CHECK-LABEL: @test6( -; CHECK-NEXT: [[AND:%.*]] = and i8 [[A:%.*]], -2 -; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[AND]], -2 -; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]]) -; CHECK-NEXT: [[A_OFF:%.*]] = add i8 [[A]], 1 -; CHECK-NEXT: [[SWITCH:%.*]] = icmp ult i8 [[A_OFF]], 1 -; CHECK-NEXT: br i1 [[SWITCH]], label [[TRUE:%.*]], label [[FALSE:%.*]] -; CHECK: true: -; CHECK-NEXT: call void @foo(i32 1) -; CHECK-NEXT: ret void -; CHECK: false: -; CHECK-NEXT: call void @foo(i32 3) -; CHECK-NEXT: ret void -; +; CHECK-LABEL: @test6 +; CHECK: @llvm.assume +; CHECK: br i1 [[IGNORE:%.*]], label %true, label %false %and = and i8 %a, 254 - %cmp = icmp eq i8 %and, 254 + %cmp = icmp eq i8 %and, 254 call void @llvm.assume(i1 %cmp) switch i8 %a, label %default [i8 255, label %true - i8 254, label %false] + i8 254, label %false] true: call void @foo(i32 1) ret void @@ -209,26 +129,15 @@ default: ; Check that we can eliminate both dead cases and dead defaults ; within a single run of simplify-cfg define void @test7(i8 %a) { -; CHECK-LABEL: @test7( -; CHECK-NEXT: [[AND:%.*]] = and i8 [[A:%.*]], -2 -; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[AND]], -2 -; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]]) -; CHECK-NEXT: [[A_OFF:%.*]] = add i8 [[A]], 1 -; CHECK-NEXT: [[SWITCH:%.*]] = icmp ult i8 [[A_OFF]], 1 -; CHECK-NEXT: br i1 [[SWITCH]], label [[TRUE:%.*]], label [[FALSE:%.*]] -; CHECK: true: -; CHECK-NEXT: call void @foo(i32 1) -; CHECK-NEXT: ret void -; CHECK: false: -; CHECK-NEXT: call void @foo(i32 3) -; CHECK-NEXT: ret void -; +; CHECK-LABEL: @test7 +; CHECK: @llvm.assume +; CHECK: br i1 [[IGNORE:%.*]], label %true, label %false %and = and i8 %a, 254 - %cmp = icmp eq i8 %and, 254 + %cmp = icmp eq i8 %and, 254 call void @llvm.assume(i1 %cmp) switch i8 %a, label %default [i8 255, label %true - i8 254, label %false - i8 0, label %also_dead] + i8 254, label %false + i8 0, label %also_dead] true: call void @foo(i32 1) ret void diff --git a/llvm/test/Transforms/SimplifyCFG/switch-masked-bits.ll b/llvm/test/Transforms/SimplifyCFG/switch-masked-bits.ll index 21cecc5c942..2d46aac23f6 100644 --- a/llvm/test/Transforms/SimplifyCFG/switch-masked-bits.ll +++ b/llvm/test/Transforms/SimplifyCFG/switch-masked-bits.ll @@ -4,10 +4,10 @@ define i32 @test1(i32 %x) nounwind { ; CHECK-LABEL: @test1( ; CHECK-NEXT: a: -; CHECK-NEXT: [[I:%.*]] = shl i32 [[X:%.*]], 1 +; CHECK-NEXT: [[I:%.*]] = shl i32 %x, 1 ; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[I]], 24 -; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[COND]], i32 5, i32 0 -; CHECK-NEXT: ret i32 [[SPEC_SELECT]] +; CHECK-NEXT: [[DOT:%.*]] = select i1 [[COND]], i32 5, i32 0 +; CHECK-NEXT: ret i32 [[DOT]] ; %i = shl i32 %x, 1 switch i32 %i, label %a [ @@ -48,19 +48,12 @@ c: define i1 @repeated_signbits(i8 %condition) { ; CHECK-LABEL: @repeated_signbits( -; CHECK-NEXT: entry: -; CHECK-NEXT: [[SEXT:%.*]] = sext i8 [[CONDITION:%.*]] to i32 -; CHECK-NEXT: switch i32 [[SEXT]], label [[DEFAULT:%.*]] [ -; CHECK-NEXT: i32 0, label [[A:%.*]] -; CHECK-NEXT: i32 127, label [[A]] -; CHECK-NEXT: i32 -128, label [[A]] -; CHECK-NEXT: i32 -1, label [[A]] +; CHECK: switch i32 +; CHECK-DAG: i32 -128, label %a +; CHECK-DAG: i32 -1, label %a +; CHECK-DAG: i32 0, label %a +; CHECK-DAG: i32 127, label %a ; CHECK-NEXT: ] -; CHECK: a: -; CHECK-NEXT: [[MERGE:%.*]] = phi i1 [ true, [[ENTRY:%.*]] ], [ true, [[ENTRY]] ], [ true, [[ENTRY]] ], [ true, [[ENTRY]] ], [ false, [[DEFAULT]] ] -; CHECK-NEXT: ret i1 [[MERGE]] -; CHECK: default: -; CHECK-NEXT: br label [[A]] ; entry: %sext = sext i8 %condition to i32 diff --git a/llvm/test/Transforms/SimplifyCFG/switch-on-const-select.ll b/llvm/test/Transforms/SimplifyCFG/switch-on-const-select.ll index 98c434a5a0e..165e5b264ae 100644 --- a/llvm/test/Transforms/SimplifyCFG/switch-on-const-select.ll +++ b/llvm/test/Transforms/SimplifyCFG/switch-on-const-select.ll @@ -1,158 +1,141 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt < %s -simplifycfg -S | FileCheck -enable-var-scope %s ; Test basic folding to a conditional branch. define i32 @foo(i64 %x, i64 %y) nounwind { ; CHECK-LABEL: @foo( -; CHECK-NEXT: entry: -; CHECK-NEXT: [[EQ:%.*]] = icmp eq i64 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: br i1 [[EQ]], label [[B:%.*]], label [[SWITCH:%.*]] -; CHECK: switch: -; CHECK-NEXT: [[LT:%.*]] = icmp slt i64 [[X]], [[Y]] -; CHECK-NEXT: br i1 [[LT]], label [[A:%.*]], label [[B]] -; CHECK: a: -; CHECK-NEXT: tail call void @bees.a() #0 -; CHECK-NEXT: ret i32 1 -; CHECK: b: -; CHECK-NEXT: [[RETVAL:%.*]] = phi i32 [ 0, [[SWITCH]] ], [ 2, [[ENTRY:%.*]] ] -; CHECK-NEXT: tail call void @bees.b() #0 -; CHECK-NEXT: ret i32 [[RETVAL]] -; entry: - %eq = icmp eq i64 %x, %y - br i1 %eq, label %b, label %switch + %eq = icmp eq i64 %x, %y + br i1 %eq, label %b, label %switch switch: - %lt = icmp slt i64 %x, %y - %qux = select i1 %lt, i32 0, i32 2 - switch i32 %qux, label %bees [ - i32 0, label %a - i32 1, label %b - i32 2, label %b - ] + %lt = icmp slt i64 %x, %y +; CHECK: br i1 %lt, label %a, label %b + %qux = select i1 %lt, i32 0, i32 2 + switch i32 %qux, label %bees [ + i32 0, label %a + i32 1, label %b + i32 2, label %b + ] a: - tail call void @bees.a() nounwind - ret i32 1 + tail call void @bees.a() nounwind + ret i32 1 +; CHECK: b: +; CHECK-NEXT: %retval = phi i32 [ 0, %switch ], [ 2, %entry ] b: - %retval = phi i32 [0, %switch], [0, %switch], [2, %entry] - tail call void @bees.b() nounwind - ret i32 %retval + %retval = phi i32 [0, %switch], [0, %switch], [2, %entry] + tail call void @bees.b() nounwind + ret i32 %retval +; CHECK-NOT: bees: bees: - tail call void @llvm.trap() nounwind - unreachable + tail call void @llvm.trap() nounwind + unreachable } ; Test basic folding to an unconditional branch. define i32 @bar(i64 %x, i64 %y) nounwind { ; CHECK-LABEL: @bar( -; CHECK-NEXT: entry: -; CHECK-NEXT: tail call void @bees.a() #0 -; CHECK-NEXT: ret i32 0 -; entry: - %lt = icmp slt i64 %x, %y - %qux = select i1 %lt, i32 0, i32 2 - switch i32 %qux, label %bees [ - i32 0, label %a - i32 1, label %b - i32 2, label %a - ] +; CHECK-NEXT: entry: +; CHECK-NEXT: tail call void @bees.a() [[$NUW:#[0-9]+]] +; CHECK-NEXT: ret i32 0 + %lt = icmp slt i64 %x, %y + %qux = select i1 %lt, i32 0, i32 2 + switch i32 %qux, label %bees [ + i32 0, label %a + i32 1, label %b + i32 2, label %a + ] a: - %retval = phi i32 [0, %entry], [0, %entry], [1, %b] - tail call void @bees.a() nounwind - ret i32 0 + %retval = phi i32 [0, %entry], [0, %entry], [1, %b] + tail call void @bees.a() nounwind + ret i32 0 b: - tail call void @bees.b() nounwind - br label %a + tail call void @bees.b() nounwind + br label %a bees: - tail call void @llvm.trap() nounwind - unreachable + tail call void @llvm.trap() nounwind + unreachable } ; Test the edge case where both values from the select are the default case. define void @bazz(i64 %x, i64 %y) nounwind { ; CHECK-LABEL: @bazz( -; CHECK-NEXT: entry: -; CHECK-NEXT: tail call void @bees.b() #0 -; CHECK-NEXT: ret void -; entry: - %lt = icmp slt i64 %x, %y - %qux = select i1 %lt, i32 10, i32 12 - switch i32 %qux, label %b [ - i32 0, label %a - i32 1, label %bees - i32 2, label %bees - ] +; CHECK-NEXT: entry: +; CHECK-NEXT: tail call void @bees.b() [[$NUW]] +; CHECK-NEXT: ret void + %lt = icmp slt i64 %x, %y + %qux = select i1 %lt, i32 10, i32 12 + switch i32 %qux, label %b [ + i32 0, label %a + i32 1, label %bees + i32 2, label %bees + ] a: - tail call void @bees.a() nounwind - ret void + tail call void @bees.a() nounwind + ret void b: - tail call void @bees.b() nounwind - ret void + tail call void @bees.b() nounwind + ret void bees: - tail call void @llvm.trap() - unreachable + tail call void @llvm.trap() + unreachable } ; Test the edge case where both values from the select are equal. define void @quux(i64 %x, i64 %y) nounwind { ; CHECK-LABEL: @quux( -; CHECK-NEXT: entry: -; CHECK-NEXT: tail call void @bees.a() #0 -; CHECK-NEXT: ret void -; entry: - %lt = icmp slt i64 %x, %y - %qux = select i1 %lt, i32 0, i32 0 - switch i32 %qux, label %b [ - i32 0, label %a - i32 1, label %bees - i32 2, label %bees - ] +; CHECK-NEXT: entry: +; CHECK-NEXT: tail call void @bees.a() [[$NUW]] +; CHECK-NEXT: ret void + %lt = icmp slt i64 %x, %y + %qux = select i1 %lt, i32 0, i32 0 + switch i32 %qux, label %b [ + i32 0, label %a + i32 1, label %bees + i32 2, label %bees + ] a: - tail call void @bees.a() nounwind - ret void + tail call void @bees.a() nounwind + ret void b: - tail call void @bees.b() nounwind - ret void + tail call void @bees.b() nounwind + ret void bees: - tail call void @llvm.trap() - unreachable + tail call void @llvm.trap() + unreachable } ; A final test, for phi node munging. define i32 @xyzzy(i64 %x, i64 %y) { ; CHECK-LABEL: @xyzzy( -; CHECK-NEXT: entry: -; CHECK-NEXT: [[EQ:%.*]] = icmp eq i64 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[LT:%.*]] = icmp slt i64 [[X]], [[Y]] -; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[LT]], i32 -1, i32 1 -; CHECK-NEXT: [[VAL:%.*]] = select i1 [[EQ]], i32 0, i32 [[SPEC_SELECT]] -; CHECK-NEXT: ret i32 [[VAL]] -; entry: - %eq = icmp eq i64 %x, %y - br i1 %eq, label %r, label %cont + %eq = icmp eq i64 %x, %y + br i1 %eq, label %r, label %cont cont: - %lt = icmp slt i64 %x, %y - %qux = select i1 %lt, i32 0, i32 2 - switch i32 %qux, label %bees [ - i32 0, label %a - i32 1, label %r - i32 2, label %r - ] +; CHECK: %lt = icmp slt i64 %x, %y + %lt = icmp slt i64 %x, %y +; CHECK-NEXT: select i1 %lt, i32 -1, i32 1 + %qux = select i1 %lt, i32 0, i32 2 + switch i32 %qux, label %bees [ + i32 0, label %a + i32 1, label %r + i32 2, label %r + ] r: - %val = phi i32 [0, %entry], [1, %cont], [1, %cont] - ret i32 %val + %val = phi i32 [0, %entry], [1, %cont], [1, %cont] + ret i32 %val a: - ret i32 -1 + ret i32 -1 +; CHECK-NOT: bees: bees: - tail call void @llvm.trap() - unreachable + tail call void @llvm.trap() + unreachable } declare void @llvm.trap() nounwind noreturn declare void @bees.a() nounwind declare void @bees.b() nounwind +; CHECK: attributes [[$NUW]] = { nounwind } ; CHECK: attributes #1 = { cold noreturn nounwind } diff --git a/llvm/test/Transforms/SimplifyCFG/switch-range-to-icmp.ll b/llvm/test/Transforms/SimplifyCFG/switch-range-to-icmp.ll index c0f6a43fda3..a109b317c73 100644 --- a/llvm/test/Transforms/SimplifyCFG/switch-range-to-icmp.ll +++ b/llvm/test/Transforms/SimplifyCFG/switch-range-to-icmp.ll @@ -1,27 +1,18 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt %s -simplifycfg -S | FileCheck %s declare i32 @f(i32) define i32 @basic(i32 %x) { -; CHECK-LABEL: @basic( -; CHECK-NEXT: entry: -; CHECK-NEXT: [[X_OFF:%.*]] = add i32 [[X:%.*]], -5 -; CHECK-NEXT: [[SWITCH:%.*]] = icmp ult i32 [[X_OFF]], 3 -; CHECK-NEXT: br i1 [[SWITCH]], label [[A:%.*]], label [[DEFAULT:%.*]] -; CHECK: default: -; CHECK-NEXT: [[TMP0:%.*]] = call i32 @f(i32 0) -; CHECK-NEXT: ret i32 [[TMP0]] -; CHECK: a: -; CHECK-NEXT: [[TMP1:%.*]] = call i32 @f(i32 1) -; CHECK-NEXT: ret i32 [[TMP1]] -; +; CHECK-LABEL: @basic +; CHECK: x.off = add i32 %x, -5 +; CHECK: %switch = icmp ult i32 %x.off, 3 +; CHECK: br i1 %switch, label %a, label %default entry: switch i32 %x, label %default [ - i32 5, label %a - i32 6, label %a - i32 7, label %a + i32 5, label %a + i32 6, label %a + i32 7, label %a ] default: %0 = call i32 @f(i32 0) @@ -33,28 +24,20 @@ a: define i32 @unreachable(i32 %x) { -; CHECK-LABEL: @unreachable( -; CHECK-NEXT: entry: -; CHECK-NEXT: [[X_OFF:%.*]] = add i32 [[X:%.*]], -5 -; CHECK-NEXT: [[SWITCH:%.*]] = icmp ult i32 [[X_OFF]], 3 -; CHECK-NEXT: br i1 [[SWITCH]], label [[A:%.*]], label [[B:%.*]] -; CHECK: a: -; CHECK-NEXT: [[TMP0:%.*]] = call i32 @f(i32 0) -; CHECK-NEXT: ret i32 [[TMP0]] -; CHECK: b: -; CHECK-NEXT: [[TMP1:%.*]] = call i32 @f(i32 1) -; CHECK-NEXT: ret i32 [[TMP1]] -; +; CHECK-LABEL: @unreachable +; CHECK: x.off = add i32 %x, -5 +; CHECK: %switch = icmp ult i32 %x.off, 3 +; CHECK: br i1 %switch, label %a, label %b entry: switch i32 %x, label %unreachable [ - i32 5, label %a - i32 6, label %a - i32 7, label %a - i32 10, label %b - i32 20, label %b - i32 30, label %b - i32 40, label %b + i32 5, label %a + i32 6, label %a + i32 7, label %a + i32 10, label %b + i32 20, label %b + i32 30, label %b + i32 40, label %b ] unreachable: unreachable @@ -68,28 +51,20 @@ b: define i32 @unreachable2(i32 %x) { -; CHECK-LABEL: @unreachable2( -; CHECK-NEXT: entry: -; CHECK-NEXT: [[X_OFF:%.*]] = add i32 [[X:%.*]], -5 -; CHECK-NEXT: [[SWITCH:%.*]] = icmp ult i32 [[X_OFF]], 3 -; CHECK-NEXT: br i1 [[SWITCH]], label [[A:%.*]], label [[B:%.*]] -; CHECK: a: -; CHECK-NEXT: [[TMP0:%.*]] = call i32 @f(i32 0) -; CHECK-NEXT: ret i32 [[TMP0]] -; CHECK: b: -; CHECK-NEXT: [[TMP1:%.*]] = call i32 @f(i32 1) -; CHECK-NEXT: ret i32 [[TMP1]] -; +; CHECK-LABEL: @unreachable2 +; CHECK: x.off = add i32 %x, -5 +; CHECK: %switch = icmp ult i32 %x.off, 3 +; CHECK: br i1 %switch, label %a, label %b entry: ; Note: folding the most popular case destination into the default ; would prevent switch-to-icmp here. switch i32 %x, label %unreachable [ - i32 5, label %a - i32 6, label %a - i32 7, label %a - i32 10, label %b - i32 20, label %b + i32 5, label %a + i32 6, label %a + i32 7, label %a + i32 10, label %b + i32 20, label %b ] unreachable: unreachable diff --git a/llvm/test/Transforms/SimplifyCFG/switch_create-custom-dl.ll b/llvm/test/Transforms/SimplifyCFG/switch_create-custom-dl.ll index 083cfe1ee29..7dce54d75d6 100644 --- a/llvm/test/Transforms/SimplifyCFG/switch_create-custom-dl.ll +++ b/llvm/test/Transforms/SimplifyCFG/switch_create-custom-dl.ll @@ -1,4 +1,3 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt -S -simplifycfg < %s | FileCheck %s target datalayout="p:40:64:64:32" @@ -7,151 +6,102 @@ declare void @foo1() declare void @foo2() define void @test1(i32 %V) { -; CHECK-LABEL: @test1( -; CHECK-NEXT: switch i32 [[V:%.*]], label [[F:%.*]] [ -; CHECK-NEXT: i32 17, label [[T:%.*]] -; CHECK-NEXT: i32 4, label [[T]] -; CHECK-NEXT: ] -; CHECK: T: -; CHECK-NEXT: call void @foo1() -; CHECK-NEXT: ret void -; CHECK: F: -; CHECK-NEXT: call void @foo2() -; CHECK-NEXT: ret void -; - %C1 = icmp eq i32 %V, 4 ; <i1> [#uses=1] - %C2 = icmp eq i32 %V, 17 ; <i1> [#uses=1] - %CN = or i1 %C1, %C2 ; <i1> [#uses=1] - br i1 %CN, label %T, label %F + %C1 = icmp eq i32 %V, 4 ; <i1> [#uses=1] + %C2 = icmp eq i32 %V, 17 ; <i1> [#uses=1] + %CN = or i1 %C1, %C2 ; <i1> [#uses=1] + br i1 %CN, label %T, label %F T: ; preds = %0 - call void @foo1( ) - ret void + call void @foo1( ) + ret void F: ; preds = %0 - call void @foo2( ) - ret void + call void @foo2( ) + ret void +; CHECK-LABEL: @test1( +; CHECK: switch i32 %V, label %F [ +; CHECK: i32 17, label %T +; CHECK: i32 4, label %T +; CHECK: ] } define void @test1_ptr(i32* %V) { -; CHECK-LABEL: @test1_ptr( -; CHECK-NEXT: [[MAGICPTR:%.*]] = ptrtoint i32* [[V:%.*]] to i32 -; CHECK-NEXT: switch i32 [[MAGICPTR]], label [[F:%.*]] [ -; CHECK-NEXT: i32 17, label [[T:%.*]] -; CHECK-NEXT: i32 4, label [[T]] -; CHECK-NEXT: ] -; CHECK: T: -; CHECK-NEXT: call void @foo1() -; CHECK-NEXT: ret void -; CHECK: F: -; CHECK-NEXT: call void @foo2() -; CHECK-NEXT: ret void -; - %C1 = icmp eq i32* %V, inttoptr (i32 4 to i32*) - %C2 = icmp eq i32* %V, inttoptr (i32 17 to i32*) - %CN = or i1 %C1, %C2 ; <i1> [#uses=1] - br i1 %CN, label %T, label %F + %C1 = icmp eq i32* %V, inttoptr (i32 4 to i32*) + %C2 = icmp eq i32* %V, inttoptr (i32 17 to i32*) + %CN = or i1 %C1, %C2 ; <i1> [#uses=1] + br i1 %CN, label %T, label %F T: ; preds = %0 - call void @foo1( ) - ret void + call void @foo1( ) + ret void F: ; preds = %0 - call void @foo2( ) - ret void + call void @foo2( ) + ret void +; CHECK-LABEL: @test1_ptr( +; DL: %magicptr = ptrtoint i32* %V to i32 +; DL: switch i32 %magicptr, label %F [ +; DL: i32 17, label %T +; DL: i32 4, label %T +; DL: ] } define void @test1_ptr_as1(i32 addrspace(1)* %V) { -; CHECK-LABEL: @test1_ptr_as1( -; CHECK-NEXT: [[MAGICPTR:%.*]] = ptrtoint i32 addrspace(1)* [[V:%.*]] to i32 -; CHECK-NEXT: switch i32 [[MAGICPTR]], label [[F:%.*]] [ -; CHECK-NEXT: i32 17, label [[T:%.*]] -; CHECK-NEXT: i32 4, label [[T]] -; CHECK-NEXT: ] -; CHECK: T: -; CHECK-NEXT: call void @foo1() -; CHECK-NEXT: ret void -; CHECK: F: -; CHECK-NEXT: call void @foo2() -; CHECK-NEXT: ret void -; - %C1 = icmp eq i32 addrspace(1)* %V, inttoptr (i32 4 to i32 addrspace(1)*) - %C2 = icmp eq i32 addrspace(1)* %V, inttoptr (i32 17 to i32 addrspace(1)*) - %CN = or i1 %C1, %C2 ; <i1> [#uses=1] - br i1 %CN, label %T, label %F + %C1 = icmp eq i32 addrspace(1)* %V, inttoptr (i32 4 to i32 addrspace(1)*) + %C2 = icmp eq i32 addrspace(1)* %V, inttoptr (i32 17 to i32 addrspace(1)*) + %CN = or i1 %C1, %C2 ; <i1> [#uses=1] + br i1 %CN, label %T, label %F T: ; preds = %0 - call void @foo1( ) - ret void + call void @foo1( ) + ret void F: ; preds = %0 - call void @foo2( ) - ret void + call void @foo2( ) + ret void +; CHECK-LABEL: @test1_ptr_as1( +; DL: %magicptr = ptrtoint i32 addrspace(1)* %V to i16 +; DL: switch i16 %magicptr, label %F [ +; DL: i16 17, label %T +; DL: i16 4, label %T +; DL: ] } define void @test2(i32 %V) { -; CHECK-LABEL: @test2( -; CHECK-NEXT: switch i32 [[V:%.*]], label [[T:%.*]] [ -; CHECK-NEXT: i32 17, label [[F:%.*]] -; CHECK-NEXT: i32 4, label [[F]] -; CHECK-NEXT: ] -; CHECK: T: -; CHECK-NEXT: call void @foo1() -; CHECK-NEXT: ret void -; CHECK: F: -; CHECK-NEXT: call void @foo2() -; CHECK-NEXT: ret void -; - %C1 = icmp ne i32 %V, 4 ; <i1> [#uses=1] - %C2 = icmp ne i32 %V, 17 ; <i1> [#uses=1] - %CN = and i1 %C1, %C2 ; <i1> [#uses=1] - br i1 %CN, label %T, label %F + %C1 = icmp ne i32 %V, 4 ; <i1> [#uses=1] + %C2 = icmp ne i32 %V, 17 ; <i1> [#uses=1] + %CN = and i1 %C1, %C2 ; <i1> [#uses=1] + br i1 %CN, label %T, label %F T: ; preds = %0 - call void @foo1( ) - ret void + call void @foo1( ) + ret void F: ; preds = %0 - call void @foo2( ) - ret void + call void @foo2( ) + ret void +; CHECK-LABEL: @test2( +; CHECK: switch i32 %V, label %T [ +; CHECK: i32 17, label %F +; CHECK: i32 4, label %F +; CHECK: ] } define void @test3(i32 %V) { -; CHECK-LABEL: @test3( -; CHECK-NEXT: switch i32 [[V:%.*]], label [[F:%.*]] [ -; CHECK-NEXT: i32 4, label [[T:%.*]] -; CHECK-NEXT: i32 17, label [[T]] -; CHECK-NEXT: ] -; CHECK: T: -; CHECK-NEXT: call void @foo1() -; CHECK-NEXT: ret void -; CHECK: F: -; CHECK-NEXT: call void @foo2() -; CHECK-NEXT: ret void -; - %C1 = icmp eq i32 %V, 4 ; <i1> [#uses=1] - br i1 %C1, label %T, label %N + %C1 = icmp eq i32 %V, 4 ; <i1> [#uses=1] + br i1 %C1, label %T, label %N N: ; preds = %0 - %C2 = icmp eq i32 %V, 17 ; <i1> [#uses=1] - br i1 %C2, label %T, label %F + %C2 = icmp eq i32 %V, 17 ; <i1> [#uses=1] + br i1 %C2, label %T, label %F T: ; preds = %N, %0 - call void @foo1( ) - ret void + call void @foo1( ) + ret void F: ; preds = %N - call void @foo2( ) - ret void + call void @foo2( ) + ret void +; CHECK-LABEL: @test3( +; CHECK: switch i32 %V, label %F [ +; CHECK: i32 4, label %T +; CHECK: i32 17, label %T +; CHECK: ] } define i32 @test4(i8 zeroext %c) nounwind ssp noredzone { -; CHECK-LABEL: @test4( -; CHECK-NEXT: entry: -; CHECK-NEXT: switch i8 [[C:%.*]], label [[LOR_RHS:%.*]] [ -; CHECK-NEXT: i8 62, label [[LOR_END:%.*]] -; CHECK-NEXT: i8 34, label [[LOR_END]] -; CHECK-NEXT: i8 92, label [[LOR_END]] -; CHECK-NEXT: ] -; CHECK: lor.rhs: -; CHECK-NEXT: br label [[LOR_END]] -; CHECK: lor.end: -; CHECK-NEXT: [[TMP0:%.*]] = phi i1 [ true, [[ENTRY:%.*]] ], [ false, [[LOR_RHS]] ], [ true, [[ENTRY]] ], [ true, [[ENTRY]] ] -; CHECK-NEXT: [[LOR_EXT:%.*]] = zext i1 [[TMP0]] to i32 -; CHECK-NEXT: ret i32 [[LOR_EXT]] -; entry: %cmp = icmp eq i8 %c, 62 br i1 %cmp, label %lor.end, label %lor.lhs.false @@ -169,28 +119,20 @@ lor.end: ; preds = %lor.rhs, %lor.lhs.f %lor.ext = zext i1 %0 to i32 ret i32 %lor.ext +; CHECK-LABEL: @test4( +; CHECK: switch i8 %c, label %lor.rhs [ +; CHECK: i8 62, label %lor.end +; CHECK: i8 34, label %lor.end +; CHECK: i8 92, label %lor.end +; CHECK: ] } define i32 @test5(i8 zeroext %c) nounwind ssp noredzone { -; CHECK-LABEL: @test5( -; CHECK-NEXT: entry: -; CHECK-NEXT: switch i8 [[C:%.*]], label [[LOR_RHS:%.*]] [ -; CHECK-NEXT: i8 62, label [[LOR_END:%.*]] -; CHECK-NEXT: i8 34, label [[LOR_END]] -; CHECK-NEXT: i8 92, label [[LOR_END]] -; CHECK-NEXT: ] -; CHECK: lor.rhs: -; CHECK-NEXT: br label [[LOR_END]] -; CHECK: lor.end: -; CHECK-NEXT: [[TMP0:%.*]] = phi i1 [ true, [[ENTRY:%.*]] ], [ false, [[LOR_RHS]] ], [ true, [[ENTRY]] ], [ true, [[ENTRY]] ] -; CHECK-NEXT: [[LOR_EXT:%.*]] = zext i1 [[TMP0]] to i32 -; CHECK-NEXT: ret i32 [[LOR_EXT]] -; entry: switch i8 %c, label %lor.rhs [ - i8 62, label %lor.end - i8 34, label %lor.end - i8 92, label %lor.end + i8 62, label %lor.end + i8 34, label %lor.end + i8 92, label %lor.end ] lor.rhs: ; preds = %entry @@ -201,63 +143,48 @@ lor.end: ; preds = %entry, %entry, %ent %0 = phi i1 [ true, %entry ], [ %V, %lor.rhs ], [ true, %entry ], [ true, %entry ] %lor.ext = zext i1 %0 to i32 ret i32 %lor.ext +; CHECK-LABEL: @test5( +; CHECK: switch i8 %c, label %lor.rhs [ +; CHECK: i8 62, label %lor.end +; CHECK: i8 34, label %lor.end +; CHECK: i8 92, label %lor.end +; CHECK: ] } define i1 @test6({ i32, i32 }* %I) { -; CHECK-LABEL: @test6( -; CHECK-NEXT: entry: -; CHECK-NEXT: [[TMP_1_I:%.*]] = getelementptr { i32, i32 }, { i32, i32 }* [[I:%.*]], i64 0, i32 1 -; CHECK-NEXT: [[TMP_2_I:%.*]] = load i32, i32* [[TMP_1_I]] -; CHECK-NEXT: [[TMP_2_I_OFF:%.*]] = add i32 [[TMP_2_I]], -14 -; CHECK-NEXT: [[SWITCH:%.*]] = icmp ult i32 [[TMP_2_I_OFF]], 6 -; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[SWITCH]], i1 true, i1 false -; CHECK-NEXT: ret i1 [[SPEC_SELECT]] -; entry: - %tmp.1.i = getelementptr { i32, i32 }, { i32, i32 }* %I, i64 0, i32 1 ; <i32*> [#uses=1] - %tmp.2.i = load i32, i32* %tmp.1.i ; <i32> [#uses=6] - %tmp.2 = icmp eq i32 %tmp.2.i, 14 ; <i1> [#uses=1] - br i1 %tmp.2, label %shortcirc_done.4, label %shortcirc_next.0 + %tmp.1.i = getelementptr { i32, i32 }, { i32, i32 }* %I, i64 0, i32 1 ; <i32*> [#uses=1] + %tmp.2.i = load i32, i32* %tmp.1.i ; <i32> [#uses=6] + %tmp.2 = icmp eq i32 %tmp.2.i, 14 ; <i1> [#uses=1] + br i1 %tmp.2, label %shortcirc_done.4, label %shortcirc_next.0 shortcirc_next.0: ; preds = %entry - %tmp.6 = icmp eq i32 %tmp.2.i, 15 ; <i1> [#uses=1] - br i1 %tmp.6, label %shortcirc_done.4, label %shortcirc_next.1 + %tmp.6 = icmp eq i32 %tmp.2.i, 15 ; <i1> [#uses=1] + br i1 %tmp.6, label %shortcirc_done.4, label %shortcirc_next.1 shortcirc_next.1: ; preds = %shortcirc_next.0 - %tmp.11 = icmp eq i32 %tmp.2.i, 16 ; <i1> [#uses=1] - br i1 %tmp.11, label %shortcirc_done.4, label %shortcirc_next.2 + %tmp.11 = icmp eq i32 %tmp.2.i, 16 ; <i1> [#uses=1] + br i1 %tmp.11, label %shortcirc_done.4, label %shortcirc_next.2 shortcirc_next.2: ; preds = %shortcirc_next.1 - %tmp.16 = icmp eq i32 %tmp.2.i, 17 ; <i1> [#uses=1] - br i1 %tmp.16, label %shortcirc_done.4, label %shortcirc_next.3 + %tmp.16 = icmp eq i32 %tmp.2.i, 17 ; <i1> [#uses=1] + br i1 %tmp.16, label %shortcirc_done.4, label %shortcirc_next.3 shortcirc_next.3: ; preds = %shortcirc_next.2 - %tmp.21 = icmp eq i32 %tmp.2.i, 18 ; <i1> [#uses=1] - br i1 %tmp.21, label %shortcirc_done.4, label %shortcirc_next.4 + %tmp.21 = icmp eq i32 %tmp.2.i, 18 ; <i1> [#uses=1] + br i1 %tmp.21, label %shortcirc_done.4, label %shortcirc_next.4 shortcirc_next.4: ; preds = %shortcirc_next.3 - %tmp.26 = icmp eq i32 %tmp.2.i, 19 ; <i1> [#uses=1] - br label %UnifiedReturnBlock + %tmp.26 = icmp eq i32 %tmp.2.i, 19 ; <i1> [#uses=1] + br label %UnifiedReturnBlock shortcirc_done.4: ; preds = %shortcirc_next.3, %shortcirc_next.2, %shortcirc_next.1, %shortcirc_next.0, %entry - br label %UnifiedReturnBlock + br label %UnifiedReturnBlock UnifiedReturnBlock: ; preds = %shortcirc_done.4, %shortcirc_next.4 - %UnifiedRetVal = phi i1 [ %tmp.26, %shortcirc_next.4 ], [ true, %shortcirc_done.4 ] ; <i1> [#uses=1] - ret i1 %UnifiedRetVal + %UnifiedRetVal = phi i1 [ %tmp.26, %shortcirc_next.4 ], [ true, %shortcirc_done.4 ] ; <i1> [#uses=1] + ret i1 %UnifiedRetVal +; CHECK-LABEL: @test6( +; CHECK: %tmp.2.i.off = add i32 %tmp.2.i, -14 +; CHECK: %switch = icmp ult i32 %tmp.2.i.off, 6 } define void @test7(i8 zeroext %c, i32 %x) nounwind ssp noredzone { -; CHECK-LABEL: @test7( -; CHECK-NEXT: entry: -; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[X:%.*]], 32 -; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[SWITCH_EARLY_TEST:%.*]] -; CHECK: switch.early.test: -; CHECK-NEXT: switch i8 [[C:%.*]], label [[IF_END:%.*]] [ -; CHECK-NEXT: i8 99, label [[IF_THEN]] -; CHECK-NEXT: i8 97, label [[IF_THEN]] -; CHECK-NEXT: ] -; CHECK: if.then: -; CHECK-NEXT: tail call void @foo1() #2 -; CHECK-NEXT: ret void -; CHECK: if.end: -; CHECK-NEXT: ret void -; entry: %cmp = icmp ult i32 %x, 32 %cmp4 = icmp eq i8 %c, 97 @@ -273,27 +200,17 @@ if.then: ; preds = %entry if.end: ; preds = %entry ret void +; CHECK-LABEL: @test7( +; CHECK: %cmp = icmp ult i32 %x, 32 +; CHECK: br i1 %cmp, label %if.then, label %switch.early.test +; CHECK: switch.early.test: +; CHECK: switch i8 %c, label %if.end [ +; CHECK: i8 99, label %if.then +; CHECK: i8 97, label %if.then +; CHECK: ] } define i32 @test8(i8 zeroext %c, i32 %x, i1 %C) nounwind ssp noredzone { -; CHECK-LABEL: @test8( -; CHECK-NEXT: entry: -; CHECK-NEXT: br i1 [[C:%.*]], label [[N:%.*]], label [[IF_THEN:%.*]] -; CHECK: N: -; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[X:%.*]], 32 -; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN]], label [[SWITCH_EARLY_TEST:%.*]] -; CHECK: switch.early.test: -; CHECK-NEXT: switch i8 [[C:%.*]], label [[IF_END:%.*]] [ -; CHECK-NEXT: i8 99, label [[IF_THEN]] -; CHECK-NEXT: i8 97, label [[IF_THEN]] -; CHECK-NEXT: ] -; CHECK: if.then: -; CHECK-NEXT: [[A:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ 42, [[SWITCH_EARLY_TEST]] ], [ 42, [[N]] ], [ 42, [[SWITCH_EARLY_TEST]] ] -; CHECK-NEXT: tail call void @foo1() #2 -; CHECK-NEXT: ret i32 [[A]] -; CHECK: if.end: -; CHECK-NEXT: ret i32 0 -; entry: br i1 %C, label %N, label %if.then N: @@ -312,33 +229,17 @@ if.then: ; preds = %entry if.end: ; preds = %entry ret i32 0 +; CHECK-LABEL: @test8( +; CHECK: switch.early.test: +; CHECK: switch i8 %c, label %if.end [ +; CHECK: i8 99, label %if.then +; CHECK: i8 97, label %if.then +; CHECK: ] +; CHECK: %A = phi i32 [ 0, %entry ], [ 42, %switch.early.test ], [ 42, %N ], [ 42, %switch.early.test ] } ;; This is "Example 7" from http://blog.regehr.org/archives/320 define i32 @test9(i8 zeroext %c) nounwind ssp noredzone { -; CHECK-LABEL: @test9( -; CHECK-NEXT: entry: -; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[C:%.*]], 33 -; CHECK-NEXT: br i1 [[CMP]], label [[LOR_END:%.*]], label [[SWITCH_EARLY_TEST:%.*]] -; CHECK: switch.early.test: -; CHECK-NEXT: switch i8 [[C]], label [[LOR_RHS:%.*]] [ -; CHECK-NEXT: i8 92, label [[LOR_END]] -; CHECK-NEXT: i8 62, label [[LOR_END]] -; CHECK-NEXT: i8 60, label [[LOR_END]] -; CHECK-NEXT: i8 59, label [[LOR_END]] -; CHECK-NEXT: i8 58, label [[LOR_END]] -; CHECK-NEXT: i8 46, label [[LOR_END]] -; CHECK-NEXT: i8 44, label [[LOR_END]] -; CHECK-NEXT: i8 34, label [[LOR_END]] -; CHECK-NEXT: i8 39, label [[LOR_END]] -; CHECK-NEXT: ] -; CHECK: lor.rhs: -; CHECK-NEXT: br label [[LOR_END]] -; CHECK: lor.end: -; CHECK-NEXT: [[TMP0:%.*]] = phi i1 [ true, [[SWITCH_EARLY_TEST]] ], [ false, [[LOR_RHS]] ], [ true, [[ENTRY:%.*]] ], [ true, [[SWITCH_EARLY_TEST]] ], [ true, [[SWITCH_EARLY_TEST]] ], [ true, [[SWITCH_EARLY_TEST]] ], [ true, [[SWITCH_EARLY_TEST]] ], [ true, [[SWITCH_EARLY_TEST]] ], [ true, [[SWITCH_EARLY_TEST]] ], [ true, [[SWITCH_EARLY_TEST]] ], [ true, [[SWITCH_EARLY_TEST]] ] -; CHECK-NEXT: [[CONV46:%.*]] = zext i1 [[TMP0]] to i32 -; CHECK-NEXT: ret i32 [[CONV46]] -; entry: %cmp = icmp ult i8 %c, 33 br i1 %cmp, label %lor.end, label %lor.lhs.false @@ -384,23 +285,25 @@ lor.end: ; preds = %lor.rhs, %lor.lhs.f %conv46 = zext i1 %0 to i32 ret i32 %conv46 - +; CHECK-LABEL: @test9( +; CHECK: %cmp = icmp ult i8 %c, 33 +; CHECK: br i1 %cmp, label %lor.end, label %switch.early.test + +; CHECK: switch.early.test: +; CHECK: switch i8 %c, label %lor.rhs [ +; CHECK: i8 92, label %lor.end +; CHECK: i8 62, label %lor.end +; CHECK: i8 60, label %lor.end +; CHECK: i8 59, label %lor.end +; CHECK: i8 58, label %lor.end +; CHECK: i8 46, label %lor.end +; CHECK: i8 44, label %lor.end +; CHECK: i8 34, label %lor.end +; CHECK: i8 39, label %lor.end +; CHECK: ] } define i32 @test10(i32 %mode, i1 %Cond) { -; CHECK-LABEL: @test10( -; CHECK-NEXT: br i1 [[COND:%.*]], label [[SWITCH_EARLY_TEST:%.*]], label [[F:%.*]] -; CHECK: switch.early.test: -; CHECK-NEXT: switch i32 [[MODE:%.*]], label [[T:%.*]] [ -; CHECK-NEXT: i32 51, label [[F]] -; CHECK-NEXT: i32 0, label [[F]] -; CHECK-NEXT: ] -; CHECK: T: -; CHECK-NEXT: [[MERGE:%.*]] = phi i32 [ 123, [[SWITCH_EARLY_TEST]] ], [ 324, [[F]] ] -; CHECK-NEXT: ret i32 [[MERGE]] -; CHECK: F: -; CHECK-NEXT: br label [[T]] -; %A = icmp ne i32 %mode, 0 %B = icmp ne i32 %mode, 51 %C = and i1 %A, %B @@ -411,27 +314,17 @@ T: F: ret i32 324 +; CHECK-LABEL: @test10( +; CHECK: br i1 %Cond, label %switch.early.test, label %F +; CHECK:switch.early.test: +; CHECK: switch i32 %mode, label %T [ +; CHECK: i32 51, label %F +; CHECK: i32 0, label %F +; CHECK: ] } ; PR8780 define i32 @test11(i32 %bar) nounwind { -; CHECK-LABEL: @test11( -; CHECK-NEXT: entry: -; CHECK-NEXT: switch i32 [[BAR:%.*]], label [[IF_END:%.*]] [ -; CHECK-NEXT: i32 55, label [[RETURN:%.*]] -; CHECK-NEXT: i32 53, label [[RETURN]] -; CHECK-NEXT: i32 35, label [[RETURN]] -; CHECK-NEXT: i32 24, label [[RETURN]] -; CHECK-NEXT: i32 23, label [[RETURN]] -; CHECK-NEXT: i32 12, label [[RETURN]] -; CHECK-NEXT: i32 4, label [[RETURN]] -; CHECK-NEXT: ] -; CHECK: if.end: -; CHECK-NEXT: br label [[RETURN]] -; CHECK: return: -; CHECK-NEXT: [[RETVAL_0:%.*]] = phi i32 [ 0, [[IF_END]] ], [ 1, [[ENTRY:%.*]] ], [ 1, [[ENTRY]] ], [ 1, [[ENTRY]] ], [ 1, [[ENTRY]] ], [ 1, [[ENTRY]] ], [ 1, [[ENTRY]] ], [ 1, [[ENTRY]] ] -; CHECK-NEXT: ret i32 [[RETVAL_0]] -; entry: %cmp = icmp eq i32 %bar, 4 %cmp2 = icmp eq i32 %bar, 35 @@ -460,21 +353,19 @@ return: ; preds = %if.end, %if.then %retval.0 = phi i32 [ 1, %if.then ], [ 0, %if.end ] ret i32 %retval.0 +; CHECK-LABEL: @test11( +; CHECK: switch i32 %bar, label %if.end [ +; CHECK: i32 55, label %return +; CHECK: i32 53, label %return +; CHECK: i32 35, label %return +; CHECK: i32 24, label %return +; CHECK: i32 23, label %return +; CHECK: i32 12, label %return +; CHECK: i32 4, label %return +; CHECK: ] } define void @test12() nounwind { -; CHECK-LABEL: @test12( -; CHECK-NEXT: entry: -; CHECK-NEXT: [[A_OLD:%.*]] = icmp eq i32 undef, undef -; CHECK-NEXT: br i1 [[A_OLD]], label [[BB55_US_US:%.*]], label [[MALFORMED:%.*]] -; CHECK: bb55.us.us: -; CHECK-NEXT: [[B:%.*]] = icmp ugt i32 undef, undef -; CHECK-NEXT: [[A:%.*]] = icmp eq i32 undef, undef -; CHECK-NEXT: [[OR_COND:%.*]] = or i1 [[B]], [[A]] -; CHECK-NEXT: br i1 [[OR_COND]], label [[BB55_US_US]], label [[MALFORMED]] -; CHECK: malformed: -; CHECK-NEXT: ret void -; entry: br label %bb49.us.us @@ -491,26 +382,12 @@ bb55.us.us: malformed: ret void +; CHECK-LABEL: @test12( } ; test13 - handle switch formation with ult. define void @test13(i32 %x) nounwind ssp noredzone { -; CHECK-LABEL: @test13( -; CHECK-NEXT: entry: -; CHECK-NEXT: switch i32 [[X:%.*]], label [[IF_END:%.*]] [ -; CHECK-NEXT: i32 6, label [[IF_THEN:%.*]] -; CHECK-NEXT: i32 4, label [[IF_THEN]] -; CHECK-NEXT: i32 3, label [[IF_THEN]] -; CHECK-NEXT: i32 1, label [[IF_THEN]] -; CHECK-NEXT: i32 0, label [[IF_THEN]] -; CHECK-NEXT: ] -; CHECK: if.then: -; CHECK-NEXT: call void @foo1() #3 -; CHECK-NEXT: br label [[IF_END]] -; CHECK: if.end: -; CHECK-NEXT: ret void -; entry: %cmp = icmp ult i32 %x, 2 br i1 %cmp, label %if.then, label %lor.lhs.false3 @@ -533,26 +410,18 @@ if.then: ; preds = %lor.lhs.false9, %lo if.end: ; preds = %if.then, %lor.lhs.false9 ret void +; CHECK-LABEL: @test13( +; CHECK: switch i32 %x, label %if.end [ +; CHECK: i32 6, label %if.then +; CHECK: i32 4, label %if.then +; CHECK: i32 3, label %if.then +; CHECK: i32 1, label %if.then +; CHECK: i32 0, label %if.then +; CHECK: ] } ; test14 - handle switch formation with ult. define void @test14(i32 %x) nounwind ssp noredzone { -; CHECK-LABEL: @test14( -; CHECK-NEXT: entry: -; CHECK-NEXT: switch i32 [[X:%.*]], label [[IF_END:%.*]] [ -; CHECK-NEXT: i32 6, label [[IF_THEN:%.*]] -; CHECK-NEXT: i32 4, label [[IF_THEN]] -; CHECK-NEXT: i32 3, label [[IF_THEN]] -; CHECK-NEXT: i32 2, label [[IF_THEN]] -; CHECK-NEXT: i32 1, label [[IF_THEN]] -; CHECK-NEXT: i32 0, label [[IF_THEN]] -; CHECK-NEXT: ] -; CHECK: if.then: -; CHECK-NEXT: call void @foo1() #3 -; CHECK-NEXT: br label [[IF_END]] -; CHECK: if.end: -; CHECK-NEXT: ret void -; entry: %cmp = icmp ugt i32 %x, 2 br i1 %cmp, label %lor.lhs.false3, label %if.then @@ -575,15 +444,18 @@ if.then: ; preds = %lor.lhs.false9, %lo if.end: ; preds = %if.then, %lor.lhs.false9 ret void +; CHECK-LABEL: @test14( +; CHECK: switch i32 %x, label %if.end [ +; CHECK: i32 6, label %if.then +; CHECK: i32 4, label %if.then +; CHECK: i32 3, label %if.then +; CHECK: i32 1, label %if.then +; CHECK: i32 0, label %if.then +; CHECK: ] } ; Don't crash on ginormous ranges. define void @test15(i128 %x) nounwind { -; CHECK-LABEL: @test15( -; CHECK-NEXT: if.end: -; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i128 [[X:%.*]], 2 -; CHECK-NEXT: ret void -; %cmp = icmp ugt i128 %x, 2 br i1 %cmp, label %if.end, label %lor.false @@ -598,19 +470,18 @@ if.then: if.end: ret void +; CHECK-LABEL: @test15( +; CHECK-NOT: switch +; CHECK: ret void } ; PR8675 ; rdar://5134905 define zeroext i1 @test16(i32 %x) nounwind { -; CHECK-LABEL: @test16( -; CHECK-NEXT: entry: -; CHECK-NEXT: [[X_OFF:%.*]] = add i32 [[X:%.*]], -1 -; CHECK-NEXT: [[SWITCH:%.*]] = icmp ult i32 [[X_OFF]], 3 -; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[SWITCH]], i1 true, i1 false -; CHECK-NEXT: ret i1 [[SPEC_SELECT]] -; entry: +; CHECK-LABEL: @test16( +; CHECK: %x.off = add i32 %x, -1 +; CHECK: %switch = icmp ult i32 %x.off, 3 %cmp.i = icmp eq i32 %x, 1 br i1 %cmp.i, label %lor.end, label %lor.lhs.false @@ -629,17 +500,6 @@ lor.end: ; Check that we don't turn an icmp into a switch where it's not useful. define void @test17(i32 %x, i32 %y) { -; CHECK-LABEL: @test17( -; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[X:%.*]], 3 -; CHECK-NEXT: [[SWITCH:%.*]] = icmp ult i32 [[Y:%.*]], 2 -; CHECK-NEXT: [[OR_COND775:%.*]] = or i1 [[CMP]], [[SWITCH]] -; CHECK-NEXT: br i1 [[OR_COND775]], label [[LOR_LHS_FALSE8:%.*]], label [[RETURN:%.*]] -; CHECK: lor.lhs.false8: -; CHECK-NEXT: tail call void @foo1() -; CHECK-NEXT: ret void -; CHECK: return: -; CHECK-NEXT: ret void -; %cmp = icmp ult i32 %x, 3 %switch = icmp ult i32 %y, 2 %or.cond775 = or i1 %cmp, %switch @@ -652,20 +512,13 @@ lor.lhs.false8: return: ret void +; CHECK-LABEL: @test17( +; CHECK-NOT: switch.early.test +; CHECK-NOT: switch i32 +; CHECK: ret void } define void @test18(i32 %arg) { -; CHECK-LABEL: @test18( -; CHECK-NEXT: bb: -; CHECK-NEXT: [[ARG_OFF:%.*]] = add i32 [[ARG:%.*]], -8 -; CHECK-NEXT: [[SWITCH:%.*]] = icmp ult i32 [[ARG_OFF]], 11 -; CHECK-NEXT: br i1 [[SWITCH]], label [[BB19:%.*]], label [[BB20:%.*]] -; CHECK: bb19: -; CHECK-NEXT: tail call void @foo1() -; CHECK-NEXT: br label [[BB20]] -; CHECK: bb20: -; CHECK-NEXT: ret void -; bb: %tmp = and i32 %arg, -2 %tmp1 = icmp eq i32 %tmp, 8 @@ -697,23 +550,12 @@ bb19: ; preds = %bb8, %bb bb20: ; preds = %bb19, %bb8 ret void +; CHECK-LABEL: @test18( +; CHECK: %arg.off = add i32 %arg, -8 +; CHECK: icmp ult i32 %arg.off, 11 } define void @PR26323(i1 %tobool23, i32 %tmp3) { -; CHECK-LABEL: @PR26323( -; CHECK-NEXT: entry: -; CHECK-NEXT: [[TOBOOL5:%.*]] = icmp ne i32 [[TMP3:%.*]], 0 -; CHECK-NEXT: [[NEG14:%.*]] = and i32 [[TMP3]], -2 -; CHECK-NEXT: [[CMP17:%.*]] = icmp ne i32 [[NEG14]], -1 -; CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[TOBOOL5]], [[TOBOOL23:%.*]] -; CHECK-NEXT: [[OR_COND1:%.*]] = and i1 [[CMP17]], [[OR_COND]] -; CHECK-NEXT: br i1 [[OR_COND1]], label [[IF_END29:%.*]], label [[IF_THEN27:%.*]] -; CHECK: if.then27: -; CHECK-NEXT: call void @foo1() -; CHECK-NEXT: unreachable -; CHECK: if.end29: -; CHECK-NEXT: ret void -; entry: %tobool5 = icmp ne i32 %tmp3, 0 %neg14 = and i32 %tmp3, -2 @@ -730,19 +572,21 @@ if.end29: ; preds = %entry ret void } +; CHECK-LABEL: define void @PR26323( +; CHECK: %tobool5 = icmp ne i32 %tmp3, 0 +; CHECK: %neg14 = and i32 %tmp3, -2 +; CHECK: %cmp17 = icmp ne i32 %neg14, -1 +; CHECK: %or.cond = and i1 %tobool5, %tobool23 +; CHECK: %or.cond1 = and i1 %cmp17, %or.cond +; CHECK: br i1 %or.cond1, label %if.end29, label %if.then27 + +; Form a switch when and'ing a negated power of two +; CHECK-LABEL: define void @test19 +; CHECK: switch i32 %arg, label %else [ +; CHECK: i32 32, label %if +; CHECK: i32 13, label %if +; CHECK: i32 12, label %if define void @test19(i32 %arg) { -; CHECK-LABEL: @test19( -; CHECK-NEXT: switch i32 [[ARG:%.*]], label [[ELSE:%.*]] [ -; CHECK-NEXT: i32 32, label [[IF:%.*]] -; CHECK-NEXT: i32 13, label [[IF]] -; CHECK-NEXT: i32 12, label [[IF]] -; CHECK-NEXT: ] -; CHECK: if: -; CHECK-NEXT: call void @foo1() -; CHECK-NEXT: ret void -; CHECK: else: -; CHECK-NEXT: ret void -; %and = and i32 %arg, -2 %cmp1 = icmp eq i32 %and, 12 %cmp2 = icmp eq i32 %arg, 32 @@ -758,19 +602,10 @@ else: } ; Since %cmp1 is always false, a switch is never formed +; CHECK-LABEL: define void @test20 +; CHECK-NOT: switch +; CHECK: ret void define void @test20(i32 %arg) { -; CHECK-LABEL: @test20( -; CHECK-NEXT: [[AND:%.*]] = and i32 [[ARG:%.*]], -2 -; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[AND]], 13 -; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i32 [[ARG]], 32 -; CHECK-NEXT: [[PRED:%.*]] = or i1 [[CMP1]], [[CMP2]] -; CHECK-NEXT: br i1 [[PRED]], label [[IF:%.*]], label [[ELSE:%.*]] -; CHECK: if: -; CHECK-NEXT: call void @foo1() -; CHECK-NEXT: ret void -; CHECK: else: -; CHECK-NEXT: ret void -; %and = and i32 %arg, -2 %cmp1 = icmp eq i32 %and, 13 %cmp2 = icmp eq i32 %arg, 32 @@ -786,19 +621,11 @@ else: } ; Form a switch when or'ing a power of two +; CHECK-LABEL: define void @test21 +; CHECK: i32 32, label %else +; CHECK: i32 13, label %else +; CHECK: i32 12, label %else define void @test21(i32 %arg) { -; CHECK-LABEL: @test21( -; CHECK-NEXT: switch i32 [[ARG:%.*]], label [[IF:%.*]] [ -; CHECK-NEXT: i32 32, label [[ELSE:%.*]] -; CHECK-NEXT: i32 13, label [[ELSE]] -; CHECK-NEXT: i32 12, label [[ELSE]] -; CHECK-NEXT: ] -; CHECK: if: -; CHECK-NEXT: call void @foo1() -; CHECK-NEXT: ret void -; CHECK: else: -; CHECK-NEXT: ret void -; %and = or i32 %arg, 1 %cmp1 = icmp ne i32 %and, 13 %cmp2 = icmp ne i32 %arg, 32 @@ -814,19 +641,10 @@ else: } ; Since %cmp1 is always false, a switch is never formed +; CHECK-LABEL: define void @test22 +; CHECK-NOT: switch +; CHECK: ret void define void @test22(i32 %arg) { -; CHECK-LABEL: @test22( -; CHECK-NEXT: [[AND:%.*]] = or i32 [[ARG:%.*]], 1 -; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i32 [[AND]], 12 -; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i32 [[ARG]], 32 -; CHECK-NEXT: [[PRED:%.*]] = and i1 [[CMP1]], [[CMP2]] -; CHECK-NEXT: br i1 [[PRED]], label [[IF:%.*]], label [[ELSE:%.*]] -; CHECK: if: -; CHECK-NEXT: call void @foo1() -; CHECK-NEXT: ret void -; CHECK: else: -; CHECK-NEXT: ret void -; %and = or i32 %arg, 1 %cmp1 = icmp ne i32 %and, 12 %cmp2 = icmp ne i32 %arg, 32 @@ -839,4 +657,4 @@ if: else: ret void -} +}
\ No newline at end of file diff --git a/llvm/test/Transforms/SimplifyCFG/switch_create.ll b/llvm/test/Transforms/SimplifyCFG/switch_create.ll index 3314fc982ae..c752636ae83 100644 --- a/llvm/test/Transforms/SimplifyCFG/switch_create.ll +++ b/llvm/test/Transforms/SimplifyCFG/switch_create.ll @@ -1,4 +1,3 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt -S -simplifycfg < %s | FileCheck %s ; RUN: opt -S -data-layout="p:32:32-p1:16:16" -simplifycfg < %s | FileCheck -check-prefix=CHECK -check-prefix=DL %s @@ -7,151 +6,102 @@ declare void @foo1() declare void @foo2() define void @test1(i32 %V) { -; CHECK-LABEL: @test1( -; CHECK-NEXT: switch i32 [[V:%.*]], label [[F:%.*]] [ -; CHECK-NEXT: i32 17, label [[T:%.*]] -; CHECK-NEXT: i32 4, label [[T]] -; CHECK-NEXT: ] -; CHECK: T: -; CHECK-NEXT: call void @foo1() -; CHECK-NEXT: ret void -; CHECK: F: -; CHECK-NEXT: call void @foo2() -; CHECK-NEXT: ret void -; - %C1 = icmp eq i32 %V, 4 ; <i1> [#uses=1] - %C2 = icmp eq i32 %V, 17 ; <i1> [#uses=1] - %CN = or i1 %C1, %C2 ; <i1> [#uses=1] - br i1 %CN, label %T, label %F + %C1 = icmp eq i32 %V, 4 ; <i1> [#uses=1] + %C2 = icmp eq i32 %V, 17 ; <i1> [#uses=1] + %CN = or i1 %C1, %C2 ; <i1> [#uses=1] + br i1 %CN, label %T, label %F T: ; preds = %0 - call void @foo1( ) - ret void + call void @foo1( ) + ret void F: ; preds = %0 - call void @foo2( ) - ret void + call void @foo2( ) + ret void +; CHECK-LABEL: @test1( +; CHECK: switch i32 %V, label %F [ +; CHECK: i32 17, label %T +; CHECK: i32 4, label %T +; CHECK: ] } define void @test1_ptr(i32* %V) { -; DL-LABEL: @test1_ptr( -; DL-NEXT: [[MAGICPTR:%.*]] = ptrtoint i32* [[V:%.*]] to i32 -; DL-NEXT: switch i32 [[MAGICPTR]], label [[F:%.*]] [ -; DL-NEXT: i32 17, label [[T:%.*]] -; DL-NEXT: i32 4, label [[T]] -; DL-NEXT: ] -; DL: T: -; DL-NEXT: call void @foo1() -; DL-NEXT: ret void -; DL: F: -; DL-NEXT: call void @foo2() -; DL-NEXT: ret void -; - %C1 = icmp eq i32* %V, inttoptr (i32 4 to i32*) - %C2 = icmp eq i32* %V, inttoptr (i32 17 to i32*) - %CN = or i1 %C1, %C2 ; <i1> [#uses=1] - br i1 %CN, label %T, label %F + %C1 = icmp eq i32* %V, inttoptr (i32 4 to i32*) + %C2 = icmp eq i32* %V, inttoptr (i32 17 to i32*) + %CN = or i1 %C1, %C2 ; <i1> [#uses=1] + br i1 %CN, label %T, label %F T: ; preds = %0 - call void @foo1( ) - ret void + call void @foo1( ) + ret void F: ; preds = %0 - call void @foo2( ) - ret void + call void @foo2( ) + ret void +; CHECK-LABEL: @test1_ptr( +; DL: %magicptr = ptrtoint i32* %V to i32 +; DL: switch i32 %magicptr, label %F [ +; DL: i32 17, label %T +; DL: i32 4, label %T +; DL: ] } define void @test1_ptr_as1(i32 addrspace(1)* %V) { -; DL-LABEL: @test1_ptr_as1( -; DL-NEXT: [[MAGICPTR:%.*]] = ptrtoint i32 addrspace(1)* [[V:%.*]] to i16 -; DL-NEXT: switch i16 [[MAGICPTR]], label [[F:%.*]] [ -; DL-NEXT: i16 17, label [[T:%.*]] -; DL-NEXT: i16 4, label [[T]] -; DL-NEXT: ] -; DL: T: -; DL-NEXT: call void @foo1() -; DL-NEXT: ret void -; DL: F: -; DL-NEXT: call void @foo2() -; DL-NEXT: ret void -; - %C1 = icmp eq i32 addrspace(1)* %V, inttoptr (i32 4 to i32 addrspace(1)*) - %C2 = icmp eq i32 addrspace(1)* %V, inttoptr (i32 17 to i32 addrspace(1)*) - %CN = or i1 %C1, %C2 ; <i1> [#uses=1] - br i1 %CN, label %T, label %F + %C1 = icmp eq i32 addrspace(1)* %V, inttoptr (i32 4 to i32 addrspace(1)*) + %C2 = icmp eq i32 addrspace(1)* %V, inttoptr (i32 17 to i32 addrspace(1)*) + %CN = or i1 %C1, %C2 ; <i1> [#uses=1] + br i1 %CN, label %T, label %F T: ; preds = %0 - call void @foo1( ) - ret void + call void @foo1( ) + ret void F: ; preds = %0 - call void @foo2( ) - ret void + call void @foo2( ) + ret void +; CHECK-LABEL: @test1_ptr_as1( +; DL: %magicptr = ptrtoint i32 addrspace(1)* %V to i16 +; DL: switch i16 %magicptr, label %F [ +; DL: i16 17, label %T +; DL: i16 4, label %T +; DL: ] } define void @test2(i32 %V) { -; CHECK-LABEL: @test2( -; CHECK-NEXT: switch i32 [[V:%.*]], label [[T:%.*]] [ -; CHECK-NEXT: i32 17, label [[F:%.*]] -; CHECK-NEXT: i32 4, label [[F]] -; CHECK-NEXT: ] -; CHECK: T: -; CHECK-NEXT: call void @foo1() -; CHECK-NEXT: ret void -; CHECK: F: -; CHECK-NEXT: call void @foo2() -; CHECK-NEXT: ret void -; - %C1 = icmp ne i32 %V, 4 ; <i1> [#uses=1] - %C2 = icmp ne i32 %V, 17 ; <i1> [#uses=1] - %CN = and i1 %C1, %C2 ; <i1> [#uses=1] - br i1 %CN, label %T, label %F + %C1 = icmp ne i32 %V, 4 ; <i1> [#uses=1] + %C2 = icmp ne i32 %V, 17 ; <i1> [#uses=1] + %CN = and i1 %C1, %C2 ; <i1> [#uses=1] + br i1 %CN, label %T, label %F T: ; preds = %0 - call void @foo1( ) - ret void + call void @foo1( ) + ret void F: ; preds = %0 - call void @foo2( ) - ret void + call void @foo2( ) + ret void +; CHECK-LABEL: @test2( +; CHECK: switch i32 %V, label %T [ +; CHECK: i32 17, label %F +; CHECK: i32 4, label %F +; CHECK: ] } define void @test3(i32 %V) { -; CHECK-LABEL: @test3( -; CHECK-NEXT: switch i32 [[V:%.*]], label [[F:%.*]] [ -; CHECK-NEXT: i32 4, label [[T:%.*]] -; CHECK-NEXT: i32 17, label [[T]] -; CHECK-NEXT: ] -; CHECK: T: -; CHECK-NEXT: call void @foo1() -; CHECK-NEXT: ret void -; CHECK: F: -; CHECK-NEXT: call void @foo2() -; CHECK-NEXT: ret void -; - %C1 = icmp eq i32 %V, 4 ; <i1> [#uses=1] - br i1 %C1, label %T, label %N + %C1 = icmp eq i32 %V, 4 ; <i1> [#uses=1] + br i1 %C1, label %T, label %N N: ; preds = %0 - %C2 = icmp eq i32 %V, 17 ; <i1> [#uses=1] - br i1 %C2, label %T, label %F + %C2 = icmp eq i32 %V, 17 ; <i1> [#uses=1] + br i1 %C2, label %T, label %F T: ; preds = %N, %0 - call void @foo1( ) - ret void + call void @foo1( ) + ret void F: ; preds = %N - call void @foo2( ) - ret void + call void @foo2( ) + ret void +; CHECK-LABEL: @test3( +; CHECK: switch i32 %V, label %F [ +; CHECK: i32 4, label %T +; CHECK: i32 17, label %T +; CHECK: ] } define i32 @test4(i8 zeroext %c) nounwind ssp noredzone { -; CHECK-LABEL: @test4( -; CHECK-NEXT: entry: -; CHECK-NEXT: switch i8 [[C:%.*]], label [[LOR_RHS:%.*]] [ -; CHECK-NEXT: i8 62, label [[LOR_END:%.*]] -; CHECK-NEXT: i8 34, label [[LOR_END]] -; CHECK-NEXT: i8 92, label [[LOR_END]] -; CHECK-NEXT: ] -; CHECK: lor.rhs: -; CHECK-NEXT: br label [[LOR_END]] -; CHECK: lor.end: -; CHECK-NEXT: [[TMP0:%.*]] = phi i1 [ true, [[ENTRY:%.*]] ], [ false, [[LOR_RHS]] ], [ true, [[ENTRY]] ], [ true, [[ENTRY]] ] -; CHECK-NEXT: [[LOR_EXT:%.*]] = zext i1 [[TMP0]] to i32 -; CHECK-NEXT: ret i32 [[LOR_EXT]] -; entry: %cmp = icmp eq i8 %c, 62 br i1 %cmp, label %lor.end, label %lor.lhs.false @@ -169,28 +119,20 @@ lor.end: ; preds = %lor.rhs, %lor.lhs.f %lor.ext = zext i1 %0 to i32 ret i32 %lor.ext +; CHECK-LABEL: @test4( +; CHECK: switch i8 %c, label %lor.rhs [ +; CHECK: i8 62, label %lor.end +; CHECK: i8 34, label %lor.end +; CHECK: i8 92, label %lor.end +; CHECK: ] } define i32 @test5(i8 zeroext %c) nounwind ssp noredzone { -; CHECK-LABEL: @test5( -; CHECK-NEXT: entry: -; CHECK-NEXT: switch i8 [[C:%.*]], label [[LOR_RHS:%.*]] [ -; CHECK-NEXT: i8 62, label [[LOR_END:%.*]] -; CHECK-NEXT: i8 34, label [[LOR_END]] -; CHECK-NEXT: i8 92, label [[LOR_END]] -; CHECK-NEXT: ] -; CHECK: lor.rhs: -; CHECK-NEXT: br label [[LOR_END]] -; CHECK: lor.end: -; CHECK-NEXT: [[TMP0:%.*]] = phi i1 [ true, [[ENTRY:%.*]] ], [ false, [[LOR_RHS]] ], [ true, [[ENTRY]] ], [ true, [[ENTRY]] ] -; CHECK-NEXT: [[LOR_EXT:%.*]] = zext i1 [[TMP0]] to i32 -; CHECK-NEXT: ret i32 [[LOR_EXT]] -; entry: switch i8 %c, label %lor.rhs [ - i8 62, label %lor.end - i8 34, label %lor.end - i8 92, label %lor.end + i8 62, label %lor.end + i8 34, label %lor.end + i8 92, label %lor.end ] lor.rhs: ; preds = %entry @@ -201,63 +143,48 @@ lor.end: ; preds = %entry, %entry, %ent %0 = phi i1 [ true, %entry ], [ %V, %lor.rhs ], [ true, %entry ], [ true, %entry ] %lor.ext = zext i1 %0 to i32 ret i32 %lor.ext +; CHECK-LABEL: @test5( +; CHECK: switch i8 %c, label %lor.rhs [ +; CHECK: i8 62, label %lor.end +; CHECK: i8 34, label %lor.end +; CHECK: i8 92, label %lor.end +; CHECK: ] } define i1 @test6({ i32, i32 }* %I) { -; CHECK-LABEL: @test6( -; CHECK-NEXT: entry: -; CHECK-NEXT: [[TMP_1_I:%.*]] = getelementptr { i32, i32 }, { i32, i32 }* [[I:%.*]], i64 0, i32 1 -; CHECK-NEXT: [[TMP_2_I:%.*]] = load i32, i32* [[TMP_1_I]] -; CHECK-NEXT: [[TMP_2_I_OFF:%.*]] = add i32 [[TMP_2_I]], -14 -; CHECK-NEXT: [[SWITCH:%.*]] = icmp ult i32 [[TMP_2_I_OFF]], 6 -; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[SWITCH]], i1 true, i1 false -; CHECK-NEXT: ret i1 [[SPEC_SELECT]] -; entry: - %tmp.1.i = getelementptr { i32, i32 }, { i32, i32 }* %I, i64 0, i32 1 ; <i32*> [#uses=1] - %tmp.2.i = load i32, i32* %tmp.1.i ; <i32> [#uses=6] - %tmp.2 = icmp eq i32 %tmp.2.i, 14 ; <i1> [#uses=1] - br i1 %tmp.2, label %shortcirc_done.4, label %shortcirc_next.0 + %tmp.1.i = getelementptr { i32, i32 }, { i32, i32 }* %I, i64 0, i32 1 ; <i32*> [#uses=1] + %tmp.2.i = load i32, i32* %tmp.1.i ; <i32> [#uses=6] + %tmp.2 = icmp eq i32 %tmp.2.i, 14 ; <i1> [#uses=1] + br i1 %tmp.2, label %shortcirc_done.4, label %shortcirc_next.0 shortcirc_next.0: ; preds = %entry - %tmp.6 = icmp eq i32 %tmp.2.i, 15 ; <i1> [#uses=1] - br i1 %tmp.6, label %shortcirc_done.4, label %shortcirc_next.1 + %tmp.6 = icmp eq i32 %tmp.2.i, 15 ; <i1> [#uses=1] + br i1 %tmp.6, label %shortcirc_done.4, label %shortcirc_next.1 shortcirc_next.1: ; preds = %shortcirc_next.0 - %tmp.11 = icmp eq i32 %tmp.2.i, 16 ; <i1> [#uses=1] - br i1 %tmp.11, label %shortcirc_done.4, label %shortcirc_next.2 + %tmp.11 = icmp eq i32 %tmp.2.i, 16 ; <i1> [#uses=1] + br i1 %tmp.11, label %shortcirc_done.4, label %shortcirc_next.2 shortcirc_next.2: ; preds = %shortcirc_next.1 - %tmp.16 = icmp eq i32 %tmp.2.i, 17 ; <i1> [#uses=1] - br i1 %tmp.16, label %shortcirc_done.4, label %shortcirc_next.3 + %tmp.16 = icmp eq i32 %tmp.2.i, 17 ; <i1> [#uses=1] + br i1 %tmp.16, label %shortcirc_done.4, label %shortcirc_next.3 shortcirc_next.3: ; preds = %shortcirc_next.2 - %tmp.21 = icmp eq i32 %tmp.2.i, 18 ; <i1> [#uses=1] - br i1 %tmp.21, label %shortcirc_done.4, label %shortcirc_next.4 + %tmp.21 = icmp eq i32 %tmp.2.i, 18 ; <i1> [#uses=1] + br i1 %tmp.21, label %shortcirc_done.4, label %shortcirc_next.4 shortcirc_next.4: ; preds = %shortcirc_next.3 - %tmp.26 = icmp eq i32 %tmp.2.i, 19 ; <i1> [#uses=1] - br label %UnifiedReturnBlock + %tmp.26 = icmp eq i32 %tmp.2.i, 19 ; <i1> [#uses=1] + br label %UnifiedReturnBlock shortcirc_done.4: ; preds = %shortcirc_next.3, %shortcirc_next.2, %shortcirc_next.1, %shortcirc_next.0, %entry - br label %UnifiedReturnBlock + br label %UnifiedReturnBlock UnifiedReturnBlock: ; preds = %shortcirc_done.4, %shortcirc_next.4 - %UnifiedRetVal = phi i1 [ %tmp.26, %shortcirc_next.4 ], [ true, %shortcirc_done.4 ] ; <i1> [#uses=1] - ret i1 %UnifiedRetVal + %UnifiedRetVal = phi i1 [ %tmp.26, %shortcirc_next.4 ], [ true, %shortcirc_done.4 ] ; <i1> [#uses=1] + ret i1 %UnifiedRetVal +; CHECK-LABEL: @test6( +; CHECK: %tmp.2.i.off = add i32 %tmp.2.i, -14 +; CHECK: %switch = icmp ult i32 %tmp.2.i.off, 6 } define void @test7(i8 zeroext %c, i32 %x) nounwind ssp noredzone { -; CHECK-LABEL: @test7( -; CHECK-NEXT: entry: -; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[X:%.*]], 32 -; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[SWITCH_EARLY_TEST:%.*]] -; CHECK: switch.early.test: -; CHECK-NEXT: switch i8 [[C:%.*]], label [[IF_END:%.*]] [ -; CHECK-NEXT: i8 99, label [[IF_THEN]] -; CHECK-NEXT: i8 97, label [[IF_THEN]] -; CHECK-NEXT: ] -; CHECK: if.then: -; CHECK-NEXT: tail call void @foo1() #2 -; CHECK-NEXT: ret void -; CHECK: if.end: -; CHECK-NEXT: ret void -; entry: %cmp = icmp ult i32 %x, 32 %cmp4 = icmp eq i8 %c, 97 @@ -273,27 +200,17 @@ if.then: ; preds = %entry if.end: ; preds = %entry ret void +; CHECK-LABEL: @test7( +; CHECK: %cmp = icmp ult i32 %x, 32 +; CHECK: br i1 %cmp, label %if.then, label %switch.early.test +; CHECK: switch.early.test: +; CHECK: switch i8 %c, label %if.end [ +; CHECK: i8 99, label %if.then +; CHECK: i8 97, label %if.then +; CHECK: ] } define i32 @test8(i8 zeroext %c, i32 %x, i1 %C) nounwind ssp noredzone { -; CHECK-LABEL: @test8( -; CHECK-NEXT: entry: -; CHECK-NEXT: br i1 [[C:%.*]], label [[N:%.*]], label [[IF_THEN:%.*]] -; CHECK: N: -; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[X:%.*]], 32 -; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN]], label [[SWITCH_EARLY_TEST:%.*]] -; CHECK: switch.early.test: -; CHECK-NEXT: switch i8 [[C:%.*]], label [[IF_END:%.*]] [ -; CHECK-NEXT: i8 99, label [[IF_THEN]] -; CHECK-NEXT: i8 97, label [[IF_THEN]] -; CHECK-NEXT: ] -; CHECK: if.then: -; CHECK-NEXT: [[A:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ 42, [[SWITCH_EARLY_TEST]] ], [ 42, [[N]] ], [ 42, [[SWITCH_EARLY_TEST]] ] -; CHECK-NEXT: tail call void @foo1() #2 -; CHECK-NEXT: ret i32 [[A]] -; CHECK: if.end: -; CHECK-NEXT: ret i32 0 -; entry: br i1 %C, label %N, label %if.then N: @@ -312,33 +229,17 @@ if.then: ; preds = %entry if.end: ; preds = %entry ret i32 0 +; CHECK-LABEL: @test8( +; CHECK: switch.early.test: +; CHECK: switch i8 %c, label %if.end [ +; CHECK: i8 99, label %if.then +; CHECK: i8 97, label %if.then +; CHECK: ] +; CHECK: %A = phi i32 [ 0, %entry ], [ 42, %switch.early.test ], [ 42, %N ], [ 42, %switch.early.test ] } ;; This is "Example 7" from http://blog.regehr.org/archives/320 define i32 @test9(i8 zeroext %c) nounwind ssp noredzone { -; CHECK-LABEL: @test9( -; CHECK-NEXT: entry: -; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[C:%.*]], 33 -; CHECK-NEXT: br i1 [[CMP]], label [[LOR_END:%.*]], label [[SWITCH_EARLY_TEST:%.*]] -; CHECK: switch.early.test: -; CHECK-NEXT: switch i8 [[C]], label [[LOR_RHS:%.*]] [ -; CHECK-NEXT: i8 92, label [[LOR_END]] -; CHECK-NEXT: i8 62, label [[LOR_END]] -; CHECK-NEXT: i8 60, label [[LOR_END]] -; CHECK-NEXT: i8 59, label [[LOR_END]] -; CHECK-NEXT: i8 58, label [[LOR_END]] -; CHECK-NEXT: i8 46, label [[LOR_END]] -; CHECK-NEXT: i8 44, label [[LOR_END]] -; CHECK-NEXT: i8 34, label [[LOR_END]] -; CHECK-NEXT: i8 39, label [[LOR_END]] -; CHECK-NEXT: ] -; CHECK: lor.rhs: -; CHECK-NEXT: br label [[LOR_END]] -; CHECK: lor.end: -; CHECK-NEXT: [[TMP0:%.*]] = phi i1 [ true, [[SWITCH_EARLY_TEST]] ], [ false, [[LOR_RHS]] ], [ true, [[ENTRY:%.*]] ], [ true, [[SWITCH_EARLY_TEST]] ], [ true, [[SWITCH_EARLY_TEST]] ], [ true, [[SWITCH_EARLY_TEST]] ], [ true, [[SWITCH_EARLY_TEST]] ], [ true, [[SWITCH_EARLY_TEST]] ], [ true, [[SWITCH_EARLY_TEST]] ], [ true, [[SWITCH_EARLY_TEST]] ], [ true, [[SWITCH_EARLY_TEST]] ] -; CHECK-NEXT: [[CONV46:%.*]] = zext i1 [[TMP0]] to i32 -; CHECK-NEXT: ret i32 [[CONV46]] -; entry: %cmp = icmp ult i8 %c, 33 br i1 %cmp, label %lor.end, label %lor.lhs.false @@ -384,23 +285,25 @@ lor.end: ; preds = %lor.rhs, %lor.lhs.f %conv46 = zext i1 %0 to i32 ret i32 %conv46 - +; CHECK-LABEL: @test9( +; CHECK: %cmp = icmp ult i8 %c, 33 +; CHECK: br i1 %cmp, label %lor.end, label %switch.early.test + +; CHECK: switch.early.test: +; CHECK: switch i8 %c, label %lor.rhs [ +; CHECK: i8 92, label %lor.end +; CHECK: i8 62, label %lor.end +; CHECK: i8 60, label %lor.end +; CHECK: i8 59, label %lor.end +; CHECK: i8 58, label %lor.end +; CHECK: i8 46, label %lor.end +; CHECK: i8 44, label %lor.end +; CHECK: i8 34, label %lor.end +; CHECK: i8 39, label %lor.end +; CHECK: ] } define i32 @test10(i32 %mode, i1 %Cond) { -; CHECK-LABEL: @test10( -; CHECK-NEXT: br i1 [[COND:%.*]], label [[SWITCH_EARLY_TEST:%.*]], label [[F:%.*]] -; CHECK: switch.early.test: -; CHECK-NEXT: switch i32 [[MODE:%.*]], label [[T:%.*]] [ -; CHECK-NEXT: i32 51, label [[F]] -; CHECK-NEXT: i32 0, label [[F]] -; CHECK-NEXT: ] -; CHECK: T: -; CHECK-NEXT: [[MERGE:%.*]] = phi i32 [ 123, [[SWITCH_EARLY_TEST]] ], [ 324, [[F]] ] -; CHECK-NEXT: ret i32 [[MERGE]] -; CHECK: F: -; CHECK-NEXT: br label [[T]] -; %A = icmp ne i32 %mode, 0 %B = icmp ne i32 %mode, 51 %C = and i1 %A, %B @@ -411,27 +314,17 @@ T: F: ret i32 324 +; CHECK-LABEL: @test10( +; CHECK: br i1 %Cond, label %switch.early.test, label %F +; CHECK:switch.early.test: +; CHECK: switch i32 %mode, label %T [ +; CHECK: i32 51, label %F +; CHECK: i32 0, label %F +; CHECK: ] } ; PR8780 define i32 @test11(i32 %bar) nounwind { -; CHECK-LABEL: @test11( -; CHECK-NEXT: entry: -; CHECK-NEXT: switch i32 [[BAR:%.*]], label [[IF_END:%.*]] [ -; CHECK-NEXT: i32 55, label [[RETURN:%.*]] -; CHECK-NEXT: i32 53, label [[RETURN]] -; CHECK-NEXT: i32 35, label [[RETURN]] -; CHECK-NEXT: i32 24, label [[RETURN]] -; CHECK-NEXT: i32 23, label [[RETURN]] -; CHECK-NEXT: i32 12, label [[RETURN]] -; CHECK-NEXT: i32 4, label [[RETURN]] -; CHECK-NEXT: ] -; CHECK: if.end: -; CHECK-NEXT: br label [[RETURN]] -; CHECK: return: -; CHECK-NEXT: [[RETVAL_0:%.*]] = phi i32 [ 0, [[IF_END]] ], [ 1, [[ENTRY:%.*]] ], [ 1, [[ENTRY]] ], [ 1, [[ENTRY]] ], [ 1, [[ENTRY]] ], [ 1, [[ENTRY]] ], [ 1, [[ENTRY]] ], [ 1, [[ENTRY]] ] -; CHECK-NEXT: ret i32 [[RETVAL_0]] -; entry: %cmp = icmp eq i32 %bar, 4 %cmp2 = icmp eq i32 %bar, 35 @@ -460,21 +353,19 @@ return: ; preds = %if.end, %if.then %retval.0 = phi i32 [ 1, %if.then ], [ 0, %if.end ] ret i32 %retval.0 +; CHECK-LABEL: @test11( +; CHECK: switch i32 %bar, label %if.end [ +; CHECK: i32 55, label %return +; CHECK: i32 53, label %return +; CHECK: i32 35, label %return +; CHECK: i32 24, label %return +; CHECK: i32 23, label %return +; CHECK: i32 12, label %return +; CHECK: i32 4, label %return +; CHECK: ] } define void @test12() nounwind { -; CHECK-LABEL: @test12( -; CHECK-NEXT: entry: -; CHECK-NEXT: [[A_OLD:%.*]] = icmp eq i32 undef, undef -; CHECK-NEXT: br i1 [[A_OLD]], label [[BB55_US_US:%.*]], label [[MALFORMED:%.*]] -; CHECK: bb55.us.us: -; CHECK-NEXT: [[B:%.*]] = icmp ugt i32 undef, undef -; CHECK-NEXT: [[A:%.*]] = icmp eq i32 undef, undef -; CHECK-NEXT: [[OR_COND:%.*]] = or i1 [[B]], [[A]] -; CHECK-NEXT: br i1 [[OR_COND]], label [[BB55_US_US]], label [[MALFORMED]] -; CHECK: malformed: -; CHECK-NEXT: ret void -; entry: br label %bb49.us.us @@ -491,26 +382,12 @@ bb55.us.us: malformed: ret void +; CHECK-LABEL: @test12( } ; test13 - handle switch formation with ult. define void @test13(i32 %x) nounwind ssp noredzone { -; CHECK-LABEL: @test13( -; CHECK-NEXT: entry: -; CHECK-NEXT: switch i32 [[X:%.*]], label [[IF_END:%.*]] [ -; CHECK-NEXT: i32 6, label [[IF_THEN:%.*]] -; CHECK-NEXT: i32 4, label [[IF_THEN]] -; CHECK-NEXT: i32 3, label [[IF_THEN]] -; CHECK-NEXT: i32 1, label [[IF_THEN]] -; CHECK-NEXT: i32 0, label [[IF_THEN]] -; CHECK-NEXT: ] -; CHECK: if.then: -; CHECK-NEXT: call void @foo1() #3 -; CHECK-NEXT: br label [[IF_END]] -; CHECK: if.end: -; CHECK-NEXT: ret void -; entry: %cmp = icmp ult i32 %x, 2 br i1 %cmp, label %if.then, label %lor.lhs.false3 @@ -533,26 +410,18 @@ if.then: ; preds = %lor.lhs.false9, %lo if.end: ; preds = %if.then, %lor.lhs.false9 ret void +; CHECK-LABEL: @test13( +; CHECK: switch i32 %x, label %if.end [ +; CHECK: i32 6, label %if.then +; CHECK: i32 4, label %if.then +; CHECK: i32 3, label %if.then +; CHECK: i32 1, label %if.then +; CHECK: i32 0, label %if.then +; CHECK: ] } ; test14 - handle switch formation with ult. define void @test14(i32 %x) nounwind ssp noredzone { -; CHECK-LABEL: @test14( -; CHECK-NEXT: entry: -; CHECK-NEXT: switch i32 [[X:%.*]], label [[IF_END:%.*]] [ -; CHECK-NEXT: i32 6, label [[IF_THEN:%.*]] -; CHECK-NEXT: i32 4, label [[IF_THEN]] -; CHECK-NEXT: i32 3, label [[IF_THEN]] -; CHECK-NEXT: i32 2, label [[IF_THEN]] -; CHECK-NEXT: i32 1, label [[IF_THEN]] -; CHECK-NEXT: i32 0, label [[IF_THEN]] -; CHECK-NEXT: ] -; CHECK: if.then: -; CHECK-NEXT: call void @foo1() #3 -; CHECK-NEXT: br label [[IF_END]] -; CHECK: if.end: -; CHECK-NEXT: ret void -; entry: %cmp = icmp ugt i32 %x, 2 br i1 %cmp, label %lor.lhs.false3, label %if.then @@ -575,15 +444,18 @@ if.then: ; preds = %lor.lhs.false9, %lo if.end: ; preds = %if.then, %lor.lhs.false9 ret void +; CHECK-LABEL: @test14( +; CHECK: switch i32 %x, label %if.end [ +; CHECK: i32 6, label %if.then +; CHECK: i32 4, label %if.then +; CHECK: i32 3, label %if.then +; CHECK: i32 1, label %if.then +; CHECK: i32 0, label %if.then +; CHECK: ] } ; Don't crash on ginormous ranges. define void @test15(i128 %x) nounwind { -; CHECK-LABEL: @test15( -; CHECK-NEXT: if.end: -; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i128 [[X:%.*]], 2 -; CHECK-NEXT: ret void -; %cmp = icmp ugt i128 %x, 2 br i1 %cmp, label %if.end, label %lor.false @@ -598,19 +470,18 @@ if.then: if.end: ret void +; CHECK-LABEL: @test15( +; CHECK-NOT: switch +; CHECK: ret void } ; PR8675 ; rdar://5134905 define zeroext i1 @test16(i32 %x) nounwind { -; CHECK-LABEL: @test16( -; CHECK-NEXT: entry: -; CHECK-NEXT: [[X_OFF:%.*]] = add i32 [[X:%.*]], -1 -; CHECK-NEXT: [[SWITCH:%.*]] = icmp ult i32 [[X_OFF]], 3 -; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[SWITCH]], i1 true, i1 false -; CHECK-NEXT: ret i1 [[SPEC_SELECT]] -; entry: +; CHECK-LABEL: @test16( +; CHECK: %x.off = add i32 %x, -1 +; CHECK: %switch = icmp ult i32 %x.off, 3 %cmp.i = icmp eq i32 %x, 1 br i1 %cmp.i, label %lor.end, label %lor.lhs.false @@ -629,17 +500,6 @@ lor.end: ; Check that we don't turn an icmp into a switch where it's not useful. define void @test17(i32 %x, i32 %y) { -; CHECK-LABEL: @test17( -; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[X:%.*]], 3 -; CHECK-NEXT: [[SWITCH:%.*]] = icmp ult i32 [[Y:%.*]], 2 -; CHECK-NEXT: [[OR_COND775:%.*]] = or i1 [[CMP]], [[SWITCH]] -; CHECK-NEXT: br i1 [[OR_COND775]], label [[LOR_LHS_FALSE8:%.*]], label [[RETURN:%.*]] -; CHECK: lor.lhs.false8: -; CHECK-NEXT: tail call void @foo1() -; CHECK-NEXT: ret void -; CHECK: return: -; CHECK-NEXT: ret void -; %cmp = icmp ult i32 %x, 3 %switch = icmp ult i32 %y, 2 %or.cond775 = or i1 %cmp, %switch @@ -652,20 +512,13 @@ lor.lhs.false8: return: ret void +; CHECK-LABEL: @test17( +; CHECK-NOT: switch.early.test +; CHECK-NOT: switch i32 +; CHECK: ret void } define void @test18(i32 %arg) { -; CHECK-LABEL: @test18( -; CHECK-NEXT: bb: -; CHECK-NEXT: [[ARG_OFF:%.*]] = add i32 [[ARG:%.*]], -8 -; CHECK-NEXT: [[SWITCH:%.*]] = icmp ult i32 [[ARG_OFF]], 11 -; CHECK-NEXT: br i1 [[SWITCH]], label [[BB19:%.*]], label [[BB20:%.*]] -; CHECK: bb19: -; CHECK-NEXT: tail call void @foo1() -; CHECK-NEXT: br label [[BB20]] -; CHECK: bb20: -; CHECK-NEXT: ret void -; bb: %tmp = and i32 %arg, -2 %tmp1 = icmp eq i32 %tmp, 8 @@ -697,23 +550,12 @@ bb19: ; preds = %bb8, %bb bb20: ; preds = %bb19, %bb8 ret void +; CHECK-LABEL: @test18( +; CHECK: %arg.off = add i32 %arg, -8 +; CHECK: icmp ult i32 %arg.off, 11 } define void @PR26323(i1 %tobool23, i32 %tmp3) { -; CHECK-LABEL: @PR26323( -; CHECK-NEXT: entry: -; CHECK-NEXT: [[TOBOOL5:%.*]] = icmp ne i32 [[TMP3:%.*]], 0 -; CHECK-NEXT: [[NEG14:%.*]] = and i32 [[TMP3]], -2 -; CHECK-NEXT: [[CMP17:%.*]] = icmp ne i32 [[NEG14]], -1 -; CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[TOBOOL5]], [[TOBOOL23:%.*]] -; CHECK-NEXT: [[OR_COND1:%.*]] = and i1 [[CMP17]], [[OR_COND]] -; CHECK-NEXT: br i1 [[OR_COND1]], label [[IF_END29:%.*]], label [[IF_THEN27:%.*]] -; CHECK: if.then27: -; CHECK-NEXT: call void @foo1() -; CHECK-NEXT: unreachable -; CHECK: if.end29: -; CHECK-NEXT: ret void -; entry: %tobool5 = icmp ne i32 %tmp3, 0 %neg14 = and i32 %tmp3, -2 @@ -730,20 +572,21 @@ if.end29: ; preds = %entry ret void } +; CHECK-LABEL: define void @PR26323( +; CHECK: %tobool5 = icmp ne i32 %tmp3, 0 +; CHECK: %neg14 = and i32 %tmp3, -2 +; CHECK: %cmp17 = icmp ne i32 %neg14, -1 +; CHECK: %or.cond = and i1 %tobool5, %tobool23 +; CHECK: %or.cond1 = and i1 %cmp17, %or.cond +; CHECK: br i1 %or.cond1, label %if.end29, label %if.then27 + ; Form a switch when and'ing a negated power of two +; CHECK-LABEL: define void @test19 +; CHECK: switch i32 %arg, label %else [ +; CHECK: i32 32, label %if +; CHECK: i32 13, label %if +; CHECK: i32 12, label %if define void @test19(i32 %arg) { -; CHECK-LABEL: @test19( -; CHECK-NEXT: switch i32 [[ARG:%.*]], label [[ELSE:%.*]] [ -; CHECK-NEXT: i32 32, label [[IF:%.*]] -; CHECK-NEXT: i32 13, label [[IF]] -; CHECK-NEXT: i32 12, label [[IF]] -; CHECK-NEXT: ] -; CHECK: if: -; CHECK-NEXT: call void @foo1() -; CHECK-NEXT: ret void -; CHECK: else: -; CHECK-NEXT: ret void -; %and = and i32 %arg, -2 %cmp1 = icmp eq i32 %and, 12 %cmp2 = icmp eq i32 %arg, 32 @@ -759,19 +602,10 @@ else: } ; Since %cmp1 is always false, a switch is never formed +; CHECK-LABEL: define void @test20 +; CHECK-NOT: switch +; CHECK: ret void define void @test20(i32 %arg) { -; CHECK-LABEL: @test20( -; CHECK-NEXT: [[AND:%.*]] = and i32 [[ARG:%.*]], -2 -; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[AND]], 13 -; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i32 [[ARG]], 32 -; CHECK-NEXT: [[PRED:%.*]] = or i1 [[CMP1]], [[CMP2]] -; CHECK-NEXT: br i1 [[PRED]], label [[IF:%.*]], label [[ELSE:%.*]] -; CHECK: if: -; CHECK-NEXT: call void @foo1() -; CHECK-NEXT: ret void -; CHECK: else: -; CHECK-NEXT: ret void -; %and = and i32 %arg, -2 %cmp1 = icmp eq i32 %and, 13 %cmp2 = icmp eq i32 %arg, 32 @@ -787,19 +621,11 @@ else: } ; Form a switch when or'ing a power of two +; CHECK-LABEL: define void @test21 +; CHECK: i32 32, label %else +; CHECK: i32 13, label %else +; CHECK: i32 12, label %else define void @test21(i32 %arg) { -; CHECK-LABEL: @test21( -; CHECK-NEXT: switch i32 [[ARG:%.*]], label [[IF:%.*]] [ -; CHECK-NEXT: i32 32, label [[ELSE:%.*]] -; CHECK-NEXT: i32 13, label [[ELSE]] -; CHECK-NEXT: i32 12, label [[ELSE]] -; CHECK-NEXT: ] -; CHECK: if: -; CHECK-NEXT: call void @foo1() -; CHECK-NEXT: ret void -; CHECK: else: -; CHECK-NEXT: ret void -; %and = or i32 %arg, 1 %cmp1 = icmp ne i32 %and, 13 %cmp2 = icmp ne i32 %arg, 32 @@ -815,19 +641,10 @@ else: } ; Since %cmp1 is always false, a switch is never formed +; CHECK-LABEL: define void @test22 +; CHECK-NOT: switch +; CHECK: ret void define void @test22(i32 %arg) { -; CHECK-LABEL: @test22( -; CHECK-NEXT: [[AND:%.*]] = or i32 [[ARG:%.*]], 1 -; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i32 [[AND]], 12 -; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i32 [[ARG]], 32 -; CHECK-NEXT: [[PRED:%.*]] = and i1 [[CMP1]], [[CMP2]] -; CHECK-NEXT: br i1 [[PRED]], label [[IF:%.*]], label [[ELSE:%.*]] -; CHECK: if: -; CHECK-NEXT: call void @foo1() -; CHECK-NEXT: ret void -; CHECK: else: -; CHECK-NEXT: ret void -; %and = or i32 %arg, 1 %cmp1 = icmp ne i32 %and, 12 %cmp2 = icmp ne i32 %arg, 32 @@ -840,4 +657,4 @@ if: else: ret void -} +}
\ No newline at end of file diff --git a/llvm/test/Transforms/SimplifyCFG/switch_switch_fold.ll b/llvm/test/Transforms/SimplifyCFG/switch_switch_fold.ll index 0df40349c1b..7f6f1c94bd4 100644 --- a/llvm/test/Transforms/SimplifyCFG/switch_switch_fold.ll +++ b/llvm/test/Transforms/SimplifyCFG/switch_switch_fold.ll @@ -1,4 +1,3 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt < %s -simplifycfg -S | FileCheck %s ; Test that a switch going to a switch on the same value can be merged. @@ -13,12 +12,43 @@ declare void @foo3() declare void @foo4() define void @test1(i32 %V) { + switch i32 %V, label %F [ + i32 4, label %T + i32 17, label %T + i32 5, label %T + i32 1234, label %F + ] +T: ; preds = %0, %0, %0 + switch i32 %V, label %F [ + i32 4, label %A + i32 17, label %B + i32 42, label %C + ] +A: ; preds = %T + call void @foo1( ) + ret void +B: ; preds = %F, %F, %T + call void @foo2( ) + ret void +C: ; preds = %T + call void @foo3( ) + ret void +F: ; preds = %F, %T, %0, %0 + switch i32 %V, label %F [ + i32 4, label %B + i32 18, label %B + i32 42, label %D + ] +D: ; preds = %F + call void @foo4( ) + ret void + ; CHECK-LABEL: @test1( -; CHECK-NEXT: switch i32 [[V:%.*]], label [[INFLOOP:%.*]] [ -; CHECK-NEXT: i32 4, label [[A:%.*]] -; CHECK-NEXT: i32 17, label [[B:%.*]] -; CHECK-NEXT: i32 18, label [[B]] -; CHECK-NEXT: i32 42, label [[D:%.*]] +; CHECK-NEXT: switch i32 %V, label %infloop [ +; CHECK-NEXT: i32 4, label %A +; CHECK-NEXT: i32 17, label %B +; CHECK-NEXT: i32 18, label %B +; CHECK-NEXT: i32 42, label %D ; CHECK-NEXT: ] ; CHECK: A: ; CHECK-NEXT: call void @foo1() @@ -30,38 +60,6 @@ define void @test1(i32 %V) { ; CHECK-NEXT: call void @foo4() ; CHECK-NEXT: ret void ; CHECK: infloop: -; CHECK-NEXT: br label [[INFLOOP]] -; - switch i32 %V, label %F [ - i32 4, label %T - i32 17, label %T - i32 5, label %T - i32 1234, label %F - ] -T: ; preds = %0, %0, %0 - switch i32 %V, label %F [ - i32 4, label %A - i32 17, label %B - i32 42, label %C - ] -A: ; preds = %T - call void @foo1( ) - ret void -B: ; preds = %F, %F, %T - call void @foo2( ) - ret void -C: ; preds = %T - call void @foo3( ) - ret void -F: ; preds = %F, %T, %0, %0 - switch i32 %V, label %F [ - i32 4, label %B - i32 18, label %B - i32 42, label %D - ] -D: ; preds = %F - call void @foo4( ) - ret void - +; CHECK-NEXT: br label %infloop } diff --git a/llvm/test/Transforms/SimplifyCFG/switch_thread.ll b/llvm/test/Transforms/SimplifyCFG/switch_thread.ll index e38865699d2..32e0325df7f 100644 --- a/llvm/test/Transforms/SimplifyCFG/switch_thread.ll +++ b/llvm/test/Transforms/SimplifyCFG/switch_thread.ll @@ -1,4 +1,3 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt < %s -simplifycfg -S | FileCheck %s ; Test that we can thread a simple known condition through switch statements. @@ -10,70 +9,97 @@ declare void @foo2() declare void @DEAD() define void @test1(i32 %V) { + switch i32 %V, label %A [ + i32 4, label %T + i32 17, label %Done + i32 1234, label %A + ] +;; V == 4 if we get here. +T: ; preds = %0 + call void @foo1( ) + ;; This switch is always statically determined. + switch i32 %V, label %A2 [ + i32 4, label %B + i32 17, label %C + i32 42, label %C + ] +A2: ; preds = %T + call void @DEAD( ) + call void @DEAD( ) + ;; always true + %cond2 = icmp eq i32 %V, 4 ; <i1> [#uses=1] + br i1 %cond2, label %Done, label %C +A: ; preds = %0, %0 + call void @foo1( ) + ;; always true + %cond = icmp ne i32 %V, 4 ; <i1> [#uses=1] + br i1 %cond, label %Done, label %C +Done: ; preds = %B, %A, %A2, %0 + ret void +B: ; preds = %T + call void @foo2( ) + ;; always true + %cond3 = icmp eq i32 %V, 4 ; <i1> [#uses=1] + br i1 %cond3, label %Done, label %C +C: ; preds = %B, %A, %A2, %T, %T + call void @DEAD( ) + ret void + ; CHECK-LABEL: @test1( -; CHECK-NEXT: switch i32 [[V:%.*]], label [[A:%.*]] [ -; CHECK-NEXT: i32 4, label [[T:%.*]] -; CHECK-NEXT: i32 17, label [[DONE:%.*]] +; CHECK-NEXT: switch i32 %V, label %A [ +; CHECK-NEXT: i32 4, label %T +; CHECK-NEXT: i32 17, label %Done ; CHECK-NEXT: ] ; CHECK: T: ; CHECK-NEXT: call void @foo1() ; CHECK-NEXT: call void @foo2() -; CHECK-NEXT: br label [[DONE]] +; CHECK-NEXT: br label %Done ; CHECK: A: ; CHECK-NEXT: call void @foo1() -; CHECK-NEXT: br label [[DONE]] +; CHECK-NEXT: br label %Done ; CHECK: Done: ; CHECK-NEXT: ret void -; - switch i32 %V, label %A [ - i32 4, label %T - i32 17, label %Done - i32 1234, label %A - ] -;; V == 4 if we get here. -T: ; preds = %0 - call void @foo1( ) - ;; This switch is always statically determined. - switch i32 %V, label %A2 [ - i32 4, label %B - i32 17, label %C - i32 42, label %C - ] -A2: ; preds = %T - call void @DEAD( ) - call void @DEAD( ) - ;; always true - %cond2 = icmp eq i32 %V, 4 ; <i1> [#uses=1] - br i1 %cond2, label %Done, label %C -A: ; preds = %0, %0 - call void @foo1( ) - ;; always true - %cond = icmp ne i32 %V, 4 ; <i1> [#uses=1] - br i1 %cond, label %Done, label %C -Done: ; preds = %B, %A, %A2, %0 - ret void -B: ; preds = %T - call void @foo2( ) - ;; always true - %cond3 = icmp eq i32 %V, 4 ; <i1> [#uses=1] - br i1 %cond3, label %Done, label %C -C: ; preds = %B, %A, %A2, %T, %T - call void @DEAD( ) - ret void - } define void @test2(i32 %V) { + switch i32 %V, label %A [ + i32 4, label %T + i32 17, label %D + i32 1234, label %E + ] +;; V != 4, 17, 1234 here. +A: ; preds = %0 + call void @foo1( ) + ;; This switch is always statically determined. + switch i32 %V, label %E [ + i32 4, label %C + i32 17, label %C + i32 42, label %D + ] +;; unreacahble. +C: ; preds = %A, %A + call void @DEAD( ) + ret void +T: ; preds = %0 + call void @foo1( ) + call void @foo1( ) + ret void +D: ; preds = %A, %0 + call void @foo1( ) + ret void +E: ; preds = %A, %0 + ret void + ; CHECK-LABEL: @test2( -; CHECK-NEXT: switch i32 [[V:%.*]], label [[A:%.*]] [ -; CHECK-NEXT: i32 4, label [[T:%.*]] -; CHECK-NEXT: i32 17, label [[D:%.*]] -; CHECK-NEXT: i32 1234, label [[E:%.*]] +; CHECK-NEXT: switch i32 %V, label %A [ +; CHECK-NEXT: i32 4, label %T +; CHECK-NEXT: i32 17, label %D +; CHECK-NEXT: i32 1234, label %E ; CHECK-NEXT: ] ; CHECK: A: ; CHECK-NEXT: call void @foo1() -; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[V]], 42 -; CHECK-NEXT: br i1 [[COND]], label [[D]], label [[E]] +; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 %V, 42 +; CHECK-NEXT: br i1 [[COND]], label %D, label %E ; CHECK: T: ; CHECK-NEXT: call void @foo1() ; CHECK-NEXT: call void @foo1() @@ -83,34 +109,5 @@ define void @test2(i32 %V) { ; CHECK-NEXT: ret void ; CHECK: E: ; CHECK-NEXT: ret void -; - switch i32 %V, label %A [ - i32 4, label %T - i32 17, label %D - i32 1234, label %E - ] -;; V != 4, 17, 1234 here. -A: ; preds = %0 - call void @foo1( ) - ;; This switch is always statically determined. - switch i32 %V, label %E [ - i32 4, label %C - i32 17, label %C - i32 42, label %D - ] -;; unreacahble. -C: ; preds = %A, %A - call void @DEAD( ) - ret void -T: ; preds = %0 - call void @foo1( ) - call void @foo1( ) - ret void -D: ; preds = %A, %0 - call void @foo1( ) - ret void -E: ; preds = %A, %0 - ret void - } diff --git a/llvm/test/Transforms/SimplifyCFG/switch_undef.ll b/llvm/test/Transforms/SimplifyCFG/switch_undef.ll index 83d18c924dc..e5acf41644a 100644 --- a/llvm/test/Transforms/SimplifyCFG/switch_undef.ll +++ b/llvm/test/Transforms/SimplifyCFG/switch_undef.ll @@ -1,24 +1,17 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt %s -keep-loops=false -switch-to-lookup=true -simplifycfg -S | FileCheck %s ; RUN: opt %s -passes='simplify-cfg<no-keep-loops;switch-to-lookup>' -S | FileCheck %s define void @f6() #0 { -; CHECK-LABEL: @f6( -; CHECK-NEXT: entry: -; CHECK-NEXT: br label [[FOR_COND_I:%.*]] -; CHECK: for.cond.i: -; CHECK-NEXT: [[TOBOOL7_I:%.*]] = icmp ne i16 1, 0 -; CHECK-NEXT: br label [[FOR_COND_I]] -; +; CHECK-LABEL: entry: entry: br label %for.cond.i for.cond.i: ; preds = %f1.exit.i, %entry switch i16 undef, label %f1.exit.i [ - i16 -1, label %cond.false.i3.i - i16 1, label %cond.false.i3.i - i16 0, label %cond.false.i3.i + i16 -1, label %cond.false.i3.i + i16 1, label %cond.false.i3.i + i16 0, label %cond.false.i3.i ] cond.false.i3.i: ; preds = %for.cond.i, %for.cond.i, %for.cond.i |