aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2003-10-05 00:17:43 +0000
committerChris Lattner <sabre@nondot.org>2003-10-05 00:17:43 +0000
commited468e37a1b15e17e0fd44e0b39bd53bc4174e69 (patch)
tree343e9ad1a882f760f37f520a1c2e37dfff45f55e
parent5133a5cf2ee42b5a4d4c7af2d90b41af769cc307 (diff)
Type tables are now AbstractTypeUsers. This allows them to merge together
constants as necessary due to type resolution. With this change, the following spec benchmarks now link: 176.gcc, 177.mesa, 252.eon, 253.perlbmk, & 300.twolf. IOW, all SPEC INT and FP benchmarks now link. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@8853 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/VMCore/Constants.cpp352
1 files changed, 217 insertions, 135 deletions
diff --git a/lib/VMCore/Constants.cpp b/lib/VMCore/Constants.cpp
index 8fb665ac0e..3e481fd048 100644
--- a/lib/VMCore/Constants.cpp
+++ b/lib/VMCore/Constants.cpp
@@ -524,19 +524,30 @@ struct ConstantCreator {
}
};
+template<class ConstantClass, class TypeClass>
+struct ConvertConstantType {
+ static void convert(ConstantClass *OldC, const TypeClass *NewTy) {
+ assert(0 && "This type cannot be converted!\n");
+ abort();
+ }
+};
+
namespace {
template<class ValType, class TypeClass, class ConstantClass>
- class ValueMap {
- protected:
- typedef std::pair<const TypeClass*, ValType> ConstHashKey;
- std::map<ConstHashKey, ConstantClass *> Map;
+ class ValueMap : public AbstractTypeUser {
+ typedef std::pair<const TypeClass*, ValType> MapKey;
+ typedef std::map<MapKey, ConstantClass *> MapTy;
+ typedef typename MapTy::iterator MapIterator;
+ MapTy Map;
+
+ typedef std::map<const TypeClass*, MapIterator> AbstractTypeMapTy;
+ AbstractTypeMapTy AbstractTypeMap;
public:
// getOrCreate - Return the specified constant from the map, creating it if
// necessary.
ConstantClass *getOrCreate(const TypeClass *Ty, const ValType &V) {
- ConstHashKey Lookup(Ty, V);
- typename std::map<ConstHashKey,ConstantClass *>::iterator I =
- Map.lower_bound(Lookup);
+ MapKey Lookup(Ty, V);
+ MapIterator I = Map.lower_bound(Lookup);
if (I != Map.end() && I->first == Lookup)
return I->second; // Is it in the map?
@@ -544,20 +555,105 @@ namespace {
ConstantClass *Result =
ConstantCreator<ConstantClass,TypeClass,ValType>::create(Ty, V);
- Map.insert(I, std::make_pair(ConstHashKey(Ty, V), Result));
+
+ /// FIXME: why does this assert fail when loading 176.gcc?
+ //assert(Result->getType() == Ty && "Type specified is not correct!");
+ I = Map.insert(I, std::make_pair(MapKey(Ty, V), Result));
+
+ // If the type of the constant is abstract, make sure that an entry exists
+ // for it in the AbstractTypeMap.
+ if (Ty->isAbstract()) {
+ typename AbstractTypeMapTy::iterator TI =
+ AbstractTypeMap.lower_bound(Ty);
+
+ if (TI == AbstractTypeMap.end() || TI->first != Ty) {
+ // Add ourselves to the ATU list of the type.
+ cast<DerivedType>(Ty)->addAbstractTypeUser(this);
+
+ AbstractTypeMap.insert(TI, std::make_pair(Ty, I));
+ }
+ }
return Result;
}
void remove(ConstantClass *CP) {
- // FIXME: This could be sped up a LOT. If this gets to be a performance
- // problem, someone should look at this.
- for (typename std::map<ConstHashKey, ConstantClass*>::iterator
- I = Map.begin(), E = Map.end(); I != E; ++I)
- if (I->second == CP) {
- Map.erase(I);
- return;
+ // FIXME: This should not use a linear scan. If this gets to be a
+ // performance problem, someone should look at this.
+ MapIterator I = Map.begin();
+ for (MapIterator E = Map.end(); I != E && I->second != CP; ++I)
+ /* empty */;
+
+ assert(I != Map.end() && "Constant not found in constant table!");
+
+ // Now that we found the entry, make sure this isn't the entry that
+ // the AbstractTypeMap points to.
+ const TypeClass *Ty = I->first.first;
+ if (Ty->isAbstract()) {
+ assert(AbstractTypeMap.count(Ty) &&
+ "Abstract type not in AbstractTypeMap?");
+ MapIterator &ATMEntryIt = AbstractTypeMap[Ty];
+ if (ATMEntryIt == I) {
+ // Yes, we are removing the representative entry for this type.
+ // See if there are any other entries of the same type.
+ MapIterator TmpIt = ATMEntryIt;
+
+ // First check the entry before this one...
+ if (TmpIt != Map.begin()) {
+ --TmpIt;
+ if (TmpIt->first.first != Ty) // Not the same type, move back...
+ ++TmpIt;
+ }
+
+ // If we didn't find the same type, try to move forward...
+ if (TmpIt == ATMEntryIt) {
+ ++TmpIt;
+ if (TmpIt == Map.end() || TmpIt->first.first != Ty)
+ --TmpIt; // No entry afterwards with the same type
+ }
+
+ // If there is another entry in the map of the same abstract type,
+ // update the AbstractTypeMap entry now.
+ if (TmpIt != ATMEntryIt) {
+ ATMEntryIt = TmpIt;
+ } else {
+ // Otherwise, we are removing the last instance of this type
+ // from the table. Remove from the ATM, and from user list.
+ cast<DerivedType>(Ty)->removeAbstractTypeUser(this);
+ AbstractTypeMap.erase(Ty);
+ }
}
- assert(0 && "Constant not found in constant table!");
+ }
+
+ Map.erase(I);
+ }
+
+ void refineAbstractType(const DerivedType *OldTy, const Type *NewTy) {
+ typename AbstractTypeMapTy::iterator I =
+ AbstractTypeMap.find(cast<TypeClass>(OldTy));
+
+ assert(I != AbstractTypeMap.end() &&
+ "Abstract type not in AbstractTypeMap?");
+
+ // Convert a constant at a time until the last one is gone. The last one
+ // leaving will remove() itself, causing the AbstractTypeMapEntry to be
+ // eliminated eventually.
+ do {
+ ConvertConstantType<ConstantClass,
+ TypeClass>::convert(I->second->second,
+ cast<TypeClass>(NewTy));
+
+ I = AbstractTypeMap.find(cast<TypeClass>(OldTy));
+ } while (I != AbstractTypeMap.end());
+ }
+
+ // If the type became concrete without being refined to any other existing
+ // type, we just remove ourselves from the ATU list.
+ void typeBecameConcrete(const DerivedType *AbsTy) {
+ AbsTy->removeAbstractTypeUser(this);
+ }
+
+ void dump() const {
+ std::cerr << "Constant.cpp: ValueMap\n";
}
};
}
@@ -593,6 +689,22 @@ ConstantFP *ConstantFP::get(const Type *Ty, double V) {
//---- ConstantArray::get() implementation...
//
+
+template<>
+struct ConvertConstantType<ConstantArray, ArrayType> {
+ static void convert(ConstantArray *OldC, const ArrayType *NewTy) {
+ // Make everyone now use a constant of the new type...
+ std::vector<Constant*> C;
+ for (unsigned i = 0, e = OldC->getNumOperands(); i != e; ++i)
+ C.push_back(cast<Constant>(OldC->getOperand(i)));
+ Constant *New = ConstantArray::get(NewTy, C);
+ assert(New != OldC && "Didn't replace constant??");
+ OldC->uncheckedReplaceAllUsesWith(New);
+ OldC->destroyConstant(); // This constant is now dead, destroy it.
+ }
+};
+
+
static ValueMap<std::vector<Constant*>, ArrayType,
ConstantArray> ArrayConstants;
@@ -608,26 +720,6 @@ void ConstantArray::destroyConstant() {
destroyConstantImpl();
}
-#if 0
-/// refineAbstractType - If this callback is invoked, then this constant is of a
-/// derived type, change all users to use a concrete constant of the new type.
-///
-void ConstantArray::refineAbstractType(const DerivedType *OldTy,
- const Type *NewTy) {
- if (OldTy == NewTy) return;
-
- // Make everyone now use a constant of the new type...
- std::vector<Constant*> C;
- for (unsigned i = 0, e = getNumOperands(); i != e; ++i)
- C.push_back(cast<Constant>(getOperand(i)));
- Constant *New = ConstantArray::get(cast<ArrayType>(NewTy), C);
- if (New != this) {
- uncheckedReplaceAllUsesWith(New);
- destroyConstant(); // This constant is now dead, destroy it.
- }
-}
-#endif
-
// ConstantArray::get(const string&) - Return an array that is initialized to
// contain the specified string. A null terminator is added to the specified
// string so that it may be used in a natural way...
@@ -662,6 +754,22 @@ std::string ConstantArray::getAsString() const {
//---- ConstantStruct::get() implementation...
//
+
+template<>
+struct ConvertConstantType<ConstantStruct, StructType> {
+ static void convert(ConstantStruct *OldC, const StructType *NewTy) {
+ // Make everyone now use a constant of the new type...
+ std::vector<Constant*> C;
+ for (unsigned i = 0, e = OldC->getNumOperands(); i != e; ++i)
+ C.push_back(cast<Constant>(OldC->getOperand(i)));
+ Constant *New = ConstantStruct::get(NewTy, C);
+ assert(New != OldC && "Didn't replace constant??");
+
+ OldC->uncheckedReplaceAllUsesWith(New);
+ OldC->destroyConstant(); // This constant is now dead, destroy it.
+ }
+};
+
static ValueMap<std::vector<Constant*>, StructType,
ConstantStruct> StructConstants;
@@ -677,26 +785,6 @@ void ConstantStruct::destroyConstant() {
destroyConstantImpl();
}
-#if 0
-/// refineAbstractType - If this callback is invoked, then this constant is of a
-/// derived type, change all users to use a concrete constant of the new type.
-///
-void ConstantStruct::refineAbstractType(const DerivedType *OldTy,
- const Type *NewTy) {
- if (OldTy == NewTy) return;
-
- // Make everyone now use a constant of the new type...
- std::vector<Constant*> C;
- for (unsigned i = 0, e = getNumOperands(); i != e; ++i)
- C.push_back(cast<Constant>(getOperand(i)));
- Constant *New = ConstantStruct::get(cast<StructType>(NewTy), C);
- if (New != this) {
- uncheckedReplaceAllUsesWith(New);
- destroyConstant(); // This constant is now dead, destroy it.
- }
-}
-#endif
-
//---- ConstantPointerNull::get() implementation...
//
@@ -708,6 +796,17 @@ struct ConstantCreator<ConstantPointerNull, PointerType, ValType> {
}
};
+template<>
+struct ConvertConstantType<ConstantPointerNull, PointerType> {
+ static void convert(ConstantPointerNull *OldC, const PointerType *NewTy) {
+ // Make everyone now use a constant of the new type...
+ Constant *New = ConstantPointerNull::get(NewTy);
+ assert(New != OldC && "Didn't replace constant??");
+ OldC->uncheckedReplaceAllUsesWith(New);
+ OldC->destroyConstant(); // This constant is now dead, destroy it.
+ }
+};
+
static ValueMap<char, PointerType, ConstantPointerNull> NullPtrConstants;
ConstantPointerNull *ConstantPointerNull::get(const PointerType *Ty) {
@@ -721,26 +820,6 @@ void ConstantPointerNull::destroyConstant() {
destroyConstantImpl();
}
-#if 0
-/// refineAbstractType - If this callback is invoked, then this constant is of a
-/// derived type, change all users to use a concrete constant of the new type.
-///
-void ConstantPointerNull::refineAbstractType(const DerivedType *OldTy,
- const Type *NewTy) {
- if (OldTy == NewTy) return;
-
- // Make everyone now use a constant of the new type...
- Constant *New = ConstantPointerNull::get(cast<PointerType>(NewTy));
- if (New != this) {
- uncheckedReplaceAllUsesWith(New);
-
- // This constant is now dead, destroy it.
- destroyConstant();
- }
-}
-#endif
-
-
//---- ConstantPointerRef::get() implementation...
//
@@ -775,17 +854,46 @@ struct ConstantCreator<ConstantExpr, Type, ExprMapKeyType> {
assert(V.first == Instruction::GetElementPtr && "Invalid ConstantExpr!");
- // Check that the indices list is valid...
- std::vector<Value*> ValIdxList(V.second.begin()+1, V.second.end());
- const Type *DestTy = GetElementPtrInst::getIndexedType(Ty, ValIdxList,
- true);
- assert(DestTy && "Invalid index list for GetElementPtr expression");
-
std::vector<Constant*> IdxList(V.second.begin()+1, V.second.end());
- return new ConstantExpr(V.second[0], IdxList, PointerType::get(DestTy));
+ return new ConstantExpr(V.second[0], IdxList, Ty);
+ }
+};
+
+template<>
+struct ConvertConstantType<ConstantExpr, Type> {
+ static void convert(ConstantExpr *OldC, const Type *NewTy) {
+ Constant *New;
+ switch (OldC->getOpcode()) {
+ case Instruction::Cast:
+ New = ConstantExpr::getCast(OldC->getOperand(0), NewTy);
+ break;
+ case Instruction::Shl:
+ case Instruction::Shr:
+ New = ConstantExpr::getShiftTy(NewTy, OldC->getOpcode(),
+ OldC->getOperand(0), OldC->getOperand(1));
+ break;
+ default:
+ assert(OldC->getOpcode() >= Instruction::BinaryOpsBegin &&
+ OldC->getOpcode() < Instruction::BinaryOpsEnd);
+ New = ConstantExpr::getTy(NewTy, OldC->getOpcode(), OldC->getOperand(0),
+ OldC->getOperand(1));
+ break;
+ case Instruction::GetElementPtr:
+ // Make everyone now use a constant of the new type...
+ std::vector<Constant*> C;
+ for (unsigned i = 1, e = OldC->getNumOperands(); i != e; ++i)
+ C.push_back(cast<Constant>(OldC->getOperand(i)));
+ New = ConstantExpr::getGetElementPtrTy(NewTy, OldC->getOperand(0), C);
+ break;
+ }
+
+ assert(New != OldC && "Didn't replace constant??");
+ OldC->uncheckedReplaceAllUsesWith(New);
+ OldC->destroyConstant(); // This constant is now dead, destroy it.
}
};
+
static ValueMap<ExprMapKeyType, Type, ConstantExpr> ExprConstants;
Constant *ConstantExpr::getCast(Constant *C, const Type *Ty) {
@@ -798,24 +906,27 @@ Constant *ConstantExpr::getCast(Constant *C, const Type *Ty) {
return ExprConstants.getOrCreate(Ty, Key);
}
-Constant *ConstantExpr::get(unsigned Opcode, Constant *C1, Constant *C2) {
+Constant *ConstantExpr::getTy(const Type *ReqTy, unsigned Opcode,
+ Constant *C1, Constant *C2) {
// Check the operands for consistency first
assert((Opcode >= Instruction::BinaryOpsBegin &&
Opcode < Instruction::BinaryOpsEnd) &&
"Invalid opcode in binary constant expression");
assert(C1->getType() == C2->getType() &&
"Operand types in binary constant expression should match");
-
- if (Constant *FC = ConstantFoldBinaryInstruction(Opcode, C1, C2))
- return FC; // Fold a few common cases...
+
+ if (ReqTy == C1->getType())
+ if (Constant *FC = ConstantFoldBinaryInstruction(Opcode, C1, C2))
+ return FC; // Fold a few common cases...
std::vector<Constant*> argVec(1, C1); argVec.push_back(C2);
ExprMapKeyType Key = std::make_pair(Opcode, argVec);
- return ExprConstants.getOrCreate(C1->getType(), Key);
+ return ExprConstants.getOrCreate(ReqTy, Key);
}
/// getShift - Return a shift left or shift right constant expr
-Constant *ConstantExpr::getShift(unsigned Opcode, Constant *C1, Constant *C2) {
+Constant *ConstantExpr::getShiftTy(const Type *ReqTy, unsigned Opcode,
+ Constant *C1, Constant *C2) {
// Check the operands for consistency first
assert((Opcode == Instruction::Shl ||
Opcode == Instruction::Shr) &&
@@ -829,26 +940,36 @@ Constant *ConstantExpr::getShift(unsigned Opcode, Constant *C1, Constant *C2) {
// Look up the constant in the table first to ensure uniqueness
std::vector<Constant*> argVec(1, C1); argVec.push_back(C2);
ExprMapKeyType Key = std::make_pair(Opcode, argVec);
- return ExprConstants.getOrCreate(C1->getType(), Key);
+ return ExprConstants.getOrCreate(ReqTy, Key);
}
-Constant *ConstantExpr::getGetElementPtr(Constant *C,
- const std::vector<Constant*> &IdxList){
+Constant *ConstantExpr::getGetElementPtrTy(const Type *ReqTy, Constant *C,
+ const std::vector<Constant*> &IdxList) {
if (Constant *FC = ConstantFoldGetElementPtr(C, IdxList))
return FC; // Fold a few common cases...
- const Type *Ty = C->getType();
- assert(isa<PointerType>(Ty) &&
+ assert(isa<PointerType>(C->getType()) &&
"Non-pointer type for constant GetElementPtr expression");
// Look up the constant in the table first to ensure uniqueness
std::vector<Constant*> argVec(1, C);
argVec.insert(argVec.end(), IdxList.begin(), IdxList.end());
-
const ExprMapKeyType &Key = std::make_pair(Instruction::GetElementPtr,argVec);
- return ExprConstants.getOrCreate(Ty, Key);
+ return ExprConstants.getOrCreate(ReqTy, Key);
+}
+
+Constant *ConstantExpr::getGetElementPtr(Constant *C,
+ const std::vector<Constant*> &IdxList){
+ // Get the result type of the getelementptr!
+ std::vector<Value*> VIdxList(IdxList.begin(), IdxList.end());
+
+ const Type *Ty = GetElementPtrInst::getIndexedType(C->getType(), VIdxList,
+ true);
+ assert(Ty && "GEP indices invalid!");
+ return getGetElementPtrTy(PointerType::get(Ty), C, IdxList);
}
+
// destroyConstant - Remove the constant from the constant table...
//
void ConstantExpr::destroyConstant() {
@@ -856,45 +977,6 @@ void ConstantExpr::destroyConstant() {
destroyConstantImpl();
}
-#if 0
-/// refineAbstractType - If this callback is invoked, then this constant is of a
-/// derived type, change all users to use a concrete constant of the new type.
-///
-void ConstantExpr::refineAbstractType(const DerivedType *OldTy,
- const Type *NewTy) {
- if (OldTy == NewTy) return;
-
- // FIXME: These need to use a lower-level implementation method, because the
- // ::get methods intuit the type of the result based on the types of the
- // operands. The operand types may not have had their types resolved yet.
- //
- Constant *New;
- if (getOpcode() == Instruction::Cast) {
- New = getCast(getOperand(0), NewTy);
- } else if (getOpcode() >= Instruction::BinaryOpsBegin &&
- getOpcode() < Instruction::BinaryOpsEnd) {
- New = get(getOpcode(), getOperand(0), getOperand(0));
- } else if (getOpcode() == Instruction::Shl || getOpcode() ==Instruction::Shr){
- New = getShift(getOpcode(), getOperand(0), getOperand(0));
- } else {
- assert(getOpcode() == Instruction::GetElementPtr);
-
- // Make everyone now use a constant of the new type...
- std::vector<Constant*> C;
- for (unsigned i = 1, e = getNumOperands(); i != e; ++i)
- C.push_back(cast<Constant>(getOperand(i)));
- New = ConstantExpr::getGetElementPtr(getOperand(0), C);
- }
- if (New != this) {
- uncheckedReplaceAllUsesWith(New);
- destroyConstant(); // This constant is now dead, destroy it.
- }
-}
-#endif
-
-
-
-
const char *ConstantExpr::getOpcodeName() const {
return Instruction::getOpcodeName(getOpcode());
}