Skip to content

Commit 83e9777

Browse files
committed
EscapeAnalysis: refactoring so that we don't have to store a pointer to EscapeAnalysis in ConnectionGraph.
NFC
1 parent c25ed8c commit 83e9777

File tree

2 files changed

+68
-58
lines changed

2 files changed

+68
-58
lines changed

include/swift/SILAnalysis/EscapeAnalysis.h

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -329,9 +329,6 @@ class EscapeAnalysis : public SILAnalysis {
329329
/// Backlink to the graph's function.
330330
SILFunction *F;
331331

332-
/// Backlink to the parent escape analysis.
333-
EscapeAnalysis *EA;
334-
335332
/// Mapping from pointer SIL values to nodes in the graph. Such a value can
336333
/// never be a projection, because in case of projection-instruction the
337334
/// based operand value is used instead.
@@ -412,7 +409,7 @@ class EscapeAnalysis : public SILAnalysis {
412409

413410
public:
414411
/// Constructs a connection graph for a function.
415-
ConnectionGraph(SILFunction *F, EscapeAnalysis *EA) : F(F), EA(EA) {
412+
ConnectionGraph(SILFunction *F) : F(F) {
416413
}
417414

418415
bool isValid() const { return Valid; }
@@ -442,12 +439,7 @@ class EscapeAnalysis : public SILAnalysis {
442439
/// taken. This means the node is always created for the "outermost" value
443440
/// where V is contained.
444441
/// Returns null, if V is not a "pointer".
445-
CGNode *getNode(ValueBase *V);
446-
447-
/// Gets or creates a node for a SILValue (same as above).
448-
CGNode *getNode(SILValue V) {
449-
return getNode(V.getDef());
450-
}
442+
CGNode *getOrCreateNode(ValueBase *V);
451443

452444
/// Gets or creates a content node to which \a AddrNode points to.
453445
CGNode *getContentNode(CGNode *AddrNode);
@@ -505,12 +497,6 @@ class EscapeAnalysis : public SILAnalysis {
505497
getContentNode(Node);
506498
}
507499

508-
/// If V is a pointer, set it to global escaping.
509-
void setEscapesGlobal(SILValue V) {
510-
if (CGNode *Node = getNode(V))
511-
setEscapesGlobal(Node);
512-
}
513-
514500
/// Creates a defer-edge between \p From and \p To.
515501
/// This may invalidate the graph invariance 4). See addDeferEdge.
516502
bool defer(CGNode *From, CGNode *To) {
@@ -593,6 +579,24 @@ class EscapeAnalysis : public SILAnalysis {
593579
/// See EscapeAnalysis::NodeType::Value.
594580
bool isPointer(ValueBase *V);
595581

582+
/// Gets or creates a node for a value \p V.
583+
/// If V is a projection(-path) then the base of the projection(-path) is
584+
/// taken. This means the node is always created for the "outermost" value
585+
/// where V is contained.
586+
/// Returns null, if V is not a "pointer".
587+
CGNode *getNode(ConnectionGraph *ConGraph, ValueBase *V);
588+
589+
/// Gets or creates a node for a SILValue (same as above).
590+
CGNode *getNode(ConnectionGraph *ConGraph, SILValue V) {
591+
return getNode(ConGraph, V.getDef());
592+
}
593+
594+
/// If V is a pointer, set it to global escaping.
595+
void setEscapesGlobal(ConnectionGraph *ConGraph, SILValue V) {
596+
if (CGNode *Node = getNode(ConGraph, V))
597+
ConGraph->setEscapesGlobal(Node);
598+
}
599+
596600
/// Builds the connection graph for a function, but does not handle applys to
597601
/// known callees. This is done afterwards by mergeAllCallees.
598602
void buildConnectionGraph(SILFunction *F, ConnectionGraph *ConGraph);

lib/SILAnalysis/EscapeAnalysis.cpp

Lines changed: 48 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -76,18 +76,8 @@ void EscapeAnalysis::ConnectionGraph::invalidate() {
7676
assert(!NeedMergeCallees);
7777
}
7878

79-
EscapeAnalysis::CGNode *EscapeAnalysis::ConnectionGraph::getNode(ValueBase *V) {
80-
if (isa<FunctionRefInst>(V))
81-
return nullptr;
82-
83-
if (!V->hasValue())
84-
return nullptr;
85-
86-
if (!EA->isPointer(V))
87-
return nullptr;
88-
89-
V = skipProjections(V);
90-
79+
EscapeAnalysis::CGNode *EscapeAnalysis::ConnectionGraph::
80+
getOrCreateNode(ValueBase *V) {
9181
CGNode * &Node = Values2Nodes[V];
9282
if (!Node) {
9383
if (SILArgument *Arg = dyn_cast<SILArgument>(V)) {
@@ -923,6 +913,22 @@ bool EscapeAnalysis::isPointer(ValueBase *V) {
923913
return IP;
924914
}
925915

916+
EscapeAnalysis::CGNode *EscapeAnalysis::getNode(ConnectionGraph *ConGraph,
917+
ValueBase *V) {
918+
if (isa<FunctionRefInst>(V))
919+
return nullptr;
920+
921+
if (!V->hasValue())
922+
return nullptr;
923+
924+
if (!isPointer(V))
925+
return nullptr;
926+
927+
V = skipProjections(V);
928+
929+
return ConGraph->getOrCreateNode(V);
930+
}
931+
926932
void EscapeAnalysis::buildConnectionGraph(SILFunction *F,
927933
ConnectionGraph *ConGraph) {
928934
// We use a worklist for iteration to visit the blocks in dominance order.
@@ -952,7 +958,7 @@ void EscapeAnalysis::buildConnectionGraph(SILFunction *F,
952958
// Create defer-edges from the block arguments to it's values in the
953959
// predecessor's terminator instructions.
954960
for (SILArgument *BBArg : BB.getBBArgs()) {
955-
CGNode *ArgNode = ConGraph->getNode(BBArg);
961+
CGNode *ArgNode = getNode(ConGraph, BBArg);
956962
if (!ArgNode)
957963
continue;
958964

@@ -965,7 +971,7 @@ void EscapeAnalysis::buildConnectionGraph(SILFunction *F,
965971
}
966972

967973
for (SILValue Src : Incoming) {
968-
CGNode *SrcArg = ConGraph->getNode(Src);
974+
CGNode *SrcArg = getNode(ConGraph, Src);
969975
if (SrcArg) {
970976
ConGraph->defer(ArgNode, SrcArg);
971977
} else {
@@ -1017,20 +1023,20 @@ void EscapeAnalysis::analyzeInstruction(SILInstruction *I,
10171023
// array.uninitialized may have a first argument which is the
10181024
// allocated array buffer. The call is like a struct(buffer)
10191025
// instruction.
1020-
if (CGNode *BufferNode = ConGraph->getNode(FAS.getArgument(0))) {
1021-
ConGraph->defer(ConGraph->getNode(I), BufferNode);
1026+
if (CGNode *BufferNode = getNode(ConGraph, FAS.getArgument(0))) {
1027+
ConGraph->defer(getNode(ConGraph, I), BufferNode);
10221028
}
10231029
return;
10241030
case ArrayCallKind::kGetArrayOwner:
1025-
if (CGNode *BufferNode = ConGraph->getNode(ASC.getSelf())) {
1026-
ConGraph->defer(ConGraph->getNode(I), BufferNode);
1031+
if (CGNode *BufferNode = getNode(ConGraph, ASC.getSelf())) {
1032+
ConGraph->defer(getNode(ConGraph, I), BufferNode);
10271033
}
10281034
return;
10291035
case ArrayCallKind::kGetElement:
10301036
// This is like a load from a ref_element_addr.
10311037
if (FAS.getArgument(0).getType().isAddress()) {
1032-
if (CGNode *AddrNode = ConGraph->getNode(ASC.getSelf())) {
1033-
if (CGNode *DestNode = ConGraph->getNode(FAS.getArgument(0))) {
1038+
if (CGNode *AddrNode = getNode(ConGraph, ASC.getSelf())) {
1039+
if (CGNode *DestNode = getNode(ConGraph, FAS.getArgument(0))) {
10341040
// One content node for going from the array buffer pointer to
10351041
// the element address (like ref_element_addr).
10361042
CGNode *RefElement = ConGraph->getContentNode(AddrNode);
@@ -1046,8 +1052,8 @@ void EscapeAnalysis::analyzeInstruction(SILInstruction *I,
10461052
break;
10471053
case ArrayCallKind::kGetElementAddress:
10481054
// This is like a ref_element_addr.
1049-
if (CGNode *SelfNode = ConGraph->getNode(ASC.getSelf())) {
1050-
ConGraph->defer(ConGraph->getNode(I),
1055+
if (CGNode *SelfNode = getNode(ConGraph, ASC.getSelf())) {
1056+
ConGraph->defer(getNode(ConGraph, I),
10511057
ConGraph->getContentNode(SelfNode));
10521058
}
10531059
return;
@@ -1096,7 +1102,7 @@ void EscapeAnalysis::analyzeInstruction(SILInstruction *I,
10961102
case ValueKind::ReleaseValueInst:
10971103
case ValueKind::UnownedReleaseInst: {
10981104
SILValue OpV = I->getOperand(0);
1099-
if (CGNode *AddrNode = ConGraph->getNode(OpV)) {
1105+
if (CGNode *AddrNode = getNode(ConGraph, OpV)) {
11001106
// A release instruction may deallocate the pointer operand. This may
11011107
// capture any content of the released object, but not the pointer to
11021108
// the object itself (because it will be a dangling pointer after
@@ -1115,10 +1121,10 @@ void EscapeAnalysis::analyzeInstruction(SILInstruction *I,
11151121
// We treat ref_element_addr like a load (see NodeType::Content).
11161122
case ValueKind::RefElementAddrInst:
11171123
if (isPointer(I)) {
1118-
CGNode *AddrNode = ConGraph->getNode(I->getOperand(0));
1124+
CGNode *AddrNode = getNode(ConGraph, I->getOperand(0));
11191125
if (!AddrNode) {
11201126
// A load from an address we don't handle -> be conservative.
1121-
CGNode *ValueNode = ConGraph->getNode(I);
1127+
CGNode *ValueNode = getNode(ConGraph, I);
11221128
ConGraph->setEscapesGlobal(ValueNode);
11231129
return;
11241130
}
@@ -1130,8 +1136,8 @@ void EscapeAnalysis::analyzeInstruction(SILInstruction *I,
11301136
return;
11311137
case ValueKind::StoreInst:
11321138
case ValueKind::StoreWeakInst:
1133-
if (CGNode *ValueNode = ConGraph->getNode(I->getOperand(StoreInst::Src))) {
1134-
CGNode *AddrNode = ConGraph->getNode(I->getOperand(StoreInst::Dest));
1139+
if (CGNode *ValueNode = getNode(ConGraph, I->getOperand(StoreInst::Src))) {
1140+
CGNode *AddrNode = getNode(ConGraph, I->getOperand(StoreInst::Dest));
11351141
if (AddrNode) {
11361142
// Create a defer-edge from the content to the stored value.
11371143
CGNode *PointsTo = ConGraph->getContentNode(AddrNode);
@@ -1146,10 +1152,10 @@ void EscapeAnalysis::analyzeInstruction(SILInstruction *I,
11461152
// The result of a partial_apply is a thick function which stores the
11471153
// boxed partial applied arguments. We create defer-edges from the
11481154
// partial_apply values to the arguments.
1149-
CGNode *ResultNode = ConGraph->getNode(I);
1155+
CGNode *ResultNode = getNode(ConGraph, I);
11501156
assert(ResultNode && "thick functions must have a CG node");
11511157
for (const Operand &Op : I->getAllOperands()) {
1152-
if (CGNode *ArgNode = ConGraph->getNode(Op.get())) {
1158+
if (CGNode *ArgNode = getNode(ConGraph, Op.get())) {
11531159
ConGraph->defer(ResultNode, ArgNode);
11541160
}
11551161
}
@@ -1162,7 +1168,7 @@ void EscapeAnalysis::analyzeInstruction(SILInstruction *I,
11621168
// resulting aggregate value.
11631169
CGNode *ResultNode = nullptr;
11641170
for (const Operand &Op : I->getAllOperands()) {
1165-
if (CGNode *FieldNode = ConGraph->getNode(Op.get())) {
1171+
if (CGNode *FieldNode = getNode(ConGraph, Op.get())) {
11661172
if (!ResultNode) {
11671173
// A small optimization to reduce the graph size: we re-use the
11681174
// first field node as result node.
@@ -1178,12 +1184,12 @@ void EscapeAnalysis::analyzeInstruction(SILInstruction *I,
11781184
}
11791185
case ValueKind::UncheckedRefCastInst:
11801186
// A cast is almost like a projection.
1181-
if (CGNode *OpNode = ConGraph->getNode(I->getOperand(0))) {
1187+
if (CGNode *OpNode = getNode(ConGraph, I->getOperand(0))) {
11821188
ConGraph->setNode(I, OpNode);
11831189
}
11841190
break;
11851191
case ValueKind::ReturnInst:
1186-
if (CGNode *ValueNd = ConGraph->getNode(cast<ReturnInst>(I)->getOperand())) {
1192+
if (CGNode *ValueNd = getNode(ConGraph, cast<ReturnInst>(I)->getOperand())) {
11871193
ConGraph->defer(ConGraph->getReturnNode(),
11881194
ValueNd);
11891195
}
@@ -1210,8 +1216,8 @@ bool EscapeAnalysis::isArrayOrArrayStorage(SILValue V) {
12101216
void EscapeAnalysis::setAllEscaping(SILInstruction *I,
12111217
ConnectionGraph *ConGraph) {
12121218
if (auto *TAI = dyn_cast<TryApplyInst>(I)) {
1213-
ConGraph->setEscapesGlobal(TAI->getNormalBB()->getBBArg(0));
1214-
ConGraph->setEscapesGlobal(TAI->getErrorBB()->getBBArg(0));
1219+
setEscapesGlobal(ConGraph, TAI->getNormalBB()->getBBArg(0));
1220+
setEscapesGlobal(ConGraph, TAI->getErrorBB()->getBBArg(0));
12151221
}
12161222
// Even if the instruction does not write memory we conservatively set all
12171223
// operands to escaping, because they may "escape" to the result value in
@@ -1220,11 +1226,11 @@ void EscapeAnalysis::setAllEscaping(SILInstruction *I,
12201226
for (const Operand &Op : I->getAllOperands()) {
12211227
SILValue OpVal = Op.get();
12221228
if (!isNonWritableMemoryAddress(OpVal.getDef()))
1223-
ConGraph->setEscapesGlobal(OpVal);
1229+
setEscapesGlobal(ConGraph, OpVal);
12241230
}
12251231
// Even if the instruction does not write memory it could e.g. return the
12261232
// address of global memory. Therefore we have to define it as escaping.
1227-
ConGraph->setEscapesGlobal(I);
1233+
setEscapesGlobal(ConGraph, I);
12281234
}
12291235

12301236
void EscapeAnalysis::recompute() {
@@ -1256,7 +1262,7 @@ void EscapeAnalysis::recompute() {
12561262

12571263
DEBUG(llvm::dbgs() << " build initial graph for " << F->getName() << '\n');
12581264

1259-
auto *ConGraph = new (Allocator.Allocate()) ConnectionGraph(F, this);
1265+
auto *ConGraph = new (Allocator.Allocate()) ConnectionGraph(F);
12601266
Function2ConGraph[F] = ConGraph;
12611267
buildConnectionGraph(F, ConGraph);
12621268

@@ -1348,8 +1354,8 @@ bool EscapeAnalysis::mergeCalleeGraph(FullApplySite FAS,
13481354
// of the apply site.
13491355
SILValue CallerArg = (Idx < numCallerArgs ? FAS.getArgument(Idx) :
13501356
FAS.getCallee());
1351-
if (CGNode *CalleeNd = CalleeGraph->getNode(Callee->getArgument(Idx))) {
1352-
Callee2CallerMapping.add(CalleeNd, CallerGraph->getNode(CallerArg));
1357+
if (CGNode *CalleeNd = getNode(CalleeGraph, Callee->getArgument(Idx))) {
1358+
Callee2CallerMapping.add(CalleeNd, getNode(CallerGraph, CallerArg));
13531359
}
13541360
}
13551361

@@ -1361,7 +1367,7 @@ bool EscapeAnalysis::mergeCalleeGraph(FullApplySite FAS,
13611367
} else {
13621368
CallerReturnVal = FAS.getInstruction();
13631369
}
1364-
CGNode *CallerRetNd = CallerGraph->getNode(CallerReturnVal);
1370+
CGNode *CallerRetNd = getNode(CallerGraph, CallerReturnVal);
13651371
Callee2CallerMapping.add(RetNd, CallerRetNd);
13661372
}
13671373
return CallerGraph->mergeFrom(CalleeGraph, Callee2CallerMapping);
@@ -1374,8 +1380,8 @@ void EscapeAnalysis::createSummaryGraph(ConnectionGraph *SummaryGraph,
13741380
CGNodeMap Mapping;
13751381
SILFunction *F = Graph->getFunction();
13761382
for (SILArgument *Arg : F->getArguments()) {
1377-
if (CGNode *ArgNd = Graph->getNode(Arg)) {
1378-
Mapping.add(ArgNd, SummaryGraph->getNode(Arg));
1383+
if (CGNode *ArgNd = getNode(Graph, Arg)) {
1384+
Mapping.add(ArgNd, getNode(SummaryGraph, Arg));
13791385
}
13801386
}
13811387
if (CGNode *RetNd = Graph->getReturnNodeOrNull()) {

0 commit comments

Comments
 (0)