diff options
Diffstat (limited to 'llvm/lib/Transforms')
-rw-r--r-- | llvm/lib/Transforms/IPO/GlobalDCE.cpp | 49 | ||||
-rw-r--r-- | llvm/lib/Transforms/IPO/GlobalSplit.cpp | 6 | ||||
-rw-r--r-- | llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp | 8 | ||||
-rw-r--r-- | llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp | 31 |
4 files changed, 67 insertions, 27 deletions
diff --git a/llvm/lib/Transforms/IPO/GlobalDCE.cpp b/llvm/lib/Transforms/IPO/GlobalDCE.cpp index 411d3c8..e36d524 100644 --- a/llvm/lib/Transforms/IPO/GlobalDCE.cpp +++ b/llvm/lib/Transforms/IPO/GlobalDCE.cpp @@ -187,29 +187,36 @@ void GlobalDCEPass::ScanTypeCheckedLoadIntrinsics(Module &M) { LLVM_DEBUG(dbgs() << "Scanning type.checked.load intrinsics\n"); Function *TypeCheckedLoadFunc = M.getFunction(Intrinsic::getName(Intrinsic::type_checked_load)); - - if (!TypeCheckedLoadFunc) - return; - - for (auto *U : TypeCheckedLoadFunc->users()) { - auto CI = dyn_cast<CallInst>(U); - if (!CI) - continue; - - auto *Offset = dyn_cast<ConstantInt>(CI->getArgOperand(1)); - Value *TypeIdValue = CI->getArgOperand(2); - auto *TypeId = cast<MetadataAsValue>(TypeIdValue)->getMetadata(); - - if (Offset) { - ScanVTableLoad(CI->getFunction(), TypeId, Offset->getZExtValue()); - } else { - // type.checked.load with a non-constant offset, so assume every entry in - // every matching vtable is used. - for (const auto &VTableInfo : TypeIdMap[TypeId]) { - VFESafeVTables.erase(VTableInfo.first); + Function *TypeCheckedLoadRelativeFunc = + M.getFunction(Intrinsic::getName(Intrinsic::type_checked_load_relative)); + + auto scan = [&](Function *CheckedLoadFunc) { + if (!CheckedLoadFunc) + return; + + for (auto *U : CheckedLoadFunc->users()) { + auto CI = dyn_cast<CallInst>(U); + if (!CI) + continue; + + auto *Offset = dyn_cast<ConstantInt>(CI->getArgOperand(1)); + Value *TypeIdValue = CI->getArgOperand(2); + auto *TypeId = cast<MetadataAsValue>(TypeIdValue)->getMetadata(); + + if (Offset) { + ScanVTableLoad(CI->getFunction(), TypeId, Offset->getZExtValue()); + } else { + // type.checked.load with a non-constant offset, so assume every entry + // in every matching vtable is used. + for (const auto &VTableInfo : TypeIdMap[TypeId]) { + VFESafeVTables.erase(VTableInfo.first); + } } } - } + }; + + scan(TypeCheckedLoadFunc); + scan(TypeCheckedLoadRelativeFunc); } void GlobalDCEPass::AddVirtualFunctionDependencies(Module &M) { diff --git a/llvm/lib/Transforms/IPO/GlobalSplit.cpp b/llvm/lib/Transforms/IPO/GlobalSplit.cpp index c2438df..84e9c21 100644 --- a/llvm/lib/Transforms/IPO/GlobalSplit.cpp +++ b/llvm/lib/Transforms/IPO/GlobalSplit.cpp @@ -147,8 +147,12 @@ static bool splitGlobals(Module &M) { M.getFunction(Intrinsic::getName(Intrinsic::type_test)); Function *TypeCheckedLoadFunc = M.getFunction(Intrinsic::getName(Intrinsic::type_checked_load)); + Function *TypeCheckedLoadRelativeFunc = + M.getFunction(Intrinsic::getName(Intrinsic::type_checked_load_relative)); if ((!TypeTestFunc || TypeTestFunc->use_empty()) && - (!TypeCheckedLoadFunc || TypeCheckedLoadFunc->use_empty())) + (!TypeCheckedLoadFunc || TypeCheckedLoadFunc->use_empty()) && + (!TypeCheckedLoadRelativeFunc || + TypeCheckedLoadRelativeFunc->use_empty())) return false; bool Changed = false; diff --git a/llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp b/llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp index 4b36c7b..a7adb74 100644 --- a/llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp +++ b/llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp @@ -146,6 +146,14 @@ void promoteTypeIds(Module &M, StringRef ModuleId) { } } + if (Function *TypeCheckedLoadRelativeFunc = M.getFunction( + Intrinsic::getName(Intrinsic::type_checked_load_relative))) { + for (const Use &U : TypeCheckedLoadRelativeFunc->uses()) { + auto CI = cast<CallInst>(U.getUser()); + ExternalizeTypeId(CI, 2); + } + } + for (GlobalObject &GO : M.global_objects()) { SmallVector<MDNode *, 1> MDs; GO.getMetadata(LLVMContext::MD_type, MDs); diff --git a/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp b/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp index 203846d..d332586 100644 --- a/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp +++ b/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp @@ -1006,7 +1006,7 @@ bool DevirtModule::tryFindVirtualCallTargets( return false; Constant *Ptr = getPointerAtOffset(TM.Bits->GV->getInitializer(), - TM.Offset + ByteOffset, M); + TM.Offset + ByteOffset, M, TM.Bits->GV); if (!Ptr) return false; @@ -2002,9 +2002,23 @@ void DevirtModule::scanTypeCheckedLoadUsers(Function *TypeCheckedLoadFunc) { // This helps avoid unnecessary spills. IRBuilder<> LoadB( (LoadedPtrs.size() == 1 && !HasNonCallUses) ? LoadedPtrs[0] : CI); - Value *GEP = LoadB.CreateGEP(Int8Ty, Ptr, Offset); - Value *GEPPtr = LoadB.CreateBitCast(GEP, PointerType::getUnqual(Int8PtrTy)); - Value *LoadedValue = LoadB.CreateLoad(Int8PtrTy, GEPPtr); + + Value *LoadedValue = nullptr; + if (TypeCheckedLoadFunc->getIntrinsicID() == + Intrinsic::type_checked_load_relative) { + Value *GEP = LoadB.CreateGEP(Int8Ty, Ptr, Offset); + Value *GEPPtr = LoadB.CreateBitCast(GEP, PointerType::getUnqual(Int32Ty)); + LoadedValue = LoadB.CreateLoad(Int32Ty, GEPPtr); + LoadedValue = LoadB.CreateSExt(LoadedValue, IntPtrTy); + GEP = LoadB.CreatePtrToInt(GEP, IntPtrTy); + LoadedValue = LoadB.CreateAdd(GEP, LoadedValue); + LoadedValue = LoadB.CreateIntToPtr(LoadedValue, Int8PtrTy); + } else { + Value *GEP = LoadB.CreateGEP(Int8Ty, Ptr, Offset); + Value *GEPPtr = + LoadB.CreateBitCast(GEP, PointerType::getUnqual(Int8PtrTy)); + LoadedValue = LoadB.CreateLoad(Int8PtrTy, GEPPtr); + } for (Instruction *LoadedPtr : LoadedPtrs) { LoadedPtr->replaceAllUsesWith(LoadedValue); @@ -2185,6 +2199,8 @@ bool DevirtModule::run() { M.getFunction(Intrinsic::getName(Intrinsic::type_test)); Function *TypeCheckedLoadFunc = M.getFunction(Intrinsic::getName(Intrinsic::type_checked_load)); + Function *TypeCheckedLoadRelativeFunc = + M.getFunction(Intrinsic::getName(Intrinsic::type_checked_load_relative)); Function *AssumeFunc = M.getFunction(Intrinsic::getName(Intrinsic::assume)); // Normally if there are no users of the devirtualization intrinsics in the @@ -2193,7 +2209,9 @@ bool DevirtModule::run() { if (!ExportSummary && (!TypeTestFunc || TypeTestFunc->use_empty() || !AssumeFunc || AssumeFunc->use_empty()) && - (!TypeCheckedLoadFunc || TypeCheckedLoadFunc->use_empty())) + (!TypeCheckedLoadFunc || TypeCheckedLoadFunc->use_empty()) && + (!TypeCheckedLoadRelativeFunc || + TypeCheckedLoadRelativeFunc->use_empty())) return false; // Rebuild type metadata into a map for easy lookup. @@ -2207,6 +2225,9 @@ bool DevirtModule::run() { if (TypeCheckedLoadFunc) scanTypeCheckedLoadUsers(TypeCheckedLoadFunc); + if (TypeCheckedLoadRelativeFunc) + scanTypeCheckedLoadUsers(TypeCheckedLoadRelativeFunc); + if (ImportSummary) { for (auto &S : CallSlots) importResolution(S.first, S.second); |