From 6731d5c494934d9ca58e89ea9a7b454dd6bdf605 Mon Sep 17 00:00:00 2001 From: Reid Spencer Date: Sun, 28 Nov 2004 21:31:15 +0000 Subject: [PATCH] Fix for PR454: * Make sure we handle signed to unsigned conversion correctly * Move this visitSetCondInst case to its own method. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@18312 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Scalar/InstructionCombining.cpp | 121 ++++++++++++------ 1 file changed, 80 insertions(+), 41 deletions(-) diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp index 4acbc140900..8915598da11 100644 --- a/lib/Transforms/Scalar/InstructionCombining.cpp +++ b/lib/Transforms/Scalar/InstructionCombining.cpp @@ -111,6 +111,9 @@ namespace { Instruction *visitOr (BinaryOperator &I); Instruction *visitXor(BinaryOperator &I); Instruction *visitSetCondInst(BinaryOperator &I); + Instruction *visitSetCondInstWithCastAndConstant(BinaryOperator&I, + CastInst*LHSI, + ConstantInt* CI); Instruction *visitShiftInst(ShiftInst &I); Instruction *visitCastInst(CastInst &CI); Instruction *visitSelectInst(SelectInst &CI); @@ -2034,49 +2037,15 @@ Instruction *InstCombiner::visitSetCondInst(BinaryOperator &I) { } break; - case Instruction::Cast: { // (setcc (cast X to larger), CI) - const Type *SrcTy = LHSI->getOperand(0)->getType(); - if (SrcTy->isIntegral() && LHSI->getType()->isIntegral()) { - unsigned SrcBits = SrcTy->getPrimitiveSize()*8; - if (SrcTy == Type::BoolTy) SrcBits = 1; - unsigned DestBits = LHSI->getType()->getPrimitiveSize()*8; - if (LHSI->getType() == Type::BoolTy) DestBits = 1; - if (SrcBits < DestBits && - // FIXME: Reenable the code below for < and >. However, we have - // to handle the cases when the source of the cast and the dest of - // the cast have different signs. e.g: - // (cast sbyte %X to uint) >u 255U -> X getType()) != CI) { - switch (I.getOpcode()) { - default: assert(0 && "unknown integer comparison"); -#if 0 - case Instruction::SetLT: { - Constant *Max = ConstantIntegral::getMaxValue(SrcTy); - Max = ConstantExpr::getCast(Max, LHSI->getType()); - return ReplaceInstUsesWith(I, ConstantExpr::getSetLT(Max, CI)); - } - case Instruction::SetGT: { - Constant *Min = ConstantIntegral::getMinValue(SrcTy); - Min = ConstantExpr::getCast(Min, LHSI->getType()); - return ReplaceInstUsesWith(I, ConstantExpr::getSetGT(Min, CI)); - } -#endif - case Instruction::SetEQ: - return ReplaceInstUsesWith(I, ConstantBool::False); - case Instruction::SetNE: - return ReplaceInstUsesWith(I, ConstantBool::True); - } - } - - return new SetCondInst(I.getOpcode(), LHSI->getOperand(0), NewCst); - } - } + // (setcc (cast X to larger), CI) + case Instruction::Cast: { + Instruction* replacement = + visitSetCondInstWithCastAndConstant(I,cast(LHSI),CI); + if (replacement) + return replacement; break; } + case Instruction::Shl: // (setcc (shl X, ShAmt), CI) if (ConstantUInt *ShAmt = dyn_cast(LHSI->getOperand(1))) { switch (I.getOpcode()) { @@ -2530,6 +2499,76 @@ Instruction *InstCombiner::visitSetCondInst(BinaryOperator &I) { return Changed ? &I : 0; } +// visitSetCondInstWithCastAndConstant - this method is part of the +// visitSetCondInst method. It handles the situation where we have: +// (setcc (cast X to larger), CI) +// It tries to remove the cast and even the setcc if the CI value +// and range of the cast allow it. +Instruction * +InstCombiner::visitSetCondInstWithCastAndConstant(BinaryOperator&I, + CastInst* LHSI, + ConstantInt* CI) { + const Type *SrcTy = LHSI->getOperand(0)->getType(); + const Type *DestTy = LHSI->getType(); + if (SrcTy->isIntegral() && DestTy->isIntegral()) { + unsigned SrcBits = SrcTy->getPrimitiveSize()*8; + unsigned DestBits = DestTy->getPrimitiveSize()*8; + if (SrcTy == Type::BoolTy) + SrcBits = 1; + if (DestTy == Type::BoolTy) + DestBits = 1; + if (SrcBits < DestBits) { + // There are fewer bits in the source of the cast than in the result + // of the cast. Any other case doesn't matter because the constant + // value won't have changed due to sign extension. + Constant *NewCst = ConstantExpr::getCast(CI, SrcTy); + if (ConstantExpr::getCast(NewCst, DestTy) == CI) { + // The constant value operand of the setCC before and after a + // cast to the source type of the cast instruction is the same + // value, so we just replace with the same setcc opcode, but + // using the source value compared to the constant casted to the + // source type. + if (SrcTy->isSigned() && DestTy->isUnsigned()) { + CastInst* Cst = new CastInst(LHSI->getOperand(0), + SrcTy->getUnsignedVersion(), LHSI->getName()); + InsertNewInstBefore(Cst,I); + return new SetCondInst(I.getOpcode(), Cst, + ConstantExpr::getCast(CI, SrcTy->getUnsignedVersion())); + } + return new SetCondInst(I.getOpcode(), LHSI->getOperand(0),NewCst); + } + // The constant value before and after a cast to the source type + // is different, so various cases are possible depending on the + // opcode and the signs of the types involved in the cast. + switch (I.getOpcode()) { + case Instruction::SetLT: { + Constant* Max = ConstantIntegral::getMaxValue(SrcTy); + Max = ConstantExpr::getCast(Max, DestTy); + return ReplaceInstUsesWith(I, ConstantExpr::getSetLT(Max, CI)); + } + case Instruction::SetGT: { + Constant* Min = ConstantIntegral::getMinValue(SrcTy); + Min = ConstantExpr::getCast(Min, DestTy); + return ReplaceInstUsesWith(I, ConstantExpr::getSetGT(Min, CI)); + } + case Instruction::SetEQ: + // We're looking for equality, and we know the values are not + // equal so replace with constant False. + return ReplaceInstUsesWith(I, ConstantBool::False); + case Instruction::SetNE: + // We're testing for inequality, and we know the values are not + // equal so replace with constant True. + return ReplaceInstUsesWith(I, ConstantBool::True); + case Instruction::SetLE: + case Instruction::SetGE: + assert(!"SetLE and SetGE should be handled elsewhere"); + default: + assert(!"unknown integer comparison"); + } + } + } + return 0; +} Instruction *InstCombiner::visitShiftInst(ShiftInst &I) { -- 2.34.1