@@ -252,16 +252,18 @@ class EscapeAnalysis : public BottomUpIPAnalysis {
252
252
// / pointer points to (see NodeType).
253
253
class CGNode {
254
254
255
- // / The associated value in the function. This is always valid for Argument
256
- // / and Value nodes, and always nullptr for Return nodes. For Content nodes,
257
- // / i is only used for debug printing. A Content's value 'V' is unreliable
258
- // / because it can change as a result of the order the the graph is
259
- // / constructed and summary graphs are merged. Sometimes it is derived from
260
- // / the instructions that access the content, other times, it's simply
261
- // / inherited from its parent. There may be multiple nodes associated to the
262
- // / same value, e.g. a Content node has the same V as its points-to
263
- // / predecessor.
264
- ValueBase *V;
255
+ // / The associated value in the function. This is only valid for nodes that
256
+ // / are mapped to a value in the graph's Values2Nodes map. Multiple values
257
+ // / may be mapped to the same node, but only one value is associated with
258
+ // / the node via 'mappedValue'. Setting 'mappedValue' to a valid SILValue
259
+ // / for an unmapped node would result in a dangling pointer when the
260
+ // / SILValue is deleted.
261
+ // /
262
+ // / Argument and Value nodes are always initially mapped, but may become
263
+ // / unmapped when their SILValue is deleted. Content nodes are conditionally
264
+ // / mapped, only if they are associated with an explicit dereference in the
265
+ // / code (which has not been deleted). Return nodes are never mapped.
266
+ ValueBase *mappedValue;
265
267
266
268
// / The outgoing points-to edge (if any) to a Content node. See also:
267
269
// / pointsToIsEdge.
@@ -317,7 +319,7 @@ class EscapeAnalysis : public BottomUpIPAnalysis {
317
319
318
320
// / The constructor.
319
321
CGNode (ValueBase *V, NodeType Type, bool hasRC)
320
- : V (V), UsePoints(0 ), hasRC(hasRC), Type(Type) {
322
+ : mappedValue (V), UsePoints(0 ), hasRC(hasRC), Type(Type) {
321
323
switch (Type) {
322
324
case NodeType::Argument:
323
325
case NodeType::Value:
@@ -333,6 +335,11 @@ class EscapeAnalysis : public BottomUpIPAnalysis {
333
335
}
334
336
}
335
337
338
+ // / Get the representative node that maps to a SILValue and depth in the
339
+ // / pointsTo graph.
340
+ std::pair<const CGNode *, unsigned >
341
+ getRepNode (SmallPtrSetImpl<const CGNode *> &visited) const ;
342
+
336
343
// / Merges the use points from another node and returns true if there are
337
344
// / any changes.
338
345
bool mergeUsePoints (CGNode *RHS) {
@@ -417,24 +424,28 @@ class EscapeAnalysis : public BottomUpIPAnalysis {
417
424
friend struct CGNodeWorklist ;
418
425
419
426
public:
420
- SILValue getValue () const {
421
- assert (Type == NodeType::Argument || Type == NodeType::Value);
422
- return V;
423
- }
424
- SILValue getValueOrNull () const { return V; }
425
-
426
- void updateValue (SILValue newValue) {
427
- assert (isContent ());
428
- V = newValue;
429
- }
427
+ struct RepValue {
428
+ // May only be an invalid SILValue for Return nodes or deleted values.
429
+ llvm::PointerIntPair<SILValue, 1 , bool > valueAndIsReturn;
430
+ unsigned depth;
431
+
432
+ SILValue getValue () const { return valueAndIsReturn.getPointer (); }
433
+ bool isReturn () const { return valueAndIsReturn.getInt (); }
434
+ void
435
+ print (llvm::raw_ostream &stream,
436
+ const llvm::DenseMap<const SILNode *, unsigned > &instToIDMap) const ;
437
+ };
438
+ // Get the representative SILValue for this node its depth relative to the
439
+ // node that is mapped to this value.
440
+ RepValue getRepValue () const ;
430
441
431
442
// / Return true if this node represents content.
432
443
bool isContent () const { return Type == NodeType::Content; }
433
444
434
445
// / Return true if this node represents an entire reference counted object.
435
446
bool hasRefCount () const { return hasRC; }
436
447
437
- void setRefCount () { hasRC = true ; }
448
+ void setRefCount (bool rc ) { hasRC = rc ; }
438
449
439
450
// / Returns the escape state.
440
451
EscapeState getEscapeState () const { return State; }
@@ -465,9 +476,8 @@ class EscapeAnalysis : public BottomUpIPAnalysis {
465
476
// / Note that in the false-case the node's value can still escape via
466
477
// / the return instruction.
467
478
// /
468
- // / \p nodeValue is often the same as 'this->V', but is sometimes a more
469
- // / refined value. For content nodes, 'this->V' is only a placeholder that
470
- // / does not necessarilly represent the node's memory.
479
+ // / \p nodeValue is often the same as 'this->getRepValue().getValue()', but
480
+ // / is sometimes a more refined value specific to a content nodes.
471
481
bool escapesInsideFunction (SILValue nodeValue) const {
472
482
switch (getEscapeState ()) {
473
483
case EscapeState::None:
@@ -478,7 +488,6 @@ class EscapeAnalysis : public BottomUpIPAnalysis {
478
488
case EscapeState::Global:
479
489
return true ;
480
490
}
481
-
482
491
llvm_unreachable (" Unhandled EscapeState in switch." );
483
492
}
484
493
@@ -644,10 +653,9 @@ class EscapeAnalysis : public BottomUpIPAnalysis {
644
653
// / Returns null, if V is not a "pointer".
645
654
CGNode *getNode (ValueBase *V, bool createIfNeeded = true );
646
655
647
- // / Helper to create a content node and update the pointsTo graph. \p
648
- // / addrNode will point to the new content node. The new content node is
649
- // / directly initialized with the remaining function arguments.
650
- CGNode *createContentNode (CGNode *addrNode, SILValue addrVal, bool hasRC);
656
+ // / Helper to create and return a content node with the given \p hasRC
657
+ // / flag. \p addrNode will gain a points-to edge to the new content node.
658
+ CGNode *createContentNode (CGNode *addrNode, bool hasRC);
651
659
652
660
// / Create a new content node based on an existing content node to support
653
661
// / graph merging.
@@ -687,6 +695,8 @@ class EscapeAnalysis : public BottomUpIPAnalysis {
687
695
void setNode (ValueBase *V, CGNode *Node) {
688
696
assert (Values2Nodes.find (V) == Values2Nodes.end ());
689
697
Values2Nodes[V] = Node;
698
+ if (!Node->mappedValue )
699
+ Node->mappedValue = V;
690
700
}
691
701
692
702
// / Adds an argument/instruction in which the node's value is used.
@@ -707,7 +717,7 @@ class EscapeAnalysis : public BottomUpIPAnalysis {
707
717
void escapeContentsOf (CGNode *Node) {
708
718
CGNode *escapedContent = Node->getContentNodeOrNull ();
709
719
if (!escapedContent) {
710
- escapedContent = createContentNode (Node, Node-> V , /* hasRC=*/ false );
720
+ escapedContent = createContentNode (Node, /* hasRC=*/ false );
711
721
}
712
722
escapedContent->markEscaping ();
713
723
}
@@ -736,10 +746,10 @@ class EscapeAnalysis : public BottomUpIPAnalysis {
736
746
// / Propagates the escape states through the graph.
737
747
void propagateEscapeStates ();
738
748
739
- // / Removes a value from the graph.
740
- // / It does not delete its node but makes sure that the value cannot be
741
- // / lookup- up with getNode() anymore .
742
- void removeFromGraph (ValueBase *V) { Values2Nodes. erase (V); }
749
+ // / Remove a value from the graph. Do not delete the mapped node, but reset
750
+ // / mappedValue if it is set to this value, and make sure that the node
751
+ // / cannot be looked up with getNode().
752
+ void removeFromGraph (ValueBase *V);
743
753
744
754
enum class Traversal { Follow, Backtrack, Halt };
745
755
@@ -821,7 +831,7 @@ class EscapeAnalysis : public BottomUpIPAnalysis {
821
831
822
832
// / Just verifies the graph structure. This function can also be called
823
833
// / during the graph is modified, e.g. in mergeAllScheduledNodes().
824
- void verifyStructure () const ;
834
+ void verifyStructure (bool allowMerge = false ) const ;
825
835
826
836
friend struct ::CGForDotView;
827
837
friend class EscapeAnalysis ;
0 commit comments