* Changes to make NodeType be private to DSNode.

* Add new MultiObject flag to DSNode which keeps track of whether or not
  multiple objects have been merged into the node, allowing must-alias info
  to be tracked.

llvm-svn: 6794
This commit is contained in:
Chris Lattner 2003-06-19 21:15:11 +00:00
parent 065162a250
commit 4853d162af
5 changed files with 107 additions and 76 deletions

View File

@ -33,7 +33,7 @@ static bool isVAHackFn(const Function *F) {
// if the call sites are not external. // if the call sites are not external.
// //
static inline bool isCompleteNode(DSNode *N) { static inline bool isCompleteNode(DSNode *N) {
if (N->NodeType & DSNode::Incomplete) return false; if (N->isIncomplete()) return false;
const std::vector<GlobalValue*> &Callees = N->getGlobals(); const std::vector<GlobalValue*> &Callees = N->getGlobals();
for (unsigned i = 0, e = Callees.size(); i != e; ++i) for (unsigned i = 0, e = Callees.size(); i != e; ++i)
if (Callees[i]->isExternal()) if (Callees[i]->isExternal())

View File

@ -49,8 +49,8 @@ DSNode *DSNodeHandle::HandleForwarding() const {
// DSNode Implementation // DSNode Implementation
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
DSNode::DSNode(unsigned NT, const Type *T, DSGraph *G) DSNode::DSNode(const Type *T, DSGraph *G)
: NumReferrers(0), Size(0), ParentGraph(G), Ty(Type::VoidTy), NodeType(NT) { : NumReferrers(0), Size(0), ParentGraph(G), Ty(Type::VoidTy), NodeType(0) {
// Add the type entry if it is specified... // Add the type entry if it is specified...
if (T) mergeTypeInfo(T, 0); if (T) mergeTypeInfo(T, 0);
G->getNodes().push_back(this); G->getNodes().push_back(this);
@ -68,6 +68,12 @@ void DSNode::assertOK() const {
Ty == Type::VoidTy && (Size == 0 || Ty == Type::VoidTy && (Size == 0 ||
(NodeType & DSNode::Array))) && (NodeType & DSNode::Array))) &&
"Node not OK!"); "Node not OK!");
// Check to ensure that the multiobject constraints are met...
unsigned Comp = NodeType & DSNode::Composition;
assert((NodeType & DSNode::MultiObject) ||
Comp == 0 || Comp == DSNode::AllocaNode || Comp == DSNode::HeapNode ||
Comp == DSNode::GlobalNode || Comp == DSNode::UnknownNode);
} }
/// forwardNode - Mark this node as being obsolete, and all references to it /// forwardNode - Mark this node as being obsolete, and all references to it
@ -97,6 +103,8 @@ void DSNode::addGlobal(GlobalValue *GV) {
if (I == Globals.end() || *I != GV) { if (I == Globals.end() || *I != GV) {
//assert(GV->getType()->getElementType() == Ty); //assert(GV->getType()->getElementType() == Ty);
Globals.insert(I, GV); Globals.insert(I, GV);
if (NodeType & DSNode::Composition)
NodeType |= DSNode::MultiObject;
NodeType |= GlobalNode; NodeType |= GlobalNode;
} }
} }
@ -112,7 +120,8 @@ void DSNode::foldNodeCompletely() {
++NumFolds; ++NumFolds;
// Create the node we are going to forward to... // Create the node we are going to forward to...
DSNode *DestNode = new DSNode(NodeType|DSNode::Array, 0, ParentGraph); DSNode *DestNode = new DSNode(0, ParentGraph);
DestNode->NodeType = NodeType|DSNode::Array;
DestNode->Ty = Type::VoidTy; DestNode->Ty = Type::VoidTy;
DestNode->Size = 1; DestNode->Size = 1;
DestNode->Globals.swap(Globals); DestNode->Globals.swap(Globals);
@ -446,7 +455,7 @@ void DSNode::MergeNodes(DSNodeHandle& CurNodeH, DSNodeHandle& NH) {
// Merge the type entries of the two nodes together... // Merge the type entries of the two nodes together...
if (NH.getNode()->Ty != Type::VoidTy) if (NH.getNode()->Ty != Type::VoidTy)
CurNodeH.getNode()->mergeTypeInfo(NH.getNode()->Ty, NOffset); CurNodeH.getNode()->mergeTypeInfo(NH.getNode()->Ty, NOffset);
assert((CurNodeH.getNode()->NodeType & DSNode::DEAD) == 0); assert(!CurNodeH.getNode()->isDeadNode());
// If we are merging a node with a completely folded node, then both nodes are // If we are merging a node with a completely folded node, then both nodes are
// now completely folded. // now completely folded.
@ -471,12 +480,17 @@ void DSNode::MergeNodes(DSNodeHandle& CurNodeH, DSNodeHandle& NH) {
DSNode *N = NH.getNode(); DSNode *N = NH.getNode();
if (CurNodeH.getNode() == N || N == 0) return; if (CurNodeH.getNode() == N || N == 0) return;
assert((CurNodeH.getNode()->NodeType & DSNode::DEAD) == 0); assert(!CurNodeH.getNode()->isDeadNode());
// Merge the NodeType information...
if ((CurNodeH.getNode()->NodeType & DSNode::Composition) != 0 &&
(N->NodeType & DSNode::Composition) != 0)
N->NodeType |= DSNode::MultiObject; // Multiple composition -> multiobject
CurNodeH.getNode()->NodeType |= N->NodeType;
// Start forwarding to the new node! // Start forwarding to the new node!
CurNodeH.getNode()->NodeType |= N->NodeType;
N->forwardNode(CurNodeH.getNode(), NOffset); N->forwardNode(CurNodeH.getNode(), NOffset);
assert((CurNodeH.getNode()->NodeType & DSNode::DEAD) == 0); assert(!CurNodeH.getNode()->isDeadNode());
// Make all of the outgoing links of N now be outgoing links of CurNodeH. // Make all of the outgoing links of N now be outgoing links of CurNodeH.
// //
@ -522,8 +536,7 @@ void DSNode::mergeWith(const DSNodeHandle &NH, unsigned Offset) {
if (N == 0 || (N == this && NH.getOffset() == Offset)) if (N == 0 || (N == this && NH.getOffset() == Offset))
return; // Noop return; // Noop
assert((N->NodeType & DSNode::DEAD) == 0); assert(!N->isDeadNode() && !isDeadNode());
assert((NodeType & DSNode::DEAD) == 0);
assert(!hasNoReferrers() && "Should not try to fold a useless node!"); assert(!hasNoReferrers() && "Should not try to fold a useless node!");
if (N == this) { if (N == this) {
@ -630,13 +643,13 @@ DSNodeHandle DSGraph::cloneInto(const DSGraph &G,
Nodes.reserve(FN+G.Nodes.size()); Nodes.reserve(FN+G.Nodes.size());
// Remove alloca or mod/ref bits as specified... // Remove alloca or mod/ref bits as specified...
unsigned clearBits = (CloneFlags & StripAllocaBit ? DSNode::AllocaNode : 0) unsigned BitsToClear =((CloneFlags & StripAllocaBit) ? DSNode::AllocaNode : 0)
| (CloneFlags & StripModRefBits ? (DSNode::Modified | DSNode::Read) : 0); | ((CloneFlags & StripModRefBits) ? (DSNode::Modified | DSNode::Read) : 0);
clearBits |= DSNode::DEAD; // Clear dead flag... BitsToClear |= DSNode::DEAD; // Clear dead flag...
for (unsigned i = 0, e = G.Nodes.size(); i != e; ++i) { for (unsigned i = 0, e = G.Nodes.size(); i != e; ++i) {
DSNode *Old = G.Nodes[i]; DSNode *Old = G.Nodes[i];
DSNode *New = new DSNode(*Old, this); DSNode *New = new DSNode(*Old, this);
New->NodeType &= ~clearBits; New->maskNodeTypes(~BitsToClear);
OldNodeMap[Old] = New; OldNodeMap[Old] = New;
} }
@ -743,16 +756,16 @@ void DSGraph::mergeInGraph(DSCallSite &CS, const DSGraph &Graph,
// markIncompleteNodes - Mark the specified node as having contents that are not // markIncompleteNodes - Mark the specified node as having contents that are not
// known with the current analysis we have performed. Because a node makes all // known with the current analysis we have performed. Because a node makes all
// of the nodes it can reach imcomplete if the node itself is incomplete, we // of the nodes it can reach incomplete if the node itself is incomplete, we
// must recursively traverse the data structure graph, marking all reachable // must recursively traverse the data structure graph, marking all reachable
// nodes as incomplete. // nodes as incomplete.
// //
static void markIncompleteNode(DSNode *N) { static void markIncompleteNode(DSNode *N) {
// Stop recursion if no node, or if node already marked... // Stop recursion if no node, or if node already marked...
if (N == 0 || (N->NodeType & DSNode::Incomplete)) return; if (N == 0 || (N->isIncomplete())) return;
// Actually mark the node // Actually mark the node
N->NodeType |= DSNode::Incomplete; N->setIncompleteMarker();
// Recusively process children... // Recusively process children...
for (unsigned i = 0, e = N->getSize(); i < e; i += DS::PointerSize) for (unsigned i = 0, e = N->getSize(); i < e; i += DS::PointerSize)
@ -798,14 +811,15 @@ void DSGraph::markIncompleteNodes(unsigned Flags) {
// Mark all global nodes as incomplete... // Mark all global nodes as incomplete...
if ((Flags & DSGraph::IgnoreGlobals) == 0) if ((Flags & DSGraph::IgnoreGlobals) == 0)
for (unsigned i = 0, e = Nodes.size(); i != e; ++i) for (unsigned i = 0, e = Nodes.size(); i != e; ++i)
if (Nodes[i]->NodeType & DSNode::GlobalNode && Nodes[i]->getNumLinks()) if (Nodes[i]->isGlobalNode() && Nodes[i]->getNumLinks())
markIncompleteNode(Nodes[i]); markIncompleteNode(Nodes[i]);
} }
static inline void killIfUselessEdge(DSNodeHandle &Edge) { static inline void killIfUselessEdge(DSNodeHandle &Edge) {
if (DSNode *N = Edge.getNode()) // Is there an edge? if (DSNode *N = Edge.getNode()) // Is there an edge?
if (N->getNumReferrers() == 1) // Does it point to a lonely node? if (N->getNumReferrers() == 1) // Does it point to a lonely node?
if ((N->NodeType & ~DSNode::Incomplete) == 0 && // No interesting info? // No interesting info?
if ((N->getNodeFlags() & ~DSNode::Incomplete) == 0 &&
N->getType() == Type::VoidTy && !N->isNodeCompletelyFolded()) N->getType() == Type::VoidTy && !N->isNodeCompletelyFolded())
Edge.setNode(0); // Kill the edge! Edge.setNode(0); // Kill the edge!
} }
@ -835,7 +849,7 @@ static void removeIdenticalCalls(std::vector<DSCallSite> &Calls,
// If the Callee is a useless edge, this must be an unreachable call site, // If the Callee is a useless edge, this must be an unreachable call site,
// eliminate it. // eliminate it.
if (CS.isIndirectCall() && CS.getCalleeNode()->getNumReferrers() == 1 && if (CS.isIndirectCall() && CS.getCalleeNode()->getNumReferrers() == 1 &&
CS.getCalleeNode()->NodeType == 0) { // No useful info? CS.getCalleeNode()->getNodeFlags() == 0) { // No useful info?
std::cerr << "WARNING: Useless call site found??\n"; std::cerr << "WARNING: Useless call site found??\n";
CS.swap(Calls.back()); CS.swap(Calls.back());
Calls.pop_back(); Calls.pop_back();
@ -914,8 +928,7 @@ void DSGraph::removeTriviallyDeadNodes() {
for (unsigned i = 0; i != Nodes.size(); ++i) { for (unsigned i = 0; i != Nodes.size(); ++i) {
DSNode *Node = Nodes[i]; DSNode *Node = Nodes[i];
if (!(Node->NodeType & ~(DSNode::Composition | DSNode::Array | if (!Node->isIncomplete() && !Node->isModified() && !Node->isRead()) {
DSNode::DEAD))) {
// This is a useless node if it has no mod/ref info (checked above), // This is a useless node if it has no mod/ref info (checked above),
// outgoing edges (which it cannot, as it is not modified in this // outgoing edges (which it cannot, as it is not modified in this
// context), and it has no incoming edges. If it is a global node it may // context), and it has no incoming edges. If it is a global node it may
@ -923,7 +936,7 @@ void DSGraph::removeTriviallyDeadNodes() {
// scalar map, so we check those now. // scalar map, so we check those now.
// //
if (Node->getNumReferrers() == Node->getGlobals().size()) { if (Node->getNumReferrers() == Node->getGlobals().size()) {
std::vector<GlobalValue*> &Globals = Node->getGlobals(); const std::vector<GlobalValue*> &Globals = Node->getGlobals();
// Loop through and make sure all of the globals are referring directly // Loop through and make sure all of the globals are referring directly
// to the node... // to the node...
@ -932,20 +945,16 @@ void DSGraph::removeTriviallyDeadNodes() {
assert(N == Node && "ScalarMap doesn't match globals list!"); assert(N == Node && "ScalarMap doesn't match globals list!");
} }
// Make sure numreferrers still agrees, if so, the node is truely dead. // Make sure NumReferrers still agrees, if so, the node is truly dead.
if (Node->getNumReferrers() == Globals.size()) { if (Node->getNumReferrers() == Globals.size()) {
for (unsigned j = 0, e = Globals.size(); j != e; ++j) for (unsigned j = 0, e = Globals.size(); j != e; ++j)
ScalarMap.erase(Globals[j]); ScalarMap.erase(Globals[j]);
Node->makeNodeDead();
Globals.clear();
assert(Node->hasNoReferrers() && "Shouldn't have refs now!");
Node->NodeType = DSNode::DEAD;
} }
} }
} }
if ((Node->NodeType & ~DSNode::DEAD) == 0 && Node->hasNoReferrers()) { if (Node->getNodeFlags() == 0 && Node->hasNoReferrers()) {
// This node is dead! // This node is dead!
delete Node; // Free memory... delete Node; // Free memory...
Nodes[i--] = Nodes.back(); Nodes[i--] = Nodes.back();
@ -1055,7 +1064,7 @@ void DSGraph::removeDeadNodes(unsigned Flags) {
// these, prune the scalar pointing to it. // these, prune the scalar pointing to it.
// //
DSNode *N = I->second.getNode(); DSNode *N = I->second.getNode();
if (N->NodeType == DSNode::UnknownNode && !isa<Argument>(I->first)) { if (N->isUnknownNode() && !isa<Argument>(I->first)) {
ScalarMap.erase(I++); ScalarMap.erase(I++);
} else { } else {
I->second.getNode()->markReachableNodes(Alive); I->second.getNode()->markReachableNodes(Alive);
@ -1128,7 +1137,7 @@ void DSGraph::removeDeadNodes(unsigned Flags) {
GlobalsGraph->Nodes.push_back(N); // Move node to globals graph GlobalsGraph->Nodes.push_back(N); // Move node to globals graph
N->setParentGraph(GlobalsGraph); N->setParentGraph(GlobalsGraph);
} else { // Otherwise, delete the node } else { // Otherwise, delete the node
assert(((N->NodeType & DSNode::GlobalNode) == 0 || assert((!N->isGlobalNode() ||
(Flags & DSGraph::RemoveUnreachableGlobals)) (Flags & DSGraph::RemoveUnreachableGlobals))
&& "Killing a global?"); && "Killing a global?");
//std::cerr << "[" << i+1 << "/" << DeadNodes.size() //std::cerr << "[" << i+1 << "/" << DeadNodes.size()
@ -1189,7 +1198,7 @@ void DSGraph::AssertGraphOK() const {
assert(I->second.getNode() && "Null node in scalarmap!"); assert(I->second.getNode() && "Null node in scalarmap!");
AssertNodeInGraph(I->second.getNode()); AssertNodeInGraph(I->second.getNode());
if (GlobalValue *GV = dyn_cast<GlobalValue>(I->first)) { if (GlobalValue *GV = dyn_cast<GlobalValue>(I->first)) {
assert((I->second.getNode()->NodeType & DSNode::GlobalNode) && assert(I->second.getNode()->isGlobalNode() &&
"Global points to node, but node isn't global?"); "Global points to node, but node isn't global?");
AssertNodeContainsGlobal(I->second.getNode(), GV); AssertNodeContainsGlobal(I->second.getNode(), GV);
} }

View File

@ -68,15 +68,12 @@ static const Function *getValueFunction(const Value *V) {
// alias - This is the only method here that does anything interesting... // alias - This is the only method here that does anything interesting...
AliasAnalysis::AliasResult DSAA::alias(const Value *V1, unsigned V1Size, AliasAnalysis::AliasResult DSAA::alias(const Value *V1, unsigned V1Size,
const Value *V2, unsigned V2Size) { const Value *V2, unsigned V2Size) {
// FIXME: This should handle the Size argument as well! if (V1 == V2) return MustAlias;
const Function *F1 = getValueFunction(V1); const Function *F1 = getValueFunction(V1);
const Function *F2 = getValueFunction(V2); const Function *F2 = getValueFunction(V2);
assert((!F1 || !F2 || F1 == F2) && "Alias query for 2 different functions?"); assert((!F1 || !F2 || F1 == F2) && "Alias query for 2 different functions?");
// FIXME: This can return must alias if querying a DSNode for a global value
// where the node has only the G composition bit set, and only one entry in
// the globals list...
if (F2) F1 = F2; if (F2) F1 = F2;
if (F1) { if (F1) {
// Get the graph for a function... // Get the graph for a function...
@ -88,17 +85,33 @@ AliasAnalysis::AliasResult DSAA::alias(const Value *V1, unsigned V1Size,
hash_map<Value*, DSNodeHandle>::iterator J = GSM.find((Value*)V2); hash_map<Value*, DSNodeHandle>::iterator J = GSM.find((Value*)V2);
if (J != GSM.end()) { if (J != GSM.end()) {
assert(J->second.getNode() && "Scalar map points to null node?"); assert(J->second.getNode() && "Scalar map points to null node?");
if (I->second.getNode() != J->second.getNode()) {
// Return noalias if one of the nodes is complete... DSNode *N1 = I->second.getNode(), *N2 = J->second.getNode();
if ((~I->second.getNode()->NodeType | ~J->second.getNode()->NodeType) unsigned O1 = I->second.getOffset(), O2 = J->second.getOffset();
& DSNode::Incomplete)
return NoAlias; // We can only make a judgement of one of the nodes is complete...
// both are incomplete, they may alias... if (!N1->isIncomplete() || !N2->isIncomplete()) {
} else { if (N1 != N2)
// Both point to the same node, see if they point to different return NoAlias; // Completely different nodes.
// offsets... FIXME: This needs to know the size of the alias query
if (I->second.getOffset() != J->second.getOffset()) // Both point to the same node and same offset, and there is only one
return NoAlias; // physical memory object represented in the node, return must alias.
if (O1 == O2 && !N1->isMultiObject())
return MustAlias; // Exactly the same object & offset
// See if they point to different offsets... if so, we may be able to
// determine that they do not alias...
if (O1 != O2) {
if (O2 < O1) { // Ensure that O1 <= O2
std::swap(V1, V2);
std::swap(O1, O2);
std::swap(V1Size, V2Size);
}
// FIXME: This is not correct because we do not handle array
// indexing correctly with this check!
//if (O1+V1Size <= O2) return NoAlias;
}
} }
} }
} }

View File

@ -86,9 +86,9 @@ namespace {
private: private:
// Visitor functions, used to handle each instruction type we encounter... // Visitor functions, used to handle each instruction type we encounter...
friend class InstVisitor<GraphBuilder>; friend class InstVisitor<GraphBuilder>;
void visitMallocInst(MallocInst &MI) { handleAlloc(MI, DSNode::HeapNode); } void visitMallocInst(MallocInst &MI) { handleAlloc(MI, true); }
void visitAllocaInst(AllocaInst &AI) { handleAlloc(AI, DSNode::AllocaNode);} void visitAllocaInst(AllocaInst &AI) { handleAlloc(AI, false); }
void handleAlloc(AllocationInst &AI, DSNode::NodeTy NT); void handleAlloc(AllocationInst &AI, bool isHeap);
void visitPHINode(PHINode &PN); void visitPHINode(PHINode &PN);
@ -108,8 +108,8 @@ namespace {
/// createNode - Create a new DSNode, ensuring that it is properly added to /// createNode - Create a new DSNode, ensuring that it is properly added to
/// the graph. /// the graph.
/// ///
DSNode *createNode(DSNode::NodeTy NodeType, const Type *Ty = 0) { DSNode *createNode(const Type *Ty = 0) {
DSNode *N = new DSNode(NodeType, Ty, &G); // Create the node DSNode *N = new DSNode(Ty, &G); // Create the node
if (DisableFieldSensitivity) { if (DisableFieldSensitivity) {
N->foldNodeCompletely(); N->foldNodeCompletely();
if (DSNode *FN = N->getForwardNode()) if (DSNode *FN = N->getForwardNode())
@ -194,7 +194,7 @@ DSNodeHandle GraphBuilder::getValueDest(Value &Val) {
NH = I->second; NH = I->second;
} else { } else {
// This returns a conservative unknown node for any unhandled ConstExpr // This returns a conservative unknown node for any unhandled ConstExpr
return NH = createNode(DSNode::UnknownNode); return NH = createNode()->setUnknownNodeMarker();
} }
if (NH.getNode() == 0) { // (getelementptr null, X) returns null if (NH.getNode() == 0) { // (getelementptr null, X) returns null
ScalarMap.erase(V); ScalarMap.erase(V);
@ -204,7 +204,7 @@ DSNodeHandle GraphBuilder::getValueDest(Value &Val) {
} else if (ConstantIntegral *CI = dyn_cast<ConstantIntegral>(C)) { } else if (ConstantIntegral *CI = dyn_cast<ConstantIntegral>(C)) {
// Random constants are unknown mem // Random constants are unknown mem
return NH = createNode(DSNode::UnknownNode); return NH = createNode()->setUnknownNodeMarker();
} else { } else {
assert(0 && "Unknown constant type!"); assert(0 && "Unknown constant type!");
} }
@ -213,11 +213,11 @@ DSNodeHandle GraphBuilder::getValueDest(Value &Val) {
DSNode *N; DSNode *N;
if (GlobalValue *GV = dyn_cast<GlobalValue>(V)) { if (GlobalValue *GV = dyn_cast<GlobalValue>(V)) {
// Create a new global node for this global variable... // Create a new global node for this global variable...
N = createNode(DSNode::GlobalNode, GV->getType()->getElementType()); N = createNode(GV->getType()->getElementType());
N->addGlobal(GV); N->addGlobal(GV);
} else { } else {
// Otherwise just create a shadow node // Otherwise just create a shadow node
N = createNode(DSNode::ShadowNode); N = createNode();
} }
NH.setNode(N); // Remember that we are pointing to it... NH.setNode(N); // Remember that we are pointing to it...
@ -237,7 +237,7 @@ DSNodeHandle &GraphBuilder::getLink(const DSNodeHandle &node, unsigned LinkNo) {
DSNodeHandle &Link = Node.getLink(LinkNo); DSNodeHandle &Link = Node.getLink(LinkNo);
if (!Link.getNode()) { if (!Link.getNode()) {
// If the link hasn't been created yet, make and return a new shadow node // If the link hasn't been created yet, make and return a new shadow node
Link = createNode(DSNode::ShadowNode); Link = createNode();
} }
return Link; return Link;
} }
@ -263,8 +263,13 @@ void GraphBuilder::setDestTo(Value &V, const DSNodeHandle &NH) {
/// Alloca & Malloc instruction implementation - Simply create a new memory /// Alloca & Malloc instruction implementation - Simply create a new memory
/// object, pointing the scalar to it. /// object, pointing the scalar to it.
/// ///
void GraphBuilder::handleAlloc(AllocationInst &AI, DSNode::NodeTy NodeType) { void GraphBuilder::handleAlloc(AllocationInst &AI, bool isHeap) {
setDestTo(AI, createNode(NodeType)); DSNode *N = createNode();
if (isHeap)
N->setHeapNodeMarker();
else
N->setAllocaNodeMarker();
setDestTo(AI, N);
} }
// PHINode - Make the scalar for the PHI node point to all of the things the // PHINode - Make the scalar for the PHI node point to all of the things the
@ -368,7 +373,7 @@ void GraphBuilder::visitLoadInst(LoadInst &LI) {
if (Ptr.getNode() == 0) return; if (Ptr.getNode() == 0) return;
// Make that the node is read from... // Make that the node is read from...
Ptr.getNode()->NodeType |= DSNode::Read; Ptr.getNode()->setReadMarker();
// Ensure a typerecord exists... // Ensure a typerecord exists...
Ptr.getNode()->mergeTypeInfo(LI.getType(), Ptr.getOffset(), false); Ptr.getNode()->mergeTypeInfo(LI.getType(), Ptr.getOffset(), false);
@ -383,7 +388,7 @@ void GraphBuilder::visitStoreInst(StoreInst &SI) {
if (Dest.getNode() == 0) return; if (Dest.getNode() == 0) return;
// Mark that the node is written to... // Mark that the node is written to...
Dest.getNode()->NodeType |= DSNode::Modified; Dest.getNode()->setModifiedMarker();
// Ensure a typerecord exists... // Ensure a typerecord exists...
Dest.getNode()->mergeTypeInfo(StoredTy, Dest.getOffset()); Dest.getNode()->mergeTypeInfo(StoredTy, Dest.getOffset());
@ -426,8 +431,9 @@ void GraphBuilder::visitCallInst(CallInst &CI) {
void GraphBuilder::visitFreeInst(FreeInst &FI) { void GraphBuilder::visitFreeInst(FreeInst &FI) {
// Mark that the node is written to... // Mark that the node is written to...
getValueDest(*FI.getOperand(0)).getNode()->NodeType DSNode *N = getValueDest(*FI.getOperand(0)).getNode();
|= DSNode::Modified | DSNode::HeapNode; N->setModifiedMarker();
N->setHeapNodeMarker();
} }
/// Handle casts... /// Handle casts...
@ -441,7 +447,7 @@ void GraphBuilder::visitCastInst(CastInst &CI) {
// to track the fact that the node points to SOMETHING, just something we // to track the fact that the node points to SOMETHING, just something we
// don't know about. Make an "Unknown" node. // don't know about. Make an "Unknown" node.
// //
setDestTo(CI, createNode(DSNode::UnknownNode)); setDestTo(CI, createNode()->setUnknownNodeMarker());
} }
} }
@ -458,7 +464,7 @@ void GraphBuilder::visitInstruction(Instruction &Inst) {
CurNode.mergeWith(getValueDest(**I)); CurNode.mergeWith(getValueDest(**I));
if (CurNode.getNode()) if (CurNode.getNode())
CurNode.getNode()->NodeType |= DSNode::UnknownNode; CurNode.getNode()->setUnknownNodeMarker();
} }

View File

@ -38,16 +38,19 @@ static std::string getCaption(const DSNode *N, const DSGraph *G) {
if (N->isArray()) if (N->isArray())
OS << " array"; OS << " array";
} }
if (N->NodeType) { if (unsigned NodeType = N->getNodeFlags()) {
OS << ": "; OS << ": ";
if (N->NodeType & DSNode::AllocaNode ) OS << "S"; if (NodeType & DSNode::AllocaNode ) OS << "S";
if (N->NodeType & DSNode::HeapNode ) OS << "H"; if (NodeType & DSNode::HeapNode ) OS << "H";
if (N->NodeType & DSNode::GlobalNode ) OS << "G"; if (NodeType & DSNode::GlobalNode ) OS << "G";
if (N->NodeType & DSNode::UnknownNode) OS << "U"; if (NodeType & DSNode::UnknownNode) OS << "U";
if (N->NodeType & DSNode::Incomplete ) OS << "I"; if (NodeType & DSNode::Incomplete ) OS << "I";
if (N->NodeType & DSNode::Modified ) OS << "M"; if (NodeType & DSNode::Modified ) OS << "M";
if (N->NodeType & DSNode::Read ) OS << "R"; if (NodeType & DSNode::Read ) OS << "R";
if (N->NodeType & DSNode::DEAD ) OS << "<dead>"; if (NodeType & DSNode::MultiObject) OS << "m";
#ifndef NDEBUG
if (NodeType & DSNode::DEAD ) OS << "<dead>";
#endif
OS << "\n"; OS << "\n";
} }