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))) {