diff options
author | Chris Lattner <sabre@nondot.org> | 2006-09-18 05:27:43 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2006-09-18 05:27:43 +0000 |
commit | e695a3bd32443aa7da9f5d699f2ad763643d0032 (patch) | |
tree | 7b8fa933d7af09bc9b2e23b09d407754369402c8 | |
parent | e04deb9914b524da60f92615b8f45bc27ccb3d2d (diff) |
Implement InstCombine/cast.ll:test31. This speeds up 462.libquantum by 26%.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@30456 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Transforms/Scalar/InstructionCombining.cpp | 43 |
1 files changed, 39 insertions, 4 deletions
diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp index 4ed827944d..c3d6f1465e 100644 --- a/lib/Transforms/Scalar/InstructionCombining.cpp +++ b/lib/Transforms/Scalar/InstructionCombining.cpp @@ -3871,12 +3871,46 @@ Instruction *InstCombiner::visitSetCondInst(SetCondInst &I) { case Instruction::And: if (LHSI->hasOneUse() && isa<ConstantInt>(LHSI->getOperand(1)) && LHSI->getOperand(0)->hasOneUse()) { + ConstantInt *AndCST = cast<ConstantInt>(LHSI->getOperand(1)); + + // If an operand is an AND of a truncating cast, we can widen the + // and/compare to be the input width without changing the value + // produced, eliminating a cast. + if (CastInst *Cast = dyn_cast<CastInst>(LHSI->getOperand(0))) { + // We can do this transformation if either the AND constant does not + // have its sign bit set or if it is an equality comparison. + // Extending a relational comparison when we're checking the sign + // bit would not work. + if (Cast->hasOneUse() && Cast->isTruncIntCast() && + (I.isEquality() || + (AndCST->getZExtValue() == (uint64_t)AndCST->getSExtValue()) && + (CI->getZExtValue() == (uint64_t)CI->getSExtValue()))) { + ConstantInt *NewCST; + ConstantInt *NewCI; + if (Cast->getOperand(0)->getType()->isSigned()) { + NewCST = ConstantSInt::get(Cast->getOperand(0)->getType(), + AndCST->getZExtValue()); + NewCI = ConstantSInt::get(Cast->getOperand(0)->getType(), + CI->getZExtValue()); + } else { + NewCST = ConstantUInt::get(Cast->getOperand(0)->getType(), + AndCST->getZExtValue()); + NewCI = ConstantUInt::get(Cast->getOperand(0)->getType(), + CI->getZExtValue()); + } + Instruction *NewAnd = + BinaryOperator::createAnd(Cast->getOperand(0), NewCST, + LHSI->getName()); + InsertNewInstBefore(NewAnd, I); + return new SetCondInst(I.getOpcode(), NewAnd, NewCI); + } + } + // If this is: (X >> C1) & C2 != C3 (where any shift and any compare // could exist), turn it into (X & (C2 << C1)) != (C3 << C1). This // happens a LOT in code produced by the C front-end, for bitfield // access. ShiftInst *Shift = dyn_cast<ShiftInst>(LHSI->getOperand(0)); - Constant *AndCST = cast<ConstantInt>(LHSI->getOperand(1)); // Check to see if there is a noop-cast between the shift and the and. if (!Shift) { @@ -3962,11 +3996,12 @@ Instruction *InstCombiner::visitSetCondInst(SetCondInst &I) { "tmp"); } else { // Make sure we insert a logical shift. + Constant *NewAndCST = AndCST; if (AndCST->getType()->isSigned()) - AndCST = ConstantExpr::getCast(AndCST, + NewAndCST = ConstantExpr::getCast(AndCST, AndCST->getType()->getUnsignedVersion()); - NS = new ShiftInst(Instruction::Shr, AndCST, Shift->getOperand(1), - "tmp"); + NS = new ShiftInst(Instruction::Shr, NewAndCST, + Shift->getOperand(1), "tmp"); } InsertNewInstBefore(cast<Instruction>(NS), I); |