Author: baldrick Date: Sun Jan 6 04:12:28 2008 New Revision: 45657 URL: http://llvm.org/viewvc/llvm-project?rev=45657&view=rev Log: When transforming a call to a bitcast function into a direct call with cast parameters and cast return value (if any), instcombine was prepared to cast any non-void return value into any other, whether castable or not. Add a new predicate for testing whether casting is valid, and check it both for the return value and (as a cleanup) for the parameters.
Added: llvm/trunk/test/Transforms/InstCombine/2008-01-06-CastCrash.ll llvm/trunk/test/Transforms/InstCombine/2008-01-06-VoidCast.ll Modified: llvm/trunk/include/llvm/InstrTypes.h llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp llvm/trunk/lib/VMCore/Instructions.cpp Modified: llvm/trunk/include/llvm/InstrTypes.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/InstrTypes.h?rev=45657&r1=45656&r2=45657&view=diff ============================================================================== --- llvm/trunk/include/llvm/InstrTypes.h (original) +++ llvm/trunk/include/llvm/InstrTypes.h Sun Jan 6 04:12:28 2008 @@ -398,8 +398,14 @@ BasicBlock *InsertAtEnd ///< The block to insert the instruction into ); + /// @brief Check whether it is valid to call getCastOpcode for these types. + static bool isCastable( + const Type *SrcTy, ///< The Type from which the value should be cast. + const Type *DestTy ///< The Type to which the value should be cast. + ); + /// Returns the opcode necessary to cast Val into Ty using usual casting - /// rules. + /// rules. /// @brief Infer the opcode for cast operand and type static Instruction::CastOps getCastOpcode( const Value *Val, ///< The value to cast Modified: llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp?rev=45657&r1=45656&r2=45657&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp Sun Jan 6 04:12:28 2008 @@ -8082,11 +8082,7 @@ const FunctionType *FT = Callee->getFunctionType(); const Type *OldRetTy = Caller->getType(); - const ParamAttrsList* CallerPAL = 0; - if (CallInst *CallerCI = dyn_cast<CallInst>(Caller)) - CallerPAL = CallerCI->getParamAttrs(); - else if (InvokeInst *CallerII = dyn_cast<InvokeInst>(Caller)) - CallerPAL = CallerII->getParamAttrs(); + const ParamAttrsList* CallerPAL = CS.getParamAttrs(); // If the parameter attributes are not compatible, don't do the xform. We // don't want to lose an sret attribute or something. @@ -8101,6 +8097,12 @@ TD->getIntPtrType() == OldRetTy)) return false; // Cannot transform this return value. + if (!Caller->use_empty() && + !CastInst::isCastable(FT->getReturnType(), OldRetTy) && + // void -> non-void is handled specially + FT->getReturnType() != Type::VoidTy) + return false; // Cannot transform this return value. + // If the callsite is an invoke instruction, and the return value is used by // a PHI node in a successor, we cannot change the return type of the call // because there is no place to put the cast instruction (without breaking @@ -8122,9 +8124,13 @@ for (unsigned i = 0, e = NumCommonArgs; i != e; ++i, ++AI) { const Type *ParamTy = FT->getParamType(i); const Type *ActTy = (*AI)->getType(); + + if (!CastInst::isCastable(ActTy, ParamTy)) + return false; + ConstantInt *c = dyn_cast<ConstantInt>(*AI); - //Some conversions are safe even if we do not have a body. - //Either we can cast directly, or we can upconvert the argument + // Some conversions are safe even if we do not have a body. + // Either we can cast directly, or we can upconvert the argument bool isConvertible = ActTy == ParamTy || (isa<PointerType>(ParamTy) && isa<PointerType>(ActTy)) || (ParamTy->isInteger() && ActTy->isInteger() && @@ -8132,40 +8138,6 @@ (c && ParamTy->getPrimitiveSizeInBits() >= ActTy->getPrimitiveSizeInBits() && c->getValue().isStrictlyPositive()); if (Callee->isDeclaration() && !isConvertible) return false; - - // Most other conversions can be done if we have a body, even if these - // lose information, e.g. int->short. - // Some conversions cannot be done at all, e.g. float to pointer. - // Logic here parallels CastInst::getCastOpcode (the design there - // requires legality checks like this be done before calling it). - if (ParamTy->isInteger()) { - if (const VectorType *VActTy = dyn_cast<VectorType>(ActTy)) { - if (VActTy->getBitWidth() != ParamTy->getPrimitiveSizeInBits()) - return false; - } - if (!ActTy->isInteger() && !ActTy->isFloatingPoint() && - !isa<PointerType>(ActTy)) - return false; - } else if (ParamTy->isFloatingPoint()) { - if (const VectorType *VActTy = dyn_cast<VectorType>(ActTy)) { - if (VActTy->getBitWidth() != ParamTy->getPrimitiveSizeInBits()) - return false; - } - if (!ActTy->isInteger() && !ActTy->isFloatingPoint()) - return false; - } else if (const VectorType *VParamTy = dyn_cast<VectorType>(ParamTy)) { - if (const VectorType *VActTy = dyn_cast<VectorType>(ActTy)) { - if (VActTy->getBitWidth() != VParamTy->getBitWidth()) - return false; - } - if (VParamTy->getBitWidth() != ActTy->getPrimitiveSizeInBits()) - return false; - } else if (isa<PointerType>(ParamTy)) { - if (!ActTy->isInteger() && !isa<PointerType>(ActTy)) - return false; - } else { - return false; - } } if (FT->getNumParams() < NumActualArgs && !FT->isVarArg() && @@ -8238,12 +8210,11 @@ // Insert a cast of the return type as necessary. Value *NV = NC; - if (Caller->getType() != NV->getType() && !Caller->use_empty()) { + if (OldRetTy != NV->getType() && !Caller->use_empty()) { if (NV->getType() != Type::VoidTy) { - const Type *CallerTy = Caller->getType(); Instruction::CastOps opcode = CastInst::getCastOpcode(NC, false, - CallerTy, false); - NV = NC = CastInst::create(opcode, NC, CallerTy, "tmp"); + OldRetTy, false); + NV = NC = CastInst::create(opcode, NC, OldRetTy, "tmp"); // If this is an invoke instruction, we should insert it after the first // non-phi, instruction in the normal successor block. Modified: llvm/trunk/lib/VMCore/Instructions.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/Instructions.cpp?rev=45657&r1=45656&r2=45657&view=diff ============================================================================== --- llvm/trunk/lib/VMCore/Instructions.cpp (original) +++ llvm/trunk/lib/VMCore/Instructions.cpp Sun Jan 6 04:12:28 2008 @@ -1895,12 +1895,70 @@ return create(opcode, C, Ty, Name, InsertAtEnd); } +// Check whether it is valid to call getCastOpcode for these types. +// This routine must be kept in sync with getCastOpcode. +bool CastInst::isCastable(const Type *SrcTy, const Type *DestTy) { + if (!SrcTy->isFirstClassType() || !DestTy->isFirstClassType()) + return false; + + if (SrcTy == DestTy) + return true; + + // Get the bit sizes, we'll need these + unsigned SrcBits = SrcTy->getPrimitiveSizeInBits(); // 0 for ptr/vector + unsigned DestBits = DestTy->getPrimitiveSizeInBits(); // 0 for ptr/vector + + // Run through the possibilities ... + if (DestTy->isInteger()) { // Casting to integral + if (SrcTy->isInteger()) { // Casting from integral + return true; + } else if (SrcTy->isFloatingPoint()) { // Casting from floating pt + return true; + } else if (const VectorType *PTy = dyn_cast<VectorType>(SrcTy)) { + // Casting from vector + return DestBits == PTy->getBitWidth(); + } else { // Casting from something else + return isa<PointerType>(SrcTy); + } + } else if (DestTy->isFloatingPoint()) { // Casting to floating pt + if (SrcTy->isInteger()) { // Casting from integral + return true; + } else if (SrcTy->isFloatingPoint()) { // Casting from floating pt + return true; + } else if (const VectorType *PTy = dyn_cast<VectorType>(SrcTy)) { + // Casting from vector + return DestBits == PTy->getBitWidth(); + } else { // Casting from something else + return false; + } + } else if (const VectorType *DestPTy = dyn_cast<VectorType>(DestTy)) { + // Casting to vector + if (const VectorType *SrcPTy = dyn_cast<VectorType>(SrcTy)) { + // Casting from vector + return DestPTy->getBitWidth() == SrcPTy->getBitWidth(); + } else { // Casting from something else + return DestPTy->getBitWidth() == SrcBits; + } + } else if (isa<PointerType>(DestTy)) { // Casting to pointer + if (isa<PointerType>(SrcTy)) { // Casting from pointer + return true; + } else if (SrcTy->isInteger()) { // Casting from integral + return true; + } else { // Casting from something else + return false; + } + } else { // Casting to something else + return false; + } +} + // Provide a way to get a "cast" where the cast opcode is inferred from the // types and size of the operand. This, basically, is a parallel of the // logic in the castIsValid function below. This axiom should hold: // castIsValid( getCastOpcode(Val, Ty), Val, Ty) // should not assert in castIsValid. In other words, this produces a "correct" // casting opcode for the arguments passed to it. +// This routine must be kept in sync with isCastable. Instruction::CastOps CastInst::getCastOpcode( const Value *Src, bool SrcIsSigned, const Type *DestTy, bool DestIsSigned) { @@ -1909,6 +1967,9 @@ unsigned SrcBits = SrcTy->getPrimitiveSizeInBits(); // 0 for ptr/vector unsigned DestBits = DestTy->getPrimitiveSizeInBits(); // 0 for ptr/vector + assert(SrcTy->isFirstClassType() && DestTy->isFirstClassType() && + "Only first class types are castable!"); + // Run through the possibilities ... if (DestTy->isInteger()) { // Casting to integral if (SrcTy->isInteger()) { // Casting from integral @@ -2050,7 +2111,7 @@ if (isa<PointerType>(SrcTy) != isa<PointerType>(DstTy)) return false; - // Now we know we're not dealing with a pointer/non-poiner mismatch. In all + // Now we know we're not dealing with a pointer/non-pointer mismatch. In all // these cases, the cast is okay if the source and destination bit widths // are identical. return SrcBitSize == DstBitSize; Added: llvm/trunk/test/Transforms/InstCombine/2008-01-06-CastCrash.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/2008-01-06-CastCrash.ll?rev=45657&view=auto ============================================================================== --- llvm/trunk/test/Transforms/InstCombine/2008-01-06-CastCrash.ll (added) +++ llvm/trunk/test/Transforms/InstCombine/2008-01-06-CastCrash.ll Sun Jan 6 04:12:28 2008 @@ -0,0 +1,10 @@ +; RUN: llvm-as < %s | opt -instcombine -disable-output + +define <2 x i32> @f() { + ret <2 x i32> undef +} + +define i32 @g() { + %x = call i32 bitcast (<2 x i32> ()* @f to i32 ()*)( ) ; <i32> [#uses=1] + ret i32 %x +} Added: llvm/trunk/test/Transforms/InstCombine/2008-01-06-VoidCast.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/2008-01-06-VoidCast.ll?rev=45657&view=auto ============================================================================== --- llvm/trunk/test/Transforms/InstCombine/2008-01-06-VoidCast.ll (added) +++ llvm/trunk/test/Transforms/InstCombine/2008-01-06-VoidCast.ll Sun Jan 6 04:12:28 2008 @@ -0,0 +1,10 @@ +; RUN: llvm-as < %s | opt -instcombine | llvm-dis | not grep bitcast + +define void @f(i16 %y) { + ret void +} + +define i32 @g(i32 %y) { + %x = call i32 bitcast (void (i16)* @f to i32 (i32)*)( i32 %y ) ; <i32> [#uses=1] + ret i32 %x +} _______________________________________________ llvm-commits mailing list llvm-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits