[llvm] [clang] Support VFE in thinLTO (PR #69735)
Teresa Johnson via cfe-commits
cfe-commits at lists.llvm.org
Mon Nov 6 18:20:04 PST 2023
================
@@ -34,12 +40,223 @@ static cl::opt<bool>
ClEnableVFE("enable-vfe", cl::Hidden, cl::init(true),
cl::desc("Enable virtual function elimination"));
+static cl::opt<std::string> ClReadSummary(
+ "globaldce-read-summary",
+ cl::desc("Read summary from given bitcode before running pass"),
+ cl::Hidden);
+
STATISTIC(NumAliases , "Number of global aliases removed");
STATISTIC(NumFunctions, "Number of functions removed");
STATISTIC(NumIFuncs, "Number of indirect functions removed");
STATISTIC(NumVariables, "Number of global variables removed");
STATISTIC(NumVFuncs, "Number of virtual functions removed");
+namespace llvm {
+
+// Returning a representative summary for the vtable, also set isSafe.
+static const GlobalVarSummary *
+getVTableFuncsForTId(const TypeIdOffsetVtableInfo &P, bool &isSafe) {
+ // Find a representative copy of the vtable initializer.
+ const GlobalVarSummary *VS = nullptr;
+ bool LocalFound = false;
+ for (auto &S : P.VTableVI.getSummaryList()) {
+ if (GlobalValue::isLocalLinkage(S->linkage())) {
+ if (LocalFound) {
+ isSafe = false;
+ return nullptr;
+ }
+ LocalFound = true;
+ }
+ auto *CurVS = cast<GlobalVarSummary>(S->getBaseObject());
+ // Ignore if vTableFuncs is empty and vtable is available_externally.
+ if (!CurVS->vTableFuncs().empty() ||
+ !GlobalValue::isAvailableExternallyLinkage(S->linkage())) {
+ VS = CurVS;
+ if (VS->getVCallVisibility() == GlobalObject::VCallVisibilityPublic) {
+ isSafe = false;
+ return VS;
+ }
+ }
+ }
+
+ if (!VS) {
+ isSafe = false;
+ return nullptr;
+ }
+ if (!VS->isLive()) {
+ isSafe = true;
+ return nullptr;
+ }
+ isSafe = true;
+ return VS;
+}
+
+static void collectSafeVTables(
+ ModuleSummaryIndex &Summary,
+ DenseMap<GlobalValue::GUID, std::vector<StringRef>> &NameByGUID,
+ std::map<ValueInfo, std::vector<VirtFuncOffset>> &VFESafeVTablesAndFns) {
+ // Update VFESafeVTablesAndFns with information from summary.
+ for (auto &P : Summary.typeIdCompatibleVtableMap()) {
+ NameByGUID[GlobalValue::getGUID(P.first)].push_back(P.first);
+ LLVM_DEBUG(dbgs() << "TId " << GlobalValue::getGUID(P.first) << " "
+ << P.first << "\n");
+ }
+ llvm::errs() << "VFEThinLTO number of TIds: " << NameByGUID.size() << "\n";
+
+ // VFESafeVTablesAndFns: map from VI for vTable to VI for vfunc
+ std::map<ValueInfo, std::set<GlobalValue::GUID>> vFuncSet;
+ unsigned numSafeVFuncs = 0;
+ // Collect stats for VTables (safe, public-visibility, other).
+ std::set<ValueInfo> vTablePublicVis;
+ std::set<ValueInfo> vTableOther;
+ for (auto &TidSummary : Summary.typeIdCompatibleVtableMap()) {
+ for (const TypeIdOffsetVtableInfo &P : TidSummary.second) {
+ LLVM_DEBUG(dbgs() << "TId-vTable " << TidSummary.first << " "
+ << P.VTableVI.name() << " " << P.AddressPointOffset
+ << "\n");
+ bool isSafe = false;
+ const GlobalVarSummary *VS = getVTableFuncsForTId(P, isSafe);
+ if (!isSafe && VS)
+ vTablePublicVis.insert(P.VTableVI);
+ if ((isSafe && !VS) || (!isSafe && !VS))
+ vTableOther.insert(P.VTableVI);
+ if (!isSafe || !VS) {
+ continue;
+ }
+
+ // Go through VS->vTableFuncs
+ for (auto VTP : VS->vTableFuncs()) {
+ if (vFuncSet.find(P.VTableVI) == vFuncSet.end() ||
+ !vFuncSet[P.VTableVI].count(VTP.FuncVI.getGUID())) {
+ VFESafeVTablesAndFns[P.VTableVI].push_back(VTP);
+ LLVM_DEBUG(dbgs()
+ << "vTable " << P.VTableVI.name() << " "
+ << VTP.FuncVI.name() << " " << VTP.VTableOffset << "\n");
+ ++numSafeVFuncs;
+ }
+ vFuncSet[P.VTableVI].insert(VTP.FuncVI.getGUID());
+ }
+ }
+ }
+ llvm::errs() << "VFEThinLTO number of vTables: " << vFuncSet.size() << " "
+ << vTablePublicVis.size() << " " << vTableOther.size() << "\n";
+ llvm::errs() << "VFEThinLTO numSafeVFuncs: " << numSafeVFuncs << "\n";
+}
+
+static void checkVTableLoadsIndex(
+ ModuleSummaryIndex &Summary,
+ DenseMap<GlobalValue::GUID, std::vector<StringRef>> &NameByGUID,
+ std::map<ValueInfo, std::vector<VirtFuncOffset>> &VFESafeVTablesAndFns,
+ std::map<ValueInfo, std::vector<ValueInfo>> &VFuncsAndCallers) {
+ // Go through Function summarys for intrinsics, also funcHasNonVTableRef to
+ // erase entries from VFESafeVTableAndFns.
----------------
teresajohnson wrote:
why and when are entries being erased? More qualitative comments about what this algorithm is doing would be helpful.
https://github.com/llvm/llvm-project/pull/69735
More information about the cfe-commits
mailing list