Reapply r219832 - InstCombine: Narrow switch instructions using known bits.

The code committed in r219832 asserted when it attempted to shrink a switch
statement whose type was larger than 64-bit.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@219902 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Akira Hatanaka 2014-10-16 06:00:46 +00:00
parent ebe6584c32
commit 4eb03123df
2 changed files with 124 additions and 0 deletions

View File

@ -2075,6 +2075,37 @@ Instruction *InstCombiner::visitBranchInst(BranchInst &BI) {
Instruction *InstCombiner::visitSwitchInst(SwitchInst &SI) {
Value *Cond = SI.getCondition();
unsigned BitWidth = cast<IntegerType>(Cond->getType())->getBitWidth();
APInt KnownZero(BitWidth, 0), KnownOne(BitWidth, 0);
computeKnownBits(Cond, KnownZero, KnownOne);
unsigned LeadingKnownZeros = KnownZero.countLeadingOnes();
unsigned LeadingKnownOnes = KnownOne.countLeadingOnes();
// Compute the number of leading bits we can ignore.
for (auto &C : SI.cases()) {
LeadingKnownZeros = std::min(
LeadingKnownZeros, C.getCaseValue()->getValue().countLeadingZeros());
LeadingKnownOnes = std::min(
LeadingKnownOnes, C.getCaseValue()->getValue().countLeadingOnes());
}
unsigned NewWidth = BitWidth - std::max(LeadingKnownZeros, LeadingKnownOnes);
// Truncate the condition operand if the new type is equal to or larger than
// the largest legal integer type. We need to be conservative here since
// x86 generates redundant zero-extenstion instructions if the operand is
// truncated to i8 or i16.
if (BitWidth > NewWidth && NewWidth >= DL->getLargestLegalIntTypeSize()) {
IntegerType *Ty = IntegerType::get(SI.getContext(), NewWidth);
Builder->SetInsertPoint(&SI);
Value *NewCond = Builder->CreateTrunc(SI.getCondition(), Ty, "trunc");
SI.setCondition(NewCond);
for (auto &C : SI.cases())
static_cast<SwitchInst::CaseIt *>(&C)->setValue(ConstantInt::get(
SI.getContext(), C.getCaseValue()->getValue().trunc(NewWidth)));
}
if (Instruction *I = dyn_cast<Instruction>(Cond)) {
if (I->getOpcode() == Instruction::Add)
if (ConstantInt *AddRHS = dyn_cast<ConstantInt>(I->getOperand(1))) {

View File

@ -0,0 +1,93 @@
; RUN: opt < %s -instcombine -S | FileCheck %s
target datalayout = "e-m:o-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32"
; CHECK-LABEL: define i32 @positive1
; CHECK: switch i32
; CHECK: i32 10, label
; CHECK: i32 100, label
; CHECK: i32 1001, label
define i32 @positive1(i64 %a) {
entry:
%and = and i64 %a, 4294967295
switch i64 %and, label %sw.default [
i64 10, label %return
i64 100, label %sw.bb1
i64 1001, label %sw.bb2
]
sw.bb1:
br label %return
sw.bb2:
br label %return
sw.default:
br label %return
return:
%retval.0 = phi i32 [ 24, %sw.default ], [ 123, %sw.bb2 ], [ 213, %sw.bb1 ], [ 231, %entry ]
ret i32 %retval.0
}
; CHECK-LABEL: define i32 @negative1
; CHECK: switch i32
; CHECK: i32 -10, label
; CHECK: i32 -100, label
; CHECK: i32 -1001, label
define i32 @negative1(i64 %a) {
entry:
%or = or i64 %a, -4294967296
switch i64 %or, label %sw.default [
i64 -10, label %return
i64 -100, label %sw.bb1
i64 -1001, label %sw.bb2
]
sw.bb1:
br label %return
sw.bb2:
br label %return
sw.default:
br label %return
return:
%retval.0 = phi i32 [ 24, %sw.default ], [ 123, %sw.bb2 ], [ 213, %sw.bb1 ], [ 231, %entry ]
ret i32 %retval.0
}
; Make sure truncating a constant int larger than 64-bit doesn't trigger an
; assertion.
; CHECK-LABEL: define i32 @trunc72to68
; CHECK: switch i68
; CHECK: i68 10, label
; CHECK: i68 100, label
; CHECK: i68 1001, label
define i32 @trunc72to68(i72 %a) {
entry:
%and = and i72 %a, 295147905179352825855
switch i72 %and, label %sw.default [
i72 10, label %return
i72 100, label %sw.bb1
i72 1001, label %sw.bb2
]
sw.bb1:
br label %return
sw.bb2:
br label %return
sw.default:
br label %return
return:
%retval.0 = phi i32 [ 24, %sw.default ], [ 123, %sw.bb2 ], [ 213, %sw.bb1 ], [ 231, %entry ]
ret i32 %retval.0
}