From 4eb03123dfda2de88a84852834845678833c8c36 Mon Sep 17 00:00:00 2001 From: Akira Hatanaka Date: Thu, 16 Oct 2014 06:00:46 +0000 Subject: [PATCH] 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 --- .../InstCombine/InstructionCombining.cpp | 31 +++++++ test/Transforms/InstCombine/narrow-switch.ll | 93 +++++++++++++++++++ 2 files changed, 124 insertions(+) create mode 100644 test/Transforms/InstCombine/narrow-switch.ll diff --git a/lib/Transforms/InstCombine/InstructionCombining.cpp b/lib/Transforms/InstCombine/InstructionCombining.cpp index ac0c01e3c7b..8d74976cb18 100644 --- a/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -2075,6 +2075,37 @@ Instruction *InstCombiner::visitBranchInst(BranchInst &BI) { Instruction *InstCombiner::visitSwitchInst(SwitchInst &SI) { Value *Cond = SI.getCondition(); + unsigned BitWidth = cast(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(&C)->setValue(ConstantInt::get( + SI.getContext(), C.getCaseValue()->getValue().trunc(NewWidth))); + } + if (Instruction *I = dyn_cast(Cond)) { if (I->getOpcode() == Instruction::Add) if (ConstantInt *AddRHS = dyn_cast(I->getOperand(1))) { diff --git a/test/Transforms/InstCombine/narrow-switch.ll b/test/Transforms/InstCombine/narrow-switch.ll new file mode 100644 index 00000000000..7646189b854 --- /dev/null +++ b/test/Transforms/InstCombine/narrow-switch.ll @@ -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 +} -- 2.34.1