diff options
author | Shawn Landden <shawn@git.icu> | 2019-05-26 13:52:41 +0000 |
---|---|---|
committer | Shawn Landden <shawn@git.icu> | 2019-05-26 13:52:41 +0000 |
commit | 50c73a044f22e97ea384c461bcdd2ea4fbed0156 (patch) | |
tree | 1d109d8525688ead078843e158d760e62ea19d82 /llvm/test/Transforms/SimplifyCFG/X86 | |
parent | b7cc093db28cf6d20b35092c4108bc8aa15cc011 (diff) | |
download | bcm5719-llvm-50c73a044f22e97ea384c461bcdd2ea4fbed0156.tar.gz bcm5719-llvm-50c73a044f22e97ea384c461bcdd2ea4fbed0156.zip |
[SimplifyCFG] NFC, update Switch tests to HEAD so I can see if my changes change anything
Also add baseline tests to show effect of later patches.
llvm-svn: 361725
Diffstat (limited to 'llvm/test/Transforms/SimplifyCFG/X86')
5 files changed, 1235 insertions, 693 deletions
diff --git a/llvm/test/Transforms/SimplifyCFG/X86/disable-lookup-table.ll b/llvm/test/Transforms/SimplifyCFG/X86/disable-lookup-table.ll index a8758a789ec..adb0a9819dc 100644 --- a/llvm/test/Transforms/SimplifyCFG/X86/disable-lookup-table.ll +++ b/llvm/test/Transforms/SimplifyCFG/X86/disable-lookup-table.ll @@ -1,3 +1,4 @@ +; 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 @@ -8,12 +9,32 @@ ; 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 @@ -27,12 +48,24 @@ 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 bee80e6acce..11ba3984f35 100644 --- a/llvm/test/Transforms/SimplifyCFG/X86/speculate-cttz-ctlz.ll +++ b/llvm/test/Transforms/SimplifyCFG/X86/speculate-cttz-ctlz.ll @@ -1,14 +1,31 @@ +; 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) { -; 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 +; 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]] +; entry: %tobool = icmp eq i64 %A, 0 br i1 %tobool, label %cond.end, label %cond.true @@ -23,11 +40,27 @@ cond.end: ; preds = %entry, %cond.true } define i32 @test2(i32 %A) { -; 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 +; 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]] +; entry: %tobool = icmp eq i32 %A, 0 br i1 %tobool, label %cond.end, label %cond.true @@ -43,11 +76,27 @@ cond.end: ; preds = %entry, %cond.true define signext i16 @test3(i16 signext %A) { -; 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 +; 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]] +; entry: %tobool = icmp eq i16 %A, 0 br i1 %tobool, label %cond.end, label %cond.true @@ -63,11 +112,27 @@ cond.end: ; preds = %entry, %cond.true define i64 @test1b(i64 %A) { -; 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 +; 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]] +; entry: %tobool = icmp eq i64 %A, 0 br i1 %tobool, label %cond.end, label %cond.true @@ -83,11 +148,27 @@ cond.end: ; preds = %entry, %cond.true define i32 @test2b(i32 %A) { -; 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 +; 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]] +; entry: %tobool = icmp eq i32 %A, 0 br i1 %tobool, label %cond.end, label %cond.true @@ -103,11 +184,27 @@ cond.end: ; preds = %entry, %cond.true define signext i16 @test3b(i16 signext %A) { -; 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 +; 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]] +; entry: %tobool = icmp eq i16 %A, 0 br i1 %tobool, label %cond.end, label %cond.true @@ -126,14 +223,38 @@ cond.end: ; preds = %entry, %cond.true ; for the target. define i64 @test1e(i32 %x) { -; 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 +; 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]] +; entry: %tobool = icmp eq i32 %x, 0 br i1 %tobool, label %cond.end, label %cond.true @@ -149,14 +270,38 @@ cond.end: ; preds = %entry, %cond.true } define i32 @test2e(i64 %x) { -; 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 +; 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]] +; entry: %tobool = icmp eq i64 %x, 0 br i1 %tobool, label %cond.end, label %cond.true @@ -172,14 +317,38 @@ cond.end: ; preds = %entry, %cond.true } define i64 @test3e(i32 %x) { -; 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 +; 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]] +; entry: %tobool = icmp eq i32 %x, 0 br i1 %tobool, label %cond.end, label %cond.true @@ -195,14 +364,38 @@ cond.end: ; preds = %entry, %cond.true } define i32 @test4e(i64 %x) { -; 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 +; 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]] +; entry: %tobool = icmp eq i64 %x, 0 br i1 %tobool, label %cond.end, label %cond.true @@ -218,14 +411,38 @@ cond.end: ; preds = %entry, %cond.true } define i16 @test5e(i64 %x) { -; 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 +; 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]] +; entry: %tobool = icmp eq i64 %x, 0 br i1 %tobool, label %cond.end, label %cond.true @@ -241,14 +458,38 @@ cond.end: ; preds = %entry, %cond.true } define i16 @test6e(i32 %x) { -; 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 +; 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]] +; entry: %tobool = icmp eq i32 %x, 0 br i1 %tobool, label %cond.end, label %cond.true @@ -264,14 +505,38 @@ cond.end: ; preds = %entry, %cond.true } define i16 @test7e(i64 %x) { -; 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 +; 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]] +; entry: %tobool = icmp eq i64 %x, 0 br i1 %tobool, label %cond.end, label %cond.true @@ -287,14 +552,38 @@ cond.end: ; preds = %entry, %cond.true } define i16 @test8e(i32 %x) { -; 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 +; 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]] +; 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 c42568ffa93..b7bf8054a6f 100644 --- a/llvm/test/Transforms/SimplifyCFG/X86/switch-covered-bug.ll +++ b/llvm/test/Transforms/SimplifyCFG/X86/switch-covered-bug.ll @@ -1,3 +1,4 @@ +; 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 @@ -5,25 +6,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" -; 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 0b9d6ebe825..e50a913f9e5 100644 --- a/llvm/test/Transforms/SimplifyCFG/X86/switch-table-bug.ll +++ b/llvm/test/Transforms/SimplifyCFG/X86/switch-table-bug.ll @@ -1,3 +1,4 @@ +; 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 @@ -5,21 +6,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 3128ce4afa6..c77438974b2 100644 --- a/llvm/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll +++ b/llvm/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll @@ -1,3 +1,4 @@ +; 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" @@ -33,15 +34,27 @@ 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 @@ -55,33 +68,34 @@ 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 @@ -97,29 +111,35 @@ 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 @@ -133,22 +153,6 @@ 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 } @@ -161,12 +165,23 @@ 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 @@ -176,32 +191,35 @@ 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 @@ -214,13 +232,6 @@ 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 } @@ -229,21 +240,40 @@ 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 @@ -251,49 +281,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 @@ -306,19 +336,29 @@ 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 @@ -327,16 +367,27 @@ 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 @@ -348,205 +399,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 @@ -755,15 +806,27 @@ 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 @@ -790,23 +853,31 @@ 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 @@ -819,18 +890,21 @@ 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 @@ -843,24 +917,40 @@ 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 @@ -872,75 +962,106 @@ 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 @@ -948,19 +1069,16 @@ 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: @@ -987,9 +1105,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]] ; @@ -1013,11 +1131,28 @@ 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 @@ -1028,9 +1163,6 @@ 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. @@ -1039,11 +1171,28 @@ 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 @@ -1053,23 +1202,33 @@ 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 @@ -1078,24 +1237,28 @@ 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 @@ -1104,23 +1267,28 @@ 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 @@ -1129,23 +1297,27 @@ 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 @@ -1154,22 +1326,26 @@ 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 @@ -1185,22 +1361,24 @@ 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 @@ -1216,24 +1394,26 @@ 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 @@ -1249,25 +1429,35 @@ 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 @@ -1283,28 +1473,49 @@ 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: @@ -1326,8 +1537,6 @@ 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 @@ -1335,12 +1544,28 @@ 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 @@ -1354,18 +1579,17 @@ 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 - -define i32 @PR26308(i1 %B, i64 %load) { +; CHECK-NEXT: br label [[CLEANUP4]] +; entry: br label %while.body @@ -1393,9 +1617,32 @@ 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 @@ -1403,9 +1650,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: @@ -1421,32 +1668,4 @@ 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(...) |