diff --git a/include/llvm/Assembly/AutoUpgrade.h b/include/llvm/Assembly/AutoUpgrade.h index 548068fb22c..b8f9e22cca4 100644 --- a/include/llvm/Assembly/AutoUpgrade.h +++ b/include/llvm/Assembly/AutoUpgrade.h @@ -15,11 +15,14 @@ #define LLVM_ASSEMBLY_AUTOUPGRADE_H #include +#include namespace llvm { class Function; class CallInst; class Instruction; + class Value; + class BasicBlock; /// This function determines if the \p Name provides is a name for which the /// auto-upgrade to a non-overloaded name applies. @@ -39,6 +42,14 @@ namespace llvm { /// @brief Remove overloaded intrinsic function names. Function* UpgradeIntrinsicFunction(Function* F); + Instruction* MakeUpgradedCall( + Function* F, ///< The function to call + const std::vector& Params, ///< Operands of the call + BasicBlock* BB, ///< Basic block the caller will insert result to + bool isTailCall = false, ///< True if this is a tail call. + unsigned CallingConv = 0 ///< Calling convention to use + ); + /// In LLVM 1.7, the overloading of intrinsic functions was replaced with /// separate functions for each of the various argument sizes. This function /// implements the auto-upgrade feature from old overloaded names to the new @@ -52,7 +63,7 @@ namespace llvm { /// @param CI The CallInst to potentially auto-upgrade. /// @returns An instrution to replace \p CI with. /// @brief Get replacement instruction for overloaded intrinsic function call. - Instruction* UpgradeIntrinsicCall(CallInst* CI); + Instruction* UpgradeIntrinsicCall(CallInst* CI, Function* newF = 0); /// Upgrade both the function and all the calls made to it, if that function /// needs to be upgraded. This is like a combination of the above two diff --git a/lib/Bytecode/Reader/Reader.cpp b/lib/Bytecode/Reader/Reader.cpp index d142aacfa50..f9ac0bab1b9 100644 --- a/lib/Bytecode/Reader/Reader.cpp +++ b/lib/Bytecode/Reader/Reader.cpp @@ -861,7 +861,6 @@ void BytecodeReader::ParseInstruction(std::vector &Oprnds, Result = new CallInst(F, Params); if (isTailCall) cast(Result)->setTailCall(); if (CallingConv) cast(Result)->setCallingConv(CallingConv); - isCall = true; break; } case 56: // Invoke with encoded CC @@ -1034,13 +1033,6 @@ void BytecodeReader::ParseInstruction(std::vector &Oprnds, BB->getInstList().push_back(Result); - if (this->hasUpgradedIntrinsicFunctions && isCall) - if (Instruction* inst = UpgradeIntrinsicCall(cast(Result))) { - Result->replaceAllUsesWith(inst); - Result->eraseFromParent(); - Result = inst; - } - unsigned TypeSlot; if (Result->getType() == InstTy) TypeSlot = iType; @@ -1862,6 +1854,25 @@ void BytecodeReader::ParseFunctionBody(Function* F) { delete PlaceHolder; } + // If upgraded intrinsic functions were detected during reading of the + // module information, then we need to look for instructions that need to + // be upgraded. This can't be done while the instructions are read in because + // additional instructions inserted mess up the slot numbering. + if (!upgradedFunctions.empty()) { + for (Function::iterator BI = F->begin(), BE = F->end(); BI != BE; ++BI) + for (BasicBlock::iterator II = BI->begin(), IE = BI->end(); + II != IE; ++II) + if (CallInst* CI = dyn_cast(II)) { + std::map::iterator FI = + upgradedFunctions.find(CI->getCalledFunction()); + if (FI != upgradedFunctions.end()) { + Instruction* newI = UpgradeIntrinsicCall(CI,FI->second); + CI->replaceAllUsesWith(newI); + CI->eraseFromParent(); + } + } + } + // Clear out function-level types... FunctionTypes.clear(); CompactionTypes.clear(); @@ -1937,6 +1948,7 @@ void BytecodeReader::ParseAllFunctionBodies() { ++Fi; } LazyFunctionLoadMap.clear(); + } /// Parse the global type list @@ -2055,13 +2067,6 @@ void BytecodeReader::ParseModuleGlobalInfo() { Function *Func = new Function(FTy, GlobalValue::ExternalLinkage, "", TheModule); - // Replace with upgraded intrinsic function, if applicable. - if (Function* upgrdF = UpgradeIntrinsicFunction(Func)) { - hasUpgradedIntrinsicFunctions = true; - Func->eraseFromParent(); - Func = upgrdF; - } - insertValue(Func, (FnSignature & (~0U >> 1)) >> 5, ModuleValues); // Flags are not used yet. @@ -2433,6 +2438,16 @@ void BytecodeReader::ParseBytecode(BufPtr Buf, unsigned Length, if (hasFunctions()) error("Function expected, but bytecode stream ended!"); + // Look for intrinsic functions to upgrade, upgrade them, and save the + // mapping from old function to new for use later when instructions are + // converted. + for (Module::iterator FI = TheModule->begin(), FE = TheModule->end(); + FI != FE; ++FI) + if (Function* newF = UpgradeIntrinsicFunction(FI)) { + upgradedFunctions.insert(std::make_pair(FI,newF)); + FI->setName(""); + } + // Tell the handler we're done with the module if (Handler) Handler->handleModuleEnd(ModuleID); diff --git a/lib/Bytecode/Reader/Reader.h b/lib/Bytecode/Reader/Reader.h index 21eb8462fb2..ffc251b64ef 100644 --- a/lib/Bytecode/Reader/Reader.h +++ b/lib/Bytecode/Reader/Reader.h @@ -323,9 +323,9 @@ private: /// In release 1.7 we changed intrinsic functions to not be overloaded. There /// is no bytecode change for this, but to optimize the auto-upgrade of calls - /// to intrinsic functions, we set this flag to identify when a module has - /// been read that contains intrinsics that were upgraded. - bool hasUpgradedIntrinsicFunctions; + /// to intrinsic functions, we save a mapping of old function definitions to + /// the new ones so call instructions can be upgraded efficiently. + std::map upgradedFunctions; /// CompactionTypes - If a compaction table is active in the current function, /// this is the mapping that it contains. We keep track of what resolved type diff --git a/lib/VMCore/AutoUpgrade.cpp b/lib/VMCore/AutoUpgrade.cpp index b68b8b70fef..91b0d31dff4 100644 --- a/lib/VMCore/AutoUpgrade.cpp +++ b/lib/VMCore/AutoUpgrade.cpp @@ -75,9 +75,26 @@ static inline const Type* getTypeFromFunctionName(Function* F) { return 0; } +// This assumes the Function is one of the intrinsics we upgraded. +static inline const Type* getTypeFromFunction(Function *F) { + const Type* Ty = F->getReturnType(); + if (Ty->isFloatingPoint()) + return Ty; + if (Ty->isSigned()) + return Ty->getUnsignedVersion(); + if (Ty->isInteger()) + return Ty; + if (Ty == Type::BoolTy) { + Function::const_arg_iterator ArgIt = F->arg_begin(); + if (ArgIt != F->arg_end()) + return ArgIt->getType(); + } + return 0; +} + bool llvm::IsUpgradeableIntrinsicName(const std::string& Name) { // Quickly eliminate it, if it's not a candidate. - if (Name.length() <= 5 || Name[0] != 'l' || Name[1] != 'l' || Name[2] != + if (Name.length() <= 8 || Name[0] != 'l' || Name[1] != 'l' || Name[2] != 'v' || Name[3] != 'm' || Name[4] != '.') return false; @@ -140,23 +157,68 @@ Function* llvm::UpgradeIntrinsicFunction(Function* F) { return 0; } -Instruction* llvm::UpgradeIntrinsicCall(CallInst *CI) { - Function *F = CI->getCalledFunction(); - if (const Type* Ty = getTypeFromFunctionName(F)) { - Function* newF = UpgradeIntrinsicFunction(F); - std::vector Oprnds; - for (User::op_iterator OI = CI->op_begin(), OE = CI->op_end(); - OI != OE; ++OI) - Oprnds.push_back(CI); - CallInst* newCI = new CallInst(newF,Oprnds,"autoupgrade_call",CI); - if (Ty->isSigned()) { - const Type* newTy = Ty->getUnsignedVersion(); - newCI->setOperand(1,new CastInst(newCI->getOperand(1), newTy, - "autoupgrade_cast", newCI)); - CastInst* final = new CastInst(newCI, Ty, "autoupgrade_uncast",newCI); - newCI->moveBefore(final); - return final; + +Instruction* llvm::MakeUpgradedCall( + Function* F, const std::vector& Params, BasicBlock* BB, + bool isTailCall, unsigned CallingConv) { + assert(F && "Need a Function to make a CallInst"); + assert(BB && "Need a BasicBlock to make a CallInst"); + + // Convert the params + bool signedArg = false; + std::vector Oprnds; + for (std::vector::const_iterator PI = Params.begin(), + PE = Params.end(); PI != PE; ++PI) { + const Type* opTy = (*PI)->getType(); + if (opTy->isSigned()) { + signedArg = true; + CastInst* cast = + new CastInst(*PI,opTy->getUnsignedVersion(), "autoupgrade_cast"); + BB->getInstList().push_back(cast); + Oprnds.push_back(cast); } + else + Oprnds.push_back(*PI); + } + + Instruction* result = new CallInst(F,Oprnds,"autoupgrade_call"); + if (isTailCall) cast(result)->setTailCall(); + if (CallingConv) cast(result)->setCallingConv(CallingConv); + if (signedArg) { + const Type* newTy = F->getReturnType()->getUnsignedVersion(); + CastInst* final = new CastInst(result, newTy, "autoupgrade_uncast"); + BB->getInstList().push_back(result); + result = final; + } + return result; +} + +Instruction* llvm::UpgradeIntrinsicCall(CallInst *CI, Function* newF) { + Function *F = CI->getCalledFunction(); + if (const Type* Ty = + (newF ? getTypeFromFunction(newF) : getTypeFromFunctionName(F))) { + std::vector Oprnds; + User::op_iterator OI = CI->op_begin(); + ++OI; + for (User::op_iterator OE = CI->op_end() ; OI != OE; ++OI) { + const Type* opTy = OI->get()->getType(); + if (opTy->isSigned()) + Oprnds.push_back( + new CastInst(OI->get(),opTy->getUnsignedVersion(), + "autoupgrade_cast",CI)); + else + Oprnds.push_back(*OI); + } + CallInst* newCI = new CallInst((newF?newF:F),Oprnds,"autoupgrade_call",CI); + newCI->setTailCall(CI->isTailCall()); + newCI->setCallingConv(CI->getCallingConv()); + if (const Type* oldType = CI->getCalledFunction()->getReturnType()) + if (oldType->isSigned()) { + CastInst* final = + new CastInst(newCI, oldType, "autoupgrade_uncast",newCI); + newCI->moveBefore(final); + return final; + } return newCI; } return 0; @@ -170,20 +232,28 @@ bool llvm::UpgradeCallsToIntrinsic(Function* F) { std::vector Oprnds; User::op_iterator OI = CI->op_begin(); ++OI; - for (User::op_iterator OE = CI->op_end(); OI != OE; ++OI) - Oprnds.push_back(*OI); - CallInst* newCI = new CallInst(newF,Oprnds,"autoupgrade_call",CI); - const Type* Ty = Oprnds[0]->getType(); - if (Ty->isSigned()) { - const Type* newTy = Ty->getUnsignedVersion(); - newCI->setOperand(1,new CastInst(newCI->getOperand(1), newTy, - "autoupgrade_cast", newCI)); - CastInst* final = new CastInst(newCI, Ty, "autoupgrade_uncast",newCI); - newCI->moveBefore(final); - CI->replaceAllUsesWith(final); - } else { - CI->replaceAllUsesWith(newCI); + for (User::op_iterator OE = CI->op_end(); OI != OE; ++OI) { + const Type* opTy = OI->get()->getType(); + if (opTy->isSigned()) { + Oprnds.push_back( + new CastInst(OI->get(),opTy->getUnsignedVersion(), + "autoupgrade_cast",CI)); + } + else + Oprnds.push_back(*OI); } + CallInst* newCI = new CallInst(newF,Oprnds,"autoupgrade_call",CI); + newCI->setTailCall(CI->isTailCall()); + newCI->setCallingConv(CI->getCallingConv()); + if (const Type* Ty = CI->getCalledFunction()->getReturnType()) + if (Ty->isSigned()) { + CastInst* final = + new CastInst(newCI, Ty, "autoupgrade_uncast",newCI); + newCI->moveBefore(final); + CI->replaceAllUsesWith(final); + } else { + CI->replaceAllUsesWith(newCI); + } CI->eraseFromParent(); } }