mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-10-30 16:17:05 +00:00 
			
		
		
		
	Completely rewrite support for the Value::use_* list. Now, all operations on
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
This commit is contained in:
		| @@ -35,7 +35,7 @@ Value::~Value() { | |||||||
|   // |   // | ||||||
|   if (Uses.begin() != Uses.end()) { |   if (Uses.begin() != Uses.end()) { | ||||||
|     std::cerr << "While deleting: " << *Ty << "%" << Name << "\n"; |     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:" |       std::cerr << "Use still stuck around after Def is destroyed:" | ||||||
|                 << **I << "\n"; |                 << **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, | // uncheckedReplaceAllUsesWith - This is exactly the same as replaceAllUsesWith, | ||||||
| // except that it doesn't have all of the asserts.  The asserts fail because we | // 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 | // 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) { | void Value::uncheckedReplaceAllUsesWith(Value *New) { | ||||||
|   while (!Uses.empty()) { |   while (!Uses.empty()) { | ||||||
|     User *Use = Uses.back(); |     Use &U = Uses.back(); | ||||||
|     // Must handle Constants specially, we cannot call replaceUsesOfWith on a |     // Must handle Constants specially, we cannot call replaceUsesOfWith on a | ||||||
|     // constant! |     // constant! | ||||||
|     if (Constant *C = dyn_cast<Constant>(Use)) { |     if (Constant *C = dyn_cast<Constant>(U.getUser())) { | ||||||
|       C->replaceUsesOfWithOnConstant(this, New, true); |       C->replaceUsesOfWithOnConstant(this, New); | ||||||
|     } else { |     } 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) { |   uncheckedReplaceAllUsesWith(New); | ||||||
|   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(); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| //===----------------------------------------------------------------------===// | //===----------------------------------------------------------------------===// | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user