Index: include/llvm/IR/Intrinsics.h =================================================================== --- include/llvm/IR/Intrinsics.h +++ include/llvm/IR/Intrinsics.h @@ -18,6 +18,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/None.h" +#include "llvm/ADT/Optional.h" #include namespace llvm { @@ -142,6 +143,10 @@ bool matchIntrinsicType(Type *Ty, ArrayRef &Infos, SmallVectorImpl &ArgTys); + // Checks if the intrinsic name matches with its signature and if not + // returns the declaration with the same signature and remangled name. + llvm::Optional remangleIntrinsicFunction(Function *F); + } // End Intrinsic namespace } // End llvm namespace Index: lib/AsmParser/LLParser.cpp =================================================================== --- lib/AsmParser/LLParser.cpp +++ lib/AsmParser/LLParser.cpp @@ -24,6 +24,7 @@ #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/InlineAsm.h" #include "llvm/IR/Instructions.h" +#include "llvm/IR/Intrinsics.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/IR/Operator.h" @@ -210,6 +211,20 @@ for (Module::iterator FI = M->begin(), FE = M->end(); FI != FE; ) UpgradeCallsToIntrinsic(&*FI++); // must be post-increment, as we remove + // Some types could be renamed during loading if several modules are + // loaded in the same LLVMContext (LTO scenario). In this case we should + // remangle intrinsics names as well. + for (Module::iterator FI = M->begin(), FE = M->end(); FI != FE; ) { + Function *F = &*FI++; + if (auto Remangled = Intrinsic::remangleIntrinsicFunction(F)) { + // Replace all users of the old function with the new function + for (User *U : F->users()) + if (CallInst *CI = dyn_cast(U)) + CI->setCalledFunction(Remangled.getValue()); + F->eraseFromParent(); + } + } + UpgradeDebugInfo(*M); if (!Slots) Index: lib/Bitcode/Reader/BitcodeReader.cpp =================================================================== --- lib/Bitcode/Reader/BitcodeReader.cpp +++ lib/Bitcode/Reader/BitcodeReader.cpp @@ -194,8 +194,10 @@ // When intrinsic functions are encountered which require upgrading they are // stored here with their replacement function. - typedef DenseMap UpgradedIntrinsicMap; - UpgradedIntrinsicMap UpgradedIntrinsics; + typedef DenseMap UpdatedIntrinsicMap; + UpdatedIntrinsicMap UpgradedIntrinsics; + // Intrinsics which were remangled because of types rename + UpdatedIntrinsicMap RemangledIntrinsics; // Map the bitcode's custom MDKind ID to the Module's MDKind ID. DenseMap MDKindMap; @@ -3217,6 +3219,11 @@ Function *NewFn; if (UpgradeIntrinsicFunction(&F, NewFn)) UpgradedIntrinsics[&F] = NewFn; + else if (auto Remangled = Intrinsic::remangleIntrinsicFunction(&F)) + // Some types could be renamed during loading if several modules are + // loaded in the same LLVMContext (LTO scenario). In this case we should + // remangle intrinsics names as well. + RemangledIntrinsics[&F] = Remangled.getValue(); } // Look for global variables which need to be renamed. @@ -5370,16 +5377,27 @@ if (StripDebugInfo) stripDebugInfo(*F); - // Upgrade any old intrinsic calls in the function. - for (auto &I : UpgradedIntrinsics) { - for (auto UI = I.first->materialized_user_begin(), UE = I.first->user_end(); - UI != UE;) { - User *U = *UI; - ++UI; - if (CallInst *CI = dyn_cast(U)) - UpgradeIntrinsicCall(CI, I.second); + // Update intrinsics calls in the function + auto UpdateIntrinsicsCalls = [] (UpdatedIntrinsicMap IntrinsicsMap, + void (*Do)(CallInst *, Function *)) { + for (auto &I : IntrinsicsMap) { + for (auto UI = I.first->materialized_user_begin(), + UE = I.first->user_end(); UI != UE;) { + User *U = *UI; + ++UI; + if (CallInst *CI = dyn_cast(U)) + Do(CI, I.second); + } } - } + }; + + // Upgrade old intrinsic calls + UpdateIntrinsicsCalls(UpgradedIntrinsics, UpgradeIntrinsicCall); + // Update calls to the remangled intrinsics + UpdateIntrinsicsCalls(RemangledIntrinsics, + [] (CallInst *CI, Function *F) { + CI->setCalledFunction(F); + }); // Finish fn->subprogram upgrade for materialized functions. if (DISubprogram *SP = FunctionsWithSPs.lookup(F)) @@ -5420,20 +5438,31 @@ for (unsigned I = 0, E = InstsWithTBAATag.size(); I < E; I++) UpgradeInstWithTBAATag(InstsWithTBAATag[I]); - // Upgrade any intrinsic calls that slipped through (should not happen!) and + // Update any intrinsic calls that slipped through (should not happen!) and // delete the old functions to clean up. We can't do this unless the entire // module is materialized because there could always be another function body // with calls to the old function. - for (auto &I : UpgradedIntrinsics) { - for (auto *U : I.first->users()) { - if (CallInst *CI = dyn_cast(U)) - UpgradeIntrinsicCall(CI, I.second); - } - if (!I.first->use_empty()) - I.first->replaceAllUsesWith(I.second); - I.first->eraseFromParent(); - } - UpgradedIntrinsics.clear(); + auto UpdateIntrinsicsCalls = [] (UpdatedIntrinsicMap IntrinsicsMap, + void (*Do)(CallInst *, Function *)) { + for (auto &I : IntrinsicsMap) { + for (auto *U : I.first->users()) { + if (CallInst *CI = dyn_cast(U)) + Do(CI, I.second); + } + if (!I.first->use_empty()) + I.first->replaceAllUsesWith(I.second); + I.first->eraseFromParent(); + } + IntrinsicsMap.clear(); + }; + + // Upgrade old intrinsics calls + UpdateIntrinsicsCalls(UpgradedIntrinsics, UpgradeIntrinsicCall); + // Update calls to remangled intrinsics + UpdateIntrinsicsCalls(RemangledIntrinsics, + [] (CallInst *CI, Function *F) { + CI->setCalledFunction(F); + }); UpgradeDebugInfo(*TheModule); return std::error_code(); Index: lib/IR/Function.cpp =================================================================== --- lib/IR/Function.cpp +++ lib/IR/Function.cpp @@ -1046,6 +1046,37 @@ llvm_unreachable("unhandled"); } +Optional Intrinsic::remangleIntrinsicFunction(Function *F) { + Intrinsic::ID id = F->getIntrinsicID(); + if (!id) + return None; + + F->dump(); + + // Accumulate an array of overloaded types for the given intrinsic + SmallVector ArgTys; + { + SmallVector Table; + getIntrinsicInfoTableEntries(id, Table); + ArrayRef TableRef = Table; + FunctionType *FTy = F->getFunctionType(); + + // If we encounter any problems matching the signature with the descriptor + // just give up remangling. It's up to verifier to report the discrepancy. + if (Intrinsic::matchIntrinsicType(FTy->getReturnType(), TableRef, ArgTys)) + return None; + for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i) + if (Intrinsic::matchIntrinsicType(FTy->getParamType(i), TableRef, ArgTys)) + return None; + } + + StringRef Name = F->getName(); + if (Name == Intrinsic::getName(id, ArgTys)) + return None; + + return Intrinsic::getDeclaration(F->getParent(), id, ArgTys); +} + /// hasAddressTaken - returns true if there are any uses of this function /// other than direct calls or invokes to it. bool Function::hasAddressTaken(const User* *PutOffender) const { Index: lib/Linker/IRMover.cpp =================================================================== --- lib/Linker/IRMover.cpp +++ lib/Linker/IRMover.cpp @@ -16,6 +16,7 @@ #include "llvm/IR/DebugInfo.h" #include "llvm/IR/DiagnosticPrinter.h" #include "llvm/IR/GVMaterializer.h" +#include "llvm/IR/Intrinsics.h" #include "llvm/IR/TypeFinder.h" #include "llvm/Transforms/Utils/Cloning.h" using namespace llvm; @@ -904,6 +905,14 @@ if (ShouldLink || !ForAlias) forceRenaming(NewGV, SGV->getName()); } + + // Overloaded intrinsics have overloaded types names as part of their + // names. If we renamed overloaded types we should rename the intrinsic + // as well. + if (Function *F = dyn_cast(NewGV)) + if (auto Remangled = Intrinsic::remangleIntrinsicFunction(F)) + NewGV = Remangled.getValue(); + if (ShouldLink || ForAlias) { if (const Comdat *SC = SGV->getComdat()) { if (auto *GO = dyn_cast(NewGV)) {