Chromium Code Reviews| 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 TypeCountMap = new TypeCountMapType(); | |
|
jvoung (off chromium)
2013/04/29 18:35:42
see question about whether this really needs to be
Karl
2013/04/29 22:19:16
As mentioned in the header file, this is only need
| |
| 34 // Enumerate the global variables. | 37 // Enumerate the global variables. |
| 35 for (Module::const_global_iterator I = M->global_begin(), | 38 for (Module::const_global_iterator I = M->global_begin(), |
| 36 E = M->global_end(); I != E; ++I) | 39 E = M->global_end(); I != E; ++I) |
| 37 EnumerateValue(I); | 40 EnumerateValue(I); |
| 38 | 41 |
| 39 // Enumerate the functions. | 42 // Enumerate the functions. |
| 40 for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I) { | 43 for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I) { |
| 41 EnumerateValue(I); | 44 EnumerateValue(I); |
| 42 EnumerateAttributes(cast<Function>(I)->getAttributes()); | 45 EnumerateAttributes(cast<Function>(I)->getAttributes()); |
| 43 } | 46 } |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 99 | 102 |
| 100 if (!I->getDebugLoc().isUnknown()) { | 103 if (!I->getDebugLoc().isUnknown()) { |
| 101 MDNode *Scope, *IA; | 104 MDNode *Scope, *IA; |
| 102 I->getDebugLoc().getScopeAndInlinedAt(Scope, IA, I->getContext()); | 105 I->getDebugLoc().getScopeAndInlinedAt(Scope, IA, I->getContext()); |
| 103 if (Scope) EnumerateMetadata(Scope); | 106 if (Scope) EnumerateMetadata(Scope); |
| 104 if (IA) EnumerateMetadata(IA); | 107 if (IA) EnumerateMetadata(IA); |
| 105 } | 108 } |
| 106 } | 109 } |
| 107 } | 110 } |
| 108 | 111 |
| 112 // Optimized type indicies to put "common" expected types in with small | |
| 113 // indices. | |
| 114 OptimizeTypes(M); | |
| 115 | |
| 109 // Optimize constant ordering. | 116 // Optimize constant ordering. |
| 110 OptimizeConstants(FirstConstant, Values.size()); | 117 OptimizeConstants(FirstConstant, Values.size()); |
| 111 } | 118 } |
| 112 | 119 |
| 120 void NaClValueEnumerator::OptimizeTypes(const Module *M) { | |
| 121 | |
| 122 // Sort types by count, so that we can index them based on | |
| 123 // frequency. | |
| 124 std::set<unsigned> type_counts; | |
| 125 typedef std::set<Type*> TypeSetType; | |
| 126 std::map<unsigned, TypeSetType> usage_count_map; | |
| 127 | |
| 128 for (TypeCountMapType::iterator iter = TypeCountMap->begin(); | |
| 129 iter != TypeCountMap->end(); ++ iter) { | |
| 130 type_counts.insert(iter->second); | |
| 131 usage_count_map[iter->second].insert(iter->first); | |
| 132 } | |
| 133 | |
| 134 // Reset type tracking maps, so that we can re-enter based | |
| 135 // on fequency ordering. | |
| 136 delete TypeCountMap; | |
| 137 TypeCountMap = NULL; | |
| 138 Types.clear(); | |
| 139 TypeMap.clear(); | |
| 140 | |
| 141 // Start by adding Common integer types. | |
| 142 EnumerateType(Type::getInt1Ty(M->getContext())); | |
| 143 EnumerateType(Type::getInt8Ty(M->getContext())); | |
| 144 EnumerateType(Type::getInt16Ty(M->getContext())); | |
| 145 EnumerateType(Type::getInt32Ty(M->getContext())); | |
| 146 EnumerateType(Type::getInt64Ty(M->getContext())); | |
| 147 | |
| 148 // Add common float types. | |
| 149 FirstFloatTypeID = TypeMap.size(); | |
|
jvoung (off chromium)
2013/04/29 18:35:42
why can't FirstFloatTypeID just be a local variabl
Karl
2013/04/29 22:19:16
Removed, since we don't use value yet.
| |
| 150 assert(FirstFloatTypeID == 5 && "Float first type id wrong!"); | |
| 151 EnumerateType(Type::getHalfTy(M->getContext())); | |
|
Derek Schuff
2013/04/29 19:38:42
half types are not allowed in the pnacl ABI. so if
Karl
2013/04/29 22:19:16
Note: Since these types are specific to NaCl, I wi
| |
| 152 EnumerateType(Type::getFloatTy(M->getContext())); | |
| 153 EnumerateType(Type::getDoubleTy(M->getContext())); | |
| 154 | |
| 155 // Insert remaining types, based on frequency. | |
| 156 for (std::set<unsigned>::reverse_iterator count_iter = type_counts.rbegin(); | |
| 157 count_iter != type_counts.rend(); ++count_iter) { | |
| 158 TypeSetType& count_types = usage_count_map[*count_iter]; | |
| 159 for (TypeSetType::iterator type_iter = count_types.begin(); | |
| 160 type_iter != count_types.end(); ++type_iter) { | |
| 161 EnumerateType(*type_iter); | |
| 162 } | |
| 163 } | |
| 164 } | |
| 165 | |
| 113 unsigned NaClValueEnumerator::getInstructionID(const Instruction *Inst) const { | 166 unsigned NaClValueEnumerator::getInstructionID(const Instruction *Inst) const { |
| 114 InstructionMapType::const_iterator I = InstructionMap.find(Inst); | 167 InstructionMapType::const_iterator I = InstructionMap.find(Inst); |
| 115 assert(I != InstructionMap.end() && "Instruction is not mapped!"); | 168 assert(I != InstructionMap.end() && "Instruction is not mapped!"); |
| 116 return I->second; | 169 return I->second; |
| 117 } | 170 } |
| 118 | 171 |
| 119 void NaClValueEnumerator::setInstructionID(const Instruction *I) { | 172 void NaClValueEnumerator::setInstructionID(const Instruction *I) { |
| 120 InstructionMap[I] = InstructionCount++; | 173 InstructionMap[I] = InstructionCount++; |
| 121 } | 174 } |
| 122 | 175 |
| (...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 345 } | 398 } |
| 346 } | 399 } |
| 347 | 400 |
| 348 // Add the value. | 401 // Add the value. |
| 349 Values.push_back(std::make_pair(V, 1U)); | 402 Values.push_back(std::make_pair(V, 1U)); |
| 350 ValueID = Values.size(); | 403 ValueID = Values.size(); |
| 351 } | 404 } |
| 352 | 405 |
| 353 | 406 |
| 354 void NaClValueEnumerator::EnumerateType(Type *Ty) { | 407 void NaClValueEnumerator::EnumerateType(Type *Ty) { |
| 408 // This function is used to enumerate types referenced by the given | |
| 409 // type. This function is called in two phases, based on the value | |
| 410 // of TypeCountMap. These phases are: | |
| 411 // | |
| 412 // (1) In this phase, TypeCountMap!=NULL. We are collecting types | |
| 413 // and all corresponding (implicitly) referenced types. In addition, | |
| 414 // we are keeping track of the number of references to each type in | |
| 415 // TypeCountMap. These reference counts will be used by method | |
| 416 // OptimizeTypes to associate the smallest type ID's with the most | |
| 417 // referenced types. | |
| 418 // | |
| 419 // (2) In this phase, TypeCountMap==NUll. We are registering types based on | |
|
jvoung (off chromium)
2013/04/29 18:35:42
NUll -> NULL
Karl
2013/04/29 22:19:16
Done.
| |
| 420 // frequency. To miniize type IDs for frequently used types, (unlike | |
|
Derek Schuff
2013/04/29 19:38:42
miniize->minimize
Karl
2013/04/29 22:19:16
Done.
| |
| 421 // the other two contextx) we are inserting the minimal (implicitly) | |
|
jvoung (off chromium)
2013/04/29 18:35:42
contextx -> contexts
Karl
2013/04/29 22:19:16
Done.
| |
| 422 // referenced types needed for each type. | |
| 355 unsigned *TypeID = &TypeMap[Ty]; | 423 unsigned *TypeID = &TypeMap[Ty]; |
| 356 | 424 |
| 425 if (TypeCountMap) ++((*TypeCountMap)[Ty]); | |
| 426 | |
| 357 // We've already seen this type. | 427 // We've already seen this type. |
| 358 if (*TypeID) | 428 if (*TypeID) |
| 359 return; | 429 return; |
| 360 | 430 |
| 361 // If it is a non-anonymous struct, mark the type as being visited so that we | 431 // 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 | 432 // don't recursively visit it. This is safe because we allow forward |
| 363 // references of these in the bitcode reader. | 433 // references of these in the bitcode reader. |
| 434 bool EnumerateSubtypes = true; | |
|
jvoung (off chromium)
2013/04/29 18:35:42
move variable decl to under the comment about "If
Karl
2013/04/29 22:19:16
Done.
| |
| 364 if (StructType *STy = dyn_cast<StructType>(Ty)) | 435 if (StructType *STy = dyn_cast<StructType>(Ty)) |
| 365 if (!STy->isLiteral()) | 436 if (!STy->isLiteral()) |
| 366 *TypeID = ~0U; | 437 *TypeID = ~0U; |
| 367 | 438 |
| 439 // If in the second phase, don't expand pointers to structures, since | |
| 440 // we can just generate a forward reference to it. This way, we don't | |
| 441 // use up unnecessary (small) ID values just to define the pointer. | |
| 442 if (TypeCountMap == NULL) | |
| 443 if (PointerType *PTy = dyn_cast<PointerType>(Ty)) | |
| 444 if (StructType *STy = dyn_cast<StructType>(Ty)) | |
|
jvoung (off chromium)
2013/04/29 18:35:42
Is this really supposed to be "Ty" in both casts?
Karl
2013/04/29 22:19:16
Good point. Fixing.
| |
| 445 if (!STy->isLiteral()) | |
| 446 EnumerateSubtypes = false; | |
| 447 | |
| 368 // Enumerate all of the subtypes before we enumerate this type. This ensures | 448 // 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. | 449 // 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(); | 450 if (EnumerateSubtypes) { |
| 371 I != E; ++I) | 451 for (Type::subtype_iterator I = Ty->subtype_begin(), E = Ty->subtype_end(); |
| 372 EnumerateType(*I); | 452 I != E; ++I) |
| 453 EnumerateType(*I); | |
| 454 } | |
| 373 | 455 |
| 374 // Refresh the TypeID pointer in case the table rehashed. | 456 // Refresh the TypeID pointer in case the table rehashed. |
| 375 TypeID = &TypeMap[Ty]; | 457 TypeID = &TypeMap[Ty]; |
| 376 | 458 |
| 377 // Check to see if we got the pointer another way. This can happen when | 459 // 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. | 460 // enumerating recursive types that hit the base case deeper than they start. |
| 379 // | 461 // |
| 380 // If this is actually a struct that we are treating as forward ref'able, | 462 // 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. | 463 // then emit the definition now that all of its contents are available. |
| 382 if (*TypeID && *TypeID != ~0U) | 464 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 | 613 /// specified basic block. This is relatively expensive information, so it |
| 532 /// should only be used by rare constructs such as address-of-label. | 614 /// should only be used by rare constructs such as address-of-label. |
| 533 unsigned NaClValueEnumerator::getGlobalBasicBlockID(const BasicBlock *BB) const { | 615 unsigned NaClValueEnumerator::getGlobalBasicBlockID(const BasicBlock *BB) const { |
| 534 unsigned &Idx = GlobalBasicBlockIDs[BB]; | 616 unsigned &Idx = GlobalBasicBlockIDs[BB]; |
| 535 if (Idx != 0) | 617 if (Idx != 0) |
| 536 return Idx-1; | 618 return Idx-1; |
| 537 | 619 |
| 538 IncorporateFunctionInfoGlobalBBIDs(BB->getParent(), GlobalBasicBlockIDs); | 620 IncorporateFunctionInfoGlobalBBIDs(BB->getParent(), GlobalBasicBlockIDs); |
| 539 return getGlobalBasicBlockID(BB); | 621 return getGlobalBasicBlockID(BB); |
| 540 } | 622 } |
| 541 | |
| OLD | NEW |