aboutsummaryrefslogtreecommitdiff
path: root/lib/Bytecode/Writer/SlotCalculator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Bytecode/Writer/SlotCalculator.cpp')
-rw-r--r--lib/Bytecode/Writer/SlotCalculator.cpp379
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);