Skip to content

Commit 7727ce7

Browse files
authored
Merge pull request #64359 from eeckstein/swift-compile-time
Compile time improvements in the Swift optimizer
2 parents d9e028f + 053a38d commit 7727ce7

File tree

12 files changed

+163
-21
lines changed

12 files changed

+163
-21
lines changed

SwiftCompilerSources/Sources/Basic/Utils.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -120,19 +120,19 @@ public typealias SwiftObject = UnsafeMutablePointer<BridgedSwiftObject>
120120

121121
extension UnsafeMutablePointer where Pointee == BridgedSwiftObject {
122122
public init<T: AnyObject>(_ object: T) {
123-
let ptr = Unmanaged.passUnretained(object).toOpaque()
123+
let ptr = unsafeBitCast(object, to: UnsafeMutableRawPointer.self)
124124
self = ptr.bindMemory(to: BridgedSwiftObject.self, capacity: 1)
125125
}
126126

127127
public func getAs<T: AnyObject>(_ objectType: T.Type) -> T {
128-
return Unmanaged<T>.fromOpaque(self).takeUnretainedValue()
128+
return unsafeBitCast(self, to: T.self)
129129
}
130130
}
131131

132132
extension Optional where Wrapped == UnsafeMutablePointer<BridgedSwiftObject> {
133133
public func getAs<T: AnyObject>(_ objectType: T.Type) -> T? {
134134
if let pointer = self {
135-
return Unmanaged<T>.fromOpaque(pointer).takeUnretainedValue()
135+
return pointer.getAs(objectType)
136136
}
137137
return nil
138138
}

SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyStrongRetainRelease.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ extension StrongReleaseInst : Simplifyable, SILCombineSimplifyable {
6767
/// Returns true if \p value is something where reference counting instructions
6868
/// don't have any effect.
6969
private func isNotReferenceCounted(value: Value) -> Bool {
70+
if value.type.isMarkedAsImmortal {
71+
return true
72+
}
7073
switch value {
7174
case let cfi as ConvertFunctionInst:
7275
return isNotReferenceCounted(value: cfi.fromFunction)

SwiftCompilerSources/Sources/Optimizer/Utilities/EscapeUtils.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -819,14 +819,14 @@ fileprivate struct EscapeWalker<V: EscapeVisitor> : ValueDefUseWalker,
819819
}
820820

821821
private func hasRelevantType(_ value: Value, at path: SmallProjectionPath) -> Bool {
822-
if !value.hasTrivialNonPointerType {
823-
return true
824-
}
825822
if visitor.followTrivialTypes &&
826823
// When part of a class field only need to follow non-trivial types
827824
!path.hasClassProjection {
828825
return true
829826
}
827+
if !value.hasTrivialNonPointerType {
828+
return true
829+
}
830830
return false
831831
}
832832

SwiftCompilerSources/Sources/SIL/BasicBlock.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import Basic
1414
import SILBridging
1515

16+
@_semantics("arc.immortal")
1617
final public class BasicBlock : CustomStringConvertible, HasShortDescription {
1718
public var next: BasicBlock? { SILBasicBlock_next(bridged).block }
1819
public var previous: BasicBlock? { SILBasicBlock_previous(bridged).block }

SwiftCompilerSources/Sources/SIL/Function.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import Basic
1414
import SILBridging
1515

16+
@_semantics("arc.immortal")
1617
final public class Function : CustomStringConvertible, HasShortDescription, Hashable {
1718
public private(set) var effects = FunctionEffects()
1819

SwiftCompilerSources/Sources/SIL/Instruction.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import SILBridging
1717
// Instruction base classes
1818
//===----------------------------------------------------------------------===//
1919

20+
@_semantics("arc.immortal")
2021
public class Instruction : CustomStringConvertible, Hashable {
2122
final public var next: Instruction? {
2223
SILInstruction_next(bridged).instruction

SwiftCompilerSources/Sources/SIL/Type.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,9 @@ public struct Type : CustomStringConvertible, NoReflectionChildren {
5858
}
5959

6060
public var isCalleeConsumedFunction: Bool { SILType_isCalleeConsumedFunction(bridged) }
61-
61+
62+
public var isMarkedAsImmortal: Bool { SILType_isMarkedAsImmortal(bridged) }
63+
6264
public func getIndexOfEnumCase(withName name: String) -> Int? {
6365
let idx = name._withStringRef {
6466
SILType_getCaseIdxOfEnumType(bridged, $0)

SwiftCompilerSources/Sources/SIL/Value.swift

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import Basic
1414
import SILBridging
1515

16+
@_semantics("arc.immortal")
1617
public protocol Value : AnyObject, CustomStringConvertible {
1718
var uses: UseList { get }
1819
var type: Type { get }
@@ -157,18 +158,21 @@ extension Value {
157158
extension BridgedValue {
158159
public func getAs<T: AnyObject>(_ valueType: T.Type) -> T { obj.getAs(T.self) }
159160

161+
public var value: Value { getAs(AnyObject.self) as! Value }
162+
}
163+
164+
extension BridgedClassifiedValue {
160165
public var value: Value {
161-
// This is much faster than a conformance lookup with `as! Value`.
162-
let v = getAs(AnyObject.self)
163-
switch v {
164-
case let inst as SingleValueInstruction:
165-
return inst
166-
case let arg as Argument:
167-
return arg
168-
case let mvr as MultipleValueInstructionResult:
169-
return mvr
170-
case let undef as Undef:
171-
return undef
166+
// Doing the type check in C++ is much faster than a conformance lookup with `as! Value`.
167+
switch kind {
168+
case .SingleValueInstruction:
169+
return obj.getAs(SingleValueInstruction.self)
170+
case .Argument:
171+
return obj.getAs(Argument.self)
172+
case .MultipleValueInstructionResult:
173+
return obj.getAs(MultipleValueInstructionResult.self)
174+
case .Undef:
175+
return obj.getAs(Undef.self)
172176
default:
173177
fatalError("unknown Value type")
174178
}

include/swift/AST/SemanticAttrs.def

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,13 @@ SEMANTICS_ATTR(OPTIMIZE_SIL_SPECIALIZE_GENERIC_SIZE_NEVER,
7676
SEMANTICS_ATTR(OPTIMIZE_SIL_SPECIALIZE_OWNED2GUARANTEE_NEVER,
7777
"optimize.sil.specialize.owned2guarantee.never")
7878

79+
// To be used on a nominal type declaration.
80+
// Assumes that a class (or class references inside a nominal type) are immortal.
81+
// ARC operations on such types can be eliminated.
82+
// If specified on a protocol declaration, all types which conform to that protocol
83+
// are assumed to be immortal.
84+
SEMANTICS_ATTR(ARC_IMMORTAL, "arc.immortal")
85+
7986
SEMANTICS_ATTR(OSLOG_MESSAGE_TYPE, "oslog.message.type")
8087
SEMANTICS_ATTR(OSLOG_MESSAGE_INIT_INTERPOLATION, "oslog.message.init_interpolation")
8188
SEMANTICS_ATTR(OSLOG_MESSAGE_INIT_STRING_LITERAL, "oslog.message.init_stringliteral")

include/swift/SIL/SILBridging.h

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,19 @@ typedef struct {
133133
SwiftObject obj;
134134
} BridgedValue;
135135

136+
// For fast SILValue -> Value briding.
137+
// This is doing the type checks in C++ rather than in Swift.
138+
// It's used for getting the value of an Operand, which is a time critical function.
139+
typedef struct {
140+
SwiftObject obj;
141+
enum class Kind {
142+
SingleValueInstruction,
143+
Argument,
144+
MultipleValueInstructionResult,
145+
Undef
146+
} kind;
147+
} BridgedClassifiedValue;
148+
136149
typedef struct {
137150
OptionalSwiftObject obj;
138151
} OptionalBridgedValue;
@@ -305,7 +318,7 @@ OptionalBridgedSuccessor SILSuccessor_getNext(BridgedSuccessor succ);
305318
BridgedBasicBlock SILSuccessor_getTargetBlock(BridgedSuccessor succ);
306319
BridgedInstruction SILSuccessor_getContainingInst(BridgedSuccessor succ);
307320

308-
BridgedValue Operand_getValue(BridgedOperand);
321+
BridgedClassifiedValue Operand_getValue(BridgedOperand);
309322
OptionalBridgedOperand Operand_nextUse(BridgedOperand);
310323
BridgedInstruction Operand_getUser(BridgedOperand);
311324
SwiftInt Operand_isTypeDependent(BridgedOperand);
@@ -332,6 +345,7 @@ BridgedType SILType_instanceTypeOfMetatype(BridgedType type, BridgedFunction fun
332345
BridgedDecl SILType_getNominal(BridgedType type);
333346
bool SILType_isOrContainsObjectiveCClass(BridgedType type);
334347
bool SILType_isCalleeConsumedFunction(BridgedType type);
348+
bool SILType_isMarkedAsImmortal(BridgedType type);
335349
SwiftInt SILType_getNumTupleElements(BridgedType type);
336350
BridgedType SILType_getTupleElementType(BridgedType type, SwiftInt elementIdx);
337351
SwiftInt SILType_getNumNominalFields(BridgedType type);

0 commit comments

Comments
 (0)