Use *OL = OperandList;
for (std::vector<Constant*>::const_iterator I = V.begin(), E = V.end();
I != E; ++I, ++OL) {
- Constant *E = *I;
- assert((E->getType() == T->getElementType() ||
+ Constant *C = *I;
+ assert((C->getType() == T->getElementType() ||
(T->isAbstract() &&
- E->getType()->getTypeID() == T->getElementType()->getTypeID())) &&
+ C->getType()->getTypeID() == T->getElementType()->getTypeID())) &&
"Initializer for array element doesn't match array element type!");
- OL->init(E, this);
+ OL->init(C, this);
}
}
Use *OL = OperandList;
for (std::vector<Constant*>::const_iterator I = V.begin(), E = V.end();
I != E; ++I, ++OL) {
- Constant *E = *I;
- assert((E->getType() == T->getElementType(I-V.begin()) ||
+ Constant *C = *I;
+ assert((C->getType() == T->getElementType(I-V.begin()) ||
((T->getElementType(I-V.begin())->isAbstract() ||
- E->getType()->isAbstract()) &&
+ C->getType()->isAbstract()) &&
T->getElementType(I-V.begin())->getTypeID() ==
- E->getType()->getTypeID())) &&
+ C->getType()->getTypeID())) &&
"Initializer for struct element doesn't match struct element type!");
- OL->init(E, this);
+ OL->init(C, this);
}
}
Use *OL = OperandList;
for (std::vector<Constant*>::const_iterator I = V.begin(), E = V.end();
I != E; ++I, ++OL) {
- Constant *E = *I;
- assert((E->getType() == T->getElementType() ||
+ Constant *C = *I;
+ assert((C->getType() == T->getElementType() ||
(T->isAbstract() &&
- E->getType()->getTypeID() == T->getElementType()->getTypeID())) &&
+ C->getType()->getTypeID() == T->getElementType()->getTypeID())) &&
"Initializer for packed element doesn't match packed element type!");
- OL->init(E, this);
+ OL->init(C, this);
}
}
}
};
+/// ExtractElementConstantExpr - This class is private to
+/// Constants.cpp, and is used behind the scenes to implement
+/// extractelement constant exprs.
+class ExtractElementConstantExpr : public ConstantExpr {
+ Use Ops[2];
+public:
+ ExtractElementConstantExpr(Constant *C1, Constant *C2)
+ : ConstantExpr(cast<PackedType>(C1->getType())->getElementType(),
+ Instruction::ExtractElement, Ops, 2) {
+ Ops[0].init(C1, this);
+ Ops[1].init(C2, this);
+ }
+};
+
+/// InsertElementConstantExpr - This class is private to
+/// Constants.cpp, and is used behind the scenes to implement
+/// insertelement constant exprs.
+class InsertElementConstantExpr : public ConstantExpr {
+ Use Ops[3];
+public:
+ InsertElementConstantExpr(Constant *C1, Constant *C2, Constant *C3)
+ : ConstantExpr(C1->getType(), Instruction::InsertElement,
+ Ops, 3) {
+ Ops[0].init(C1, this);
+ Ops[1].init(C2, this);
+ Ops[2].init(C3, this);
+ }
+};
+
/// GetElementPtrConstantExpr - This class is private to Constants.cpp, and is
/// used behind the scenes to implement getelementpr constant exprs.
struct GetElementPtrConstantExpr : public ConstantExpr {
}
namespace {
- template<class ValType, class TypeClass, class ConstantClass>
+ template<class ValType, class TypeClass, class ConstantClass,
+ bool HasLargeKey = false /*true for arrays and structs*/ >
class ValueMap : public AbstractTypeUser {
public:
typedef std::pair<const TypeClass*, ValType> MapKey;
typedef std::map<MapKey, ConstantClass *> MapTy;
typedef typename MapTy::iterator MapIterator;
private:
+ /// Map - This is the main map from the element descriptor to the Constants.
+ /// This is the primary way we avoid creating two of the same shape
+ /// constant.
MapTy Map;
+
+ /// InverseMap - If "HasLargeKey" is true, this contains an inverse mapping
+ /// from the constants to their element in Map. This is important for
+ /// removal of constants from the array, which would otherwise have to scan
+ /// through the map with very large keys.
+ std::map<ConstantClass*, MapIterator> InverseMap;
typedef std::map<const TypeClass*, MapIterator> AbstractTypeMapTy;
AbstractTypeMapTy AbstractTypeMap;
Constants.push_back(I->second);
Map.clear();
AbstractTypeMap.clear();
+ InverseMap.clear();
}
public:
Exists = !IP.second;
return IP.first;
}
+
+private:
+ MapIterator FindExistingElement(ConstantClass *CP) {
+ if (HasLargeKey) {
+ typename std::map<ConstantClass*, MapIterator>::iterator
+ IMI = InverseMap.find(CP);
+ assert(IMI != InverseMap.end() && IMI->second != Map.end() &&
+ IMI->second->second == CP &&
+ "InverseMap corrupt!");
+ return IMI->second;
+ }
+ MapIterator I =
+ Map.find(MapKey((TypeClass*)CP->getRawType(), getValType(CP)));
+ if (I == Map.end() || I->second != CP) {
+ // FIXME: This should not use a linear scan. If this gets to be a
+ // performance problem, someone should look at this.
+ for (I = Map.begin(); I != Map.end() && I->second != CP; ++I)
+ /* empty */;
+ }
+ return I;
+ }
+public:
+
/// getOrCreate - Return the specified constant from the map, creating it if
/// necessary.
ConstantClass *getOrCreate(const TypeClass *Ty, const ValType &V) {
//assert(Result->getType() == Ty && "Type specified is not correct!");
I = Map.insert(I, std::make_pair(MapKey(Ty, V), Result));
+ if (HasLargeKey) // Remember the reverse mapping if needed.
+ InverseMap.insert(std::make_pair(Result, I));
+
// If the type of the constant is abstract, make sure that an entry exists
// for it in the AbstractTypeMap.
if (Ty->isAbstract()) {
}
void remove(ConstantClass *CP) {
- MapIterator I = Map.find(MapKey((TypeClass*)CP->getRawType(),
- getValType(CP)));
- if (I == Map.end() || I->second != CP) {
- // FIXME: This should not use a linear scan. If this gets to be a
- // performance problem, someone should look at this.
- for (I = Map.begin(); I != Map.end() && I->second != CP; ++I)
- /* empty */;
- }
-
+ MapIterator I = FindExistingElement(CP);
assert(I != Map.end() && "Constant not found in constant table!");
assert(I->second == CP && "Didn't find correct element?");
+ if (HasLargeKey) // Remember the reverse mapping if needed.
+ InverseMap.erase(CP);
+
// Now that we found the entry, make sure this isn't the entry that
// the AbstractTypeMap points to.
const TypeClass *Ty = I->first.first;
Map.erase(I);
}
+
+ /// MoveConstantToNewSlot - If we are about to change C to be the element
+ /// specified by I, update our internal data structures to reflect this
+ /// fact.
+ void MoveConstantToNewSlot(ConstantClass *C, MapIterator I) {
+ // First, remove the old location of the specified constant in the map.
+ MapIterator OldI = FindExistingElement(C);
+ assert(OldI != Map.end() && "Constant not found in constant table!");
+ assert(OldI->second == C && "Didn't find correct element?");
+
+ // If this constant is the representative element for its abstract type,
+ // update the AbstractTypeMap so that the representative element is I.
+ if (C->getType()->isAbstract()) {
+ typename AbstractTypeMapTy::iterator ATI =
+ AbstractTypeMap.find(C->getType());
+ assert(ATI != AbstractTypeMap.end() &&
+ "Abstract type not in AbstractTypeMap?");
+ if (ATI->second == OldI)
+ ATI->second = I;
+ }
+
+ // Remove the old entry from the map.
+ Map.erase(OldI);
+
+ // Update the inverse map so that we know that this constant is now
+ // located at descriptor I.
+ if (HasLargeKey) {
+ assert(I->second == C && "Bad inversemap entry!");
+ InverseMap[C] = I;
+ }
+ }
+
void refineAbstractType(const DerivedType *OldTy, const Type *NewTy) {
typename AbstractTypeMapTy::iterator I =
AbstractTypeMap.find(cast<TypeClass>(OldTy));
destroyConstantImpl();
}
-void ConstantAggregateZero::replaceUsesOfWithOnConstant(Value *From, Value *To,
- bool DisableChecking) {
- assert(0 && "No uses!");
- abort();
-}
-
-
-
//---- ConstantArray::get() implementation...
//
namespace llvm {
}
typedef ValueMap<std::vector<Constant*>, ArrayType,
- ConstantArray> ArrayConstantsTy;
+ ConstantArray, true /*largekey*/> ArrayConstantsTy;
static ArrayConstantsTy ArrayConstants;
Constant *ConstantArray::get(const ArrayType *Ty,
};
}
-static ValueMap<std::vector<Constant*>, StructType,
- ConstantStruct> StructConstants;
+typedef ValueMap<std::vector<Constant*>, StructType,
+ ConstantStruct, true /*largekey*/> StructConstantsTy;
+static StructConstantsTy StructConstants;
static std::vector<Constant*> getValType(ConstantStruct *CS) {
std::vector<Constant*> Elements;
return new BinaryConstantExpr(V.first, V.second[0], V.second[1]);
if (V.first == Instruction::Select)
return new SelectConstantExpr(V.second[0], V.second[1], V.second[2]);
+ if (V.first == Instruction::ExtractElement)
+ return new ExtractElementConstantExpr(V.second[0], V.second[1]);
+ if (V.first == Instruction::InsertElement)
+ return new InsertElementConstantExpr(V.second[0], V.second[1],
+ V.second[2]);
assert(V.first == Instruction::GetElementPtr && "Invalid ConstantExpr!");
case Instruction::Mul: case Instruction::Div:
case Instruction::Rem:
assert(C1->getType() == C2->getType() && "Op types should be identical!");
- assert((C1->getType()->isInteger() || C1->getType()->isFloatingPoint()) &&
+ assert((C1->getType()->isInteger() || C1->getType()->isFloatingPoint() ||
+ isa<PackedType>(C1->getType())) &&
"Tried to create an arithmetic operation on a non-arithmetic type!");
break;
case Instruction::And:
case Instruction::Or:
case Instruction::Xor:
assert(C1->getType() == C2->getType() && "Op types should be identical!");
- assert(C1->getType()->isIntegral() &&
+ assert((C1->getType()->isIntegral() || isa<PackedType>(C1->getType())) &&
"Tried to create a logical operation on a non-integral type!");
break;
case Instruction::SetLT: case Instruction::SetGT: case Instruction::SetLE:
case Instruction::Shl:
case Instruction::Shr:
assert(C2->getType() == Type::UByteTy && "Shift should be by ubyte!");
- assert(C1->getType()->isInteger() &&
+ assert((C1->getType()->isInteger() || isa<PackedType>(C1->getType())) &&
"Tried to create a shift operation on a non-integer type!");
break;
default:
return getGetElementPtrTy(PointerType::get(Ty), C, IdxList);
}
+Constant *ConstantExpr::getExtractElementTy(const Type *ReqTy, Constant *Val,
+ Constant *Idx) {
+ if (Constant *FC = ConstantFoldExtractElementInstruction(Val, Idx))
+ return FC; // Fold a few common cases...
+ // Look up the constant in the table first to ensure uniqueness
+ std::vector<Constant*> ArgVec(1, Val);
+ ArgVec.push_back(Idx);
+ const ExprMapKeyType &Key = std::make_pair(Instruction::ExtractElement,ArgVec);
+ return ExprConstants.getOrCreate(ReqTy, Key);
+}
+
+Constant *ConstantExpr::getExtractElement(Constant *Val, Constant *Idx) {
+ assert(isa<PackedType>(Val->getType()) &&
+ "Tried to create extractelement operation on non-packed type!");
+ assert(Idx->getType() == Type::UIntTy &&
+ "Extractelement index must be uint type!");
+ return getExtractElementTy(cast<PackedType>(Val->getType())->getElementType(),
+ Val, Idx);
+}
+
+Constant *ConstantExpr::getInsertElementTy(const Type *ReqTy, Constant *Val,
+ Constant *Elt, Constant *Idx) {
+ if (Constant *FC = ConstantFoldInsertElementInstruction(Val, Elt, Idx))
+ return FC; // Fold a few common cases...
+ // Look up the constant in the table first to ensure uniqueness
+ std::vector<Constant*> ArgVec(1, Val);
+ ArgVec.push_back(Elt);
+ ArgVec.push_back(Idx);
+ const ExprMapKeyType &Key = std::make_pair(Instruction::InsertElement,ArgVec);
+ return ExprConstants.getOrCreate(ReqTy, Key);
+}
+
+Constant *ConstantExpr::getInsertElement(Constant *Val, Constant *Elt,
+ Constant *Idx) {
+ assert(isa<PackedType>(Val->getType()) &&
+ "Tried to create insertelement operation on non-packed type!");
+ assert(Elt->getType() == cast<PackedType>(Val->getType())->getElementType()
+ && "Insertelement types must match!");
+ assert(Idx->getType() == Type::UIntTy &&
+ "Insertelement index must be uint type!");
+ return getInsertElementTy(cast<PackedType>(Val->getType())->getElementType(),
+ Val, Elt, Idx);
+}
// destroyConstant - Remove the constant from the constant table...
//
// replaceUsesOfWithOnConstant implementations
void ConstantArray::replaceUsesOfWithOnConstant(Value *From, Value *To,
- bool DisableChecking) {
+ Use *U) {
assert(isa<Constant>(To) && "Cannot make Constant refer to non-constant!");
-
+ Constant *ToC = cast<Constant>(To);
+
+ unsigned OperandToUpdate = U-OperandList;
+ assert(getOperand(OperandToUpdate) == From && "ReplaceAllUsesWith broken!");
+
std::pair<ArrayConstantsTy::MapKey, ConstantArray*> Lookup;
Lookup.first.first = getType();
Lookup.second = this;
+
std::vector<Constant*> &Values = Lookup.first.second;
Values.reserve(getNumOperands()); // Build replacement array.
-
- bool isAllZeros = false; // Does this turn into an all-zeros array?
- for (unsigned i = 0, e = getNumOperands(); i != e; ++i) {
- Constant *Val = getOperand(i);
- if (Val == From) Val = cast<Constant>(To);
- Values.push_back(Val);
- if (isAllZeros) isAllZeros = Val->isNullValue();
+
+ // Fill values with the modified operands of the constant array. Also,
+ // compute whether this turns into an all-zeros array.
+ bool isAllZeros = false;
+ if (!ToC->isNullValue()) {
+ for (Use *O = OperandList, *E = OperandList+getNumOperands(); O != E; ++O)
+ Values.push_back(cast<Constant>(O->get()));
+ } else {
+ isAllZeros = true;
+ for (Use *O = OperandList, *E = OperandList+getNumOperands(); O != E; ++O) {
+ Constant *Val = cast<Constant>(O->get());
+ Values.push_back(Val);
+ if (isAllZeros) isAllZeros = Val->isNullValue();
+ }
}
+ Values[OperandToUpdate] = ToC;
Constant *Replacement = 0;
if (isAllZeros) {
// creating a new constant array, inserting it, replaceallusesof'ing the
// old with the new, then deleting the old... just update the current one
// in place!
- if (I != ArrayConstants.map_end() && I->second == this)
- ++I; // Do not invalidate iterator!
- ArrayConstants.remove(this); // Remove old shape from the map.
+ ArrayConstants.MoveConstantToNewSlot(this, I);
- // Update to the new values.
- for (unsigned i = 0, e = getNumOperands(); i != e; ++i)
- if (getOperand(i) == From)
- setOperand(i, cast<Constant>(To));
+ // Update to the new value.
+ setOperand(OperandToUpdate, ToC);
return;
}
}
// Otherwise, I do need to replace this with an existing value.
assert(Replacement != this && "I didn't contain From!");
- // Everyone using this now uses the replacement...
- if (DisableChecking)
- uncheckedReplaceAllUsesWith(Replacement);
- else
- replaceAllUsesWith(Replacement);
+ // Everyone using this now uses the replacement.
+ uncheckedReplaceAllUsesWith(Replacement);
// Delete the old constant!
destroyConstant();
}
void ConstantStruct::replaceUsesOfWithOnConstant(Value *From, Value *To,
- bool DisableChecking) {
+ Use *U) {
assert(isa<Constant>(To) && "Cannot make Constant refer to non-constant!");
+ Constant *ToC = cast<Constant>(To);
+
+ unsigned OperandToUpdate = U-OperandList;
+ assert(getOperand(OperandToUpdate) == From && "ReplaceAllUsesWith broken!");
+
+ std::pair<StructConstantsTy::MapKey, ConstantStruct*> Lookup;
+ Lookup.first.first = getType();
+ Lookup.second = this;
+ std::vector<Constant*> &Values = Lookup.first.second;
+ Values.reserve(getNumOperands()); // Build replacement struct.
- std::vector<Constant*> Values;
- Values.reserve(getNumOperands()); // Build replacement array...
- for (unsigned i = 0, e = getNumOperands(); i != e; ++i) {
- Constant *Val = getOperand(i);
- if (Val == From) Val = cast<Constant>(To);
- Values.push_back(Val);
+
+ // Fill values with the modified operands of the constant struct. Also,
+ // compute whether this turns into an all-zeros struct.
+ bool isAllZeros = false;
+ if (!ToC->isNullValue()) {
+ for (Use *O = OperandList, *E = OperandList+getNumOperands(); O != E; ++O)
+ Values.push_back(cast<Constant>(O->get()));
+ } else {
+ isAllZeros = true;
+ for (Use *O = OperandList, *E = OperandList+getNumOperands(); O != E; ++O) {
+ Constant *Val = cast<Constant>(O->get());
+ Values.push_back(Val);
+ if (isAllZeros) isAllZeros = Val->isNullValue();
+ }
+ }
+ Values[OperandToUpdate] = ToC;
+
+ Constant *Replacement = 0;
+ if (isAllZeros) {
+ Replacement = ConstantAggregateZero::get(getType());
+ } else {
+ // Check to see if we have this array type already.
+ bool Exists;
+ StructConstantsTy::MapIterator I =
+ StructConstants.InsertOrGetItem(Lookup, Exists);
+
+ if (Exists) {
+ Replacement = I->second;
+ } else {
+ // Okay, the new shape doesn't exist in the system yet. Instead of
+ // creating a new constant struct, inserting it, replaceallusesof'ing the
+ // old with the new, then deleting the old... just update the current one
+ // in place!
+ StructConstants.MoveConstantToNewSlot(this, I);
+
+ // Update to the new value.
+ setOperand(OperandToUpdate, ToC);
+ return;
+ }
}
- Constant *Replacement = ConstantStruct::get(getType(), Values);
assert(Replacement != this && "I didn't contain From!");
- // Everyone using this now uses the replacement...
- if (DisableChecking)
- uncheckedReplaceAllUsesWith(Replacement);
- else
- replaceAllUsesWith(Replacement);
+ // Everyone using this now uses the replacement.
+ uncheckedReplaceAllUsesWith(Replacement);
// Delete the old constant!
destroyConstant();
}
void ConstantPacked::replaceUsesOfWithOnConstant(Value *From, Value *To,
- bool DisableChecking) {
+ Use *U) {
assert(isa<Constant>(To) && "Cannot make Constant refer to non-constant!");
std::vector<Constant*> Values;
Constant *Replacement = ConstantPacked::get(getType(), Values);
assert(Replacement != this && "I didn't contain From!");
- // Everyone using this now uses the replacement...
- if (DisableChecking)
- uncheckedReplaceAllUsesWith(Replacement);
- else
- replaceAllUsesWith(Replacement);
+ // Everyone using this now uses the replacement.
+ uncheckedReplaceAllUsesWith(Replacement);
// Delete the old constant!
destroyConstant();
}
void ConstantExpr::replaceUsesOfWithOnConstant(Value *From, Value *ToV,
- bool DisableChecking) {
+ Use *U) {
assert(isa<Constant>(ToV) && "Cannot make Constant refer to non-constant!");
Constant *To = cast<Constant>(ToV);
if (C2 == From) C2 = To;
if (C3 == From) C3 = To;
Replacement = ConstantExpr::getSelect(C1, C2, C3);
+ } else if (getOpcode() == Instruction::ExtractElement) {
+ Constant *C1 = getOperand(0);
+ Constant *C2 = getOperand(1);
+ if (C1 == From) C1 = To;
+ if (C2 == From) C2 = To;
+ Replacement = ConstantExpr::getExtractElement(C1, C2);
} else if (getNumOperands() == 2) {
Constant *C1 = getOperand(0);
Constant *C2 = getOperand(1);
assert(Replacement != this && "I didn't contain From!");
- // Everyone using this now uses the replacement...
- if (DisableChecking)
- uncheckedReplaceAllUsesWith(Replacement);
- else
- replaceAllUsesWith(Replacement);
+ // Everyone using this now uses the replacement.
+ uncheckedReplaceAllUsesWith(Replacement);
// Delete the old constant!
destroyConstant();