aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2006-09-18 05:27:43 +0000
committerChris Lattner <sabre@nondot.org>2006-09-18 05:27:43 +0000
commite695a3bd32443aa7da9f5d699f2ad763643d0032 (patch)
tree7b8fa933d7af09bc9b2e23b09d407754369402c8
parente04deb9914b524da60f92615b8f45bc27ccb3d2d (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.cpp43
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);