Completely rewrite support for the Value::use_* list. Now, all operations on
authorChris Lattner <sabre@nondot.org>
Thu, 16 Oct 2003 16:53:07 +0000 (16:53 +0000)
committerChris Lattner <sabre@nondot.org>
Thu, 16 Oct 2003 16:53:07 +0000 (16:53 +0000)
this list (except use_size()) are constant time.  Before the killUse method
(used whenever something stopped using a value) was linear time, and thus
very very slow for large programs.

This speeds GCCAS up _substantially_ on large programs: almost 2x for 176.gcc:

176.gcc:     77.07s -> 37.38s
177.mesa:     7.59s ->  5.57s
252.eon:     21.02s -> 19.52s (*)
253.perlbmk: 11.40s -> 13.05s
254.gap:      7.25s -> 7.42s

252.eon would speed up a whole lot more, but optimization time is being
dominated by the inlining pass, which needs to be fixed.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@9160 91177308-0d34-0410-b5e6-96231b3b80d8

lib/VMCore/Value.cpp

index 95670f398262776d75501397a60bfac4a3b901de..68b4af094950594e188f21ead672d61af8907d8e 100644 (file)
@@ -35,7 +35,7 @@ Value::~Value() {
   //
   if (Uses.begin() != Uses.end()) {
     std::cerr << "While deleting: " << *Ty << "%" << Name << "\n";
-    for (use_const_iterator I = Uses.begin(); I != Uses.end(); ++I)
+    for (use_const_iterator I = Uses.begin(), E = Uses.end(); I != E; ++I)
       std::cerr << "Use still stuck around after Def is destroyed:"
                 << **I << "\n";
   }
@@ -47,25 +47,6 @@ Value::~Value() {
 }
 
 
-
-
-void Value::replaceAllUsesWith(Value *New) {
-  assert(New && "Value::replaceAllUsesWith(<null>) is invalid!");
-  assert(New != this && "this->replaceAllUsesWith(this) is NOT valid!");
-  assert(New->getType() == getType() &&
-         "replaceAllUses of value with new value of different type!");
-  while (!Uses.empty()) {
-    User *Use = Uses.back();
-    // Must handle Constants specially, we cannot call replaceUsesOfWith on a
-    // constant!
-    if (Constant *C = dyn_cast<Constant>(Use)) {
-      C->replaceUsesOfWithOnConstant(this, New);
-    } else {
-      Use->replaceUsesOfWith(this, New);
-    }
-  }
-}
-
 // uncheckedReplaceAllUsesWith - This is exactly the same as replaceAllUsesWith,
 // except that it doesn't have all of the asserts.  The asserts fail because we
 // are half-way done resolving types, which causes some types to exist as two
@@ -74,31 +55,24 @@ void Value::replaceAllUsesWith(Value *New) {
 //
 void Value::uncheckedReplaceAllUsesWith(Value *New) {
   while (!Uses.empty()) {
-    User *Use = Uses.back();
+    Use &U = Uses.back();
     // Must handle Constants specially, we cannot call replaceUsesOfWith on a
     // constant!
-    if (Constant *C = dyn_cast<Constant>(Use)) {
-      C->replaceUsesOfWithOnConstant(this, New, true);
+    if (Constant *C = dyn_cast<Constant>(U.getUser())) {
+      C->replaceUsesOfWithOnConstant(this, New);
     } else {
-      Use->replaceUsesOfWith(this, New);
+      U.set(New);
     }
   }
 }
 
+void Value::replaceAllUsesWith(Value *New) {
+  assert(New && "Value::replaceAllUsesWith(<null>) is invalid!");
+  assert(New != this && "this->replaceAllUsesWith(this) is NOT valid!");
+  assert(New->getType() == getType() &&
+         "replaceAllUses of value with new value of different type!");
 
-void Value::killUse(User *U) {
-  assert(U != 0 && "Null users are not allowed!");
-  unsigned i;
-
-  // Scan backwards through the uses list looking for the user.  We do this
-  // because vectors like to be accessed on the end.  This is incredibly
-  // important from a performance perspective.
-  for (i = Uses.size()-1; Uses[i] != U; --i)
-    /* empty */;
-
-  assert(i < Uses.size() && "Use not in uses list!!");
-  Uses[i] = Uses.back();
-  Uses.pop_back();
+  uncheckedReplaceAllUsesWith(New);
 }
 
 //===----------------------------------------------------------------------===//