Index: lib/Transforms/InstCombine/InstCombineAndOrXor.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -1193,6 +1193,27 @@ return nullptr; } +bool InstCombiner::shouldOptimizeCast(CastInst *CI) { + Value *CastSrc = CI->getOperand(0); + + // Noop casts and casts of constants should be eliminated trivially. + if (CI->getSrcTy() == CI->getDestTy() || isa(CastSrc)) return false; + + // If this cast is paired with another cast that can be eliminated, we prefer + // to have it eliminated. + if (const CastInst *PrecedingCI = dyn_cast(CastSrc)) + if (isEliminableCastPair(PrecedingCI, CI)) + return false; + + // If this is a vector sext from a compare, then we don't want to break the + // idiom where each element of the extended vector is either zero or all ones. + if (CI->getOpcode() == Instruction::SExt && + isa(CastSrc) && CI->getDestTy()->isVectorTy()) + return false; + + return true; +} + Instruction *InstCombiner::foldCastedBitwiseLogic(BinaryOperator &I) { auto LogicOpc = I.getOpcode(); assert((LogicOpc == Instruction::And || LogicOpc == Instruction::Or || @@ -1237,12 +1258,10 @@ Value *Cast0Src = Cast0->getOperand(0); Value *Cast1Src = Cast1->getOperand(0); - // fold (logic (cast A), (cast B)) -> (cast (logic A, B)) - - // Only do this if the casts both really cause code to be generated. + // fold logic(cast(A), cast(B)) -> cast(logic(A, B)) if ((!isa(Cast0Src) || !isa(Cast1Src)) && - ShouldOptimizeCast(CastOpcode, Cast0Src, DestTy) && - ShouldOptimizeCast(CastOpcode, Cast1Src, DestTy)) { + shouldOptimizeCast(Cast0) && + shouldOptimizeCast(Cast1)) { Value *NewOp = Builder->CreateBinOp(LogicOpc, Cast0Src, Cast1Src, I.getName()); return CastInst::Create(CastOpcode, NewOp, DestTy); Index: lib/Transforms/InstCombine/InstCombineCasts.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineCasts.cpp +++ lib/Transforms/InstCombine/InstCombineCasts.cpp @@ -227,20 +227,14 @@ return InsertNewInstWith(Res, *I); } - -/// This function is a wrapper around CastInst::isEliminableCastPair. It -/// simply extracts arguments and returns what that function returns. -static Instruction::CastOps -isEliminableCastPair(const CastInst *CI, ///< First cast instruction - unsigned opcode, ///< Opcode for the second cast - Type *DstTy, ///< Target type for the second cast - const DataLayout &DL) { - Type *SrcTy = CI->getOperand(0)->getType(); // A from above - Type *MidTy = CI->getType(); // B from above - - // Get the opcodes of the two Cast instructions - Instruction::CastOps firstOp = Instruction::CastOps(CI->getOpcode()); - Instruction::CastOps secondOp = Instruction::CastOps(opcode); +Instruction::CastOps InstCombiner::isEliminableCastPair(const CastInst *CI1, + const CastInst *CI2) { + Type *SrcTy = CI1->getSrcTy(); + Type *MidTy = CI1->getDestTy(); + Type *DstTy = CI2->getDestTy(); + + Instruction::CastOps firstOp = Instruction::CastOps(CI1->getOpcode()); + Instruction::CastOps secondOp = Instruction::CastOps(CI2->getOpcode()); Type *SrcIntPtrTy = SrcTy->isPtrOrPtrVectorTy() ? DL.getIntPtrType(SrcTy) : nullptr; Type *MidIntPtrTy = @@ -260,30 +254,6 @@ return Instruction::CastOps(Res); } -/// Return true if the cast from "V to Ty" actually results in any code being -/// generated and is interesting to optimize out. -/// If the cast can be eliminated by some other simple transformation, we prefer -/// to do the simplification first. -bool InstCombiner::ShouldOptimizeCast(Instruction::CastOps opc, const Value *V, - Type *Ty) { - // Noop casts and casts of constants should be eliminated trivially. - if (V->getType() == Ty || isa(V)) return false; - - // If this is another cast that can be eliminated, we prefer to have it - // eliminated. - if (const CastInst *CI = dyn_cast(V)) - if (isEliminableCastPair(CI, opc, Ty, DL)) - return false; - - // If this is a vector sext from a compare, then we don't want to break the - // idiom where each element of the extended vector is either zero or all ones. - if (opc == Instruction::SExt && isa(V) && Ty->isVectorTy()) - return false; - - return true; -} - - /// @brief Implement the transforms common to all CastInst visitors. Instruction *InstCombiner::commonCastTransforms(CastInst &CI) { Value *Src = CI.getOperand(0); @@ -292,7 +262,7 @@ // eliminate it now. if (CastInst *CSrc = dyn_cast(Src)) { // A->B->C cast if (Instruction::CastOps opc = - isEliminableCastPair(CSrc, CI.getOpcode(), CI.getType(), DL)) { + isEliminableCastPair(CSrc, &CI)) { // The first cast (CSrc) is eliminable so we need to fix up or replace // the second cast (CI). CSrc will then have a good chance of being dead. return CastInst::Create(opc, CSrc->getOperand(0), CI.getType()); @@ -578,10 +548,8 @@ return nullptr; } -/// Transform (zext icmp) to bitwise / integer operations in order to eliminate -/// the icmp. -Instruction *InstCombiner::transformZExtICmp(ICmpInst *ICI, Instruction &CI, - bool DoXform) { +Instruction *InstCombiner::transformZExtICmp(ICmpInst *ICI, ZExtInst &CI, + bool DoTransform) { // If we are just checking for a icmp eq of a single bit and zext'ing it // to an integer, then shift the bit to the appropriate place and then // cast to integer to avoid the comparison. @@ -592,7 +560,7 @@ // zext (x >s -1) to i32 --> (x>>u31)^1 true if signbit clear. if ((ICI->getPredicate() == ICmpInst::ICMP_SLT && Op1CV == 0) || (ICI->getPredicate() == ICmpInst::ICMP_SGT && Op1CV.isAllOnesValue())) { - if (!DoXform) return ICI; + if (!DoTransform) return ICI; Value *In = ICI->getOperand(0); Value *Sh = ConstantInt::get(In->getType(), @@ -627,7 +595,7 @@ APInt KnownZeroMask(~KnownZero); if (KnownZeroMask.isPowerOf2()) { // Exactly 1 possible 1? - if (!DoXform) return ICI; + if (!DoTransform) return ICI; bool isNE = ICI->getPredicate() == ICmpInst::ICMP_NE; if (Op1CV != 0 && (Op1CV != KnownZeroMask)) { @@ -678,7 +646,7 @@ APInt KnownBits = KnownZeroLHS | KnownOneLHS; APInt UnknownBit = ~KnownBits; if (UnknownBit.countPopulation() == 1) { - if (!DoXform) return ICI; + if (!DoTransform) return ICI; Value *Result = Builder->CreateXor(LHS, RHS); Index: lib/Transforms/InstCombine/InstCombineInternal.h =================================================================== --- lib/Transforms/InstCombine/InstCombineInternal.h +++ lib/Transforms/InstCombine/InstCombineInternal.h @@ -355,14 +355,16 @@ SmallVectorImpl &NewIndices); Instruction *FoldOpIntoSelect(Instruction &Op, SelectInst *SI); - /// \brief Classify whether a cast is worth optimizing. + /// Classify whether a cast is worth optimizing. /// - /// Returns true if the cast from "V to Ty" actually results in any code - /// being generated and is interesting to optimize out. If the cast can be - /// eliminated by some other simple transformation, we prefer to do the - /// simplification first. - bool ShouldOptimizeCast(Instruction::CastOps opcode, const Value *V, - Type *Ty); + /// This is a helper to decide whether the simplification of + /// logic(cast(A), cast(B)) to cast(logic(A, B)) should be performed. + /// + /// \param CI The cast we are interested in. + /// + /// \return true if this cast actually results in any code being generated and + /// if it cannot already be eliminated by some other transformation. + bool shouldOptimizeCast(CastInst *CI); /// \brief Try to optimize a sequence of instructions checking if an operation /// on LHS and RHS overflows. @@ -385,8 +387,22 @@ bool transformConstExprCastCall(CallSite CS); Instruction *transformCallThroughTrampoline(CallSite CS, IntrinsicInst *Tramp); - Instruction *transformZExtICmp(ICmpInst *ICI, Instruction &CI, - bool DoXform = true); + + /// Transform (zext icmp) to bitwise / integer operations in order to + /// eliminate it. + /// + /// \param ICI The icmp of the (zext icmp) pair we are intersted in. + /// \parem CI The zext of the (zext icmp) pair we are intersted in. + /// \param DoTransform Pass false to just test whether the given (zext icmp) + /// would be transformed. Pass true to actually perform the transformation. + /// + /// \return null if the transformation cannot be performed. If the + /// transformation can be performed the new instruction that replaces the + /// (zext icmp) pair will be returned (if \p DoTransform is false the + /// unmodified \p ICI will be returned in this case). + Instruction *transformZExtICmp(ICmpInst *ICI, ZExtInst &CI, + bool DoTransform = true); + Instruction *transformSExtICmp(ICmpInst *ICI, Instruction &CI); bool WillNotOverflowSignedAdd(Value *LHS, Value *RHS, Instruction &CxtI); bool WillNotOverflowSignedSub(Value *LHS, Value *RHS, Instruction &CxtI); @@ -397,6 +413,17 @@ Value *EvaluateInDifferentElementOrder(Value *V, ArrayRef Mask); Instruction *foldCastedBitwiseLogic(BinaryOperator &I); + /// Determine if a pair of casts can be replaced by a single cast. + /// + /// \param CI1 The first of a pair of casts. + /// \param CI2 The second of a pair of casts. + /// + /// \return 0 if the cast pair cannot be eliminated, otherwise returns an + /// Instruction::CastOps value for a cast that can replace the pair, casting + /// CI1->getSrcTy() to CI2->getDstTy(). + Instruction::CastOps isEliminableCastPair(const CastInst *CI1, + const CastInst *CI2); + public: /// \brief Inserts an instruction \p New before instruction \p Old ///