Skip to content

Commit 7db7065

Browse files
committed
swift side effects: add CalleeAnalysis.getSideEffects(of: apply)
1 parent 698196b commit 7db7065

File tree

4 files changed

+67
-2
lines changed

4 files changed

+67
-2
lines changed

SwiftCompilerSources/Sources/Optimizer/Analysis/CalleeAnalysis.swift

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,13 @@ public struct CalleeAnalysis {
2121
// isDeinitBarrierFn:
2222
{ (inst : BridgedInstruction, bca: BridgedCalleeAnalysis) -> Bool in
2323
return inst.instruction.isDeinitBarrier(bca.analysis)
24+
},
25+
// getMemBehaviorFn
26+
{ (bridgedCtxt: BridgedPassContext, bridgedApply: BridgedInstruction, observeRetains: Bool) -> BridgedMemoryBehavior in
27+
let context = PassContext(_bridged: bridgedCtxt)
28+
let apply = bridgedApply.instruction as! ApplySite
29+
let e = context.calleeAnalysis.getSideEffects(of: apply)
30+
return e.getMemBehavior(observeRetains: observeRetains)
2431
}
2532
)
2633
}
@@ -52,6 +59,40 @@ public struct CalleeAnalysis {
5259
}
5360
return FunctionArray(bridged: bridgedDtors)
5461
}
62+
63+
/// Returns the global (i.e. not argument specific) side effects of an apply.
64+
public func getSideEffects(of apply: ApplySite) -> SideEffects.GlobalEffects {
65+
guard let callees = getCallees(callee: apply.callee) else {
66+
return .worstEffects
67+
}
68+
69+
var result = SideEffects.GlobalEffects()
70+
for callee in callees {
71+
let calleeEffects = callee.getSideEffects()
72+
result.merge(with: calleeEffects)
73+
}
74+
return result
75+
}
76+
77+
/// Returns the argument specific side effects of an apply.
78+
public func getSideEffects(of apply: ApplySite, forArgument argumentIdx: Int, path: SmallProjectionPath) -> SideEffects.GlobalEffects {
79+
let calleeArgIdx = apply.calleeArgIndex(callerArgIndex: argumentIdx)
80+
let convention = apply.getArgumentConvention(calleeArgIndex: calleeArgIdx)
81+
let argument = apply.arguments[argumentIdx].at(path)
82+
83+
guard let callees = getCallees(callee: apply.callee) else {
84+
return .worstEffects.restrictedTo(argument: argument, withConvention: convention)
85+
}
86+
87+
var result = SideEffects.GlobalEffects()
88+
for callee in callees {
89+
let calleeEffects = callee.getSideEffects(forArgument: argument,
90+
atIndex: calleeArgIdx,
91+
withConvention: convention)
92+
result.merge(with: calleeEffects)
93+
}
94+
return result.restrictedTo(argument: argument, withConvention: convention)
95+
}
5596
}
5697

5798
extension FullApplySite {

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
bool isDeinitBarrier(SILInstruction *const instruction,

include/swift/SILOptimizer/OptimizerBridging.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,11 @@ typedef struct {
4141
} BridgedCalleeAnalysis;
4242

4343
typedef bool (* _Nonnull InstructionIsDeinitBarrierFn)(BridgedInstruction, BridgedCalleeAnalysis bca);
44+
typedef BridgedMemoryBehavior(* _Nonnull CalleeAnalysisGetMemBehvaiorFn)(
45+
BridgedPassContext context, BridgedInstruction apply, bool observeRetains);
4446

45-
void CalleeAnalysis_register(InstructionIsDeinitBarrierFn isDeinitBarrierFn);
47+
void CalleeAnalysis_register(InstructionIsDeinitBarrierFn isDeinitBarrierFn,
48+
CalleeAnalysisGetMemBehvaiorFn getEffectsFn);
4649

4750
typedef struct {
4851
void * _Nullable dea;

lib/SILOptimizer/Analysis/BasicCalleeAnalysis.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -367,10 +367,24 @@ BridgedFunction BridgedFunctionArray_get(BridgedCalleeList callees,
367367
}
368368

369369
static InstructionIsDeinitBarrierFn instructionIsDeinitBarrierFunction;
370+
static CalleeAnalysisGetMemBehvaiorFn getMemBehvaiorFunction = nullptr;
370371

371372
void CalleeAnalysis_register(
372-
InstructionIsDeinitBarrierFn instructionIsDeinitBarrierFn) {
373+
InstructionIsDeinitBarrierFn instructionIsDeinitBarrierFn,
374+
CalleeAnalysisGetMemBehvaiorFn getMemBehvaiorFn) {
373375
instructionIsDeinitBarrierFunction = instructionIsDeinitBarrierFn;
376+
getMemBehvaiorFunction = getMemBehvaiorFn;
377+
}
378+
379+
SILInstruction::MemoryBehavior BasicCalleeAnalysis::
380+
getMemoryBehavior(ApplySite as, bool observeRetains) {
381+
if (getMemBehvaiorFunction) {
382+
auto b = getMemBehvaiorFunction({pm->getSwiftPassInvocation()},
383+
{as.getInstruction()->asSILNode()},
384+
observeRetains);
385+
return (SILInstruction::MemoryBehavior)b;
386+
}
387+
return SILInstruction::MemoryBehavior::MayHaveSideEffects;
374388
}
375389

376390
/// Implementation of mayBeDeinitBarrierNotConsideringSideEffects for use only

0 commit comments

Comments
 (0)