From d14b0f1db7a6ca8b17adbeec25fea2eb2b907040 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Fri, 17 Dec 2010 06:20:15 +0000 Subject: 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. llvm-svn: 122045 --- llvm/test/Transforms/SimplifyCFG/switch_create.ll | 71 ++++++++++++++++++++++- 1 file changed, 70 insertions(+), 1 deletion(-) (limited to 'llvm/test') diff --git a/llvm/test/Transforms/SimplifyCFG/switch_create.ll b/llvm/test/Transforms/SimplifyCFG/switch_create.ll index 0169eb7039f..369ebc35272 100644 --- a/llvm/test/Transforms/SimplifyCFG/switch_create.ll +++ b/llvm/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: ] +} + -- cgit v1.2.3