aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Transforms/Scalar
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2003-11-03 05:17:03 +0000
committerChris Lattner <sabre@nondot.org>2003-11-03 05:17:03 +0000
commit6870805117075b9c7713d505b501cea5486fd2d8 (patch)
tree9c2b9d014f0f8b17d5f8a256f3abc1281c003ef7 /lib/Transforms/Scalar
parent26f9c065a741c4800550d47c5cd11506ea406f02 (diff)
downloadexternal_llvm-6870805117075b9c7713d505b501cea5486fd2d8.zip
external_llvm-6870805117075b9c7713d505b501cea5486fd2d8.tar.gz
external_llvm-6870805117075b9c7713d505b501cea5486fd2d8.tar.bz2
Implement InstCombine/cast-set.ll:test6[a]. This improves code generated for
a hot function in em3d git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@9673 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Transforms/Scalar')
-rw-r--r--lib/Transforms/Scalar/InstructionCombining.cpp63
1 files changed, 57 insertions, 6 deletions
diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp
index 87d7528..2780189 100644
--- a/lib/Transforms/Scalar/InstructionCombining.cpp
+++ b/lib/Transforms/Scalar/InstructionCombining.cpp
@@ -1258,21 +1258,22 @@ Instruction *InstCombiner::visitSetCondInst(BinaryOperator &I) {
// Test to see if the operands of the setcc are casted versions of other
// values. If the cast can be stripped off both arguments, we do so now.
- if (CastInst *CI = dyn_cast<CastInst>(Op0))
- if (CI->getOperand(0)->getType()->isLosslesslyConvertibleTo(CI->getType())&&
+ if (CastInst *CI = dyn_cast<CastInst>(Op0)) {
+ Value *CastOp0 = CI->getOperand(0);
+ if (CastOp0->getType()->isLosslesslyConvertibleTo(CI->getType()) &&
!isa<Argument>(Op1) &&
(I.getOpcode() == Instruction::SetEQ ||
I.getOpcode() == Instruction::SetNE)) {
// We keep moving the cast from the left operand over to the right
// operand, where it can often be eliminated completely.
- Op0 = CI->getOperand(0);
+ Op0 = CastOp0;
// If operand #1 is a cast instruction, see if we can eliminate it as
// well.
- if (CastInst *CI = dyn_cast<CastInst>(Op1))
- if (CI->getOperand(0)->getType()->isLosslesslyConvertibleTo(
+ if (CastInst *CI2 = dyn_cast<CastInst>(Op1))
+ if (CI2->getOperand(0)->getType()->isLosslesslyConvertibleTo(
Op0->getType()))
- Op1 = CI->getOperand(0);
+ Op1 = CI2->getOperand(0);
// If Op1 is a constant, we can fold the cast into the constant.
if (Op1->getType() != Op0->getType())
@@ -1286,6 +1287,56 @@ Instruction *InstCombiner::visitSetCondInst(BinaryOperator &I) {
return BinaryOperator::create(I.getOpcode(), Op0, Op1);
}
+ // Handle the special case of: setcc (cast bool to X), <cst>
+ // This comes up when you have code like
+ // int X = A < B;
+ // if (X) ...
+ // For generality, we handle any zero-extension of any operand comparison
+ // with a constant.
+ if (ConstantInt *ConstantRHS = dyn_cast<ConstantInt>(Op1)) {
+ const Type *SrcTy = CastOp0->getType();
+ const Type *DestTy = Op0->getType();
+ if (SrcTy->getPrimitiveSize() < DestTy->getPrimitiveSize() &&
+ (SrcTy->isUnsigned() || SrcTy == Type::BoolTy)) {
+ // Ok, we have an expansion of operand 0 into a new type. Get the
+ // constant value, masink off bits which are not set in the RHS. These
+ // could be set if the destination value is signed.
+ uint64_t ConstVal = ConstantRHS->getRawValue();
+ ConstVal &= (1ULL << DestTy->getPrimitiveSize()*8)-1;
+
+ // If the constant we are comparing it with has high bits set, which
+ // don't exist in the original value, the values could never be equal,
+ // because the source would be zero extended.
+ unsigned SrcBits =
+ SrcTy == Type::BoolTy ? 1 : SrcTy->getPrimitiveSize()*8;
+ bool HasSignBit = 1ULL << (DestTy->getPrimitiveSize()*8-1);
+ if (ConstVal & ((1ULL << SrcBits)-1)) {
+ switch (I.getOpcode()) {
+ default: assert(0 && "Unknown comparison type!");
+ case Instruction::SetEQ:
+ return ReplaceInstUsesWith(I, ConstantBool::False);
+ case Instruction::SetNE:
+ return ReplaceInstUsesWith(I, ConstantBool::True);
+ case Instruction::SetLT:
+ case Instruction::SetLE:
+ if (DestTy->isSigned() && HasSignBit)
+ return ReplaceInstUsesWith(I, ConstantBool::False);
+ return ReplaceInstUsesWith(I, ConstantBool::True);
+ case Instruction::SetGT:
+ case Instruction::SetGE:
+ if (DestTy->isSigned() && HasSignBit)
+ return ReplaceInstUsesWith(I, ConstantBool::True);
+ return ReplaceInstUsesWith(I, ConstantBool::False);
+ }
+ }
+
+ // Otherwise, we can replace the setcc with a setcc of the smaller
+ // operand value.
+ Op1 = ConstantExpr::getCast(cast<Constant>(Op1), SrcTy);
+ return BinaryOperator::create(I.getOpcode(), CastOp0, Op1);
+ }
+ }
+ }
return Changed ? &I : 0;
}