diff options
| author | Shawn Landden <shawn@git.icu> | 2019-06-13 02:47:47 +0000 |
|---|---|---|
| committer | Shawn Landden <shawn@git.icu> | 2019-06-13 02:47:47 +0000 |
| commit | c6cba2957d520b41de7fef7dfbfc8edc35c228e3 (patch) | |
| tree | b1f879ad01b422e9d219e0e48628623e9d4830dd /llvm/test/Transforms/SimplifyCFG/X86 | |
| parent | f93b99b2b6a429f020aca2ea8c503e7553f3777c (diff) | |
| download | bcm5719-llvm-c6cba2957d520b41de7fef7dfbfc8edc35c228e3.tar.gz bcm5719-llvm-c6cba2957d520b41de7fef7dfbfc8edc35c228e3.zip | |
[SimplifyCFG] revert the last commit.
I ran ALL the test suite locally, so I will look into this...
llvm-svn: 363223
Diffstat (limited to 'llvm/test/Transforms/SimplifyCFG/X86')
5 files changed, 699 insertions, 1237 deletions
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 b2c067ae316..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" @@ -20,10 +19,10 @@ target triple = "x86_64-unknown-linux-gnu" ; CHECK: @switch.table.earlyreturncrash = private unnamed_addr constant [4 x i32] [i32 42, i32 9, i32 88, i32 5], align 4 ; The table for @large -; CHECK: @switch.table.large = private unnamed_addr constant [200 x i32] [i32 0, i32 1, i32 4, i32 9, +; CHECK: @switch.table.large = private unnamed_addr constant [199 x i32] [i32 1, i32 4, i32 9, ; The table for @cprop -; CHECK: @switch.table.cprop = private unnamed_addr constant [8 x i32] [i32 123, i32 5, i32 42, i32 126, i32 -452, i32 128, i32 6, i32 7], align 4 +; CHECK: @switch.table.cprop = private unnamed_addr constant [7 x i32] [i32 5, i32 42, i32 126, i32 -452, i32 128, i32 6, i32 7], align 4 ; The table for @unreachable_case ; CHECK: @switch.table.unreachable_case = private unnamed_addr constant [9 x i32] [i32 0, i32 0, i32 0, i32 2, i32 -1, i32 1, i32 1, i32 1, i32 1], align 4 @@ -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(...) |

