From 6444c374889a626463925a9363e990b46ee2c01e Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Mon, 3 Nov 2003 05:17:03 +0000 Subject: [PATCH] Implement InstCombine/cast-set.ll:test6[a]. This improves code generated for a hot function in em3d llvm-svn: 9673 --- .../Scalar/InstructionCombining.cpp | 63 +++++++++++++++++-- 1 file changed, 57 insertions(+), 6 deletions(-) diff --git a/llvm/lib/Transforms/Scalar/InstructionCombining.cpp b/llvm/lib/Transforms/Scalar/InstructionCombining.cpp index 87d7528b192a..278018954028 100644 --- a/llvm/lib/Transforms/Scalar/InstructionCombining.cpp +++ b/llvm/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(Op0)) - if (CI->getOperand(0)->getType()->isLosslesslyConvertibleTo(CI->getType())&& + if (CastInst *CI = dyn_cast(Op0)) { + Value *CastOp0 = CI->getOperand(0); + if (CastOp0->getType()->isLosslesslyConvertibleTo(CI->getType()) && !isa(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(Op1)) - if (CI->getOperand(0)->getType()->isLosslesslyConvertibleTo( + if (CastInst *CI2 = dyn_cast(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), + // 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(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(Op1), SrcTy); + return BinaryOperator::create(I.getOpcode(), CastOp0, Op1); + } + } + } return Changed ? &I : 0; }