[llvm-commits] CVS: llvm/lib/Analysis/DataStructure/DataStructure.cpp

Chris Lattner lattner at cs.uiuc.edu
Tue Oct 1 23:58:00 PDT 2002


Changes in directory llvm/lib/Analysis/DataStructure:

DataStructure.cpp updated: 1.19 -> 1.20

---
Log message:

* Significant rework of DSNode to support arbitrary aliasing due to merging
* Now all and any bytes of a DSNode can be merged together individually.  This
  is neccesary to support the full generality of C and support aliasing 
  correctly.


---
Diffs of the changes:

Index: llvm/lib/Analysis/DataStructure/DataStructure.cpp
diff -u llvm/lib/Analysis/DataStructure/DataStructure.cpp:1.19 llvm/lib/Analysis/DataStructure/DataStructure.cpp:1.20
--- llvm/lib/Analysis/DataStructure/DataStructure.cpp:1.19	Tue Oct  1 17:33:50 2002
+++ llvm/lib/Analysis/DataStructure/DataStructure.cpp	Tue Oct  1 23:57:39 2002
@@ -7,9 +7,9 @@
 #include "llvm/Analysis/DSGraph.h"
 #include "llvm/Function.h"
 #include "llvm/DerivedTypes.h"
+#include "llvm/Target/TargetData.h"
 #include "Support/STLExtras.h"
 #include "Support/Statistic.h"
-#include "llvm/Target/TargetData.h"
 #include <algorithm>
 #include <set>
 
@@ -31,15 +31,42 @@
 
 DSNode::DSNode(enum NodeTy NT, const Type *T) : NodeType(NT) {
   // If this node is big enough to have pointer fields, add space for them now.
-  if (T != Type::VoidTy && !isa<FunctionType>(T))  // Avoid TargetData assert's
-    LinkIndex.resize(TD.getTypeSize(T), -1);
+  if (T != Type::VoidTy && !isa<FunctionType>(T)) { // Avoid TargetData assert's
+    MergeMap.resize(TD.getTypeSize(T));
+
+    // Assign unique values to all of the elements of MergeMap
+    if (MergeMap.size() < 128) {
+      // Handle the common case of reasonable size structures...
+      for (unsigned i = 0, e = MergeMap.size(); i != e; ++i)
+        MergeMap[i] = -1-i;   // Assign -1, -2, -3, ...
+    } else {
+      // It's possible that we have something really big here.  In this case,
+      // divide the object into chunks until it will fit into 128 elements.
+      unsigned Multiple = MergeMap.size()/128;
+
+      // It's probably an array, and probably some power of two in size.
+      // Because of this, find the biggest power of two that is bigger than
+      // multiple to use as our real Multiple.
+      unsigned RealMultiple = 2;
+      while (RealMultiple < Multiple) RealMultiple <<= 1;
+
+      unsigned RealBound = MergeMap.size()/RealMultiple;
+      assert(RealBound <= 128 && "Math didn't work out right");
+
+      // Now go through and assign indexes that are between -1 and -128
+      // inclusive
+      //
+      for (unsigned i = 0, e = MergeMap.size(); i != e; ++i)
+        MergeMap[i] = -1-(i % RealBound);   // Assign -1, -2, -3...
+    }
+  }
 
   TypeEntries.push_back(std::make_pair(T, 0));
 }
 
 // DSNode copy constructor... do not copy over the referrers list!
 DSNode::DSNode(const DSNode &N)
-  : Links(N.Links), LinkIndex(N.LinkIndex),
+  : Links(N.Links), MergeMap(N.MergeMap),
     TypeEntries(N.TypeEntries), Globals(N.Globals), NodeType(N.NodeType) {
 }
 
@@ -68,27 +95,89 @@
 }
 
 
+/// setLink - Set the link at the specified offset to the specified
+/// NodeHandle, replacing what was there.  It is uncommon to use this method,
+/// instead one of the higher level methods should be used, below.
+///
+void DSNode::setLink(unsigned i, const DSNodeHandle &NH) {
+  // Create a new entry in the Links vector to hold a new element for offset.
+  if (!hasLink(i)) {
+    signed char NewIdx = Links.size();
+    // Check to see if we allocate more than 128 distinct links for this node.
+    // If so, just merge with the last one.  This really shouldn't ever happen,
+    // but it should work regardless of whether it does or not.
+    //
+    if (NewIdx >= 0) {
+      Links.push_back(NH);             // Allocate space: common case
+    } else {                           // Wrap around?  Too many links?
+      NewIdx--;                        // Merge with whatever happened last
+      assert(NewIdx > 0 && "Should wrap back around");
+      std::cerr << "\n*** DSNode found that requires more than 128 "
+                << "active links at once!\n\n";
+    } 
+
+    signed char OldIdx = MergeMap[i];
+    assert (OldIdx < 0 && "Shouldn't contain link!");
+
+    // Make sure that anything aliasing this field gets updated to point to the
+    // new link field.
+    rewriteMergeMap(OldIdx, NewIdx);
+    assert(MergeMap[i] == NewIdx && "Field not replaced!");
+  } else {
+    Links[MergeMap[i]] = NH;
+  }
+}
+
 // addEdgeTo - Add an edge from the current node to the specified node.  This
 // can cause merging of nodes in the graph.
 //
 void DSNode::addEdgeTo(unsigned Offset, const DSNodeHandle &NH) {
-  assert(Offset < LinkIndex.size() && "Offset out of range!");
+  assert(Offset < getSize() && "Offset out of range!");
   if (NH.getNode() == 0) return;       // Nothing to do
 
-  if (LinkIndex[Offset] == -1) {       // No merging to perform...
-    LinkIndex[Offset] = Links.size();  // Allocate a new link...
-    Links.push_back(NH);
-    return;
+  if (DSNodeHandle *ExistingNH = getLink(Offset)) {
+    // Merge the two nodes...
+    ExistingNH->mergeWith(NH);
+  } else {                             // No merging to perform...
+    setLink(Offset, NH);               // Just force a link in there...
   }
+}
 
-  unsigned Idx = (unsigned)LinkIndex[Offset];
-  if (!Links[Idx].getNode()) {         // No merging to perform
-    Links[Idx] = NH;
-    return;
-  }
+/// mergeMappedValues - This is the higher level form of rewriteMergeMap.  It is
+/// fully capable of merging links together if neccesary as well as simply
+/// rewriting the map entries.
+///
+void DSNode::mergeMappedValues(signed char V1, signed char V2) {
+  assert(V1 != V2 && "Cannot merge two identical mapped values!");
+  
+  if (V1 < 0) {  // If there is no outgoing link from V1, merge it with V2
+    if (V2 < 0 && V1 > V2)
+       // If both are not linked, merge to the field closer to 0
+      rewriteMergeMap(V2, V1);
+    else
+      rewriteMergeMap(V1, V2);
+  } else if (V2 < 0) {           // Is V2 < 0 && V1 >= 0?
+    rewriteMergeMap(V2, V1);     // Merge into the one with the link...
+  } else {                       // Otherwise, links exist at both locations
+    // Merge Links[V1] with Links[V2] so they point to the same place now...
+    Links[V1].mergeWith(Links[V2]);
+
+    // Merge the V2 link into V1 so that we reduce the overall value of the
+    // links are reduced...
+    //
+    if (V2 < V1) std::swap(V1, V2);     // Ensure V1 < V2
+    rewriteMergeMap(V2, V1);            // After this, V2 is "dead"
+
+    // Change the user of the last link to use V2 instead
+    if ((unsigned)V2 != Links.size()-1) {
+      rewriteMergeMap(Links.size()-1, V2);  // Point to V2 instead of last el...
+      // Make sure V2 points the right DSNode
+      Links[V2] = Links.back();
+    }
 
-  // Merge the two nodes...
-  Links[Idx].mergeWith(NH);
+    // Reduce the number of distinct outgoing links...
+    Links.pop_back();
+  }
 }
 
 
@@ -171,6 +260,10 @@
   //
   unsigned NOffset = NH.getOffset()-Offset;
 
+  unsigned NSize = N->getSize();
+  assert(NSize+NOffset <= getSize() &&
+         "Don't know how to merge extend a merged nodes size yet!");
+
   // Remove all edges pointing at N, causing them to point to 'this' instead.
   // Make sure to adjust their offset, not just the node pointer.
   //
@@ -179,13 +272,46 @@
     Ref = DSNodeHandle(this, NOffset+Ref.getOffset());
   }
 
+  // We must merge fields in this node due to nodes merged in the source node.
+  // In order to handle this we build a map that converts from the source node's
+  // MergeMap values to our MergeMap values.  This map is indexed by the
+  // expression: MergeMap[SMM+SourceNodeSize] so we need to allocate at least
+  // 2*SourceNodeSize elements of space for the mapping.  We can do this because
+  // we know that there are at most SourceNodeSize outgoing links in the node
+  // (thus that many positive values) and at most SourceNodeSize distinct fields
+  // (thus that many negative values).
+  //
+  std::vector<signed char> MergeMapMap(NSize*2, 127);
+
+  // Loop through the structures, merging them together...
+  for (unsigned i = 0, e = NSize; i != e; ++i) {
+    // Get what this byte of N maps to...
+    signed char NElement = N->MergeMap[i];
+
+    // Get what we map this byte to...
+    signed char Element = MergeMap[i+NOffset];
+    // We use 127 as a sentinal and don't check for it's existence yet...
+    assert(Element != 127 && "MergeMapMap doesn't permit 127 values yet!");
+
+    signed char CurMappedVal = MergeMapMap[NElement+NSize];
+    if (CurMappedVal == 127) {               // Haven't seen this NElement yet?
+      MergeMapMap[NElement+NSize] = Element; // Map the two together...
+    } else if (CurMappedVal != Element) {
+      // If we are mapping two different fields together this means that we need
+      // to merge fields in the current node due to merging in the source node.
+      //
+      mergeMappedValues(CurMappedVal, Element);
+      MergeMapMap[NElement+NSize] = MergeMap[i+NOffset];
+    }
+  }
+
   // Make all of the outgoing links of N now be outgoing links of this.  This
   // can cause recursive merging!
   //
-  for (unsigned i = 0, e = N->LinkIndex.size(); i != e; ++i)
-    if (N->LinkIndex[i] != -1) {
-      addEdgeTo(i+NOffset, N->Links[N->LinkIndex[i]]);
-      N->LinkIndex[i] = -1;  // Reduce unneccesary edges in graph. N is dead
+  for (unsigned i = 0, e = NSize; i != e; ++i)
+    if (DSNodeHandle *Link = N->getLink(i)) {
+      addEdgeTo(i+NOffset, *Link);
+      N->MergeMap[i] = -1;  // Kill outgoing edge
     }
 
   // Now that there are no outgoing edges, all of the Links are dead.





More information about the llvm-commits mailing list