Skip to content

Commit d011771

Browse files
authored
Merge pull request swiftlang#69401 from eeckstein/noallocation-with-precondition
Add some instruction simplifications to make `precondition()` not allocate in Onone builds
2 parents a94d22e + d27ca6a commit d011771

26 files changed

+255
-40
lines changed

SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,10 @@ swift_compiler_sources(Optimizer
1313
SimplifyBuiltin.swift
1414
SimplifyCondBranch.swift
1515
SimplifyCondFail.swift
16+
SimplifyConvertEscapeToNoEscape.swift
17+
SimplifyCopyValue.swift
1618
SimplifyDebugStep.swift
19+
SimplifyDestroyValue.swift
1720
SimplifyDestructure.swift
1821
SimplifyGlobalValue.swift
1922
SimplifyInitEnumDataAddr.swift

SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyApply.swift

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ import SIL
1414

1515
extension ApplyInst : OnoneSimplifyable {
1616
func simplify(_ context: SimplifyContext) {
17+
if tryTransformThickToThinCallee(of: self, context) {
18+
return
19+
}
1720
_ = context.tryDevirtualize(apply: self, isMandatory: false)
1821
}
1922
}
@@ -29,3 +32,29 @@ extension BeginApplyInst : OnoneSimplifyable {
2932
_ = context.tryDevirtualize(apply: self, isMandatory: false)
3033
}
3134
}
35+
36+
/// Optimizes a thick function call if the callee is a `thin_to_thick_function` instruction:
37+
///
38+
/// %2 = thin_to_thick_function %1
39+
/// %3 = apply %2(...) : @callee_guaranteed
40+
/// ->
41+
/// %2 = thin_to_thick_function %1
42+
/// %3 = apply %1(...): @convention(thin)
43+
///
44+
private func tryTransformThickToThinCallee(of apply: ApplyInst, _ context: SimplifyContext) -> Bool {
45+
if let tttf = apply.callee as? ThinToThickFunctionInst,
46+
!apply.callee.type.isCalleeConsumedFunction
47+
{
48+
let builder = Builder(before: apply, context)
49+
let newApply = builder.createApply(function: tttf.operand.value,
50+
apply.substitutionMap,
51+
arguments: Array(apply.arguments),
52+
isNonThrowing: apply.isNonThrowing,
53+
isNonAsync: apply.isNonAsync,
54+
specializationInfo: apply.specializationInfo)
55+
apply.uses.replaceAll(with: newApply, context)
56+
context.erase(instruction: apply)
57+
return true
58+
}
59+
return false
60+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
//===--- SimplifyConvertEscapeToNoEscape.swift ----------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2023 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
import SIL
14+
15+
extension ConvertEscapeToNoEscapeInst : OnoneSimplifyable {
16+
func simplify(_ context: SimplifyContext) {
17+
tryCombineWithThinToThickOperand(context)
18+
}
19+
}
20+
21+
private extension ConvertEscapeToNoEscapeInst {
22+
23+
/// Combine with a thin_to_thick_function operand:
24+
///
25+
/// %2 = thin_to_thick_function %1 to $() -> ()
26+
/// %3 = convert_escape_to_noescape %2 : $() -> () to $@noescape () -> ()
27+
/// ->
28+
/// %3 = thin_to_thick_function %1 to $@noescape () -> ()
29+
30+
func tryCombineWithThinToThickOperand(_ context: SimplifyContext) {
31+
if let thinToThick = fromFunction as? ThinToThickFunctionInst {
32+
let builder = Builder(before: self, context)
33+
let noEscapeFnType = thinToThick.type.getFunctionType(withNoEscape: true)
34+
let newThinToThick = builder.createThinToThickFunction(thinFunction: thinToThick.operand.value,
35+
resultType: noEscapeFnType)
36+
uses.replaceAll(with: newThinToThick, context)
37+
context.erase(instruction: self)
38+
}
39+
}
40+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//===--- SimplifyCopyValue.swift ------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2023 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
import SIL
14+
15+
extension CopyValueInst : OnoneSimplifyable, SILCombineSimplifyable {
16+
func simplify(_ context: SimplifyContext) {
17+
if fromValue.ownership == .none {
18+
uses.replaceAll(with: fromValue, context)
19+
context.erase(instruction: self)
20+
}
21+
}
22+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//===--- SimplifyDestroyValue.swift ---------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2023 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
import SIL
14+
15+
extension DestroyValueInst : OnoneSimplifyable, SILCombineSimplifyable {
16+
func simplify(_ context: SimplifyContext) {
17+
if destroyedValue.ownership == .none {
18+
context.erase(instruction: self)
19+
}
20+
}
21+
}

SwiftCompilerSources/Sources/Optimizer/PassManager/PassRegistration.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ private func registerSwiftPasses() {
9797
registerForSILCombine(RetainValueInst.self, { run(RetainValueInst.self, $0) })
9898
registerForSILCombine(ReleaseValueInst.self, { run(ReleaseValueInst.self, $0) })
9999
registerForSILCombine(LoadInst.self, { run(LoadInst.self, $0) })
100+
registerForSILCombine(CopyValueInst.self, { run(CopyValueInst.self, $0) })
101+
registerForSILCombine(DestroyValueInst.self, { run(DestroyValueInst.self, $0) })
100102

101103
// Test passes
102104
registerPass(functionUsesDumper, { functionUsesDumper.run($0) })

SwiftCompilerSources/Sources/SIL/Builder.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,11 @@ public struct Builder {
220220
return notifyNew(enumInst.getAs(EnumInst.self))
221221
}
222222

223+
public func createThinToThickFunction(thinFunction: Value, resultType: Type) -> ThinToThickFunctionInst {
224+
let tttf = bridged.createThinToThickFunction(thinFunction.bridged, resultType.bridged)
225+
return notifyNew(tttf.getAs(ThinToThickFunctionInst.self))
226+
}
227+
223228
@discardableResult
224229
public func createSwitchEnum(enum enumVal: Value,
225230
cases: [(Int, BasicBlock)],

SwiftCompilerSources/Sources/SIL/Instruction.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -794,6 +794,11 @@ class ConvertFunctionInst : SingleValueInstruction, ConversionInstruction {
794794
final public
795795
class ThinToThickFunctionInst : SingleValueInstruction, ConversionInstruction {}
796796

797+
final public
798+
class ConvertEscapeToNoEscapeInst : SingleValueInstruction, UnaryInstruction {
799+
public var fromFunction: Value { operand.value }
800+
}
801+
797802
final public
798803
class ObjCExistentialMetatypeToObjectInst : SingleValueInstruction,
799804
ConversionInstruction {}

SwiftCompilerSources/Sources/SIL/Registration.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ public func registerSILClasses() {
131131
register(UnconditionalCheckedCastInst.self)
132132
register(ConvertFunctionInst.self)
133133
register(ThinToThickFunctionInst.self)
134+
register(ConvertEscapeToNoEscapeInst.self)
134135
register(ObjCExistentialMetatypeToObjectInst.self)
135136
register(ObjCMetatypeToObjectInst.self)
136137
register(ValueToBridgeObjectInst.self)

SwiftCompilerSources/Sources/SIL/Type.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,10 @@ public struct Type : CustomStringConvertible, NoReflectionChildren {
111111
return idx >= 0 ? idx : nil
112112
}
113113

114+
public func getFunctionType(withNoEscape: Bool) -> Type {
115+
bridged.getFunctionTypeWithNoEscape(withNoEscape).type
116+
}
117+
114118
public var description: String {
115119
String(taking: bridged.getDebugDescription())
116120
}

0 commit comments

Comments
 (0)