Skip to content

Commit 18e1905

Browse files
authored
Merge pull request swiftlang#21306 from eeckstein/dictionary-code-size
stdlib: Code size improvements for Dictionary for -Osize
2 parents 311289c + aae60ff commit 18e1905

File tree

5 files changed

+42
-10
lines changed

5 files changed

+42
-10
lines changed

lib/SILOptimizer/Utils/Generics.cpp

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -364,11 +364,18 @@ static bool createsInfiniteSpecializationLoop(ApplySite Apply) {
364364
// ReabstractionInfo
365365
// =============================================================================
366366

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

372+
if (Caller &&
373+
Caller->getEffectiveOptimizationMode() == OptimizationMode::ForSize &&
374+
Callee->hasSemanticsAttr("optimize.sil.specialize.generic.size.never")) {
375+
return true;
376+
}
377+
378+
372379
if (Subs.hasAnySubstitutableParams() &&
373380
Callee->hasSemanticsAttr("optimize.sil.specialize.generic.partial.never"))
374381
return true;
@@ -383,7 +390,7 @@ static bool shouldNotSpecializeCallee(SILFunction *Callee,
383390
bool ReabstractionInfo::prepareAndCheck(ApplySite Apply, SILFunction *Callee,
384391
SubstitutionMap ParamSubs,
385392
OptRemark::Emitter *ORE) {
386-
if (shouldNotSpecializeCallee(Callee))
393+
if (shouldNotSpecialize(Callee, Apply ? Apply.getFunction() : nullptr))
387394
return false;
388395

389396
SpecializedGenericEnv = nullptr;
@@ -489,7 +496,7 @@ bool ReabstractionInfo::prepareAndCheck(ApplySite Apply, SILFunction *Callee,
489496
return false;
490497

491498
// Bail if the callee should not be partially specialized.
492-
if (shouldNotSpecializeCallee(Callee, ParamSubs))
499+
if (shouldNotSpecialize(Callee, Apply.getFunction(), ParamSubs))
493500
return false;
494501
}
495502

@@ -1763,7 +1770,7 @@ checkSpecializationRequirements(ArrayRef<Requirement> Requirements) {
17631770
/// This constructor is used when processing @_specialize.
17641771
ReabstractionInfo::ReabstractionInfo(SILFunction *Callee,
17651772
ArrayRef<Requirement> Requirements) {
1766-
if (shouldNotSpecializeCallee(Callee))
1773+
if (shouldNotSpecialize(Callee, nullptr))
17671774
return;
17681775

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

2284-
if (shouldNotSpecializeCallee(RefF))
2291+
if (shouldNotSpecialize(RefF, F))
22852292
return;
22862293

22872294
// If the caller and callee are both fragile, preserve the fragility when

stdlib/public/core/Dictionary.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -782,7 +782,6 @@ extension Dictionary {
782782
/// otherwise, `nil`.
783783
@inlinable
784784
public subscript(key: Key) -> Value? {
785-
@inline(__always)
786785
get {
787786
return _variant.lookup(key)
788787
}
@@ -819,6 +818,7 @@ extension Dictionary: ExpressibleByDictionaryLiteral {
819818
/// dictionary. Each key in `elements` must be unique.
820819
@inlinable
821820
@_effects(readonly)
821+
@_semantics("optimize.sil.specialize.generic.size.never")
822822
public init(dictionaryLiteral elements: (Key, Value)...) {
823823
let native = _NativeDictionary<Key, Value>(capacity: elements.count)
824824
for (key, value) in elements {

stdlib/public/core/DictionaryVariant.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,7 @@ extension Dictionary._Variant {
382382
}
383383

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

414415
@inlinable
416+
@_semantics("optimize.sil.specialize.generic.size.never")
415417
internal mutating func removeAll(keepingCapacity keepCapacity: Bool) {
416418
if !keepCapacity {
417419
self = .init(native: _NativeDictionary())

stdlib/public/core/NativeDictionary.swift

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ extension _NativeDictionary { // ensureUnique
202202
}
203203

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

222223
@inlinable
224+
@_semantics("optimize.sil.specialize.generic.size.never")
223225
internal mutating func copy() {
224226
let newStorage = _DictionaryStorage<Key, Value>.copy(original: _storage)
225227
_internalInvariant(newStorage._scale == _storage._scale)
@@ -241,7 +243,7 @@ extension _NativeDictionary { // ensureUnique
241243
/// Ensure storage of self is uniquely held and can hold at least `capacity`
242244
/// elements. Returns true iff contents were rehashed.
243245
@inlinable
244-
@inline(__always)
246+
@_semantics("optimize.sil.specialize.generic.size.never")
245247
internal mutating func ensureUnique(isUnique: Bool, capacity: Int) -> Bool {
246248
if _fastPath(capacity <= self.capacity && isUnique) {
247249
return false
@@ -490,7 +492,6 @@ extension _NativeDictionary { // Insertions
490492
/// held, and with enough capacity for a single insertion (if the key isn't
491493
/// already in the dictionary.)
492494
@inlinable
493-
@inline(__always)
494495
internal mutating func mutatingFind(
495496
_ key: Key,
496497
isUnique: Bool
@@ -629,6 +630,7 @@ extension _NativeDictionary: _HashTableDelegate {
629630
extension _NativeDictionary { // Deletion
630631
@inlinable
631632
@_effects(releasenone)
633+
@_semantics("optimize.sil.specialize.generic.size.never")
632634
internal func _delete(at bucket: Bucket) {
633635
hashTable.delete(at: bucket, with: self)
634636
_storage._count -= 1
@@ -637,7 +639,7 @@ extension _NativeDictionary { // Deletion
637639
}
638640

639641
@inlinable
640-
@inline(__always)
642+
@_semantics("optimize.sil.specialize.generic.size.never")
641643
internal mutating func uncheckedRemove(
642644
at bucket: Bucket,
643645
isUnique: Bool
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// RUN: %target-swift-frontend %s -O -emit-sil | %FileCheck %s -check-prefix=CHECK-O
2+
// RUN: %target-swift-frontend %s -Osize -emit-sil | %FileCheck %s -check-prefix=CHECK-OSIZE
3+
4+
@_semantics("optimize.sil.specialize.generic.size.never")
5+
func foo<T>(_ t: T) -> T {
6+
return t
7+
}
8+
9+
// CHECK-O-LABEL: sil @{{.*}}test
10+
// CHECK-O: %0 = integer_literal
11+
// CHECK-O: %1 = struct $Int
12+
// CHECK-O: return %1
13+
14+
// CHECK-OSIZE-LABEL: sil {{.*}} @{{.*}}foo
15+
16+
// CHECK-OSIZE-LABEL: sil @{{.*}}test
17+
// CHECK-OSIZE: function_ref {{.*}}foo
18+
// CHECK-OSIZE: apply
19+
public func test() -> Int {
20+
return foo(27)
21+
}

0 commit comments

Comments
 (0)