improve switch formation to handle small range
authorChris Lattner <sabre@nondot.org>
Fri, 17 Dec 2010 06:20:15 +0000 (06:20 +0000)
committerChris Lattner <sabre@nondot.org>
Fri, 17 Dec 2010 06:20:15 +0000 (06:20 +0000)
commite27db74a60c44d2b5d2700ecde11b1adce0d0d59
tree656f8aebf6c4dccb96f57e8e42b09bab6bcfe742
parent1139d5090ab96e24342f12a6a6817d5898358e1e
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
include/llvm/Support/ConstantRange.h
lib/Transforms/Utils/SimplifyCFG.cpp
test/Transforms/SimplifyCFG/switch_create.ll