diff options
Diffstat (limited to 'lib/Bytecode/Writer/SlotCalculator.cpp')
-rw-r--r-- | lib/Bytecode/Writer/SlotCalculator.cpp | 379 |
1 files changed, 12 insertions, 367 deletions
diff --git a/lib/Bytecode/Writer/SlotCalculator.cpp b/lib/Bytecode/Writer/SlotCalculator.cpp index 65215fecb1..9115ddbc71 100644 --- a/lib/Bytecode/Writer/SlotCalculator.cpp +++ b/lib/Bytecode/Writer/SlotCalculator.cpp @@ -87,38 +87,7 @@ SlotCalculator::SlotCalculator(const Function *M ) { incorporateFunction(M); // Start out in incorporated state } -unsigned SlotCalculator::getGlobalSlot(const Value *V) const { - assert(!CompactionTable.empty() && - "This method can only be used when compaction is enabled!"); - std::map<const Value*, unsigned>::const_iterator I = NodeMap.find(V); - assert(I != NodeMap.end() && "Didn't find global slot entry!"); - return I->second; -} - -unsigned SlotCalculator::getGlobalSlot(const Type* T) const { - std::map<const Type*, unsigned>::const_iterator I = TypeMap.find(T); - assert(I != TypeMap.end() && "Didn't find global slot entry!"); - return I->second; -} - SlotCalculator::TypePlane &SlotCalculator::getPlane(unsigned Plane) { - if (CompactionTable.empty()) { // No compaction table active? - // fall out - } else if (!CompactionTable[Plane].empty()) { // Compaction table active. - assert(Plane < CompactionTable.size()); - return CompactionTable[Plane]; - } else { - // Final case: compaction table active, but this plane is not - // compactified. If the type plane is compactified, unmap back to the - // global type plane corresponding to "Plane". - if (!CompactionTypes.empty()) { - const Type *Ty = CompactionTypes[Plane]; - TypeMapType::iterator It = TypeMap.find(Ty); - assert(It != TypeMap.end() && "Type not in global constant map?"); - Plane = It->second; - } - } - // Okay we are just returning an entry out of the main Table. Make sure the // plane exists and return it. if (Plane >= Table.size()) @@ -284,10 +253,6 @@ void SlotCalculator::incorporateFunction(const Function *F) { SC_DEBUG("begin processFunction!\n"); - // If we emitted all of the function constants, build a compaction table. - if (ModuleContainsAllFunctionConstants) - buildCompactionTable(F); - // Update the ModuleLevel entries to be accurate. ModuleLevel.resize(getNumPlanes()); for (unsigned i = 0, e = getNumPlanes(); i != e; ++i) @@ -330,11 +295,6 @@ void SlotCalculator::incorporateFunction(const Function *F) { } } - // If we are building a compaction table, prune out planes that do not benefit - // from being compactified. - if (!CompactionTable.empty()) - pruneCompactionTable(); - SC_DEBUG("end processFunction!\n"); } @@ -345,10 +305,6 @@ void SlotCalculator::purgeFunction() { SC_DEBUG("begin purgeFunction!\n"); - // First, free the compaction map if used. - CompactionNodeMap.clear(); - CompactionTypeMap.clear(); - // Next, remove values from existing type planes for (unsigned i = 0; i != NumModuleTypes; ++i) { // Size of plane before function came @@ -371,23 +327,18 @@ void SlotCalculator::purgeFunction() { ModuleTypeLevel = 0; // Finally, remove any type planes defined by the function... - CompactionTypes.clear(); - if (!CompactionTable.empty()) { - CompactionTable.clear(); - } else { - while (Table.size() > NumModuleTypes) { - TypePlane &Plane = Table.back(); - SC_DEBUG("Removing Plane " << (Table.size()-1) << " of size " - << Plane.size() << "\n"); - while (Plane.size()) { - assert(!isa<GlobalValue>(Plane.back()) && - "Functions cannot define globals!"); - NodeMap.erase(Plane.back()); // Erase from nodemap - Plane.pop_back(); // Shrink plane - } - - Table.pop_back(); // Nuke the plane, we don't like it. + while (Table.size() > NumModuleTypes) { + TypePlane &Plane = Table.back(); + SC_DEBUG("Removing Plane " << (Table.size()-1) << " of size " + << Plane.size() << "\n"); + while (Plane.size()) { + assert(!isa<GlobalValue>(Plane.back()) && + "Functions cannot define globals!"); + NodeMap.erase(Plane.back()); // Erase from nodemap + Plane.pop_back(); // Shrink plane } + + Table.pop_back(); // Nuke the plane, we don't like it. } SC_DEBUG("end purgeFunction!\n"); @@ -397,278 +348,8 @@ static inline bool hasNullValue(const Type *Ty) { return Ty != Type::LabelTy && Ty != Type::VoidTy && !isa<OpaqueType>(Ty); } -/// getOrCreateCompactionTableSlot - This method is used to build up the initial -/// approximation of the compaction table. -unsigned SlotCalculator::getOrCreateCompactionTableSlot(const Value *V) { - std::map<const Value*, unsigned>::iterator I = - CompactionNodeMap.lower_bound(V); - if (I != CompactionNodeMap.end() && I->first == V) - return I->second; // Already exists? - - // Make sure the type is in the table. - unsigned Ty; - if (!CompactionTypes.empty()) - Ty = getOrCreateCompactionTableSlot(V->getType()); - else // If the type plane was decompactified, use the global plane ID - Ty = getSlot(V->getType()); - if (CompactionTable.size() <= Ty) - CompactionTable.resize(Ty+1); - - TypePlane &TyPlane = CompactionTable[Ty]; - - // Make sure to insert the null entry if the thing we are inserting is not a - // null constant. - if (TyPlane.empty() && hasNullValue(V->getType())) { - Value *ZeroInitializer = Constant::getNullValue(V->getType()); - if (V != ZeroInitializer) { - TyPlane.push_back(ZeroInitializer); - CompactionNodeMap[ZeroInitializer] = 0; - } - } - - unsigned SlotNo = TyPlane.size(); - TyPlane.push_back(V); - CompactionNodeMap.insert(std::make_pair(V, SlotNo)); - return SlotNo; -} - -/// getOrCreateCompactionTableSlot - This method is used to build up the initial -/// approximation of the compaction table. -unsigned SlotCalculator::getOrCreateCompactionTableSlot(const Type *T) { - CompactionTypeMapType::iterator I = CompactionTypeMap.lower_bound(T); - if (I != CompactionTypeMap.end() && I->first == T) - return I->second; // Already exists? - - unsigned SlotNo = CompactionTypes.size(); - SC_DEBUG("Inserting Compaction Type #" << SlotNo << ": " << *T << "\n"); - CompactionTypes.push_back(T); - CompactionTypeMap.insert(I, std::make_pair(T, SlotNo)); - return SlotNo; -} - -/// buildCompactionTable - Since all of the function constants and types are -/// stored in the module-level constant table, we don't need to emit a function -/// constant table. Also due to this, the indices for various constants and -/// types might be very large in large programs. In order to avoid blowing up -/// the size of instructions in the bytecode encoding, we build a compaction -/// table, which defines a mapping from function-local identifiers to global -/// identifiers. -void SlotCalculator::buildCompactionTable(const Function *F) { - assert(CompactionNodeMap.empty() && "Compaction table already built!"); - assert(CompactionTypeMap.empty() && "Compaction types already built!"); - // First step, insert the primitive types. - CompactionTable.resize(Type::LastPrimitiveTyID+1); - for (unsigned i = 0; i <= Type::LastPrimitiveTyID; ++i) { - const Type *PrimTy = Type::getPrimitiveType((Type::TypeID)i); - CompactionTypes.push_back(PrimTy); - CompactionTypeMap[PrimTy] = i; - } - CompactionTypeMap[Type::Int1Ty] = CompactionTypes.size(); - CompactionTypes.push_back(Type::Int1Ty); - CompactionTypeMap[Type::Int8Ty] = CompactionTypes.size(); - CompactionTypes.push_back(Type::Int8Ty); - CompactionTypeMap[Type::Int16Ty] = CompactionTypes.size(); - CompactionTypes.push_back(Type::Int16Ty); - CompactionTypeMap[Type::Int32Ty] = CompactionTypes.size(); - CompactionTypes.push_back(Type::Int32Ty); - CompactionTypeMap[Type::Int64Ty] = CompactionTypes.size(); - CompactionTypes.push_back(Type::Int64Ty); - - // Next, include any types used by function arguments. - for (Function::const_arg_iterator I = F->arg_begin(), E = F->arg_end(); - I != E; ++I) - getOrCreateCompactionTableSlot(I->getType()); - - // Next, find all of the types and values that are referred to by the - // instructions in the function. - for (const_inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) { - getOrCreateCompactionTableSlot(I->getType()); - for (unsigned op = 0, e = I->getNumOperands(); op != e; ++op) - if (isa<Constant>(I->getOperand(op)) || isa<InlineAsm>(I->getOperand(op))) - getOrCreateCompactionTableSlot(I->getOperand(op)); - } - - // Now do the constants and global values - const SymbolTable &ST = F->getValueSymbolTable(); - for (SymbolTable::plane_const_iterator PI = ST.plane_begin(), - PE = ST.plane_end(); PI != PE; ++PI) - for (SymbolTable::value_const_iterator VI = PI->second.begin(), - VE = PI->second.end(); VI != VE; ++VI) - if (isa<Constant>(VI->second) && !isa<GlobalValue>(VI->second)) - getOrCreateCompactionTableSlot(VI->second); - - // Now that we have all of the values in the table, and know what types are - // referenced, make sure that there is at least the zero initializer in any - // used type plane. Since the type was used, we will be emitting instructions - // to the plane even if there are no constants in it. - CompactionTable.resize(CompactionTypes.size()); - for (unsigned i = 0, e = CompactionTable.size(); i != e; ++i) - if (CompactionTable[i].empty() && (i != Type::VoidTyID) && - i != Type::LabelTyID) { - const Type *Ty = CompactionTypes[i]; - SC_DEBUG("Getting Null Value #" << i << " for Type " << *Ty << "\n"); - assert(Ty->getTypeID() != Type::VoidTyID); - assert(Ty->getTypeID() != Type::LabelTyID); - getOrCreateCompactionTableSlot(Constant::getNullValue(Ty)); - } - - // Okay, now at this point, we have a legal compaction table. Since we want - // to emit the smallest possible binaries, do not compactify the type plane if - // it will not save us anything. Because we have not yet incorporated the - // function body itself yet, we don't know whether or not it's a good idea to - // compactify other planes. We will defer this decision until later. - TypeList &GlobalTypes = Types; - - // All of the values types will be scrunched to the start of the types plane - // of the global table. Figure out just how many there are. - assert(!GlobalTypes.empty() && "No global types???"); - unsigned NumFCTypes = GlobalTypes.size()-1; - while (!GlobalTypes[NumFCTypes]->isFirstClassType()) - --NumFCTypes; - - // If there are fewer that 64 types, no instructions will be exploded due to - // the size of the type operands. Thus there is no need to compactify types. - // Also, if the compaction table contains most of the entries in the global - // table, there really is no reason to compactify either. - if (NumFCTypes < 64) { - // Decompactifying types is tricky, because we have to move type planes all - // over the place. At least we don't need to worry about updating the - // CompactionNodeMap for non-types though. - std::vector<TypePlane> TmpCompactionTable; - std::swap(CompactionTable, TmpCompactionTable); - TypeList TmpTypes; - std::swap(TmpTypes, CompactionTypes); - - // Move each plane back over to the uncompactified plane - while (!TmpTypes.empty()) { - const Type *Ty = TmpTypes.back(); - TmpTypes.pop_back(); - CompactionTypeMap.erase(Ty); // Decompactify type! - - // Find the global slot number for this type. - int TySlot = getSlot(Ty); - assert(TySlot != -1 && "Type doesn't exist in global table?"); - - // Now we know where to put the compaction table plane. - if (CompactionTable.size() <= unsigned(TySlot)) - CompactionTable.resize(TySlot+1); - // Move the plane back into the compaction table. - std::swap(CompactionTable[TySlot], TmpCompactionTable[TmpTypes.size()]); - - // And remove the empty plane we just moved in. - TmpCompactionTable.pop_back(); - } - } -} - - -/// pruneCompactionTable - Once the entire function being processed has been -/// incorporated into the current compaction table, look over the compaction -/// table and check to see if there are any values whose compaction will not -/// save us any space in the bytecode file. If compactifying these values -/// serves no purpose, then we might as well not even emit the compactification -/// information to the bytecode file, saving a bit more space. -/// -/// Note that the type plane has already been compactified if possible. -/// -void SlotCalculator::pruneCompactionTable() { - TypeList &TyPlane = CompactionTypes; - for (unsigned ctp = 0, e = CompactionTable.size(); ctp != e; ++ctp) - if (!CompactionTable[ctp].empty()) { - TypePlane &CPlane = CompactionTable[ctp]; - unsigned GlobalSlot = ctp; - if (!TyPlane.empty()) - GlobalSlot = getGlobalSlot(TyPlane[ctp]); - - if (GlobalSlot >= Table.size()) - Table.resize(GlobalSlot+1); - TypePlane &GPlane = Table[GlobalSlot]; - - unsigned ModLevel = getModuleLevel(ctp); - unsigned NumFunctionObjs = CPlane.size()-ModLevel; - - // If the maximum index required if all entries in this plane were merged - // into the global plane is less than 64, go ahead and eliminate the - // plane. - bool PrunePlane = GPlane.size() + NumFunctionObjs < 64; - - // If there are no function-local values defined, and the maximum - // referenced global entry is less than 64, we don't need to compactify. - if (!PrunePlane && NumFunctionObjs == 0) { - unsigned MaxIdx = 0; - for (unsigned i = 0; i != ModLevel; ++i) { - unsigned Idx = NodeMap[CPlane[i]]; - if (Idx > MaxIdx) MaxIdx = Idx; - } - PrunePlane = MaxIdx < 64; - } - - // Ok, finally, if we decided to prune this plane out of the compaction - // table, do so now. - if (PrunePlane) { - TypePlane OldPlane; - std::swap(OldPlane, CPlane); - - // Loop over the function local objects, relocating them to the global - // table plane. - for (unsigned i = ModLevel, e = OldPlane.size(); i != e; ++i) { - const Value *V = OldPlane[i]; - CompactionNodeMap.erase(V); - assert(NodeMap.count(V) == 0 && "Value already in table??"); - getOrCreateSlot(V); - } - - // For compactified global values, just remove them from the compaction - // node map. - for (unsigned i = 0; i != ModLevel; ++i) - CompactionNodeMap.erase(OldPlane[i]); - - // Update the new modulelevel for this plane. - assert(ctp < ModuleLevel.size() && "Cannot set modulelevel!"); - ModuleLevel[ctp] = GPlane.size()-NumFunctionObjs; - assert((int)ModuleLevel[ctp] >= 0 && "Bad computation!"); - } - } -} - -/// Determine if the compaction table is actually empty. Because the -/// compaction table always includes the primitive type planes, we -/// can't just check getCompactionTable().size() because it will never -/// be zero. Furthermore, the ModuleLevel factors into whether a given -/// plane is empty or not. This function does the necessary computation -/// to determine if its actually empty. -bool SlotCalculator::CompactionTableIsEmpty() const { - // Check a degenerate case, just in case. - if (CompactionTable.empty()) - return true; - - // Check each plane - for (unsigned i = 0, e = CompactionTable.size(); i < e; ++i) { - // If the plane is not empty - if (!CompactionTable[i].empty()) { - // If the module level is non-zero then at least the - // first element of the plane is valid and therefore not empty. - unsigned End = getModuleLevel(i); - if (End != 0) - return false; - } - } - // All the compaction table planes are empty so the table is - // considered empty too. - return true; -} int SlotCalculator::getSlot(const Value *V) const { - // If there is a CompactionTable active... - if (!CompactionNodeMap.empty()) { - std::map<const Value*, unsigned>::const_iterator I = - CompactionNodeMap.find(V); - if (I != CompactionNodeMap.end()) - return (int)I->second; - // Otherwise, if it's not in the compaction table, it must be in a - // non-compactified plane. - } - std::map<const Value*, unsigned>::const_iterator I = NodeMap.find(V); if (I != NodeMap.end()) return (int)I->second; @@ -677,16 +358,6 @@ int SlotCalculator::getSlot(const Value *V) const { } int SlotCalculator::getSlot(const Type*T) const { - // If there is a CompactionTable active... - if (!CompactionTypeMap.empty()) { - std::map<const Type*, unsigned>::const_iterator I = - CompactionTypeMap.find(T); - if (I != CompactionTypeMap.end()) - return (int)I->second; - // Otherwise, if it's not in the compaction table, it must be in a - // non-compactified plane. - } - std::map<const Type*, unsigned>::const_iterator I = TypeMap.find(T); if (I != TypeMap.end()) return (int)I->second; @@ -705,8 +376,6 @@ int SlotCalculator::getOrCreateSlot(const Value *V) { if (!isa<GlobalValue>(V)) // Initializers for globals are handled explicitly if (const Constant *C = dyn_cast<Constant>(V)) { - assert(CompactionNodeMap.empty() && - "All needed constants should be in the compaction map already!"); // Do not index the characters that make up constant strings. We emit // constant strings as special entities that don't require their @@ -741,20 +410,6 @@ int SlotCalculator::insertValue(const Value *D, bool dontIgnore) { assert(D && "Can't insert a null value!"); assert(getSlot(D) == -1 && "Value is already in the table!"); - // If we are building a compaction map, and if this plane is being compacted, - // insert the value into the compaction map, not into the global map. - if (!CompactionNodeMap.empty()) { - if (D->getType() == Type::VoidTy) return -1; // Do not insert void values - assert(!isa<Constant>(D) && - "Types, constants, and globals should be in global table!"); - - int Plane = getSlot(D->getType()); - assert(Plane != -1 && CompactionTable.size() > (unsigned)Plane && - "Didn't find value type!"); - if (!CompactionTable[Plane].empty()) - return getOrCreateCompactionTableSlot(D); - } - // If this node does not contribute to a plane, or if the node has a // name and we don't want names, then ignore the silly node... Note that types // do need slot numbers so that we can keep track of where other values land. @@ -773,12 +428,6 @@ int SlotCalculator::insertType(const Type *Ty, bool dontIgnore) { assert(Ty && "Can't insert a null type!"); assert(getSlot(Ty) == -1 && "Type is already in the table!"); - // If we are building a compaction map, and if this plane is being compacted, - // insert the value into the compaction map, not into the global map. - if (!CompactionTypeMap.empty()) { - getOrCreateCompactionTableSlot(Ty); - } - // Insert the current type before any subtypes. This is important because // recursive types elements are inserted in a bottom up order. Changing // this here can break things. For example: @@ -818,11 +467,7 @@ int SlotCalculator::doInsertValue(const Value *D) { // llvm_cerr << "Inserting type '"<<cast<Type>(D)->getDescription() <<"'!\n"; if (Typ->isDerivedType()) { - int ValSlot; - if (CompactionTable.empty()) - ValSlot = getSlot(Typ); - else - ValSlot = getGlobalSlot(Typ); + int ValSlot = getSlot(Typ); if (ValSlot == -1) { // Have we already entered this type? // Nope, this is the first we have seen the type, process it. ValSlot = insertType(Typ, true); |