Skip to content

Commit

Permalink
Merge pull request #21306 from eeckstein/dictionary-code-size
Browse files Browse the repository at this point in the history
stdlib: Code size improvements for Dictionary for -Osize
  • Loading branch information
eeckstein committed Dec 14, 2018
2 parents 311289c + aae60ff commit 18e1905
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 10 deletions.
19 changes: 13 additions & 6 deletions lib/SILOptimizer/Utils/Generics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -364,11 +364,18 @@ static bool createsInfiniteSpecializationLoop(ApplySite Apply) {
// ReabstractionInfo
// =============================================================================

static bool shouldNotSpecializeCallee(SILFunction *Callee,
SubstitutionMap Subs = {}) {
static bool shouldNotSpecialize(SILFunction *Callee, SILFunction *Caller,
SubstitutionMap Subs = {}) {
if (Callee->hasSemanticsAttr("optimize.sil.specialize.generic.never"))
return true;

if (Caller &&
Caller->getEffectiveOptimizationMode() == OptimizationMode::ForSize &&
Callee->hasSemanticsAttr("optimize.sil.specialize.generic.size.never")) {
return true;
}


if (Subs.hasAnySubstitutableParams() &&
Callee->hasSemanticsAttr("optimize.sil.specialize.generic.partial.never"))
return true;
Expand All @@ -383,7 +390,7 @@ static bool shouldNotSpecializeCallee(SILFunction *Callee,
bool ReabstractionInfo::prepareAndCheck(ApplySite Apply, SILFunction *Callee,
SubstitutionMap ParamSubs,
OptRemark::Emitter *ORE) {
if (shouldNotSpecializeCallee(Callee))
if (shouldNotSpecialize(Callee, Apply ? Apply.getFunction() : nullptr))
return false;

SpecializedGenericEnv = nullptr;
Expand Down Expand Up @@ -489,7 +496,7 @@ bool ReabstractionInfo::prepareAndCheck(ApplySite Apply, SILFunction *Callee,
return false;

// Bail if the callee should not be partially specialized.
if (shouldNotSpecializeCallee(Callee, ParamSubs))
if (shouldNotSpecialize(Callee, Apply.getFunction(), ParamSubs))
return false;
}

Expand Down Expand Up @@ -1763,7 +1770,7 @@ checkSpecializationRequirements(ArrayRef<Requirement> Requirements) {
/// This constructor is used when processing @_specialize.
ReabstractionInfo::ReabstractionInfo(SILFunction *Callee,
ArrayRef<Requirement> Requirements) {
if (shouldNotSpecializeCallee(Callee))
if (shouldNotSpecialize(Callee, nullptr))
return;

// Perform some sanity checks for the requirements.
Expand Down Expand Up @@ -2281,7 +2288,7 @@ void swift::trySpecializeApplyOfGeneric(
if (F->isSerialized() && !RefF->hasValidLinkageForFragileInline())
return;

if (shouldNotSpecializeCallee(RefF))
if (shouldNotSpecialize(RefF, F))
return;

// If the caller and callee are both fragile, preserve the fragility when
Expand Down
2 changes: 1 addition & 1 deletion stdlib/public/core/Dictionary.swift
Original file line number Diff line number Diff line change
Expand Up @@ -782,7 +782,6 @@ extension Dictionary {
/// otherwise, `nil`.
@inlinable
public subscript(key: Key) -> Value? {
@inline(__always)
get {
return _variant.lookup(key)
}
Expand Down Expand Up @@ -819,6 +818,7 @@ extension Dictionary: ExpressibleByDictionaryLiteral {
/// dictionary. Each key in `elements` must be unique.
@inlinable
@_effects(readonly)
@_semantics("optimize.sil.specialize.generic.size.never")
public init(dictionaryLiteral elements: (Key, Value)...) {
let native = _NativeDictionary<Key, Value>(capacity: elements.count)
for (key, value) in elements {
Expand Down
2 changes: 2 additions & 0 deletions stdlib/public/core/DictionaryVariant.swift
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,7 @@ extension Dictionary._Variant {
}

@inlinable
@_semantics("optimize.sil.specialize.generic.size.never")
internal mutating func remove(at index: Index) -> Element {
// FIXME(performance): fuse data migration and element deletion into one
// operation.
Expand Down Expand Up @@ -412,6 +413,7 @@ extension Dictionary._Variant {
}

@inlinable
@_semantics("optimize.sil.specialize.generic.size.never")
internal mutating func removeAll(keepingCapacity keepCapacity: Bool) {
if !keepCapacity {
self = .init(native: _NativeDictionary())
Expand Down
8 changes: 5 additions & 3 deletions stdlib/public/core/NativeDictionary.swift
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ extension _NativeDictionary { // ensureUnique
}

@inlinable
@_semantics("optimize.sil.specialize.generic.size.never")
internal mutating func copyAndResize(capacity: Int) {
let capacity = Swift.max(capacity, self.capacity)
let newStorage = _DictionaryStorage<Key, Value>.resize(
Expand All @@ -220,6 +221,7 @@ extension _NativeDictionary { // ensureUnique
}

@inlinable
@_semantics("optimize.sil.specialize.generic.size.never")
internal mutating func copy() {
let newStorage = _DictionaryStorage<Key, Value>.copy(original: _storage)
_internalInvariant(newStorage._scale == _storage._scale)
Expand All @@ -241,7 +243,7 @@ extension _NativeDictionary { // ensureUnique
/// Ensure storage of self is uniquely held and can hold at least `capacity`
/// elements. Returns true iff contents were rehashed.
@inlinable
@inline(__always)
@_semantics("optimize.sil.specialize.generic.size.never")
internal mutating func ensureUnique(isUnique: Bool, capacity: Int) -> Bool {
if _fastPath(capacity <= self.capacity && isUnique) {
return false
Expand Down Expand Up @@ -490,7 +492,6 @@ extension _NativeDictionary { // Insertions
/// held, and with enough capacity for a single insertion (if the key isn't
/// already in the dictionary.)
@inlinable
@inline(__always)
internal mutating func mutatingFind(
_ key: Key,
isUnique: Bool
Expand Down Expand Up @@ -629,6 +630,7 @@ extension _NativeDictionary: _HashTableDelegate {
extension _NativeDictionary { // Deletion
@inlinable
@_effects(releasenone)
@_semantics("optimize.sil.specialize.generic.size.never")
internal func _delete(at bucket: Bucket) {
hashTable.delete(at: bucket, with: self)
_storage._count -= 1
Expand All @@ -637,7 +639,7 @@ extension _NativeDictionary { // Deletion
}

@inlinable
@inline(__always)
@_semantics("optimize.sil.specialize.generic.size.never")
internal mutating func uncheckedRemove(
at bucket: Bucket,
isUnique: Bool
Expand Down
21 changes: 21 additions & 0 deletions test/SILOptimizer/no_size_specialization.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// RUN: %target-swift-frontend %s -O -emit-sil | %FileCheck %s -check-prefix=CHECK-O
// RUN: %target-swift-frontend %s -Osize -emit-sil | %FileCheck %s -check-prefix=CHECK-OSIZE

@_semantics("optimize.sil.specialize.generic.size.never")
func foo<T>(_ t: T) -> T {
return t
}

// CHECK-O-LABEL: sil @{{.*}}test
// CHECK-O: %0 = integer_literal
// CHECK-O: %1 = struct $Int
// CHECK-O: return %1

// CHECK-OSIZE-LABEL: sil {{.*}} @{{.*}}foo

// CHECK-OSIZE-LABEL: sil @{{.*}}test
// CHECK-OSIZE: function_ref {{.*}}foo
// CHECK-OSIZE: apply
public func test() -> Int {
return foo(27)
}

0 comments on commit 18e1905

Please sign in to comment.