Index: lib/Transforms/Utils/LowerSwitch.cpp =================================================================== --- lib/Transforms/Utils/LowerSwitch.cpp +++ lib/Transforms/Utils/LowerSwitch.cpp @@ -387,8 +387,34 @@ return; } - const bool DefaultIsUnreachable = - Default->size() == 1 && isa(Default->getTerminator()); + bool DefaultIsUnreachable = + isa(Default->getFirstNonPHIOrDbg()); + + if (DefaultIsUnreachable) { + DenseMap Popularity; + unsigned MaxPop = 0; + BasicBlock *MaxBB = nullptr; + for (auto I : SI->cases()) { + BasicBlock *BB = I.getCaseSuccessor(); + if (++Popularity[BB] > MaxPop) { + MaxPop = Popularity[BB]; + MaxBB = BB; + } + } + if (MaxPop > 1) { + // If some block is extra popular, use that as the default result, + // reducing the number of cases. + Default = MaxBB; + DefaultIsUnreachable = false; + for (auto I = SI->case_begin(); I != SI->case_end();) { + if (I.getCaseSuccessor() == MaxBB) + SI->removeCase(I); + else + ++I; + } + } + } + // Create a new, empty default block so that the new hierarchy of // if-then statements go to this and the PHI nodes are happy. // if the default block is set as an unreachable we avoid creating one @@ -438,11 +464,10 @@ BranchInst::Create(SwitchBlock, OrigBlock); // We are now done with the switch instruction, delete it. + BasicBlock *OldDefault = SI->getDefaultDest(); CurBlock->getInstList().erase(SI); - pred_iterator PI = pred_begin(Default), E = pred_end(Default); - // If the Default block has no more predecessors just remove it - if (PI == E) { - DeleteDeadBlock(Default); - } + // If the Default block has no more predecessors just remove it. + if (pred_begin(OldDefault) == pred_end(OldDefault)) + DeleteDeadBlock(OldDefault); } Index: test/Transforms/LowerSwitch/fold-popular-case-to-unreachable-default.ll =================================================================== --- /dev/null +++ test/Transforms/LowerSwitch/fold-popular-case-to-unreachable-default.ll @@ -0,0 +1,43 @@ +; RUN: opt %s -lowerswitch -S | FileCheck %s + +; An unreachabel default is replaced with a popular case label. + +define void @foo(i32 %x, i32* %p) { +; CHECK-LABEL: @foo +; CHECK: icmp {{[a-z]+}} i32 %x, 3 +; CHECK-NOT: icmp {{[a-z]+}} i32 %x, 4 +; CHECK-NOT: icmp {{[a-z]+}} i32 %x, 5 +; CHECK-LABEL: NewDefault: +; CHECK-NEXT: br label %bb4 +; CHECK-NOT: default: +; CEHCK-NOT: unreachable + +entry: + switch i32 %x, label %default [ + i32 0, label %bb0 + i32 1, label %bb1 + i32 2, label %bb2 + i32 3, label %bb3 + i32 4, label %bb4 + i32 5, label %bb4 + ] +bb0: + store i32 0, i32* %p + br label %exit +bb1: + store i32 1, i32* %p + br label %exit +bb2: + store i32 2, i32* %p + br label %exit +bb3: + store i32 3, i32* %p + br label %exit +bb4: + store i32 4, i32* %p + br label %exit +exit: + ret void +default: + unreachable +}