Reverting r215966, r215965, r215964, r215963, r215960, r215959, r215958, and r215957 (these commits all rely on previous commits) due to build breakage. These commits cause failed assertions when testing Clang using MSVC 2013. The asserts are triggered from the std::equal call within ArrayRef::equals due to being passed invalid input (ArrayRef.begin() is returning a nullptr which is problematic).
llvm-svn: 215981
diff --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp
index cb7c9e6..45a71dc 100644
--- a/llvm/lib/IR/Constants.cpp
+++ b/llvm/lib/IR/Constants.cpp
@@ -803,11 +803,6 @@
}
Constant *ConstantArray::get(ArrayType *Ty, ArrayRef<Constant*> V) {
- if (Constant *C = getImpl(Ty, V))
- return C;
- return Ty->getContext().pImpl->ArrayConstants.getOrCreate(Ty, V);
-}
-Constant *ConstantArray::getImpl(ArrayType *Ty, ArrayRef<Constant*> V) {
// Empty arrays are canonicalized to ConstantAggregateZero.
if (V.empty())
return ConstantAggregateZero::get(Ty);
@@ -816,6 +811,7 @@
assert(V[i]->getType() == Ty->getElementType() &&
"Wrong type in array element initializer");
}
+ LLVMContextImpl *pImpl = Ty->getContext().pImpl;
// If this is an all-zero array, return a ConstantAggregateZero object. If
// all undef, return an UndefValue, if "all simple", then return a
@@ -897,7 +893,7 @@
}
// Otherwise, we really do want to create a ConstantArray.
- return nullptr;
+ return pImpl->ArrayConstants.getOrCreate(Ty, V);
}
/// getTypeForElements - Return an anonymous struct type to use for a constant
@@ -985,14 +981,9 @@
// ConstantVector accessors.
Constant *ConstantVector::get(ArrayRef<Constant*> V) {
- if (Constant *C = getImpl(V))
- return C;
- VectorType *Ty = VectorType::get(V.front()->getType(), V.size());
- return Ty->getContext().pImpl->VectorConstants.getOrCreate(Ty, V);
-}
-Constant *ConstantVector::getImpl(ArrayRef<Constant*> V) {
assert(!V.empty() && "Vectors can't be empty");
VectorType *T = VectorType::get(V.front()->getType(), V.size());
+ LLVMContextImpl *pImpl = T->getContext().pImpl;
// If this is an all-undef or all-zero vector, return a
// ConstantAggregateZero or UndefValue.
@@ -1084,7 +1075,7 @@
// Otherwise, the element type isn't compatible with ConstantDataVector, or
// the operand list constants a ConstantExpr or something else strange.
- return nullptr;
+ return pImpl->VectorConstants.getOrCreate(T, V);
}
Constant *ConstantVector::getSplat(unsigned NumElts, Constant *V) {
@@ -1478,21 +1469,27 @@
// and return early.
BlockAddress *&NewBA =
getContext().pImpl->BlockAddresses[std::make_pair(NewF, NewBB)];
- if (NewBA) {
- replaceUsesOfWithOnConstantImpl(NewBA);
+ if (!NewBA) {
+ getBasicBlock()->AdjustBlockAddressRefCount(-1);
+
+ // Remove the old entry, this can't cause the map to rehash (just a
+ // tombstone will get added).
+ getContext().pImpl->BlockAddresses.erase(std::make_pair(getFunction(),
+ getBasicBlock()));
+ NewBA = this;
+ setOperand(0, NewF);
+ setOperand(1, NewBB);
+ getBasicBlock()->AdjustBlockAddressRefCount(1);
return;
}
- getBasicBlock()->AdjustBlockAddressRefCount(-1);
+ // Otherwise, I do need to replace this with an existing value.
+ assert(NewBA != this && "I didn't contain From!");
- // Remove the old entry, this can't cause the map to rehash (just a
- // tombstone will get added).
- getContext().pImpl->BlockAddresses.erase(std::make_pair(getFunction(),
- getBasicBlock()));
- NewBA = this;
- setOperand(0, NewF);
- setOperand(1, NewBB);
- getBasicBlock()->AdjustBlockAddressRefCount(1);
+ // Everyone using this now uses the replacement.
+ replaceAllUsesWith(NewBA);
+
+ destroyConstant();
}
//---- ConstantExpr::get() implementations.
@@ -1510,7 +1507,7 @@
LLVMContextImpl *pImpl = Ty->getContext().pImpl;
// Look up the constant in the table first to ensure uniqueness.
- ConstantExprKeyType Key(opc, C);
+ ExprMapKeyType Key(opc, C);
return pImpl->ExprConstants.getOrCreate(Ty, Key);
}
@@ -1845,7 +1842,7 @@
return FC; // Fold a few common cases.
Constant *ArgVec[] = { C1, C2 };
- ConstantExprKeyType Key(Opcode, ArgVec, 0, Flags);
+ ExprMapKeyType Key(Opcode, ArgVec, 0, Flags);
LLVMContextImpl *pImpl = C1->getContext().pImpl;
return pImpl->ExprConstants.getOrCreate(C1->getType(), Key);
@@ -1922,7 +1919,7 @@
return SC; // Fold common cases
Constant *ArgVec[] = { C, V1, V2 };
- ConstantExprKeyType Key(Instruction::Select, ArgVec);
+ ExprMapKeyType Key(Instruction::Select, ArgVec);
LLVMContextImpl *pImpl = C->getContext().pImpl;
return pImpl->ExprConstants.getOrCreate(V1->getType(), Key);
@@ -1957,8 +1954,8 @@
"getelementptr index type missmatch");
ArgVec.push_back(cast<Constant>(Idxs[i]));
}
- const ConstantExprKeyType Key(Instruction::GetElementPtr, ArgVec, 0,
- InBounds ? GEPOperator::IsInBounds : 0);
+ const ExprMapKeyType Key(Instruction::GetElementPtr, ArgVec, 0,
+ InBounds ? GEPOperator::IsInBounds : 0);
LLVMContextImpl *pImpl = C->getContext().pImpl;
return pImpl->ExprConstants.getOrCreate(ReqTy, Key);
@@ -1976,7 +1973,7 @@
// Look up the constant in the table first to ensure uniqueness
Constant *ArgVec[] = { LHS, RHS };
// Get the key type with both the opcode and predicate
- const ConstantExprKeyType Key(Instruction::ICmp, ArgVec, pred);
+ const ExprMapKeyType Key(Instruction::ICmp, ArgVec, pred);
Type *ResultTy = Type::getInt1Ty(LHS->getContext());
if (VectorType *VT = dyn_cast<VectorType>(LHS->getType()))
@@ -1997,7 +1994,7 @@
// Look up the constant in the table first to ensure uniqueness
Constant *ArgVec[] = { LHS, RHS };
// Get the key type with both the opcode and predicate
- const ConstantExprKeyType Key(Instruction::FCmp, ArgVec, pred);
+ const ExprMapKeyType Key(Instruction::FCmp, ArgVec, pred);
Type *ResultTy = Type::getInt1Ty(LHS->getContext());
if (VectorType *VT = dyn_cast<VectorType>(LHS->getType()))
@@ -2018,7 +2015,7 @@
// Look up the constant in the table first to ensure uniqueness
Constant *ArgVec[] = { Val, Idx };
- const ConstantExprKeyType Key(Instruction::ExtractElement, ArgVec);
+ const ExprMapKeyType Key(Instruction::ExtractElement, ArgVec);
LLVMContextImpl *pImpl = Val->getContext().pImpl;
Type *ReqTy = Val->getType()->getVectorElementType();
@@ -2038,7 +2035,7 @@
return FC; // Fold a few common cases.
// Look up the constant in the table first to ensure uniqueness
Constant *ArgVec[] = { Val, Elt, Idx };
- const ConstantExprKeyType Key(Instruction::InsertElement, ArgVec);
+ const ExprMapKeyType Key(Instruction::InsertElement, ArgVec);
LLVMContextImpl *pImpl = Val->getContext().pImpl;
return pImpl->ExprConstants.getOrCreate(Val->getType(), Key);
@@ -2058,7 +2055,7 @@
// Look up the constant in the table first to ensure uniqueness
Constant *ArgVec[] = { V1, V2, Mask };
- const ConstantExprKeyType Key(Instruction::ShuffleVector, ArgVec);
+ const ExprMapKeyType Key(Instruction::ShuffleVector, ArgVec);
LLVMContextImpl *pImpl = ShufTy->getContext().pImpl;
return pImpl->ExprConstants.getOrCreate(ShufTy, Key);
@@ -2078,7 +2075,7 @@
return FC;
Constant *ArgVec[] = { Agg, Val };
- const ConstantExprKeyType Key(Instruction::InsertValue, ArgVec, 0, 0, Idxs);
+ const ExprMapKeyType Key(Instruction::InsertValue, ArgVec, 0, 0, Idxs);
LLVMContextImpl *pImpl = Agg->getContext().pImpl;
return pImpl->ExprConstants.getOrCreate(ReqTy, Key);
@@ -2099,7 +2096,7 @@
return FC;
Constant *ArgVec[] = { Agg };
- const ConstantExprKeyType Key(Instruction::ExtractValue, ArgVec, 0, 0, Idxs);
+ const ExprMapKeyType Key(Instruction::ExtractValue, ArgVec, 0, 0, Idxs);
LLVMContextImpl *pImpl = Agg->getContext().pImpl;
return pImpl->ExprConstants.getOrCreate(ReqTy, Key);
@@ -2655,17 +2652,6 @@
/// work, but would be really slow because it would have to unique each updated
/// array instance.
///
-void Constant::replaceUsesOfWithOnConstantImpl(Constant *Replacement) {
- // 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.
- replaceAllUsesWith(Replacement);
-
- // Delete the old constant!
- destroyConstant();
-}
-
void ConstantArray::replaceUsesOfWithOnConstant(Value *From, Value *To,
Use *U) {
assert(isa<Constant>(To) && "Cannot make Constant refer to non-constant!");
@@ -2692,51 +2678,52 @@
AllSame &= Val == ToC;
}
+ Constant *Replacement = nullptr;
if (AllSame && ToC->isNullValue()) {
- replaceUsesOfWithOnConstantImpl(ConstantAggregateZero::get(getType()));
- return;
- }
- if (AllSame && isa<UndefValue>(ToC)) {
- replaceUsesOfWithOnConstantImpl(UndefValue::get(getType()));
- return;
- }
-
- // Check for any other type of constant-folding.
- if (Constant *C = getImpl(getType(), Values)) {
- replaceUsesOfWithOnConstantImpl(C);
- return;
- }
-
- // Check to see if we have this array type already.
- LLVMContextImpl::ArrayConstantsTy::LookupKey Lookup(
- cast<ArrayType>(getType()), makeArrayRef(Values));
- LLVMContextImpl::ArrayConstantsTy::MapTy::iterator I =
- pImpl->ArrayConstants.find(Lookup);
-
- if (I != pImpl->ArrayConstants.map_end()) {
- replaceUsesOfWithOnConstantImpl(I->first);
- return;
- }
-
- // Okay, the new shape doesn't exist in the system yet. Instead of
- // 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!
- pImpl->ArrayConstants.remove(this);
-
- // Update to the new value. Optimize for the case when we have a single
- // operand that we're changing, but handle bulk updates efficiently.
- if (NumUpdated == 1) {
- unsigned OperandToUpdate = U - OperandList;
- assert(getOperand(OperandToUpdate) == From &&
- "ReplaceAllUsesWith broken!");
- setOperand(OperandToUpdate, ToC);
+ Replacement = ConstantAggregateZero::get(getType());
+ } else if (AllSame && isa<UndefValue>(ToC)) {
+ Replacement = UndefValue::get(getType());
} else {
- for (unsigned I = 0, E = getNumOperands(); I != E; ++I)
- if (getOperand(I) == From)
- setOperand(I, ToC);
+ // Check to see if we have this array type already.
+ LLVMContextImpl::ArrayConstantsTy::LookupKey Lookup(
+ cast<ArrayType>(getType()), makeArrayRef(Values));
+ LLVMContextImpl::ArrayConstantsTy::MapTy::iterator I =
+ pImpl->ArrayConstants.find(Lookup);
+
+ if (I != pImpl->ArrayConstants.map_end()) {
+ Replacement = I->first;
+ } else {
+ // Okay, the new shape doesn't exist in the system yet. Instead of
+ // 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!
+ pImpl->ArrayConstants.remove(this);
+
+ // Update to the new value. Optimize for the case when we have a single
+ // operand that we're changing, but handle bulk updates efficiently.
+ if (NumUpdated == 1) {
+ unsigned OperandToUpdate = U - OperandList;
+ assert(getOperand(OperandToUpdate) == From &&
+ "ReplaceAllUsesWith broken!");
+ setOperand(OperandToUpdate, ToC);
+ } else {
+ for (unsigned i = 0, e = getNumOperands(); i != e; ++i)
+ if (getOperand(i) == From)
+ setOperand(i, ToC);
+ }
+ pImpl->ArrayConstants.insert(this);
+ return;
+ }
}
- pImpl->ArrayConstants.insert(this);
+
+ // 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.
+ replaceAllUsesWith(Replacement);
+
+ // Delete the old constant!
+ destroyConstant();
}
void ConstantStruct::replaceUsesOfWithOnConstant(Value *From, Value *To,
@@ -2776,75 +2763,63 @@
LLVMContextImpl *pImpl = getContext().pImpl;
+ Constant *Replacement = nullptr;
if (isAllZeros) {
- replaceUsesOfWithOnConstantImpl(ConstantAggregateZero::get(getType()));
- return;
- }
- if (isAllUndef) {
- replaceUsesOfWithOnConstantImpl(UndefValue::get(getType()));
- return;
- }
-
- // Check to see if we have this struct type already.
- LLVMContextImpl::StructConstantsTy::LookupKey Lookup(
- cast<StructType>(getType()), makeArrayRef(Values));
- LLVMContextImpl::StructConstantsTy::MapTy::iterator I =
+ Replacement = ConstantAggregateZero::get(getType());
+ } else if (isAllUndef) {
+ Replacement = UndefValue::get(getType());
+ } else {
+ // Check to see if we have this struct type already.
+ LLVMContextImpl::StructConstantsTy::LookupKey Lookup(
+ cast<StructType>(getType()), makeArrayRef(Values));
+ LLVMContextImpl::StructConstantsTy::MapTy::iterator I =
pImpl->StructConstants.find(Lookup);
- if (I != pImpl->StructConstants.map_end()) {
- replaceUsesOfWithOnConstantImpl(I->first);
- return;
+ if (I != pImpl->StructConstants.map_end()) {
+ Replacement = I->first;
+ } 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!
+ pImpl->StructConstants.remove(this);
+
+ // Update to the new value.
+ setOperand(OperandToUpdate, ToC);
+ pImpl->StructConstants.insert(this);
+ return;
+ }
}
- // 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!
- pImpl->StructConstants.remove(this);
+ assert(Replacement != this && "I didn't contain From!");
- // Update to the new value.
- setOperand(OperandToUpdate, ToC);
- pImpl->StructConstants.insert(this);
+ // Everyone using this now uses the replacement.
+ replaceAllUsesWith(Replacement);
+
+ // Delete the old constant!
+ destroyConstant();
}
void ConstantVector::replaceUsesOfWithOnConstant(Value *From, Value *To,
Use *U) {
assert(isa<Constant>(To) && "Cannot make Constant refer to non-constant!");
- Constant *ToC = cast<Constant>(To);
SmallVector<Constant*, 8> Values;
Values.reserve(getNumOperands()); // Build replacement array...
- unsigned NumUpdated = 0;
for (unsigned i = 0, e = getNumOperands(); i != e; ++i) {
Constant *Val = getOperand(i);
- if (Val == From) {
- ++NumUpdated;
- Val = ToC;
- }
+ if (Val == From) Val = cast<Constant>(To);
Values.push_back(Val);
}
- if (Constant *C = getImpl(Values)) {
- replaceUsesOfWithOnConstantImpl(C);
- return;
- }
+ Constant *Replacement = get(Values);
+ assert(Replacement != this && "I didn't contain From!");
- // Update to the new value. Optimize for the case when we have a single
- // operand that we're changing, but handle bulk updates efficiently.
- auto &pImpl = getType()->getContext().pImpl;
- pImpl->VectorConstants.remove(this);
+ // Everyone using this now uses the replacement.
+ replaceAllUsesWith(Replacement);
- if (NumUpdated == 1) {
- unsigned OperandToUpdate = U - OperandList;
- assert(getOperand(OperandToUpdate) == From && "ReplaceAllUsesWith broken!");
- setOperand(OperandToUpdate, ToC);
- } else {
- for (unsigned I = 0, E = getNumOperands(); I != E; ++I)
- if (getOperand(I) == From)
- setOperand(I, ToC);
- }
-
- pImpl->VectorConstants.insert(this);
+ // Delete the old constant!
+ destroyConstant();
}
void ConstantExpr::replaceUsesOfWithOnConstant(Value *From, Value *ToV,
@@ -2861,25 +2836,6 @@
Constant *Replacement = getWithOperands(NewOps);
assert(Replacement != this && "I didn't contain From!");
- // Check if Replacement has no users (and is the same type). Ideally, this
- // check would be done *before* creating Replacement, but threading this
- // through constant-folding isn't trivial.
- if (canBecomeReplacement(Replacement)) {
- // Avoid unnecessary RAUW traffic.
- auto &ExprConstants = getType()->getContext().pImpl->ExprConstants;
- ExprConstants.remove(this);
-
- auto *CE = cast<ConstantExpr>(Replacement);
- for (unsigned I = 0, E = getNumOperands(); I != E; ++I)
- // Only set the operands that have actually changed.
- if (getOperand(I) != CE->getOperand(I))
- setOperand(I, CE->getOperand(I));
-
- CE->destroyConstant();
- ExprConstants.insert(this);
- return;
- }
-
// Everyone using this now uses the replacement.
replaceAllUsesWith(Replacement);
@@ -2887,31 +2843,6 @@
destroyConstant();
}
-bool ConstantExpr::canBecomeReplacement(const Constant *Replacement) const {
- // If Replacement already has users, use it regardless.
- if (!Replacement->use_empty())
- return false;
-
- // Check for anything that could have changed during constant-folding.
- if (getValueID() != Replacement->getValueID())
- return false;
- const auto *CE = cast<ConstantExpr>(Replacement);
- if (getOpcode() != CE->getOpcode())
- return false;
- if (getNumOperands() != CE->getNumOperands())
- return false;
- if (getRawSubclassOptionalData() != CE->getRawSubclassOptionalData())
- return false;
- if (isCompare())
- if (getPredicate() != CE->getPredicate())
- return false;
- if (hasIndices())
- if (getIndices() != CE->getIndices())
- return false;
-
- return true;
-}
-
Instruction *ConstantExpr::getAsInstruction() {
SmallVector<Value*,4> ValueOperands;
for (op_iterator I = op_begin(), E = op_end(); I != E; ++I)
diff --git a/llvm/lib/IR/ConstantsContext.h b/llvm/lib/IR/ConstantsContext.h
index 092de71..c3aefb9 100644
--- a/llvm/lib/IR/ConstantsContext.h
+++ b/llvm/lib/IR/ConstantsContext.h
@@ -29,6 +29,8 @@
#define DEBUG_TYPE "ir"
namespace llvm {
+template<class ValType>
+struct ConstantTraits;
/// UnaryConstantExpr - This class is private to Constants.cpp, and is used
/// behind the scenes to implement unary constant exprs.
@@ -312,234 +314,379 @@
};
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CompareConstantExpr, Value)
-template <class ConstantClass> struct ConstantAggrKeyType;
-struct InlineAsmKeyType;
-struct ConstantExprKeyType;
-
-template <class ConstantClass> struct ConstantInfo;
-template <> struct ConstantInfo<ConstantExpr> {
- typedef ConstantExprKeyType ValType;
- typedef Type TypeClass;
-};
-template <> struct ConstantInfo<InlineAsm> {
- typedef InlineAsmKeyType ValType;
- typedef PointerType TypeClass;
-};
-template <> struct ConstantInfo<ConstantArray> {
- typedef ConstantAggrKeyType<ConstantArray> ValType;
- typedef ArrayType TypeClass;
-};
-template <> struct ConstantInfo<ConstantStruct> {
- typedef ConstantAggrKeyType<ConstantStruct> ValType;
- typedef StructType TypeClass;
-};
-template <> struct ConstantInfo<ConstantVector> {
- typedef ConstantAggrKeyType<ConstantVector> ValType;
- typedef VectorType TypeClass;
-};
-
-template <class ConstantClass> struct ConstantAggrKeyType {
- ArrayRef<Constant *> Operands;
- ConstantAggrKeyType(ArrayRef<Constant *> Operands) : Operands(Operands) {}
- ConstantAggrKeyType(const ConstantClass *C,
- SmallVectorImpl<Constant *> &Storage) {
- assert(Storage.empty() && "Expected empty storage");
- for (unsigned I = 0, E = C->getNumOperands(); I != E; ++I)
- Storage.push_back(C->getOperand(I));
- Operands = Storage;
+struct ExprMapKeyType {
+ ExprMapKeyType(unsigned opc,
+ ArrayRef<Constant*> ops,
+ unsigned short flags = 0,
+ unsigned short optionalflags = 0,
+ ArrayRef<unsigned> inds = None)
+ : opcode(opc), subclassoptionaldata(optionalflags), subclassdata(flags),
+ operands(ops.begin(), ops.end()), indices(inds.begin(), inds.end()) {}
+ uint8_t opcode;
+ uint8_t subclassoptionaldata;
+ uint16_t subclassdata;
+ std::vector<Constant*> operands;
+ SmallVector<unsigned, 4> indices;
+ bool operator==(const ExprMapKeyType& that) const {
+ return this->opcode == that.opcode &&
+ this->subclassdata == that.subclassdata &&
+ this->subclassoptionaldata == that.subclassoptionaldata &&
+ this->operands == that.operands &&
+ this->indices == that.indices;
+ }
+ bool operator<(const ExprMapKeyType & that) const {
+ return std::tie(opcode, operands, subclassdata, subclassoptionaldata,
+ indices) <
+ std::tie(that.opcode, that.operands, that.subclassdata,
+ that.subclassoptionaldata, that.indices);
}
- bool operator==(const ConstantAggrKeyType &X) const {
- return Operands == X.Operands;
- }
- bool operator==(const ConstantClass *C) const {
- if (Operands.size() != C->getNumOperands())
- return false;
- for (unsigned I = 0, E = Operands.size(); I != E; ++I)
- if (Operands[I] != C->getOperand(I))
- return false;
- return true;
- }
- unsigned getHash() const {
- return hash_combine_range(Operands.begin(), Operands.end());
- }
-
- typedef typename ConstantInfo<ConstantClass>::TypeClass TypeClass;
- ConstantClass *create(TypeClass *Ty) const {
- return new (Operands.size()) ConstantClass(Ty, Operands);
+ bool operator!=(const ExprMapKeyType& that) const {
+ return !(*this == that);
}
};
struct InlineAsmKeyType {
- StringRef AsmString;
- StringRef Constraints;
- bool HasSideEffects;
- bool IsAlignStack;
- InlineAsm::AsmDialect AsmDialect;
-
- InlineAsmKeyType(StringRef AsmString, StringRef Constraints,
- bool HasSideEffects, bool IsAlignStack,
- InlineAsm::AsmDialect AsmDialect)
- : AsmString(AsmString), Constraints(Constraints),
- HasSideEffects(HasSideEffects), IsAlignStack(IsAlignStack),
- AsmDialect(AsmDialect) {}
- InlineAsmKeyType(const InlineAsm *Asm, SmallVectorImpl<Constant *> &)
- : AsmString(Asm->getAsmString()), Constraints(Asm->getConstraintString()),
- HasSideEffects(Asm->hasSideEffects()),
- IsAlignStack(Asm->isAlignStack()), AsmDialect(Asm->getDialect()) {}
-
- bool operator==(const InlineAsmKeyType &X) const {
- return HasSideEffects == X.HasSideEffects &&
- IsAlignStack == X.IsAlignStack && AsmDialect == X.AsmDialect &&
- AsmString == X.AsmString && Constraints == X.Constraints;
+ InlineAsmKeyType(StringRef AsmString,
+ StringRef Constraints, bool hasSideEffects,
+ bool isAlignStack, InlineAsm::AsmDialect asmDialect)
+ : asm_string(AsmString), constraints(Constraints),
+ has_side_effects(hasSideEffects), is_align_stack(isAlignStack),
+ asm_dialect(asmDialect) {}
+ std::string asm_string;
+ std::string constraints;
+ bool has_side_effects;
+ bool is_align_stack;
+ InlineAsm::AsmDialect asm_dialect;
+ bool operator==(const InlineAsmKeyType& that) const {
+ return this->asm_string == that.asm_string &&
+ this->constraints == that.constraints &&
+ this->has_side_effects == that.has_side_effects &&
+ this->is_align_stack == that.is_align_stack &&
+ this->asm_dialect == that.asm_dialect;
}
- bool operator==(const InlineAsm *Asm) const {
- return HasSideEffects == Asm->hasSideEffects() &&
- IsAlignStack == Asm->isAlignStack() &&
- AsmDialect == Asm->getDialect() &&
- AsmString == Asm->getAsmString() &&
- Constraints == Asm->getConstraintString();
- }
- unsigned getHash() const {
- return hash_combine(AsmString, Constraints, HasSideEffects, IsAlignStack,
- AsmDialect);
+ bool operator<(const InlineAsmKeyType& that) const {
+ return std::tie(asm_string, constraints, has_side_effects, is_align_stack,
+ asm_dialect) <
+ std::tie(that.asm_string, that.constraints, that.has_side_effects,
+ that.is_align_stack, that.asm_dialect);
}
- typedef ConstantInfo<InlineAsm>::TypeClass TypeClass;
- InlineAsm *create(TypeClass *Ty) const {
- return new InlineAsm(Ty, AsmString, Constraints, HasSideEffects,
- IsAlignStack, AsmDialect);
+ bool operator!=(const InlineAsmKeyType& that) const {
+ return !(*this == that);
}
};
-struct ConstantExprKeyType {
- uint8_t Opcode;
- uint8_t SubclassOptionalData;
- uint16_t SubclassData;
- ArrayRef<Constant *> Ops;
- ArrayRef<unsigned> Indexes;
-
- ConstantExprKeyType(unsigned Opcode, ArrayRef<Constant *> Ops,
- unsigned short SubclassData = 0,
- unsigned short SubclassOptionalData = 0,
- ArrayRef<unsigned> Indexes = None)
- : Opcode(Opcode), SubclassOptionalData(SubclassOptionalData),
- SubclassData(SubclassData), Ops(Ops), Indexes(Indexes) {}
- ConstantExprKeyType(const ConstantExpr *CE,
- SmallVectorImpl<Constant *> &Storage)
- : Opcode(CE->getOpcode()),
- SubclassOptionalData(CE->getRawSubclassOptionalData()),
- SubclassData(CE->isCompare() ? CE->getPredicate() : 0),
- Indexes(CE->hasIndices() ? CE->getIndices() : ArrayRef<unsigned>()) {
- assert(Storage.empty() && "Expected empty storage");
- for (unsigned I = 0, E = CE->getNumOperands(); I != E; ++I)
- Storage.push_back(CE->getOperand(I));
- Ops = Storage;
+// The number of operands for each ConstantCreator::create method is
+// determined by the ConstantTraits template.
+// ConstantCreator - A class that is used to create constants by
+// ConstantUniqueMap*. This class should be partially specialized if there is
+// something strange that needs to be done to interface to the ctor for the
+// constant.
+//
+template<typename T, typename Alloc>
+struct ConstantTraits< std::vector<T, Alloc> > {
+ static unsigned uses(const std::vector<T, Alloc>& v) {
+ return v.size();
}
+};
- bool operator==(const ConstantExprKeyType &X) const {
- return Opcode == X.Opcode && SubclassData == X.SubclassData &&
- SubclassOptionalData == X.SubclassOptionalData && Ops == X.Ops &&
- Indexes == X.Indexes;
+template<>
+struct ConstantTraits<Constant *> {
+ static unsigned uses(Constant * const & v) {
+ return 1;
}
+};
- bool operator==(const ConstantExpr *CE) const {
- if (Opcode != CE->getOpcode())
- return false;
- if (SubclassOptionalData != CE->getRawSubclassOptionalData())
- return false;
- if (Ops.size() != CE->getNumOperands())
- return false;
- if (SubclassData != (CE->isCompare() ? CE->getPredicate() : 0))
- return false;
- for (unsigned I = 0, E = Ops.size(); I != E; ++I)
- if (Ops[I] != CE->getOperand(I))
- return false;
- if (Indexes != (CE->hasIndices() ? CE->getIndices() : ArrayRef<unsigned>()))
- return false;
- return true;
+template<class ConstantClass, class TypeClass, class ValType>
+struct ConstantCreator {
+ static ConstantClass *create(TypeClass *Ty, const ValType &V) {
+ return new(ConstantTraits<ValType>::uses(V)) ConstantClass(Ty, V);
}
+};
- unsigned getHash() const {
- return hash_combine(Opcode, SubclassOptionalData, SubclassData,
- hash_combine_range(Ops.begin(), Ops.end()),
- hash_combine_range(Indexes.begin(), Indexes.end()));
+template<class ConstantClass, class TypeClass>
+struct ConstantArrayCreator {
+ static ConstantClass *create(TypeClass *Ty, ArrayRef<Constant*> V) {
+ return new(V.size()) ConstantClass(Ty, V);
}
+};
- typedef ConstantInfo<ConstantExpr>::TypeClass TypeClass;
- ConstantExpr *create(TypeClass *Ty) const {
- switch (Opcode) {
- default:
- if (Instruction::isCast(Opcode))
- return new UnaryConstantExpr(Opcode, Ops[0], Ty);
- if ((Opcode >= Instruction::BinaryOpsBegin &&
- Opcode < Instruction::BinaryOpsEnd))
- return new BinaryConstantExpr(Opcode, Ops[0], Ops[1],
- SubclassOptionalData);
- llvm_unreachable("Invalid ConstantExpr!");
- case Instruction::Select:
- return new SelectConstantExpr(Ops[0], Ops[1], Ops[2]);
- case Instruction::ExtractElement:
- return new ExtractElementConstantExpr(Ops[0], Ops[1]);
- case Instruction::InsertElement:
- return new InsertElementConstantExpr(Ops[0], Ops[1], Ops[2]);
- case Instruction::ShuffleVector:
- return new ShuffleVectorConstantExpr(Ops[0], Ops[1], Ops[2]);
- case Instruction::InsertValue:
- return new InsertValueConstantExpr(Ops[0], Ops[1], Indexes, Ty);
- case Instruction::ExtractValue:
- return new ExtractValueConstantExpr(Ops[0], Indexes, Ty);
- case Instruction::GetElementPtr:
- return GetElementPtrConstantExpr::Create(Ops[0], Ops.slice(1), Ty,
- SubclassOptionalData);
- case Instruction::ICmp:
- return new CompareConstantExpr(Ty, Instruction::ICmp, SubclassData,
- Ops[0], Ops[1]);
- case Instruction::FCmp:
- return new CompareConstantExpr(Ty, Instruction::FCmp, SubclassData,
- Ops[0], Ops[1]);
+template<class ConstantClass>
+struct ConstantKeyData {
+ typedef void ValType;
+ static ValType getValType(ConstantClass *C) {
+ llvm_unreachable("Unknown Constant type!");
+ }
+};
+
+template<>
+struct ConstantCreator<ConstantExpr, Type, ExprMapKeyType> {
+ static ConstantExpr *create(Type *Ty, const ExprMapKeyType &V,
+ unsigned short pred = 0) {
+ if (Instruction::isCast(V.opcode))
+ return new UnaryConstantExpr(V.opcode, V.operands[0], Ty);
+ if ((V.opcode >= Instruction::BinaryOpsBegin &&
+ V.opcode < Instruction::BinaryOpsEnd))
+ return new BinaryConstantExpr(V.opcode, V.operands[0], V.operands[1],
+ V.subclassoptionaldata);
+ if (V.opcode == Instruction::Select)
+ return new SelectConstantExpr(V.operands[0], V.operands[1],
+ V.operands[2]);
+ if (V.opcode == Instruction::ExtractElement)
+ return new ExtractElementConstantExpr(V.operands[0], V.operands[1]);
+ if (V.opcode == Instruction::InsertElement)
+ return new InsertElementConstantExpr(V.operands[0], V.operands[1],
+ V.operands[2]);
+ if (V.opcode == Instruction::ShuffleVector)
+ return new ShuffleVectorConstantExpr(V.operands[0], V.operands[1],
+ V.operands[2]);
+ if (V.opcode == Instruction::InsertValue)
+ return new InsertValueConstantExpr(V.operands[0], V.operands[1],
+ V.indices, Ty);
+ if (V.opcode == Instruction::ExtractValue)
+ return new ExtractValueConstantExpr(V.operands[0], V.indices, Ty);
+ if (V.opcode == Instruction::GetElementPtr) {
+ std::vector<Constant*> IdxList(V.operands.begin()+1, V.operands.end());
+ return GetElementPtrConstantExpr::Create(V.operands[0], IdxList, Ty,
+ V.subclassoptionaldata);
+ }
+
+ // The compare instructions are weird. We have to encode the predicate
+ // value and it is combined with the instruction opcode by multiplying
+ // the opcode by one hundred. We must decode this to get the predicate.
+ if (V.opcode == Instruction::ICmp)
+ return new CompareConstantExpr(Ty, Instruction::ICmp, V.subclassdata,
+ V.operands[0], V.operands[1]);
+ if (V.opcode == Instruction::FCmp)
+ return new CompareConstantExpr(Ty, Instruction::FCmp, V.subclassdata,
+ V.operands[0], V.operands[1]);
+ llvm_unreachable("Invalid ConstantExpr!");
+ }
+};
+
+template<>
+struct ConstantKeyData<ConstantExpr> {
+ typedef ExprMapKeyType ValType;
+ static ValType getValType(ConstantExpr *CE) {
+ std::vector<Constant*> Operands;
+ Operands.reserve(CE->getNumOperands());
+ for (unsigned i = 0, e = CE->getNumOperands(); i != e; ++i)
+ Operands.push_back(cast<Constant>(CE->getOperand(i)));
+ return ExprMapKeyType(CE->getOpcode(), Operands,
+ CE->isCompare() ? CE->getPredicate() : 0,
+ CE->getRawSubclassOptionalData(),
+ CE->hasIndices() ?
+ CE->getIndices() : ArrayRef<unsigned>());
+ }
+};
+
+template<>
+struct ConstantCreator<InlineAsm, PointerType, InlineAsmKeyType> {
+ static InlineAsm *create(PointerType *Ty, const InlineAsmKeyType &Key) {
+ return new InlineAsm(Ty, Key.asm_string, Key.constraints,
+ Key.has_side_effects, Key.is_align_stack,
+ Key.asm_dialect);
+ }
+};
+
+template<>
+struct ConstantKeyData<InlineAsm> {
+ typedef InlineAsmKeyType ValType;
+ static ValType getValType(InlineAsm *Asm) {
+ return InlineAsmKeyType(Asm->getAsmString(), Asm->getConstraintString(),
+ Asm->hasSideEffects(), Asm->isAlignStack(),
+ Asm->getDialect());
+ }
+};
+
+template<class ValType, class ValRefType, class TypeClass, class ConstantClass,
+ bool HasLargeKey = false /*true for arrays and structs*/ >
+class ConstantUniqueMap {
+public:
+ typedef std::pair<TypeClass*, ValType> MapKey;
+ typedef std::map<MapKey, ConstantClass *> MapTy;
+ typedef std::map<ConstantClass *, typename MapTy::iterator> InverseMapTy;
+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.
+ InverseMapTy InverseMap;
+
+public:
+ typename MapTy::iterator map_begin() { return Map.begin(); }
+ typename MapTy::iterator map_end() { return Map.end(); }
+
+ void freeConstants() {
+ for (typename MapTy::iterator I=Map.begin(), E=Map.end();
+ I != E; ++I) {
+ // Asserts that use_empty().
+ delete I->second;
}
}
+
+ /// InsertOrGetItem - Return an iterator for the specified element.
+ /// If the element exists in the map, the returned iterator points to the
+ /// entry and Exists=true. If not, the iterator points to the newly
+ /// inserted entry and returns Exists=false. Newly inserted entries have
+ /// I->second == 0, and should be filled in.
+ typename MapTy::iterator InsertOrGetItem(std::pair<MapKey, ConstantClass *>
+ &InsertVal,
+ bool &Exists) {
+ std::pair<typename MapTy::iterator, bool> IP = Map.insert(InsertVal);
+ Exists = !IP.second;
+ return IP.first;
+ }
+
+private:
+ typename MapTy::iterator FindExistingElement(ConstantClass *CP) {
+ if (HasLargeKey) {
+ typename InverseMapTy::iterator IMI = InverseMap.find(CP);
+ assert(IMI != InverseMap.end() && IMI->second != Map.end() &&
+ IMI->second->second == CP &&
+ "InverseMap corrupt!");
+ return IMI->second;
+ }
+
+ typename MapTy::iterator I =
+ Map.find(MapKey(static_cast<TypeClass*>(CP->getType()),
+ ConstantKeyData<ConstantClass>::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;
+ }
+
+ ConstantClass *Create(TypeClass *Ty, ValRefType V,
+ typename MapTy::iterator I) {
+ ConstantClass* Result =
+ ConstantCreator<ConstantClass,TypeClass,ValType>::create(Ty, 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));
+
+ return Result;
+ }
+public:
+
+ /// getOrCreate - Return the specified constant from the map, creating it if
+ /// necessary.
+ ConstantClass *getOrCreate(TypeClass *Ty, ValRefType V) {
+ MapKey Lookup(Ty, V);
+ ConstantClass* Result = nullptr;
+
+ typename MapTy::iterator I = Map.find(Lookup);
+ // Is it in the map?
+ if (I != Map.end())
+ Result = I->second;
+
+ if (!Result) {
+ // If no preexisting value, create one now...
+ Result = Create(Ty, V, I);
+ }
+
+ return Result;
+ }
+
+ void remove(ConstantClass *CP) {
+ typename MapTy::iterator 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);
+
+ 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, typename MapTy::iterator I) {
+ // First, remove the old location of the specified constant in the map.
+ typename MapTy::iterator OldI = FindExistingElement(C);
+ assert(OldI != Map.end() && "Constant not found in constant table!");
+ assert(OldI->second == C && "Didn't find correct element?");
+
+ // 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 dump() const {
+ DEBUG(dbgs() << "Constant.cpp: ConstantUniqueMap\n");
+ }
};
-template <class ConstantClass> class ConstantUniqueMap {
+// Unique map for aggregate constants
+template<class TypeClass, class ConstantClass>
+class ConstantAggrUniqueMap {
public:
- typedef typename ConstantInfo<ConstantClass>::ValType ValType;
- typedef typename ConstantInfo<ConstantClass>::TypeClass TypeClass;
- typedef std::pair<TypeClass *, ValType> LookupKey;
-
+ typedef ArrayRef<Constant*> Operands;
+ typedef std::pair<TypeClass*, Operands> LookupKey;
private:
struct MapInfo {
- typedef DenseMapInfo<ConstantClass *> ConstantClassInfo;
- static inline ConstantClass *getEmptyKey() {
+ typedef DenseMapInfo<ConstantClass*> ConstantClassInfo;
+ typedef DenseMapInfo<Constant*> ConstantInfo;
+ typedef DenseMapInfo<TypeClass*> TypeClassInfo;
+ static inline ConstantClass* getEmptyKey() {
return ConstantClassInfo::getEmptyKey();
}
- static inline ConstantClass *getTombstoneKey() {
+ static inline ConstantClass* getTombstoneKey() {
return ConstantClassInfo::getTombstoneKey();
}
static unsigned getHashValue(const ConstantClass *CP) {
- SmallVector<Constant *, 8> Storage;
- return getHashValue(LookupKey(CP->getType(), ValType(CP, Storage)));
+ SmallVector<Constant*, 8> CPOperands;
+ CPOperands.reserve(CP->getNumOperands());
+ for (unsigned I = 0, E = CP->getNumOperands(); I < E; ++I)
+ CPOperands.push_back(CP->getOperand(I));
+ return getHashValue(LookupKey(CP->getType(), CPOperands));
}
static bool isEqual(const ConstantClass *LHS, const ConstantClass *RHS) {
return LHS == RHS;
}
static unsigned getHashValue(const LookupKey &Val) {
- return hash_combine(Val.first, Val.second.getHash());
+ return hash_combine(Val.first, hash_combine_range(Val.second.begin(),
+ Val.second.end()));
}
static bool isEqual(const LookupKey &LHS, const ConstantClass *RHS) {
if (RHS == getEmptyKey() || RHS == getTombstoneKey())
return false;
- if (LHS.first != RHS->getType())
+ if (LHS.first != RHS->getType()
+ || LHS.second.size() != RHS->getNumOperands())
return false;
- return LHS.second == RHS;
+ for (unsigned I = 0, E = RHS->getNumOperands(); I < E; ++I) {
+ if (LHS.second[I] != RHS->getOperand(I))
+ return false;
+ }
+ return true;
}
};
-
public:
typedef DenseMap<ConstantClass *, char, MapInfo> MapTy;
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;
public:
@@ -547,33 +694,44 @@
typename MapTy::iterator map_end() { return Map.end(); }
void freeConstants() {
- for (auto &I : Map)
+ for (typename MapTy::iterator I=Map.begin(), E=Map.end();
+ I != E; ++I) {
// Asserts that use_empty().
- delete I.first;
+ delete I->first;
+ }
}
private:
- ConstantClass *create(TypeClass *Ty, ValType V) {
- ConstantClass *Result = V.create(Ty);
+ typename MapTy::iterator findExistingElement(ConstantClass *CP) {
+ return Map.find(CP);
+ }
+
+ ConstantClass *Create(TypeClass *Ty, Operands V, typename MapTy::iterator I) {
+ ConstantClass* Result =
+ ConstantArrayCreator<ConstantClass,TypeClass>::create(Ty, V);
assert(Result->getType() == Ty && "Type specified is not correct!");
- insert(Result);
+ Map[Result] = '\0';
return Result;
}
-
public:
- /// Return the specified constant from the map, creating it if necessary.
- ConstantClass *getOrCreate(TypeClass *Ty, ValType V) {
- LookupKey Lookup(Ty, V);
- ConstantClass *Result = nullptr;
- auto I = find(Lookup);
- if (I == Map.end())
- Result = create(Ty, V);
- else
+ /// getOrCreate - Return the specified constant from the map, creating it if
+ /// necessary.
+ ConstantClass *getOrCreate(TypeClass *Ty, Operands V) {
+ LookupKey Lookup(Ty, V);
+ ConstantClass* Result = nullptr;
+
+ typename MapTy::iterator I = Map.find_as(Lookup);
+ // Is it in the map?
+ if (I != Map.end())
Result = I->first;
- assert(Result && "Unexpected nullptr");
+
+ if (!Result) {
+ // If no preexisting value, create one now...
+ Result = Create(Ty, V, I);
+ }
return Result;
}
@@ -584,17 +742,21 @@
}
/// Insert the constant into its proper slot.
- void insert(ConstantClass *CP) { Map[CP] = '\0'; }
+ void insert(ConstantClass *CP) {
+ Map[CP] = '\0';
+ }
/// Remove this constant from the map
void remove(ConstantClass *CP) {
- typename MapTy::iterator I = Map.find(CP);
+ typename MapTy::iterator I = findExistingElement(CP);
assert(I != Map.end() && "Constant not found in constant table!");
assert(I->first == CP && "Didn't find correct element?");
Map.erase(I);
}
- void dump() const { DEBUG(dbgs() << "Constant.cpp: ConstantUniqueMap\n"); }
+ void dump() const {
+ DEBUG(dbgs() << "Constant.cpp: ConstantUniqueMap\n");
+ }
};
} // end namespace llvm
diff --git a/llvm/lib/IR/LLVMContextImpl.cpp b/llvm/lib/IR/LLVMContextImpl.cpp
index 6513965..4c2791f 100644
--- a/llvm/lib/IR/LLVMContextImpl.cpp
+++ b/llvm/lib/IR/LLVMContextImpl.cpp
@@ -75,7 +75,7 @@
// Free the constants. This is important to do here to ensure that they are
// freed before the LeakDetector is torn down.
std::for_each(ExprConstants.map_begin(), ExprConstants.map_end(),
- DropFirst());
+ DropReferences());
std::for_each(ArrayConstants.map_begin(), ArrayConstants.map_end(),
DropFirst());
std::for_each(StructConstants.map_begin(), StructConstants.map_end(),
diff --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h
index 412f36d..1eead4a 100644
--- a/llvm/lib/IR/LLVMContextImpl.h
+++ b/llvm/lib/IR/LLVMContextImpl.h
@@ -272,13 +272,13 @@
DenseMap<Type*, ConstantAggregateZero*> CAZConstants;
- typedef ConstantUniqueMap<ConstantArray> ArrayConstantsTy;
+ typedef ConstantAggrUniqueMap<ArrayType, ConstantArray> ArrayConstantsTy;
ArrayConstantsTy ArrayConstants;
- typedef ConstantUniqueMap<ConstantStruct> StructConstantsTy;
+ typedef ConstantAggrUniqueMap<StructType, ConstantStruct> StructConstantsTy;
StructConstantsTy StructConstants;
- typedef ConstantUniqueMap<ConstantVector> VectorConstantsTy;
+ typedef ConstantAggrUniqueMap<VectorType, ConstantVector> VectorConstantsTy;
VectorConstantsTy VectorConstants;
DenseMap<PointerType*, ConstantPointerNull*> CPNConstants;
@@ -289,10 +289,12 @@
DenseMap<std::pair<const Function *, const BasicBlock *>, BlockAddress *>
BlockAddresses;
- ConstantUniqueMap<ConstantExpr> ExprConstants;
+ ConstantUniqueMap<ExprMapKeyType, const ExprMapKeyType&, Type, ConstantExpr>
+ ExprConstants;
- ConstantUniqueMap<InlineAsm> InlineAsms;
-
+ ConstantUniqueMap<InlineAsmKeyType, const InlineAsmKeyType&, PointerType,
+ InlineAsm> InlineAsms;
+
ConstantInt *TheTrueVal;
ConstantInt *TheFalseVal;