diff options
author | Peter Collingbourne <peter@pcc.me.uk> | 2017-03-10 20:09:11 +0000 |
---|---|---|
committer | Peter Collingbourne <peter@pcc.me.uk> | 2017-03-10 20:09:11 +0000 |
commit | 59675ba0f83141385b286433e7ae82a3bbb3d1f6 (patch) | |
tree | acd8a529a8d5fe7d438e7b0c1f33a555ed308e43 /llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp | |
parent | 7b79321e885e7b0c7a27127656d419ccbff4e6d2 (diff) | |
download | bcm5719-llvm-59675ba0f83141385b286433e7ae82a3bbb3d1f6.tar.gz bcm5719-llvm-59675ba0f83141385b286433e7ae82a3bbb3d1f6.zip |
WholeProgramDevirt: Implement export/import support for unique ret val opt.
Differential Revision: https://reviews.llvm.org/D29917
llvm-svn: 297502
Diffstat (limited to 'llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp')
-rw-r--r-- | llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp | 93 |
1 files changed, 80 insertions, 13 deletions
diff --git a/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp b/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp index b5d87b16740..6a9e0c9eab9 100644 --- a/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp +++ b/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp @@ -320,15 +320,18 @@ struct CallSiteInfo { /// the llvm.type.checked.load intrinsic and therefore will require /// resolutions for llvm.type.test in order to implement CFI checks if /// devirtualization was unsuccessful. If devirtualization was successful, the - /// pass will clear this vector. If at the end of the pass the vector is - /// non-empty, we will need to add a use of llvm.type.test to each of the - /// function summaries in the vector. + /// pass will clear this vector by calling markDevirt(). If at the end of the + /// pass the vector is non-empty, we will need to add a use of llvm.type.test + /// to each of the function summaries in the vector. std::vector<FunctionSummary *> SummaryTypeCheckedLoadUsers; bool isExported() const { return SummaryHasTypeTestAssumeUsers || !SummaryTypeCheckedLoadUsers.empty(); } + + /// As explained in the comment for SummaryTypeCheckedLoadUsers. + void markDevirt() { SummaryTypeCheckedLoadUsers.clear(); } }; // Call site information collected for a specific VTableSlot. @@ -431,17 +434,35 @@ struct DevirtModule { CallSiteInfo &CSInfo, WholeProgramDevirtResolution::ByArg *Res); + // Returns the global symbol name that is used to export information about the + // given vtable slot and list of arguments. + std::string getGlobalName(VTableSlot Slot, ArrayRef<uint64_t> Args, + StringRef Name); + + // This function is called during the export phase to create a symbol + // definition containing information about the given vtable slot and list of + // arguments. + void exportGlobal(VTableSlot Slot, ArrayRef<uint64_t> Args, StringRef Name, + Constant *C); + + // This function is called during the import phase to create a reference to + // the symbol definition created during the export phase. + Constant *importGlobal(VTableSlot Slot, ArrayRef<uint64_t> Args, + StringRef Name); + void applyUniqueRetValOpt(CallSiteInfo &CSInfo, StringRef FnName, bool IsOne, Constant *UniqueMemberAddr); bool tryUniqueRetValOpt(unsigned BitWidth, MutableArrayRef<VirtualCallTarget> TargetsForSlot, - CallSiteInfo &CSInfo); + CallSiteInfo &CSInfo, + WholeProgramDevirtResolution::ByArg *Res, + VTableSlot Slot, ArrayRef<uint64_t> Args); void applyVirtualConstProp(CallSiteInfo &CSInfo, StringRef FnName, Constant *Byte, Constant *Bit); bool tryVirtualConstProp(MutableArrayRef<VirtualCallTarget> TargetsForSlot, VTableSlotInfo &SlotInfo, - WholeProgramDevirtResolution *Res); + WholeProgramDevirtResolution *Res, VTableSlot Slot); void rebuildGlobal(VTableBits &B); @@ -658,7 +679,7 @@ void DevirtModule::applySingleImplDevirt(VTableSlotInfo &SlotInfo, } if (CSInfo.isExported()) { IsExported = true; - CSInfo.SummaryTypeCheckedLoadUsers.clear(); + CSInfo.markDevirt(); } }; Apply(SlotInfo.CSInfo); @@ -736,7 +757,7 @@ void DevirtModule::applyUniformRetValOpt(CallSiteInfo &CSInfo, StringRef FnName, Call.replaceAndErase( "uniform-ret-val", FnName, RemarksEnabled, ConstantInt::get(cast<IntegerType>(Call.CS.getType()), TheRetVal)); - CSInfo.SummaryTypeCheckedLoadUsers.clear(); + CSInfo.markDevirt(); } bool DevirtModule::tryUniformRetValOpt( @@ -761,6 +782,35 @@ bool DevirtModule::tryUniformRetValOpt( return true; } +std::string DevirtModule::getGlobalName(VTableSlot Slot, + ArrayRef<uint64_t> Args, + StringRef Name) { + std::string FullName = "__typeid_"; + raw_string_ostream OS(FullName); + OS << cast<MDString>(Slot.TypeID)->getString() << '_' << Slot.ByteOffset; + for (uint64_t Arg : Args) + OS << '_' << Arg; + OS << '_' << Name; + return OS.str(); +} + +void DevirtModule::exportGlobal(VTableSlot Slot, ArrayRef<uint64_t> Args, + StringRef Name, Constant *C) { + GlobalAlias *GA = GlobalAlias::create(Int8Ty, 0, GlobalValue::ExternalLinkage, + getGlobalName(Slot, Args, Name), C, &M); + GA->setVisibility(GlobalValue::HiddenVisibility); +} + +Constant *DevirtModule::importGlobal(VTableSlot Slot, ArrayRef<uint64_t> Args, + StringRef Name) { + Constant *C = M.getOrInsertGlobal(getGlobalName(Slot, Args, Name), Int8Ty); + auto *GV = dyn_cast<GlobalVariable>(C); + if (!GV) + return C; + GV->setVisibility(GlobalValue::HiddenVisibility); + return GV; +} + void DevirtModule::applyUniqueRetValOpt(CallSiteInfo &CSInfo, StringRef FnName, bool IsOne, Constant *UniqueMemberAddr) { @@ -771,11 +821,13 @@ void DevirtModule::applyUniqueRetValOpt(CallSiteInfo &CSInfo, StringRef FnName, Cmp = B.CreateZExt(Cmp, Call.CS->getType()); Call.replaceAndErase("unique-ret-val", FnName, RemarksEnabled, Cmp); } + CSInfo.markDevirt(); } bool DevirtModule::tryUniqueRetValOpt( unsigned BitWidth, MutableArrayRef<VirtualCallTarget> TargetsForSlot, - CallSiteInfo &CSInfo) { + CallSiteInfo &CSInfo, WholeProgramDevirtResolution::ByArg *Res, + VTableSlot Slot, ArrayRef<uint64_t> Args) { // IsOne controls whether we look for a 0 or a 1. auto tryUniqueRetValOptFor = [&](bool IsOne) { const TypeMemberInfo *UniqueMember = nullptr; @@ -791,13 +843,20 @@ bool DevirtModule::tryUniqueRetValOpt( // checked for a uniform return value in tryUniformRetValOpt. assert(UniqueMember); - // Replace each call with the comparison. Constant *UniqueMemberAddr = ConstantExpr::getBitCast(UniqueMember->Bits->GV, Int8PtrTy); UniqueMemberAddr = ConstantExpr::getGetElementPtr( Int8Ty, UniqueMemberAddr, ConstantInt::get(Int64Ty, UniqueMember->Offset)); + if (CSInfo.isExported()) { + Res->TheKind = WholeProgramDevirtResolution::ByArg::UniqueRetVal; + Res->Info = IsOne; + + exportGlobal(Slot, Args, "unique_member", UniqueMemberAddr); + } + + // Replace each call with the comparison. applyUniqueRetValOpt(CSInfo, TargetsForSlot[0].Fn->getName(), IsOne, UniqueMemberAddr); @@ -839,8 +898,8 @@ void DevirtModule::applyVirtualConstProp(CallSiteInfo &CSInfo, StringRef FnName, } bool DevirtModule::tryVirtualConstProp( - MutableArrayRef<VirtualCallTarget> TargetsForSlot, - VTableSlotInfo &SlotInfo, WholeProgramDevirtResolution *Res) { + MutableArrayRef<VirtualCallTarget> TargetsForSlot, VTableSlotInfo &SlotInfo, + WholeProgramDevirtResolution *Res, VTableSlot Slot) { // This only works if the function returns an integer. auto RetType = dyn_cast<IntegerType>(TargetsForSlot[0].Fn->getReturnType()); if (!RetType) @@ -879,7 +938,8 @@ bool DevirtModule::tryVirtualConstProp( if (tryUniformRetValOpt(TargetsForSlot, CSByConstantArg.second, ResByArg)) continue; - if (tryUniqueRetValOpt(BitWidth, TargetsForSlot, CSByConstantArg.second)) + if (tryUniqueRetValOpt(BitWidth, TargetsForSlot, CSByConstantArg.second, + ResByArg, Slot, CSByConstantArg.first)) continue; // Find an allocation offset in bits in all vtables associated with the @@ -1140,6 +1200,13 @@ void DevirtModule::importResolution(VTableSlot Slot, VTableSlotInfo &SlotInfo) { case WholeProgramDevirtResolution::ByArg::UniformRetVal: applyUniformRetValOpt(CSByConstantArg.second, "", ResByArg.Info); break; + case WholeProgramDevirtResolution::ByArg::UniqueRetVal: { + Constant *UniqueMemberAddr = + importGlobal(Slot, CSByConstantArg.first, "unique_member"); + applyUniqueRetValOpt(CSByConstantArg.second, "", ResByArg.Info, + UniqueMemberAddr); + break; + } default: break; } @@ -1261,7 +1328,7 @@ bool DevirtModule::run() { .WPDRes[S.first.ByteOffset]; if (!trySingleImplDevirt(TargetsForSlot, S.second, Res) && - tryVirtualConstProp(TargetsForSlot, S.second, Res)) + tryVirtualConstProp(TargetsForSlot, S.second, Res, S.first)) DidVirtualConstProp = true; // Collect functions devirtualized at least for one call site for stats. |