Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(468)

Side by Side Diff: lib/Bitcode/NaCl/Writer/NaClValueEnumerator.cpp

Issue 14495008: Create type IDs based on reference counts. (Closed) Base URL: http://git.chromium.org/native_client/pnacl-llvm.git@master
Patch Set: Fix typo in comment. Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 feild
jvoung (off chromium) 2013/05/15 21:01:36 feild -> field
Karl 2013/05/20 21:48:51 Done.
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
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
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 // Define common primitive types that we want with very small
132 //indicies, since they are used in many unary/binary operators.
133 std::vector<Type*> used_primitive_types;
134 {
135 std::vector<Type*> primitive_types;
136 // Start by adding Common integer types.
137 primitive_types.push_back(Type::getInt1Ty(M->getContext()));
138 primitive_types.push_back(Type::getInt8Ty(M->getContext()));
139 primitive_types.push_back(Type::getInt16Ty(M->getContext()));
140 primitive_types.push_back(Type::getInt32Ty(M->getContext()));
141 primitive_types.push_back(Type::getInt64Ty(M->getContext()));
142
143 // Add common float types.
144 // Note: This list is specific to NaCL, and one may want to use a
145 // more complete list if adding to LLVM bitcode format.
146 primitive_types.push_back(Type::getHalfTy(M->getContext()));
147 primitive_types.push_back(Type::getFloatTy(M->getContext()));
148 primitive_types.push_back(Type::getDoubleTy(M->getContext()));
149
150 for (std::vector<Type*>::iterator iter = primitive_types.begin();
151 iter != primitive_types.end(); ++iter) {
152 if (TypeMap.find(*iter) != TypeMap.end()) {
153 used_primitive_types.push_back(*iter);
154 }
155 }
156 }
157
158 // Sort types by count, so that we can index them based on
159 // frequency.
160 std::set<unsigned> type_counts;
161 typedef std::set<Type*> TypeSetType;
162 std::map<unsigned, TypeSetType> usage_count_map;
163
164 for (TypeCountMapType::iterator iter = TypeCountMap->begin();
165 iter != TypeCountMap->end(); ++ iter) {
166 type_counts.insert(iter->second);
167 usage_count_map[iter->second].insert(iter->first);
168 }
169
170 // Reset type tracking maps, so that we can re-enter based
171 // on fequency ordering.
172 TypeCountMap = NULL;
173 Types.clear();
174 TypeMap.clear();
175
176 // Add common primitive types that are used.
177 for (std::vector<Type*>::iterator iter = used_primitive_types.begin();
178 iter != used_primitive_types.end(); ++iter) {
179 EnumerateType(*iter, true);
180 }
181
182 // Insert remaining types, based on frequency.
183 for (std::set<unsigned>::reverse_iterator count_iter = type_counts.rbegin();
184 count_iter != type_counts.rend(); ++count_iter) {
185 TypeSetType& count_types = usage_count_map[*count_iter];
186 for (TypeSetType::iterator type_iter = count_types.begin();
187 type_iter != count_types.end(); ++type_iter) {
188 EnumerateType(*type_iter, true);
189 }
190 }
191 }
192
113 unsigned NaClValueEnumerator::getInstructionID(const Instruction *Inst) const { 193 unsigned NaClValueEnumerator::getInstructionID(const Instruction *Inst) const {
114 InstructionMapType::const_iterator I = InstructionMap.find(Inst); 194 InstructionMapType::const_iterator I = InstructionMap.find(Inst);
115 assert(I != InstructionMap.end() && "Instruction is not mapped!"); 195 assert(I != InstructionMap.end() && "Instruction is not mapped!");
116 return I->second; 196 return I->second;
117 } 197 }
118 198
119 void NaClValueEnumerator::setInstructionID(const Instruction *I) { 199 void NaClValueEnumerator::setInstructionID(const Instruction *I) {
120 InstructionMap[I] = InstructionCount++; 200 InstructionMap[I] = InstructionCount++;
121 } 201 }
122 202
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after
344 return; 424 return;
345 } 425 }
346 } 426 }
347 427
348 // Add the value. 428 // Add the value.
349 Values.push_back(std::make_pair(V, 1U)); 429 Values.push_back(std::make_pair(V, 1U));
350 ValueID = Values.size(); 430 ValueID = Values.size();
351 } 431 }
352 432
353 433
354 void NaClValueEnumerator::EnumerateType(Type *Ty) { 434 void NaClValueEnumerator::EnumerateType(Type *Ty, bool InsideOptimizeTypes) {
435 // This function is used to enumerate types referenced by the given
436 // module. This function is called in two phases, based on the value
437 // of TypeCountMap. These phases are:
438 //
439 // (1) In this phase, InsideOptimizeTypes=false. We are collecting types
440 // and all corresponding (implicitly) referenced types. In addition,
441 // we are keeping track of the number of references to each type in
442 // TypeCountMap. These reference counts will be used by method
443 // OptimizeTypes to associate the smallest type ID's with the most
444 // referenced types.
445 //
446 // (2) In this phase, InsideOptimizeTypes=true. We are registering types
447 // based on frequency. To minimize type IDs for frequently used
448 // types, (unlike the other context) we are inserting the minimal
449 // (implicitly) referenced types needed for each type.
355 unsigned *TypeID = &TypeMap[Ty]; 450 unsigned *TypeID = &TypeMap[Ty];
356 451
452 if (TypeCountMap) ++((*TypeCountMap)[Ty]);
453
357 // We've already seen this type. 454 // We've already seen this type.
358 if (*TypeID) 455 if (*TypeID)
359 return; 456 return;
360 457
361 // If it is a non-anonymous struct, mark the type as being visited so that we 458 // 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 459 // don't recursively visit it. This is safe because we allow forward
363 // references of these in the bitcode reader. 460 // references of these in the bitcode reader.
364 if (StructType *STy = dyn_cast<StructType>(Ty)) 461 if (StructType *STy = dyn_cast<StructType>(Ty))
365 if (!STy->isLiteral()) 462 if (!STy->isLiteral())
366 *TypeID = ~0U; 463 *TypeID = ~0U;
367 464
465 // If in the second phase (i.e. inside optimize types), don't expand
466 // pointers to structures, since we can just generate a forward
467 // reference to it. This way, we don't use up unnecessary (small) ID
468 // values just to define the pointer.
469 bool EnumerateSubtypes = true;
470 if (InsideOptimizeTypes)
471 if (PointerType *PTy = dyn_cast<PointerType>(Ty))
472 if (StructType *STy = dyn_cast<StructType>(PTy->getElementType()))
473 if (!STy->isLiteral())
474 EnumerateSubtypes = false;
475
368 // Enumerate all of the subtypes before we enumerate this type. This ensures 476 // 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. 477 // 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(); 478 if (EnumerateSubtypes) {
371 I != E; ++I) 479 for (Type::subtype_iterator I = Ty->subtype_begin(), E = Ty->subtype_end();
372 EnumerateType(*I); 480 I != E; ++I)
481 EnumerateType(*I, InsideOptimizeTypes);
482 }
373 483
374 // Refresh the TypeID pointer in case the table rehashed. 484 // Refresh the TypeID pointer in case the table rehashed.
375 TypeID = &TypeMap[Ty]; 485 TypeID = &TypeMap[Ty];
376 486
377 // Check to see if we got the pointer another way. This can happen when 487 // 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. 488 // enumerating recursive types that hit the base case deeper than they start.
379 // 489 //
380 // If this is actually a struct that we are treating as forward ref'able, 490 // 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. 491 // then emit the definition now that all of its contents are available.
382 if (*TypeID && *TypeID != ~0U) 492 if (*TypeID && *TypeID != ~0U)
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
531 /// specified basic block. This is relatively expensive information, so it 641 /// specified basic block. This is relatively expensive information, so it
532 /// should only be used by rare constructs such as address-of-label. 642 /// should only be used by rare constructs such as address-of-label.
533 unsigned NaClValueEnumerator::getGlobalBasicBlockID(const BasicBlock *BB) const { 643 unsigned NaClValueEnumerator::getGlobalBasicBlockID(const BasicBlock *BB) const {
534 unsigned &Idx = GlobalBasicBlockIDs[BB]; 644 unsigned &Idx = GlobalBasicBlockIDs[BB];
535 if (Idx != 0) 645 if (Idx != 0)
536 return Idx-1; 646 return Idx-1;
537 647
538 IncorporateFunctionInfoGlobalBBIDs(BB->getParent(), GlobalBasicBlockIDs); 648 IncorporateFunctionInfoGlobalBBIDs(BB->getParent(), GlobalBasicBlockIDs);
539 return getGlobalBasicBlockID(BB); 649 return getGlobalBasicBlockID(BB);
540 } 650 }
541
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698