Merge remote-tracking branch 'origin/master' into master-next

This commit is contained in:
swift-ci
2019-11-13 11:30:34 -08:00
3 changed files with 701 additions and 469 deletions

View File

@@ -403,17 +403,7 @@ public:
/// Checks an invariant of the connection graph: The points-to nodes of
/// the defer-successors must match with the points-to of this node.
bool matchPointToOfDefers() const {
for (CGNode *Def : defersTo) {
if (pointsTo != Def->pointsTo)
return false;
}
/// A defer-path in the graph must not end without the specified points-to
/// node.
if (pointsTo && !pointsToIsEdge && defersTo.empty())
return false;
return true;
}
bool matchPointToOfDefers(bool allowMerge = false) const;
friend class CGNodeMap;
friend class ConnectionGraph;
@@ -480,7 +470,7 @@ public:
llvm_unreachable("Unhandled EscapeState in switch.");
}
/// Returns the content node if of this node if it exists in the graph.
/// Returns the content node of this node if it exists in the graph.
CGNode *getContentNodeOrNull() const {
return pointsTo;
}
@@ -603,14 +593,25 @@ public:
}
}
/// Initialize the 'pointsTo' fields of all nodes in the defer web of \p
/// initialiNode.
///
/// If \p createEdge is true, a proper pointsTo edge will be created from \p
/// initialNode to \p pointsTo.
void initializePointsTo(CGNode *initialNode, CGNode *newPointsTo,
bool createEdge = false);
void initializePointsToEdge(CGNode *initialNode, CGNode *newPointsTo) {
initializePointsTo(initialNode, newPointsTo, true);
}
/// Merges all nodes which are added to the ToMerge list.
void mergeAllScheduledNodes();
/// Transitively updates pointsTo of all nodes in the defer-edge web,
/// starting at \p InitialNode.
/// If a node in the web already points to another content node, the other
/// content node is scheduled to be merged with \p pointsTo.
void updatePointsTo(CGNode *InitialNode, CGNode *pointsTo);
/// Transitively update pointsTo of all nodes in the defer-edge web,
/// reaching and reachable from \p initialNode. All nodes in this defer web
/// must already have an initialized `pointsTo`.
void mergePointsTo(CGNode *initialNode, CGNode *pointsTo);
/// Utility function to clear the isInWorkList flags of all nodes in
/// \p WorkList.
@@ -627,12 +628,20 @@ public:
/// Returns null, if V is not a "pointer".
CGNode *getNode(ValueBase *V, bool createIfNeeded = true);
/// Gets or creates a content node to which \a AddrNode points to during
/// initial graph construction. This may not be called after defer edges
/// have been created. Doing so would break the invariant that all
/// non-content nodes ultimately have a pointsTo edge to a single content
/// node.
CGNode *getContentNode(CGNode *AddrNode);
/// Helper to create a content node and update the pointsTo graph. \p
/// addrNode will point to the new content node. The new content node is
/// directly initialized with the remaining function arguments.
CGNode *createContentNode(CGNode *addrNode, SILValue addrVal);
/// Create a new content node based on an existing content node to support
/// graph merging.
///
/// \p destAddrNode will point to to new content. The content's initial
/// state will be initialized based on the \p srcContent node.
CGNode *createMergedContent(CGNode *destAddrNode, CGNode *srcContent);
/// Get a node represnting the field data within the given RC node.
CGNode *getFieldContent(CGNode *rcNode);
/// Get or creates a pseudo node for the function return value.
CGNode *getReturnNode() {
@@ -679,31 +688,21 @@ public:
return Idx;
}
/// Specifies that the node's value escapes to global or unidentified
/// memory.
void setEscapesGlobal(CGNode *Node) {
Node->mergeEscapeState(EscapeState::Global);
// Make sure to have a content node. Otherwise we may end up not merging
// the global-escape state into a caller graph (only content nodes are
// merged). Either the node itself is a content node or we let the node
// point to one.
if (Node->Type != NodeType::Content)
getContentNode(Node);
void escapeContentsOf(CGNode *Node) {
CGNode *escapedContent = Node->getContentNodeOrNull();
if (!escapedContent) {
escapedContent = createContentNode(Node, Node->V);
}
escapedContent->markEscaping();
}
/// Creates a defer-edge between \p From and \p To.
/// This may trigger node merges to keep the graph invariance 4).
/// Returns the \p From node or its merge-target in case \p From was merged
/// during adding the edge.
/// The \p EdgeAdded is set to true if there was no defer-edge between
/// \p From and \p To, yet.
CGNode *defer(CGNode *From, CGNode *To, bool &EdgeAdded) {
if (addDeferEdge(From, To))
EdgeAdded = true;
mergeAllScheduledNodes();
return From->getMergeTarget();
}
/// \p Changed is set to true if a defer edge was added or any nodes were
/// merged.
CGNode *defer(CGNode *From, CGNode *To, bool &Changed);
/// Creates a defer-edge between \p From and \p To.
/// This may trigger node merges to keep the graph invariance 4).
@@ -802,7 +801,7 @@ public:
void dumpCG() const;
/// Checks if the graph is OK.
void verify() const;
void verify(bool allowMerge = false) const;
/// Just verifies the graph structure. This function can also be called
/// during the graph is modified, e.g. in mergeAllScheduledNodes().
@@ -889,9 +888,22 @@ private:
SILValue getPointerRoot(SILValue value) const;
/// If \p pointer is a pointer, set it to global escaping.
void setEscapesGlobal(ConnectionGraph *ConGraph, ValueBase *pointer) {
if (CGNode *Node = ConGraph->getNode(pointer))
ConGraph->setEscapesGlobal(Node);
void setEscapesGlobal(ConnectionGraph *conGraph, ValueBase *pointer) {
CGNode *Node = conGraph->getNode(pointer);
if (!Node)
return;
if (Node->isContent()) {
Node->markEscaping();
return;
}
Node->mergeEscapeState(EscapeState::Global);
// Make sure to have a content node. Otherwise we may end up not merging
// the global-escape state into a caller graph (only content nodes are
// merged). Either the node itself is a content node or we let the node
// point to one.
conGraph->escapeContentsOf(Node);
}
/// Gets or creates FunctionEffects for \p F.
@@ -902,6 +914,15 @@ private:
return FInfo;
}
/// Get or create the node representing the memory pointed to by \p
/// addrVal. If \p addrVal is an address, then return the content node for the
/// variable's memory. Otherwise, \p addrVal may contain a reference, so
/// return the content node for the referenced heap object.
///
/// Note that \p addrVal cannot be an address within a heap object, such as
/// an address from ref_element_addr or project_box.
CGNode *getValueContent(ConnectionGraph *conGraph, SILValue addrVal);
/// Build a connection graph for reach callee from the callee list.
bool buildConnectionGraphForCallees(SILInstruction *Caller,
CalleeList Callees,