mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-13 04:30:23 +00:00
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:
parent
7440a83e60
commit
38537634e2
@ -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))) {
|
||||
|
61
test/Transforms/InstCombine/narrow-switch.ll
Normal file
61
test/Transforms/InstCombine/narrow-switch.ll
Normal 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
|
||||
}
|
Loading…
Reference in New Issue
Block a user