From 7780ee3dc7dba2596d7eea4b2ecd53f7aee5bb43 Mon Sep 17 00:00:00 2001 From: Dave Weston Date: Wed, 3 Jan 2018 23:05:55 -0800 Subject: [PATCH 1/2] [IRGen] Replace duplicate code with new method Fixes SR-6264 --- include/swift/SIL/SILModule.h | 4 +++- lib/SIL/SIL.cpp | 15 ++++++++++++ .../IPO/DeadFunctionElimination.cpp | 17 +------------- lib/SILOptimizer/IPO/GlobalPropertyOpt.cpp | 21 +---------------- lib/SILOptimizer/IPO/LetPropertiesOpts.cpp | 23 +------------------ 5 files changed, 21 insertions(+), 59 deletions(-) diff --git a/include/swift/SIL/SILModule.h b/include/swift/SIL/SILModule.h index 16981d619ceaf..4086cd273f928 100644 --- a/include/swift/SIL/SILModule.h +++ b/include/swift/SIL/SILModule.h @@ -471,7 +471,7 @@ class SILModule { /// Look for a global variable by name. /// /// \return null if this module has no such global variable - SILGlobalVariable *lookUpGlobalVariable(StringRef name) const { + SILGlobalVariable *lookUpGlobalVariable(StringRef name) const { return GlobalVariableMap.lookup(name); } @@ -712,6 +712,8 @@ class SILModule { } }; +bool isDeclVisibleExternally(const ValueDecl *decl, const SILModule *module); + inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const SILModule &M){ M.print(OS); return OS; diff --git a/lib/SIL/SIL.cpp b/lib/SIL/SIL.cpp index 489c61a3ac149..02502e6dad21b 100644 --- a/lib/SIL/SIL.cpp +++ b/lib/SIL/SIL.cpp @@ -115,3 +115,18 @@ swift::getLinkageForProtocolConformance(const NormalProtocolConformance *C, return (definition ? SILLinkage::Public : SILLinkage::PublicExternal); } } + +bool swift::isDeclVisibleExternally(const ValueDecl *decl, const SILModule *module) { + AccessLevel access = decl->getEffectiveAccess(); + switch (access) { + case AccessLevel::Private: + case AccessLevel::FilePrivate: + return false; + case AccessLevel::Internal: + return !module->isWholeModule(); + case AccessLevel::Public: + case AccessLevel::Open: + return true; + } + llvm_unreachable("Unhandled access level in switch"); +} diff --git a/lib/SILOptimizer/IPO/DeadFunctionElimination.cpp b/lib/SILOptimizer/IPO/DeadFunctionElimination.cpp index 3ecc2b2fa36e7..d113863e82cf0 100644 --- a/lib/SILOptimizer/IPO/DeadFunctionElimination.cpp +++ b/lib/SILOptimizer/IPO/DeadFunctionElimination.cpp @@ -407,22 +407,7 @@ class FunctionLivenessComputation { /// Retrieve the visibility information from the AST. bool isVisibleExternally(const ValueDecl *decl) { - AccessLevel access = decl->getEffectiveAccess(); - SILLinkage linkage; - switch (access) { - case AccessLevel::Private: - case AccessLevel::FilePrivate: - linkage = SILLinkage::Private; - break; - case AccessLevel::Internal: - linkage = SILLinkage::Hidden; - break; - case AccessLevel::Public: - case AccessLevel::Open: - linkage = SILLinkage::Public; - break; - } - if (isPossiblyUsedExternally(linkage, Module->isWholeModule())) + if (isDeclVisibleExternally(decl, Module)) return true; // If a vtable or witness table (method) is only visible in another module diff --git a/lib/SILOptimizer/IPO/GlobalPropertyOpt.cpp b/lib/SILOptimizer/IPO/GlobalPropertyOpt.cpp index 6b86ad1349fac..1ad30b3039a63 100644 --- a/lib/SILOptimizer/IPO/GlobalPropertyOpt.cpp +++ b/lib/SILOptimizer/IPO/GlobalPropertyOpt.cpp @@ -127,25 +127,6 @@ class GlobalPropertyOpt { } return false; } - - bool isVisibleExternally(VarDecl *decl) { - AccessLevel access = decl->getEffectiveAccess(); - SILLinkage linkage; - switch (access) { - case AccessLevel::Private: - case AccessLevel::FilePrivate: - linkage = SILLinkage::Private; - break; - case AccessLevel::Internal: - linkage = SILLinkage::Hidden; - break; - case AccessLevel::Public: - case AccessLevel::Open: - linkage = SILLinkage::Public; - break; - } - return isPossiblyUsedExternally(linkage, M.isWholeModule()); - } static bool canAddressEscape(SILValue V, bool acceptStore); @@ -154,7 +135,7 @@ class GlobalPropertyOpt { Entry * &entry = FieldEntries[Field]; if (!entry) { entry = new (EntryAllocator.Allocate()) Entry(SILValue(), Field); - if (isVisibleExternally(Field)) + if (isDeclVisibleExternally(Field, &M)) setAddressEscapes(entry); } return entry; diff --git a/lib/SILOptimizer/IPO/LetPropertiesOpts.cpp b/lib/SILOptimizer/IPO/LetPropertiesOpts.cpp index 775fbcb4fec9d..10c1d5d2cc04d 100644 --- a/lib/SILOptimizer/IPO/LetPropertiesOpts.cpp +++ b/lib/SILOptimizer/IPO/LetPropertiesOpts.cpp @@ -289,28 +289,7 @@ static bool isSameInitSequence(const InitSequence &LHS, /// Check if a given let property can be assigned externally. static bool isAssignableExternally(VarDecl *Property, SILModule *Module) { - AccessLevel access = Property->getEffectiveAccess(); - SILLinkage linkage; - switch (access) { - case AccessLevel::Private: - case AccessLevel::FilePrivate: - linkage = SILLinkage::Private; - DEBUG(llvm::dbgs() << "Property " << *Property << " has private access\n"); - break; - case AccessLevel::Internal: - linkage = SILLinkage::Hidden; - DEBUG(llvm::dbgs() << "Property " << *Property << " has internal access\n"); - break; - case AccessLevel::Public: - case AccessLevel::Open: - linkage = SILLinkage::Public; - DEBUG(llvm::dbgs() << "Property " << *Property << " has public access\n"); - break; - } - - DEBUG(llvm::dbgs() << "Module of " << *Property << " WMO mode is: " << Module->isWholeModule() << "\n"); - - if (isPossiblyUsedExternally(linkage, Module->isWholeModule())) { + if (isDeclVisibleExternally(Property, Module)) { // If at least one of the properties of the enclosing type cannot be // used externally, then no initializer can be implemented externally as // it wouldn't be able to initialize such a property. From 7d9a55c8aabb9e915bb905eef18c5e0cd24190db Mon Sep 17 00:00:00 2001 From: Dave Weston Date: Tue, 9 Jan 2018 16:12:57 -0800 Subject: [PATCH 2/2] [IRGen] Replace more duplicated code with method --- lib/SILOptimizer/IPO/GlobalOpt.cpp | 11 +------- lib/SILOptimizer/IPO/LetPropertiesOpts.cpp | 13 ++-------- .../Transforms/SpeculativeDevirtualizer.cpp | 12 +-------- lib/SILOptimizer/Utils/Devirtualize.cpp | 25 +------------------ 4 files changed, 5 insertions(+), 56 deletions(-) diff --git a/lib/SILOptimizer/IPO/GlobalOpt.cpp b/lib/SILOptimizer/IPO/GlobalOpt.cpp index bccb8c05aaa7a..1b7fcdea98ee3 100644 --- a/lib/SILOptimizer/IPO/GlobalOpt.cpp +++ b/lib/SILOptimizer/IPO/GlobalOpt.cpp @@ -911,16 +911,7 @@ static bool canBeChangedExternally(SILGlobalVariable *SILG) { // Use access specifiers from the declarations, // if possible. if (auto *Decl = SILG->getDecl()) { - switch (Decl->getEffectiveAccess()) { - case AccessLevel::Private: - case AccessLevel::FilePrivate: - return false; - case AccessLevel::Internal: - return !SILG->getModule().isWholeModule(); - case AccessLevel::Public: - case AccessLevel::Open: - return true; - } + return isDeclVisibleExternally(Decl, &SILG->getModule()); } if (SILG->getLinkage() == SILLinkage::Private) diff --git a/lib/SILOptimizer/IPO/LetPropertiesOpts.cpp b/lib/SILOptimizer/IPO/LetPropertiesOpts.cpp index 10c1d5d2cc04d..9409c04281105 100644 --- a/lib/SILOptimizer/IPO/LetPropertiesOpts.cpp +++ b/lib/SILOptimizer/IPO/LetPropertiesOpts.cpp @@ -158,18 +158,12 @@ void LetPropertiesOpt::optimizeLetPropertyAccess(VarDecl *Property, DEBUG(llvm::dbgs() << "Replacing access to property '" << *Property << "' by its constant initializer\n"); - auto PropertyAccess = Property->getEffectiveAccess(); - auto TypeAccess = Ty->getEffectiveAccess(); auto CanRemove = false; // Check if a given let property can be removed, because it // is not accessible elsewhere. This can happen if this property // is private or if it is internal and WMO mode is used. - if (TypeAccess <= AccessLevel::FilePrivate || - PropertyAccess <= AccessLevel::FilePrivate - || ((TypeAccess <= AccessLevel::Internal || - PropertyAccess <= AccessLevel::Internal) && - Module->isWholeModule())) { + if (!isDeclVisibleExternally(Ty, Module) || !isDeclVisibleExternally(Property, Module)) { CanRemove = true; DEBUG(llvm::dbgs() << "Storage for property '" << *Property << "' can be eliminated\n"); @@ -310,10 +304,7 @@ static bool isAssignableExternally(VarDecl *Property, SILModule *Module) { // it is a whole module compilation. In this case, no external initializer // may exist. for (auto SP : Ty->getStoredProperties()) { - auto storedPropertyAccess = SP->getEffectiveAccess(); - if (storedPropertyAccess <= AccessLevel::FilePrivate || - (storedPropertyAccess <= AccessLevel::Internal && - Module->isWholeModule())) { + if (!isDeclVisibleExternally(SP, Module)) { DEBUG(llvm::dbgs() << "Property " << *Property << " cannot be set externally\n"); return false; diff --git a/lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp b/lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp index a68288568444f..674d9ecb8f70d 100644 --- a/lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp +++ b/lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp @@ -257,18 +257,8 @@ static bool isDefaultCaseKnown(ClassHierarchyAnalysis *CHA, return false; // Only consider 'private' members, unless we are in whole-module compilation. - switch (CD->getEffectiveAccess()) { - case AccessLevel::Open: + if (isDeclVisibleExternally(CD, &AI.getModule())) return false; - case AccessLevel::Public: - case AccessLevel::Internal: - if (!AI.getModule().isWholeModule()) - return false; - break; - case AccessLevel::FilePrivate: - case AccessLevel::Private: - break; - } // This is a private or a module internal class. // diff --git a/lib/SILOptimizer/Utils/Devirtualize.cpp b/lib/SILOptimizer/Utils/Devirtualize.cpp index 427a00e4005c6..89d39c4117a50 100644 --- a/lib/SILOptimizer/Utils/Devirtualize.cpp +++ b/lib/SILOptimizer/Utils/Devirtualize.cpp @@ -171,18 +171,8 @@ static bool isKnownFinalClass(ClassDecl *CD, SILModule &M, return false; // Only consider 'private' members, unless we are in whole-module compilation. - switch (CD->getEffectiveAccess()) { - case AccessLevel::Open: + if (isDeclVisibleExternally(CD, &M)) return false; - case AccessLevel::Public: - case AccessLevel::Internal: - if (!M.isWholeModule()) - return false; - break; - case AccessLevel::FilePrivate: - case AccessLevel::Private: - break; - } // Take the ClassHierarchyAnalysis into account. // If a given class has no subclasses and @@ -192,19 +182,6 @@ static bool isKnownFinalClass(ClassDecl *CD, SILModule &M, // of devirtualization. if (CHA) { if (!CHA->hasKnownDirectSubclasses(CD)) { - switch (CD->getEffectiveAccess()) { - case AccessLevel::Open: - return false; - case AccessLevel::Public: - case AccessLevel::Internal: - if (!M.isWholeModule()) - return false; - break; - case AccessLevel::FilePrivate: - case AccessLevel::Private: - break; - } - return true; } }