 Chromium Code Reviews
 Chromium Code Reviews Issue 14495008:
  Create type IDs based on reference counts.  (Closed) 
  Base URL: http://git.chromium.org/native_client/pnacl-llvm.git@master
    
  
    Issue 14495008:
  Create type IDs based on reference counts.  (Closed) 
  Base URL: http://git.chromium.org/native_client/pnacl-llvm.git@master| OLD | NEW | 
|---|---|
| 1 //===-- NaClValueEnumerator.cpp ------------------------------------------===// | 1 //===-- NaClValueEnumerator.cpp ------------------------------------------===// | 
| 2 // Number values and types for bitcode writer | 2 // Number values and types for bitcode writer | 
| 3 // | 3 // | 
| 4 // The LLVM Compiler Infrastructure | 4 // The LLVM Compiler Infrastructure | 
| 5 // | 5 // | 
| 6 // This file is distributed under the University of Illinois Open Source | 6 // This file is distributed under the University of Illinois Open Source | 
| 7 // License. See LICENSE.TXT for details. | 7 // License. See LICENSE.TXT for details. | 
| 8 // | 8 // | 
| 9 //===----------------------------------------------------------------------===// | 9 //===----------------------------------------------------------------------===// | 
| 10 // | 10 // | 
| 11 // This file implements the NaClValueEnumerator class. | 11 // This file implements the NaClValueEnumerator class. | 
| 12 // | 12 // | 
| 13 //===----------------------------------------------------------------------===// | 13 //===----------------------------------------------------------------------===// | 
| 14 | 14 | 
| 15 #include "NaClValueEnumerator.h" | 15 #include "NaClValueEnumerator.h" | 
| 16 #include "llvm/ADT/STLExtras.h" | 16 #include "llvm/ADT/STLExtras.h" | 
| 17 #include "llvm/ADT/SmallPtrSet.h" | 17 #include "llvm/ADT/SmallPtrSet.h" | 
| 18 #include "llvm/IR/Constants.h" | 18 #include "llvm/IR/Constants.h" | 
| 19 #include "llvm/IR/DerivedTypes.h" | 19 #include "llvm/IR/DerivedTypes.h" | 
| 20 #include "llvm/IR/Instructions.h" | 20 #include "llvm/IR/Instructions.h" | 
| 21 #include "llvm/IR/Module.h" | 21 #include "llvm/IR/Module.h" | 
| 22 #include "llvm/IR/ValueSymbolTable.h" | 22 #include "llvm/IR/ValueSymbolTable.h" | 
| 23 #include "llvm/Support/Debug.h" | 23 #include "llvm/Support/Debug.h" | 
| 24 #include "llvm/Support/raw_ostream.h" | 24 #include "llvm/Support/raw_ostream.h" | 
| 25 #include <algorithm> | 25 #include <algorithm> | 
| 26 #include <set> | |
| 27 | |
| 26 using namespace llvm; | 28 using namespace llvm; | 
| 27 | 29 | 
| 28 static bool isIntOrIntVectorValue(const std::pair<const Value*, unsigned> &V) { | 30 static bool isIntOrIntVectorValue(const std::pair<const Value*, unsigned> &V) { | 
| 29 return V.first->getType()->isIntOrIntVectorTy(); | 31 return V.first->getType()->isIntOrIntVectorTy(); | 
| 30 } | 32 } | 
| 31 | 33 | 
| 32 /// NaClValueEnumerator - Enumerate module-level information. | 34 /// NaClValueEnumerator - Enumerate module-level information. | 
| 33 NaClValueEnumerator::NaClValueEnumerator(const Module *M) { | 35 NaClValueEnumerator::NaClValueEnumerator(const Module *M) { | 
| 36 // Create map for counting frequency of types, and set field | |
| 37 // TypeCountMap accordingly. Note: Pointer field TypeCountMap is | |
| 38 // used to deal with the fact that types are added through various | |
| 39 // method calls in this routine. Rather than pass it as an argument, | |
| 40 // we use a field. The field is a pointer so that the memory | |
| 41 // footprint of count_map can be garbage collected when this | |
| 42 // constructor completes. | |
| 43 TypeCountMapType count_map; | |
| 44 TypeCountMap = &count_map; | |
| 34 // Enumerate the global variables. | 45 // Enumerate the global variables. | 
| 35 for (Module::const_global_iterator I = M->global_begin(), | 46 for (Module::const_global_iterator I = M->global_begin(), | 
| 36 E = M->global_end(); I != E; ++I) | 47 E = M->global_end(); I != E; ++I) | 
| 37 EnumerateValue(I); | 48 EnumerateValue(I); | 
| 38 | 49 | 
| 39 // Enumerate the functions. | 50 // Enumerate the functions. | 
| 40 for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I) { | 51 for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I) { | 
| 41 EnumerateValue(I); | 52 EnumerateValue(I); | 
| 42 EnumerateAttributes(cast<Function>(I)->getAttributes()); | 53 EnumerateAttributes(cast<Function>(I)->getAttributes()); | 
| 43 } | 54 } | 
| (...skipping 10 matching lines...) Expand all Loading... | |
| 54 for (Module::const_global_iterator I = M->global_begin(), | 65 for (Module::const_global_iterator I = M->global_begin(), | 
| 55 E = M->global_end(); I != E; ++I) | 66 E = M->global_end(); I != E; ++I) | 
| 56 if (I->hasInitializer()) | 67 if (I->hasInitializer()) | 
| 57 EnumerateValue(I->getInitializer()); | 68 EnumerateValue(I->getInitializer()); | 
| 58 | 69 | 
| 59 // Enumerate the aliasees. | 70 // Enumerate the aliasees. | 
| 60 for (Module::const_alias_iterator I = M->alias_begin(), E = M->alias_end(); | 71 for (Module::const_alias_iterator I = M->alias_begin(), E = M->alias_end(); | 
| 61 I != E; ++I) | 72 I != E; ++I) | 
| 62 EnumerateValue(I->getAliasee()); | 73 EnumerateValue(I->getAliasee()); | 
| 63 | 74 | 
| 64 // Insert constants and metadata that are named at module level into the slot | 75 // Insert constants and metadata that are named at module level into the slot | 
| 65 // pool so that the module symbol table can refer to them... | 76 // pool so that the module symbol table can refer to them... | 
| 66 EnumerateValueSymbolTable(M->getValueSymbolTable()); | 77 EnumerateValueSymbolTable(M->getValueSymbolTable()); | 
| 67 EnumerateNamedMetadata(M); | 78 EnumerateNamedMetadata(M); | 
| 68 | 79 | 
| 69 SmallVector<std::pair<unsigned, MDNode*>, 8> MDs; | 80 SmallVector<std::pair<unsigned, MDNode*>, 8> MDs; | 
| 70 | 81 | 
| 71 // Enumerate types used by function bodies and argument lists. | 82 // Enumerate types used by function bodies and argument lists. | 
| 72 for (Module::const_iterator F = M->begin(), E = M->end(); F != E; ++F) { | 83 for (Module::const_iterator F = M->begin(), E = M->end(); F != E; ++F) { | 
| 73 | 84 | 
| 74 for (Function::const_arg_iterator I = F->arg_begin(), E = F->arg_end(); | 85 for (Function::const_arg_iterator I = F->arg_begin(), E = F->arg_end(); | 
| (...skipping 24 matching lines...) Expand all Loading... | |
| 99 | 110 | 
| 100 if (!I->getDebugLoc().isUnknown()) { | 111 if (!I->getDebugLoc().isUnknown()) { | 
| 101 MDNode *Scope, *IA; | 112 MDNode *Scope, *IA; | 
| 102 I->getDebugLoc().getScopeAndInlinedAt(Scope, IA, I->getContext()); | 113 I->getDebugLoc().getScopeAndInlinedAt(Scope, IA, I->getContext()); | 
| 103 if (Scope) EnumerateMetadata(Scope); | 114 if (Scope) EnumerateMetadata(Scope); | 
| 104 if (IA) EnumerateMetadata(IA); | 115 if (IA) EnumerateMetadata(IA); | 
| 105 } | 116 } | 
| 106 } | 117 } | 
| 107 } | 118 } | 
| 108 | 119 | 
| 120 // Optimized type indicies to put "common" expected types in with small | |
| 121 // indices. | |
| 122 OptimizeTypes(M); | |
| 123 TypeCountMap = NULL; | |
| 124 | |
| 109 // Optimize constant ordering. | 125 // Optimize constant ordering. | 
| 110 OptimizeConstants(FirstConstant, Values.size()); | 126 OptimizeConstants(FirstConstant, Values.size()); | 
| 111 } | 127 } | 
| 112 | 128 | 
| 129 void NaClValueEnumerator::OptimizeTypes(const Module *M) { | |
| 130 | |
| 131 // Sort types by count, so that we can index them based on | |
| 132 // frequency. Use indices of built TypeMap, so that order of | |
| 133 // construction is repeatable. | |
| 
Karl
2013/05/20 21:48:51
Changed the type of TypeSetType to be on unsigned,
 | |
| 134 std::set<unsigned> type_counts; | |
| 135 typedef std::set<unsigned> TypeSetType; | |
| 136 std::map<unsigned, TypeSetType> usage_count_map; | |
| 137 TypeList IdType(Types); | |
| 
Karl
2013/05/20 21:48:51
Also added this so that we can look up types from
 | |
| 138 | |
| 139 for (TypeCountMapType::iterator iter = TypeCountMap->begin(); | |
| 140 iter != TypeCountMap->end(); ++ iter) { | |
| 141 type_counts.insert(iter->second); | |
| 142 usage_count_map[iter->second].insert(TypeMap[iter->first]-1); | |
| 143 } | |
| 144 | |
| 145 // Reset type tracking maps, so that we can re-enter based | |
| 146 // on fequency ordering. | |
| 147 TypeCountMap = NULL; | |
| 148 Types.clear(); | |
| 149 TypeMap.clear(); | |
| 150 | |
| 151 // Reinsert types, based on frequency. | |
| 152 for (std::set<unsigned>::reverse_iterator count_iter = type_counts.rbegin(); | |
| 153 count_iter != type_counts.rend(); ++count_iter) { | |
| 154 TypeSetType& count_types = usage_count_map[*count_iter]; | |
| 155 for (TypeSetType::iterator type_iter = count_types.begin(); | |
| 156 type_iter != count_types.end(); ++type_iter) | |
| 157 EnumerateType((IdType[*type_iter]), true); | |
| 158 } | |
| 159 } | |
| 160 | |
| 113 unsigned NaClValueEnumerator::getInstructionID(const Instruction *Inst) const { | 161 unsigned NaClValueEnumerator::getInstructionID(const Instruction *Inst) const { | 
| 114 InstructionMapType::const_iterator I = InstructionMap.find(Inst); | 162 InstructionMapType::const_iterator I = InstructionMap.find(Inst); | 
| 115 assert(I != InstructionMap.end() && "Instruction is not mapped!"); | 163 assert(I != InstructionMap.end() && "Instruction is not mapped!"); | 
| 116 return I->second; | 164 return I->second; | 
| 117 } | 165 } | 
| 118 | 166 | 
| 119 void NaClValueEnumerator::setInstructionID(const Instruction *I) { | 167 void NaClValueEnumerator::setInstructionID(const Instruction *I) { | 
| 120 InstructionMap[I] = InstructionCount++; | 168 InstructionMap[I] = InstructionCount++; | 
| 121 } | 169 } | 
| 122 | 170 | 
| (...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 344 return; | 392 return; | 
| 345 } | 393 } | 
| 346 } | 394 } | 
| 347 | 395 | 
| 348 // Add the value. | 396 // Add the value. | 
| 349 Values.push_back(std::make_pair(V, 1U)); | 397 Values.push_back(std::make_pair(V, 1U)); | 
| 350 ValueID = Values.size(); | 398 ValueID = Values.size(); | 
| 351 } | 399 } | 
| 352 | 400 | 
| 353 | 401 | 
| 354 void NaClValueEnumerator::EnumerateType(Type *Ty) { | 402 void NaClValueEnumerator::EnumerateType(Type *Ty, bool InsideOptimizeTypes) { | 
| 403 // This function is used to enumerate types referenced by the given | |
| 404 // module. This function is called in two phases, based on the value | |
| 405 // of TypeCountMap. These phases are: | |
| 406 // | |
| 407 // (1) In this phase, InsideOptimizeTypes=false. We are collecting types | |
| 408 // and all corresponding (implicitly) referenced types. In addition, | |
| 409 // we are keeping track of the number of references to each type in | |
| 410 // TypeCountMap. These reference counts will be used by method | |
| 411 // OptimizeTypes to associate the smallest type ID's with the most | |
| 412 // referenced types. | |
| 413 // | |
| 414 // (2) In this phase, InsideOptimizeTypes=true. We are registering types | |
| 415 // based on frequency. To minimize type IDs for frequently used | |
| 416 // types, (unlike the other context) we are inserting the minimal | |
| 417 // (implicitly) referenced types needed for each type. | |
| 355 unsigned *TypeID = &TypeMap[Ty]; | 418 unsigned *TypeID = &TypeMap[Ty]; | 
| 356 | 419 | 
| 420 if (TypeCountMap) ++((*TypeCountMap)[Ty]); | |
| 421 | |
| 357 // We've already seen this type. | 422 // We've already seen this type. | 
| 358 if (*TypeID) | 423 if (*TypeID) | 
| 359 return; | 424 return; | 
| 360 | 425 | 
| 361 // If it is a non-anonymous struct, mark the type as being visited so that we | 426 // If it is a non-anonymous struct, mark the type as being visited so that we | 
| 362 // don't recursively visit it. This is safe because we allow forward | 427 // don't recursively visit it. This is safe because we allow forward | 
| 363 // references of these in the bitcode reader. | 428 // references of these in the bitcode reader. | 
| 364 if (StructType *STy = dyn_cast<StructType>(Ty)) | 429 if (StructType *STy = dyn_cast<StructType>(Ty)) | 
| 365 if (!STy->isLiteral()) | 430 if (!STy->isLiteral()) | 
| 366 *TypeID = ~0U; | 431 *TypeID = ~0U; | 
| 367 | 432 | 
| 433 // If in the second phase (i.e. inside optimize types), don't expand | |
| 434 // pointers to structures, since we can just generate a forward | |
| 435 // reference to it. This way, we don't use up unnecessary (small) ID | |
| 436 // values just to define the pointer. | |
| 437 bool EnumerateSubtypes = true; | |
| 438 if (InsideOptimizeTypes) | |
| 439 if (PointerType *PTy = dyn_cast<PointerType>(Ty)) | |
| 440 if (StructType *STy = dyn_cast<StructType>(PTy->getElementType())) | |
| 441 if (!STy->isLiteral()) | |
| 442 EnumerateSubtypes = false; | |
| 443 | |
| 368 // Enumerate all of the subtypes before we enumerate this type. This ensures | 444 // Enumerate all of the subtypes before we enumerate this type. This ensures | 
| 369 // that the type will be enumerated in an order that can be directly built. | 445 // that the type will be enumerated in an order that can be directly built. | 
| 370 for (Type::subtype_iterator I = Ty->subtype_begin(), E = Ty->subtype_end(); | 446 if (EnumerateSubtypes) { | 
| 371 I != E; ++I) | 447 for (Type::subtype_iterator I = Ty->subtype_begin(), E = Ty->subtype_end(); | 
| 372 EnumerateType(*I); | 448 I != E; ++I) | 
| 449 EnumerateType(*I, InsideOptimizeTypes); | |
| 450 } | |
| 373 | 451 | 
| 374 // Refresh the TypeID pointer in case the table rehashed. | 452 // Refresh the TypeID pointer in case the table rehashed. | 
| 375 TypeID = &TypeMap[Ty]; | 453 TypeID = &TypeMap[Ty]; | 
| 376 | 454 | 
| 377 // Check to see if we got the pointer another way. This can happen when | 455 // Check to see if we got the pointer another way. This can happen when | 
| 378 // enumerating recursive types that hit the base case deeper than they start. | 456 // enumerating recursive types that hit the base case deeper than they start. | 
| 379 // | 457 // | 
| 380 // If this is actually a struct that we are treating as forward ref'able, | 458 // If this is actually a struct that we are treating as forward ref'able, | 
| 381 // then emit the definition now that all of its contents are available. | 459 // then emit the definition now that all of its contents are available. | 
| 382 if (*TypeID && *TypeID != ~0U) | 460 if (*TypeID && *TypeID != ~0U) | 
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 531 /// specified basic block. This is relatively expensive information, so it | 609 /// specified basic block. This is relatively expensive information, so it | 
| 532 /// should only be used by rare constructs such as address-of-label. | 610 /// should only be used by rare constructs such as address-of-label. | 
| 533 unsigned NaClValueEnumerator::getGlobalBasicBlockID(const BasicBlock *BB) const { | 611 unsigned NaClValueEnumerator::getGlobalBasicBlockID(const BasicBlock *BB) const { | 
| 534 unsigned &Idx = GlobalBasicBlockIDs[BB]; | 612 unsigned &Idx = GlobalBasicBlockIDs[BB]; | 
| 535 if (Idx != 0) | 613 if (Idx != 0) | 
| 536 return Idx-1; | 614 return Idx-1; | 
| 537 | 615 | 
| 538 IncorporateFunctionInfoGlobalBBIDs(BB->getParent(), GlobalBasicBlockIDs); | 616 IncorporateFunctionInfoGlobalBBIDs(BB->getParent(), GlobalBasicBlockIDs); | 
| 539 return getGlobalBasicBlockID(BB); | 617 return getGlobalBasicBlockID(BB); | 
| 540 } | 618 } | 
| 541 | |
| OLD | NEW |