Skip to content

Commit 1d4adee

Browse files
committed
swift side effects: add CalleeAnalysis.getSideEffects(of: apply)
1 parent 65a9165 commit 1d4adee

File tree

5 files changed

+80
-0
lines changed

5 files changed

+80
-0
lines changed

SwiftCompilerSources/Sources/Optimizer/Analysis/CalleeAnalysis.swift

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,51 @@ public struct CalleeAnalysis {
4343
}
4444
return FunctionArray(bridged: bridgedDtors)
4545
}
46+
47+
/// Returns the global (i.e. not argument specific) side effects of an apply.
48+
public func getSideEffects(of apply: ApplySite) -> SideEffects.GlobalEffects {
49+
guard let callees = getCallees(callee: apply.callee) else {
50+
return .worstEffects
51+
}
52+
53+
var result = SideEffects.GlobalEffects()
54+
for callee in callees {
55+
let calleeEffects = callee.getSideEffects()
56+
result.merge(with: calleeEffects)
57+
}
58+
return result
59+
}
60+
61+
/// Returns the argument specific side effects of an apply.
62+
public func getSideEffects(of apply: ApplySite, forArgument argumentIdx: Int, path: SmallProjectionPath) -> SideEffects.GlobalEffects {
63+
let calleeArgIdx = apply.calleeArgIndex(callerArgIndex: argumentIdx)
64+
let convention = apply.getArgumentConvention(calleeArgIndex: calleeArgIdx)
65+
let argument = apply.arguments[argumentIdx].at(path)
66+
67+
guard let callees = getCallees(callee: apply.callee) else {
68+
return .worstEffects.restrictedTo(argument: argument, withConvention: convention)
69+
}
70+
71+
var result = SideEffects.GlobalEffects()
72+
for callee in callees {
73+
let calleeEffects = callee.getSideEffects(forArgument: argument,
74+
atIndex: calleeArgIdx,
75+
withConvention: convention)
76+
result.merge(with: calleeEffects)
77+
}
78+
return result.restrictedTo(argument: argument, withConvention: convention)
79+
}
80+
81+
static func register() {
82+
CalleeAnalysis_register(
83+
// getMemBehaviorFn
84+
{ (bridgedCtxt: BridgedPassContext, bridgedApply: BridgedInstruction, observeRetains: Bool) -> BridgedMemoryBehavior in
85+
let context = PassContext(_bridged: bridgedCtxt)
86+
let apply = bridgedApply.instruction as! ApplySite
87+
let e = context.calleeAnalysis.getSideEffects(of: apply)
88+
return e.getMemBehavior(observeRetains: observeRetains)
89+
})
90+
}
4691
}
4792

4893
public struct FunctionArray : RandomAccessCollection, FormattedLikeArray {

SwiftCompilerSources/Sources/Optimizer/PassManager/PassRegistration.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import Parse
1717
@_cdecl("initializeSwiftModules")
1818
public func initializeSwiftModules() {
1919
registerSILClasses()
20+
registerAnalysis()
2021
registerSwiftPasses()
2122
initializeSwiftParseModules()
2223
}
@@ -45,6 +46,10 @@ private func registerPass<InstType: Instruction>(
4546
}
4647
}
4748

49+
private func registerAnalysis() {
50+
CalleeAnalysis.register()
51+
}
52+
4853
private func registerSwiftPasses() {
4954
// Module passes
5055
registerPass(stackProtection, { stackProtection.run($0) })

include/swift/SILOptimizer/Analysis/BasicCalleeAnalysis.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ class ClassDecl;
3131
class SILFunction;
3232
class SILModule;
3333
class SILWitnessTable;
34+
class SILPassManager;
3435

3536
/// CalleeList is a data structure representing the list of potential
3637
/// callees at a particular apply site. It also has a query that
@@ -166,16 +167,20 @@ class CalleeCache {
166167

167168
class BasicCalleeAnalysis : public SILAnalysis {
168169
SILModule &M;
170+
SILPassManager *pm = nullptr;
169171
std::unique_ptr<CalleeCache> Cache;
170172

171173
public:
174+
172175
BasicCalleeAnalysis(SILModule *M)
173176
: SILAnalysis(SILAnalysisKind::BasicCallee), M(*M), Cache(nullptr) {}
174177

175178
static bool classof(const SILAnalysis *S) {
176179
return S->getKind() == SILAnalysisKind::BasicCallee;
177180
}
178181

182+
virtual void initialize(SILPassManager *pm) override { this->pm = pm; }
183+
179184
/// Invalidate all information in this analysis.
180185
virtual void invalidate() override {
181186
Cache.reset();
@@ -228,6 +233,8 @@ class BasicCalleeAnalysis : public SILAnalysis {
228233
updateCache();
229234
return Cache->getDestructors(type, isExactType);
230235
}
236+
237+
SILInstruction::MemoryBehavior getMemoryBehavior(ApplySite as, bool observeRetains);
231238
};
232239

233240
} // end namespace swift

include/swift/SILOptimizer/OptimizerBridging.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,11 @@ SwiftInt PostDominatorTree_postDominates(BridgedPostDomTree pdomTree,
128128
BridgedBasicBlock dominating,
129129
BridgedBasicBlock dominated);
130130

131+
typedef BridgedMemoryBehavior(* _Nonnull CalleeAnalysisGetMemBehvaiorFn)(
132+
BridgedPassContext context, BridgedInstruction apply, bool observeRetains);
133+
134+
void CalleeAnalysis_register(CalleeAnalysisGetMemBehvaiorFn getEffectsFn);
135+
131136
BridgedSlab PassContext_getNextSlab(BridgedSlab slab);
132137
BridgedSlab PassContext_getPreviousSlab(BridgedSlab slab);
133138
BridgedSlab PassContext_allocSlab(BridgedPassContext passContext,

lib/SILOptimizer/Analysis/BasicCalleeAnalysis.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@
2727

2828
using namespace swift;
2929

30+
// Bridging functions.
31+
static CalleeAnalysisGetMemBehvaiorFn getMemBehvaiorFunction = nullptr;
32+
3033
void CalleeList::dump() const {
3134
print(llvm::errs());
3235
}
@@ -311,6 +314,17 @@ CalleeList CalleeCache::getDestructors(SILType type, bool isExactType) const {
311314
return getCalleeList(SILDeclRef(classDecl->getDestructor()));
312315
}
313316

317+
SILInstruction::MemoryBehavior BasicCalleeAnalysis::
318+
getMemoryBehavior(ApplySite as, bool observeRetains) {
319+
if (getMemBehvaiorFunction) {
320+
auto b = getMemBehvaiorFunction({pm->getSwiftPassInvocation()},
321+
{as.getInstruction()->asSILNode()},
322+
observeRetains);
323+
return (SILInstruction::MemoryBehavior)b;
324+
}
325+
return SILInstruction::MemoryBehavior::MayHaveSideEffects;
326+
}
327+
314328
void BasicCalleeAnalysis::dump() const {
315329
print(llvm::errs());
316330
}
@@ -334,6 +348,10 @@ void BasicCalleeAnalysis::print(llvm::raw_ostream &os) const {
334348
// Swift Bridging
335349
//===----------------------------------------------------------------------===//
336350

351+
void CalleeAnalysis_register(CalleeAnalysisGetMemBehvaiorFn getMemBehvaiorFn) {
352+
getMemBehvaiorFunction = getMemBehvaiorFn;
353+
}
354+
337355
BridgedCalleeList CalleeAnalysis_getCallees(BridgedCalleeAnalysis calleeAnalysis,
338356
BridgedValue callee) {
339357
BasicCalleeAnalysis *bca = static_cast<BasicCalleeAnalysis *>(calleeAnalysis.bca);

0 commit comments

Comments
 (0)