InstCombine: Narrow switch instructions using known bits.

Truncate the operands of a switch instruction to a narrower type if the upper
bits are known to be all ones or zeros.

rdar://problem/17720004


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@219832 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Akira Hatanaka 2014-10-15 19:05:50 +00:00
parent 7440a83e60
commit 38537634e2
2 changed files with 92 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(Ty, C.getCaseValue()->getValue().getZExtValue()));
}
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,61 @@
; 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
}