OSDN Git Service

[SimplifyCFG] Range reduce switches
authorJames Molloy <james.molloy@arm.com>
Mon, 1 Aug 2016 07:45:11 +0000 (07:45 +0000)
committerJames Molloy <james.molloy@arm.com>
Mon, 1 Aug 2016 07:45:11 +0000 (07:45 +0000)
commit16e549f1c04f22118aee910f4ca604ded25bcc72
treedff9fe23928d634efa300f3799c7524ff9158eb6
parent5c02c44a2839b9282ed8b37bf732c92286d8ab94
[SimplifyCFG] Range reduce switches

If a switch is sparse and all the cases (once sorted) are in arithmetic progression, we can extract the common factor out of the switch and create a dense switch. For example:

    switch (i) {
    case 5: ...
    case 9: ...
    case 13: ...
    case 17: ...
    }

can become:

    if ( (i - 5) % 4 ) goto default;
    switch ((i - 5) / 4) {
    case 0: ...
    case 1: ...
    case 2: ...
    case 3: ...
    }

or even better:

   switch ( ROTR(i - 5, 2) {
   case 0: ...
   case 1: ...
   case 2: ...
   case 3: ...
   }

The division and remainder operations could be costly so we only do this if the factor is a power of two, and emit a right-rotate instead of a divide/remainder sequence. Dense switches can be lowered significantly better than sparse switches and can even be transformed into lookup tables.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@277325 91177308-0d34-0410-b5e6-96231b3b80d8
lib/Transforms/Utils/SimplifyCFG.cpp
test/Transforms/SimplifyCFG/rangereduce.ll [new file with mode: 0644]