summaryrefslogtreecommitdiff
path: root/test/Transforms/SimplifyCFG
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2010-12-17 06:20:15 +0000
committerChris Lattner <sabre@nondot.org>2010-12-17 06:20:15 +0000
commite27db74a60c44d2b5d2700ecde11b1adce0d0d59 (patch)
tree656f8aebf6c4dccb96f57e8e42b09bab6bcfe742 /test/Transforms/SimplifyCFG
parent1139d5090ab96e24342f12a6a6817d5898358e1e (diff)
downloadllvm-e27db74a60c44d2b5d2700ecde11b1adce0d0d59.tar.gz
llvm-e27db74a60c44d2b5d2700ecde11b1adce0d0d59.tar.bz2
llvm-e27db74a60c44d2b5d2700ecde11b1adce0d0d59.tar.xz
improve switch formation to handle small range
comparisons formed by comparisons. For example, this: void foo(unsigned x) { if (x == 0 || x == 1 || x == 3 || x == 4 || x == 6) bar(); } compiles into: _foo: ## @foo ## BB#0: ## %entry cmpl $6, %edi ja LBB0_2 ## BB#1: ## %entry movl %edi, %eax movl $91, %ecx btq %rax, %rcx jb LBB0_3 instead of: _foo: ## @foo ## BB#0: ## %entry cmpl $2, %edi jb LBB0_4 ## BB#1: ## %switch.early.test cmpl $6, %edi ja LBB0_3 ## BB#2: ## %switch.early.test movl %edi, %eax movl $88, %ecx btq %rax, %rcx jb LBB0_4 This catches a bunch of cases in GCC, which look like this: %804 = load i32* @which_alternative, align 4, !tbaa !0 %805 = icmp ult i32 %804, 2 %806 = icmp eq i32 %804, 3 %or.cond121 = or i1 %805, %806 %807 = icmp eq i32 %804, 4 %or.cond124 = or i1 %or.cond121, %807 br i1 %or.cond124, label %.thread, label %808 turning this into a range comparison. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@122045 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test/Transforms/SimplifyCFG')
-rw-r--r--test/Transforms/SimplifyCFG/switch_create.ll71
1 files changed, 70 insertions, 1 deletions
diff --git a/test/Transforms/SimplifyCFG/switch_create.ll b/test/Transforms/SimplifyCFG/switch_create.ll
index 0169eb7039..369ebc3527 100644
--- a/test/Transforms/SimplifyCFG/switch_create.ll
+++ b/test/Transforms/SimplifyCFG/switch_create.ll
@@ -351,4 +351,73 @@ malformed:
ret void
; CHECK: @test12
-} \ No newline at end of file
+}
+
+; test13 - handle switch formation with ult.
+define void @test13(i32 %x) nounwind ssp noredzone {
+entry:
+ %cmp = icmp ult i32 %x, 2
+ br i1 %cmp, label %if.then, label %lor.lhs.false3
+
+lor.lhs.false3: ; preds = %lor.lhs.false
+ %cmp5 = icmp eq i32 %x, 3
+ br i1 %cmp5, label %if.then, label %lor.lhs.false6
+
+lor.lhs.false6: ; preds = %lor.lhs.false3
+ %cmp8 = icmp eq i32 %x, 4
+ br i1 %cmp8, label %if.then, label %lor.lhs.false9
+
+lor.lhs.false9: ; preds = %lor.lhs.false6
+ %cmp11 = icmp eq i32 %x, 6
+ br i1 %cmp11, label %if.then, label %if.end
+
+if.then: ; preds = %lor.lhs.false9, %lor.lhs.false6, %lor.lhs.false3, %lor.lhs.false, %entry
+ call void @foo1() noredzone
+ br label %if.end
+
+if.end: ; preds = %if.then, %lor.lhs.false9
+ ret void
+; CHECK: @test13
+; CHECK: switch i32 %x, label %if.end [
+; CHECK: i32 6, label %if.then
+; CHECK: i32 4, label %if.then
+; CHECK: i32 3, label %if.then
+; CHECK: i32 1, label %if.then
+; CHECK: i32 0, label %if.then
+; CHECK: ]
+}
+
+; test14 - handle switch formation with ult.
+define void @test14(i32 %x) nounwind ssp noredzone {
+entry:
+ %cmp = icmp ugt i32 %x, 2
+ br i1 %cmp, label %lor.lhs.false3, label %if.then
+
+lor.lhs.false3: ; preds = %lor.lhs.false
+ %cmp5 = icmp ne i32 %x, 3
+ br i1 %cmp5, label %lor.lhs.false6, label %if.then
+
+lor.lhs.false6: ; preds = %lor.lhs.false3
+ %cmp8 = icmp ne i32 %x, 4
+ br i1 %cmp8, label %lor.lhs.false9, label %if.then
+
+lor.lhs.false9: ; preds = %lor.lhs.false6
+ %cmp11 = icmp ne i32 %x, 6
+ br i1 %cmp11, label %if.end, label %if.then
+
+if.then: ; preds = %lor.lhs.false9, %lor.lhs.false6, %lor.lhs.false3, %lor.lhs.false, %entry
+ call void @foo1() noredzone
+ br label %if.end
+
+if.end: ; preds = %if.then, %lor.lhs.false9
+ ret void
+; CHECK: @test14
+; CHECK: switch i32 %x, label %if.end [
+; CHECK: i32 6, label %if.then
+; CHECK: i32 4, label %if.then
+; CHECK: i32 3, label %if.then
+; CHECK: i32 1, label %if.then
+; CHECK: i32 0, label %if.then
+; CHECK: ]
+}
+