From ad9a9e15595bc9d5ba1ed752caf8572957f77a3d Mon Sep 17 00:00:00 2001 From: Duncan Sands Date: Sun, 6 Jan 2008 18:27:01 +0000 Subject: The transform that tries to turn calls to bitcast functions into direct calls bails out unless caller and callee have essentially equivalent parameter attributes. This is illogical - the callee's attributes should be of no relevance here. Rework the logic, which incidentally fixes a crash when removed arguments have attributes. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@45658 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/IPO/DeadArgumentElimination.cpp | 5 +-- lib/Transforms/Scalar/InstructionCombining.cpp | 55 +++++++++++++++++++++----- 2 files changed, 47 insertions(+), 13 deletions(-) (limited to 'lib/Transforms') diff --git a/lib/Transforms/IPO/DeadArgumentElimination.cpp b/lib/Transforms/IPO/DeadArgumentElimination.cpp index 94ae404107..8e6a3b91c1 100644 --- a/lib/Transforms/IPO/DeadArgumentElimination.cpp +++ b/lib/Transforms/IPO/DeadArgumentElimination.cpp @@ -505,7 +505,7 @@ void DAE::RemoveDeadArgumentsFromFunction(Function *F) { const Type *RetTy = FTy->getReturnType(); if (DeadRetVal.count(F)) { RetTy = Type::VoidTy; - RAttrs &= ~ParamAttr::VoidTypeIncompatible; + RAttrs &= ~ParamAttr::incompatibleWithType(RetTy, RAttrs); DeadRetVal.erase(F); } @@ -561,8 +561,7 @@ void DAE::RemoveDeadArgumentsFromFunction(Function *F) { // The call return attributes. uint16_t RAttrs = PAL ? PAL->getParamAttrs(0) : 0; // Adjust in case the function was changed to return void. - if (NF->getReturnType() == Type::VoidTy) - RAttrs &= ~ParamAttr::VoidTypeIncompatible; + RAttrs &= ~ParamAttr::incompatibleWithType(NF->getReturnType(), RAttrs); if (RAttrs) ParamAttrsVec.push_back(ParamAttrsWithIndex::get(0, RAttrs)); diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp index 4fcd47a870..3d37bcd589 100644 --- a/lib/Transforms/Scalar/InstructionCombining.cpp +++ b/lib/Transforms/Scalar/InstructionCombining.cpp @@ -8074,6 +8074,7 @@ bool InstCombiner::transformConstExprCastCall(CallSite CS) { return false; Function *Callee = cast(CE->getOperand(0)); Instruction *Caller = CS.getInstruction(); + const ParamAttrsList* CallerPAL = CS.getParamAttrs(); // Okay, this is a cast from a function to a different type. Unless doing so // would cause a type conversion of one of our arguments, change this call to @@ -8082,13 +8083,6 @@ bool InstCombiner::transformConstExprCastCall(CallSite CS) { const FunctionType *FT = Callee->getFunctionType(); const Type *OldRetTy = Caller->getType(); - 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. - if (!ParamAttrsList::areCompatible(CallerPAL, Callee->getParamAttrs())) - return false; - // Check to see if we are changing the return type... if (OldRetTy != FT->getReturnType()) { if (Callee->isDeclaration() && !Caller->use_empty() && @@ -8103,6 +8097,11 @@ bool InstCombiner::transformConstExprCastCall(CallSite CS) { FT->getReturnType() != Type::VoidTy) return false; // Cannot transform this return value. + if (!Caller->use_empty() && CallerPAL && + ParamAttr::incompatibleWithType(FT->getReturnType(), + CallerPAL->getParamAttrs(0))) + return false; // Attribute not compatible with transformed 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 @@ -8126,7 +8125,11 @@ bool InstCombiner::transformConstExprCastCall(CallSite CS) { const Type *ActTy = (*AI)->getType(); if (!CastInst::isCastable(ActTy, ParamTy)) - return false; + return false; // Cannot transform this parameter value. + + if (CallerPAL && + ParamAttr::incompatibleWithType(ParamTy, CallerPAL->getParamAttrs(i+1))) + return false; // Attribute not compatible with transformed value. ConstantInt *c = dyn_cast(*AI); // Some conversions are safe even if we do not have a body. @@ -8144,10 +8147,32 @@ bool InstCombiner::transformConstExprCastCall(CallSite CS) { Callee->isDeclaration()) return false; // Do not delete arguments unless we have a function body... + if (FT->getNumParams() < NumActualArgs && FT->isVarArg()) + // In this case we have more arguments than the new function type, but we + // won't be dropping them. Some of them may have attributes. If so, we + // cannot perform the transform because attributes are not allowed after + // the end of the function type. + if (CallerPAL && CallerPAL->size() && + CallerPAL->getParamIndex(CallerPAL->size()-1) > FT->getNumParams()) + return false; + // Okay, we decided that this is a safe thing to do: go ahead and start // inserting cast instructions as necessary... std::vector Args; Args.reserve(NumActualArgs); + ParamAttrsVector attrVec; + attrVec.reserve(NumCommonArgs); + + // Get any return attributes. + uint16_t RAttrs = CallerPAL ? CallerPAL->getParamAttrs(0) : 0; + + // If the return value is not being used, the type may not be compatible + // with the existing attributes. Wipe out any problematic attributes. + RAttrs &= ~ParamAttr::incompatibleWithType(FT->getReturnType(), RAttrs); + + // Add the new return attributes. + if (RAttrs) + attrVec.push_back(ParamAttrsWithIndex::get(0, RAttrs)); AI = CS.arg_begin(); for (unsigned i = 0; i != NumCommonArgs; ++i, ++AI) { @@ -8160,6 +8185,11 @@ bool InstCombiner::transformConstExprCastCall(CallSite CS) { CastInst *NewCast = CastInst::create(opcode, *AI, ParamTy, "tmp"); Args.push_back(InsertNewInstBefore(NewCast, *Caller)); } + + // Add any parameter attributes. + uint16_t PAttrs = CallerPAL ? CallerPAL->getParamAttrs(i + 1) : 0; + if (PAttrs) + attrVec.push_back(ParamAttrsWithIndex::get(i + 1, PAttrs)); } // If the function takes more arguments than the call was taking, add them @@ -8187,17 +8217,22 @@ bool InstCombiner::transformConstExprCastCall(CallSite CS) { Args.push_back(*AI); } } + + // No need to add parameter attributes - we already checked that there + // aren't any. } if (FT->getReturnType() == Type::VoidTy) Caller->setName(""); // Void type should not have a name. + const ParamAttrsList* NewCallerPAL = ParamAttrsList::get(attrVec); + Instruction *NC; if (InvokeInst *II = dyn_cast(Caller)) { NC = new InvokeInst(Callee, II->getNormalDest(), II->getUnwindDest(), Args.begin(), Args.end(), Caller->getName(), Caller); cast(NC)->setCallingConv(II->getCallingConv()); - cast(NC)->setParamAttrs(CallerPAL); + cast(NC)->setParamAttrs(NewCallerPAL); } else { NC = new CallInst(Callee, Args.begin(), Args.end(), Caller->getName(), Caller); @@ -8205,7 +8240,7 @@ bool InstCombiner::transformConstExprCastCall(CallSite CS) { if (CI->isTailCall()) cast(NC)->setTailCall(); cast(NC)->setCallingConv(CI->getCallingConv()); - cast(NC)->setParamAttrs(CallerPAL); + cast(NC)->setParamAttrs(NewCallerPAL); } // Insert a cast of the return type as necessary. -- cgit v1.2.3