Skip to content

Commit 90c71ad

Browse files
committed
libswift: improve and simplify pass invocation
* unify FunctionPassContext and InstructionPassContext * add a modification API: PassContext.setOperand * automatic invalidation notifications when the SIL is modified
1 parent edf0ba0 commit 90c71ad

File tree

11 files changed

+97
-68
lines changed

11 files changed

+97
-68
lines changed

include/swift/SIL/SILBridging.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,8 @@ OptionalBridgedInstruction SILInstruction_next(BridgedInstruction inst);
191191
OptionalBridgedInstruction SILInstruction_previous(BridgedInstruction inst);
192192
BridgedBasicBlock SILInstruction_getParent(BridgedInstruction inst);
193193
BridgedArrayRef SILInstruction_getOperands(BridgedInstruction inst);
194+
void SILInstruction_setOperand(BridgedInstruction inst, SwiftInt index,
195+
BridgedValue value);
194196
BridgedLocation SILInstruction_getLocation(BridgedInstruction inst);
195197
BridgedMemoryBehavior SILInstruction_getMemBehavior(BridgedInstruction inst);
196198

include/swift/SILOptimizer/OptimizerBridging.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,9 @@ void SILPassManager_registerFunctionPass(BridgedStringRef name,
5252
void SILCombine_registerInstructionPass(BridgedStringRef name,
5353
BridgedInstructionPassRunFn runFn);
5454

55-
BridgedAliasAnalysis PassContext_getAliasAnalysis(BridgedPassContext context,
56-
BridgedFunction function);
55+
SwiftInt PassContext_isSwift51RuntimeAvailable(BridgedPassContext context);
56+
57+
BridgedAliasAnalysis PassContext_getAliasAnalysis(BridgedPassContext context);
5758

5859
BridgedMemoryBehavior AliasAnalysis_getMemBehavior(BridgedAliasAnalysis aa,
5960
BridgedInstruction inst,

include/swift/SILOptimizer/PassManager/PassManager.h

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,19 +48,28 @@ void executePassPipelinePlan(SILModule *SM, const SILPassPipelinePlan &plan,
4848
class LibswiftPassInvocation {
4949
/// Backlink to the pass manager.
5050
SILPassManager *passManager;
51-
51+
52+
/// The currently optimized function.
53+
SILFunction *function = nullptr;
54+
5255
/// Non-null if this is an instruction pass, invoked from SILCombine.
53-
SILCombiner *silCombiner;
56+
SILCombiner *silCombiner = nullptr;
5457

5558
/// All slabs, allocated by the pass.
5659
SILModule::SlabList allocatedSlabs;
5760

5861
public:
59-
LibswiftPassInvocation(SILPassManager *passManager, SILCombiner *silCombiner) :
60-
passManager(passManager), silCombiner(silCombiner) {}
62+
LibswiftPassInvocation(SILPassManager *passManager, SILFunction *function,
63+
SILCombiner *silCombiner) :
64+
passManager(passManager), function(function), silCombiner(silCombiner) {}
65+
66+
LibswiftPassInvocation(SILPassManager *passManager) :
67+
passManager(passManager) {}
6168

6269
SILPassManager *getPassManager() const { return passManager; }
6370

71+
SILFunction *getFunction() const { return function; }
72+
6473
FixedSizeSlab *allocSlab(FixedSizeSlab *afterSlab);
6574

6675
FixedSizeSlab *freeSlab(FixedSizeSlab *slab);
@@ -71,6 +80,9 @@ class LibswiftPassInvocation {
7180
/// Called by the pass when changes are made to the SIL.
7281
void notifyChanges(SILAnalysis::InvalidationKind invalidationKind);
7382

83+
/// Called by the pass manager before the pass starts running.
84+
void startPassRun(SILFunction *function);
85+
7486
/// Called by the pass manager when the pass has finished.
7587
void finishedPassRun();
7688
};

lib/SIL/Utils/SILBridging.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,11 @@ BridgedArrayRef SILInstruction_getOperands(BridgedInstruction inst) {
357357
return {(const unsigned char *)operands.data(), operands.size()};
358358
}
359359

360+
void SILInstruction_setOperand(BridgedInstruction inst, SwiftInt index,
361+
BridgedValue value) {
362+
castToInst(inst)->setOperand((unsigned)index, castToSILValue(value));
363+
}
364+
360365
BridgedLocation SILInstruction_getLocation(BridgedInstruction inst) {
361366
SILDebugLocation loc = castToInst(inst)->getDebugLocation();
362367
return *reinterpret_cast<BridgedLocation *>(&loc);

lib/SILOptimizer/PassManager/PassManager.cpp

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,7 @@ void swift::executePassPipelinePlan(SILModule *SM,
322322
SILPassManager::SILPassManager(SILModule *M, bool isMandatory,
323323
irgen::IRGenModule *IRMod)
324324
: Mod(M), IRMod(IRMod),
325-
libswiftPassInvocation(this, /*SILCombiner*/ nullptr),
325+
libswiftPassInvocation(this),
326326
isMandatory(isMandatory), deserializationNotificationHandler(nullptr) {
327327
#define ANALYSIS(NAME) \
328328
Analyses.push_back(create##NAME##Analysis(Mod));
@@ -469,7 +469,9 @@ void SILPassManager::runPassOnFunction(unsigned TransIdx, SILFunction *F) {
469469

470470
assert(changeNotifications == SILAnalysis::InvalidationKind::Nothing
471471
&& "change notifications not cleared");
472-
472+
473+
libswiftPassInvocation.startPassRun(F);
474+
473475
// Run it!
474476
SFT->run();
475477

@@ -1100,8 +1102,14 @@ FixedSizeSlab *LibswiftPassInvocation::freeSlab(FixedSizeSlab *slab) {
11001102
return prev;
11011103
}
11021104

1105+
void LibswiftPassInvocation::startPassRun(SILFunction *function) {
1106+
assert(!this->function && "a pass is already running");
1107+
this->function = function;
1108+
}
1109+
11031110
void LibswiftPassInvocation::finishedPassRun() {
11041111
assert(allocatedSlabs.empty() && "StackList is leaking slabs");
1112+
function = nullptr;
11051113
}
11061114

11071115
//===----------------------------------------------------------------------===//
@@ -1166,10 +1174,17 @@ void PassContext_eraseInstruction(BridgedPassContext passContext,
11661174
castToPassInvocation(passContext)->eraseInstruction(castToInst(inst));
11671175
}
11681176

1169-
BridgedAliasAnalysis PassContext_getAliasAnalysis(BridgedPassContext context,
1170-
BridgedFunction function) {
1177+
SwiftInt PassContext_isSwift51RuntimeAvailable(BridgedPassContext context) {
11711178
SILPassManager *pm = castToPassInvocation(context)->getPassManager();
1172-
return {pm->getAnalysis<AliasAnalysis>(castToFunction(function))};
1179+
ASTContext &ctxt = pm->getModule()->getASTContext();
1180+
return AvailabilityContext::forDeploymentTarget(ctxt).
1181+
isContainedIn(ctxt.getSwift51Availability());
1182+
}
1183+
1184+
BridgedAliasAnalysis PassContext_getAliasAnalysis(BridgedPassContext context) {
1185+
LibswiftPassInvocation *invocation = castToPassInvocation(context);
1186+
SILPassManager *pm = invocation->getPassManager();
1187+
return {pm->getAnalysis<AliasAnalysis>(invocation->getFunction())};
11731188
}
11741189

11751190
BridgedCalleeAnalysis PassContext_getCalleeAnalysis(BridgedPassContext context) {

lib/SILOptimizer/SILCombiner/SILCombiner.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,8 @@ class SILCombiner :
158158
[&](SILInstruction *I) { eraseInstFromFunction(*I); }),
159159
deBlocks(&B.getFunction()),
160160
ownershipFixupContext(getInstModCallbacks(), deBlocks),
161-
libswiftPassInvocation(parentTransform->getPassManager(), this) {}
161+
libswiftPassInvocation(parentTransform->getPassManager(),
162+
parentTransform->getFunction(), this) {}
162163

163164
bool runOnFunction(SILFunction &F);
164165

libswift/Sources/Optimizer/FunctionPasses/MergeCondFails.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ private func hasOverflowConditionOperand(_ cfi: CondFailInst) -> Bool {
2929
/// write in between them.
3030
/// This pass merges cond_fail instructions by building the disjunction of
3131
/// their operands.
32-
private func runMergeCondFails(function: Function, context: FunctionPassContext) {
32+
private func runMergeCondFails(function: Function, context: PassContext) {
3333

3434
// Merge cond_fail instructions if there is no side-effect or read in
3535
// between them.
@@ -59,7 +59,7 @@ private func runMergeCondFails(function: Function, context: FunctionPassContext)
5959
/// Try to merge the cond_fail instructions. Returns true if any could
6060
/// be merge.
6161
private func mergeCondFails(_ condFailToMerge: inout StackList<CondFailInst>,
62-
context: FunctionPassContext) {
62+
context: PassContext) {
6363
guard let lastCFI = condFailToMerge.last else {
6464
return
6565
}

libswift/Sources/Optimizer/FunctionPasses/SILPrinter.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import SIL
1414

1515
let silPrinterPass = FunctionPass(name: "sil-printer", runSILPrinter)
1616

17-
func runSILPrinter(function: Function, context: FunctionPassContext) {
17+
func runSILPrinter(function: Function, context: PassContext) {
1818
print("run SILPrinter on function: \(function.name)")
1919

2020
for (bbIdx, block) in function.blocks.enumerated() {

libswift/Sources/Optimizer/InstructionPasses/SimplifyGlobalValue.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import SIL
1414

1515
let simplifyGlobalValuePass = InstructionPass<GlobalValueInst>(
1616
name: "simplify-global_value", {
17-
(globalValue: GlobalValueInst, context: InstructionPassContext) in
17+
(globalValue: GlobalValueInst, context: PassContext) in
1818

1919
var users = StackList<Instruction>(context)
2020
if checkUsers(of: globalValue, users: &users) {

libswift/Sources/Optimizer/PassManager/PassUtils.swift

Lines changed: 35 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -18,107 +18,96 @@ public typealias BridgedFunctionPassCtxt =
1818
public typealias BridgedInstructionPassCtxt =
1919
OptimizerBridging.BridgedInstructionPassCtxt
2020

21-
struct FunctionPassContext {
21+
struct PassContext {
2222

2323
fileprivate let passContext: BridgedPassContext
24-
fileprivate let function: Function
2524

26-
func erase(instruction: Instruction) {
27-
PassContext_eraseInstruction(passContext, instruction.bridged)
25+
var isSwift51RuntimeAvailable: Bool {
26+
PassContext_isSwift51RuntimeAvailable(passContext) != 0
2827
}
2928

30-
private func notifyChanges(_ kind: ChangeNotificationKind) {
31-
PassContext_notifyChanges(passContext, kind)
32-
}
33-
3429
var aliasAnalysis: AliasAnalysis {
35-
let bridgedAA = PassContext_getAliasAnalysis(passContext, function.bridged)
30+
let bridgedAA = PassContext_getAliasAnalysis(passContext)
3631
return AliasAnalysis(bridged: bridgedAA)
3732
}
3833

3934
var calleeAnalysis: CalleeAnalysis {
4035
let bridgeCA = PassContext_getCalleeAnalysis(passContext)
4136
return CalleeAnalysis(bridged: bridgeCA)
4237
}
38+
39+
func erase(instruction: Instruction) {
40+
if instruction is FullApplySite {
41+
PassContext_notifyChanges(passContext, callsChanged)
42+
}
43+
if instruction is TermInst {
44+
PassContext_notifyChanges(passContext, branchesChanged)
45+
}
46+
PassContext_notifyChanges(passContext, instructionsChanged)
47+
48+
PassContext_eraseInstruction(passContext, instruction.bridged)
49+
}
50+
51+
func setOperand(of instruction: Instruction, at index : Int, to value: Value) {
52+
if instruction is FullApplySite && index == ApplyOperands.calleeOperandIndex {
53+
PassContext_notifyChanges(passContext, callsChanged)
54+
}
55+
PassContext_notifyChanges(passContext, instructionsChanged)
56+
57+
SILInstruction_setOperand(instruction.bridged, index, value.bridged)
58+
}
4359
}
4460

4561
struct FunctionPass {
4662

4763
let name: String
48-
let runFunction: (Function, FunctionPassContext) -> ()
64+
let runFunction: (Function, PassContext) -> ()
4965

5066
public init(name: String,
51-
_ runFunction: @escaping (Function, FunctionPassContext) -> ()) {
67+
_ runFunction: @escaping (Function, PassContext) -> ()) {
5268
self.name = name
5369
self.runFunction = runFunction
5470
}
5571

5672
func run(_ bridgedCtxt: BridgedFunctionPassCtxt) {
5773
let function = bridgedCtxt.function.function
58-
let context = FunctionPassContext(passContext: bridgedCtxt.passContext,
59-
function: function)
74+
let context = PassContext(passContext: bridgedCtxt.passContext)
6075
runFunction(function, context)
6176
}
6277
}
6378

64-
struct InstructionPassContext {
65-
fileprivate let passContext: BridgedPassContext
66-
67-
func erase(instruction: Instruction) {
68-
PassContext_eraseInstruction(passContext, instruction.bridged)
69-
}
70-
71-
private func notifyChanges(_ kind: ChangeNotificationKind) {
72-
PassContext_notifyChanges(passContext, kind)
73-
}
74-
}
75-
7679
struct InstructionPass<InstType: Instruction> {
7780

7881
let name: String
79-
let runFunction: (InstType, InstructionPassContext) -> ()
82+
let runFunction: (InstType, PassContext) -> ()
8083

81-
public init(name: String, _ runFunction: @escaping (InstType, InstructionPassContext) -> ()) {
84+
public init(name: String,
85+
_ runFunction: @escaping (InstType, PassContext) -> ()) {
8286
self.name = name
8387
self.runFunction = runFunction
8488
}
8589

8690
func run(_ bridgedCtxt: BridgedInstructionPassCtxt) {
8791
let inst = bridgedCtxt.instruction.getAs(InstType.self)
88-
let context = InstructionPassContext(passContext: bridgedCtxt.passContext)
92+
let context = PassContext(passContext: bridgedCtxt.passContext)
8993
runFunction(inst, context)
9094
}
9195
}
9296

9397
extension StackList {
94-
init(_ context: FunctionPassContext) {
95-
self.init(context: context.passContext)
96-
}
97-
98-
init(_ context: InstructionPassContext) {
98+
init(_ context: PassContext) {
9999
self.init(context: context.passContext)
100100
}
101101
}
102102

103103
extension Builder {
104104
init(at insPnt: Instruction, location: Location,
105-
_ context: FunctionPassContext) {
106-
self.init(insertionPoint: insPnt, location: location,
107-
passContext: context.passContext)
108-
}
109-
110-
init(at insPnt: Instruction, _ context: FunctionPassContext) {
111-
self.init(insertionPoint: insPnt, location: insPnt.location,
112-
passContext: context.passContext)
113-
}
114-
115-
init(at insPnt: Instruction, location: Location,
116-
_ context: InstructionPassContext) {
105+
_ context: PassContext) {
117106
self.init(insertionPoint: insPnt, location: location,
118107
passContext: context.passContext)
119108
}
120109

121-
init(at insPnt: Instruction, _ context: InstructionPassContext) {
110+
init(at insPnt: Instruction, _ context: PassContext) {
122111
self.init(insertionPoint: insPnt, location: insPnt.location,
123112
passContext: context.passContext)
124113
}

libswift/Sources/SIL/ApplySite.swift

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,24 +10,28 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13+
public struct ApplyOperands {
14+
public static let calleeOperandIndex: Int = 0
15+
public static let firstArgumentIndex = 1
16+
}
17+
1318
public protocol ApplySite : AnyObject {
1419
var operands: OperandArray { get }
1520
var numArguments: Int { get }
1621
}
1722

18-
private let firstArgumentIndex = 1
19-
2023
extension ApplySite {
21-
public var callee: Value { operands[0].value }
24+
public var callee: Value { operands[ApplyOperands.calleeOperandIndex].value }
2225

2326
public func argumentIndex(of operand: Operand) -> Int? {
2427
let opIdx = operand.index
25-
if opIdx >= firstArgumentIndex &&
26-
opIdx <= firstArgumentIndex + numArguments {
27-
return opIdx - firstArgumentIndex
28+
if opIdx >= ApplyOperands.firstArgumentIndex &&
29+
opIdx <= ApplyOperands.firstArgumentIndex + numArguments {
30+
return opIdx - ApplyOperands.firstArgumentIndex
2831
}
2932
return nil
3033
}
34+
3135
}
3236

3337
public protocol FullApplySite : ApplySite {

0 commit comments

Comments
 (0)