if (SplatCFP && SplatCFP->isZero() && SplatCFP->isNegative())
return true;
+ if (const ConstantVector *CV = dyn_cast<ConstantVector>(this))
+ if (ConstantFP *SplatCFP = dyn_cast_or_null<ConstantFP>(CV->getSplatValue()))
+ if (SplatCFP && SplatCFP->isZero() && SplatCFP->isNegative())
+ return true;
+
// We've already handled true FP case; any other FP vectors can't represent -0.0.
if (getType()->isFPOrFPVectorTy())
return false;
if (const ConstantFP *CFP = dyn_cast<ConstantFP>(this))
return CFP->isZero();
+ // Equivalent for a vector of -0.0's.
+ if (const ConstantDataVector *CV = dyn_cast<ConstantDataVector>(this))
+ if (ConstantFP *SplatCFP = dyn_cast_or_null<ConstantFP>(CV->getSplatValue()))
+ if (SplatCFP && SplatCFP->isZero())
+ return true;
+
+ if (const ConstantVector *CV = dyn_cast<ConstantVector>(this))
+ if (ConstantFP *SplatCFP = dyn_cast_or_null<ConstantFP>(CV->getSplatValue()))
+ if (SplatCFP && SplatCFP->isZero())
+ return true;
+
// Otherwise, just use +0.0.
return isNullValue();
}
if (const ConstantFP *CFP = dyn_cast<ConstantFP>(this))
return CFP->isZero() && !CFP->isNegative();
- // constant zero is zero for aggregates and cpnull is null for pointers.
- return isa<ConstantAggregateZero>(this) || isa<ConstantPointerNull>(this);
+ // constant zero is zero for aggregates, cpnull is null for pointers, none for
+ // tokens.
+ return isa<ConstantAggregateZero>(this) || isa<ConstantPointerNull>(this) ||
+ isa<ConstantTokenNone>(this);
}
bool Constant::isAllOnesValue() const {
case Type::ArrayTyID:
case Type::VectorTyID:
return ConstantAggregateZero::get(Ty);
+ case Type::TokenTyID:
+ return ConstantTokenNone::get(Ty->getContext());
default:
// Function, Label, or Opaque type?
llvm_unreachable("Cannot create a null constant of that type!");
return nullptr;
}
+void Constant::destroyConstant() {
+ /// First call destroyConstantImpl on the subclass. This gives the subclass
+ /// a chance to remove the constant from any maps/pools it's contained in.
+ switch (getValueID()) {
+ default:
+ llvm_unreachable("Not a constant!");
+#define HANDLE_CONSTANT(Name) \
+ case Value::Name##Val: \
+ cast<Name>(this)->destroyConstantImpl(); \
+ break;
+#include "llvm/IR/Value.def"
+ }
-void Constant::destroyConstantImpl() {
// When a Constant is destroyed, there may be lingering
// references to the constant by other constants in the constant pool. These
// constants are implicitly dependent on the module that is being deleted,
//
while (!use_empty()) {
Value *V = user_back();
-#ifndef NDEBUG // Only in -g mode...
+#ifndef NDEBUG // Only in -g mode...
if (!isa<Constant>(V)) {
dbgs() << "While deleting: " << *this
- << "\n\nUse still stuck around after Def is destroyed: "
- << *V << "\n\n";
+ << "\n\nUse still stuck around after Def is destroyed: " << *V
+ << "\n\n";
}
#endif
assert(isa<Constant>(V) && "References remain to Constant being destroyed");
return false;
}
+bool Constant::needsRelocation() const {
+ if (isa<GlobalValue>(this))
+ return true; // Global reference.
-
-/// getRelocationInfo - This method classifies the entry according to
-/// whether or not it may generate a relocation entry. This must be
-/// conservative, so if it might codegen to a relocatable entry, it should say
-/// so. The return values are:
-///
-/// NoRelocation: This constant pool entry is guaranteed to never have a
-/// relocation applied to it (because it holds a simple constant like
-/// '4').
-/// LocalRelocation: This entry has relocations, but the entries are
-/// guaranteed to be resolvable by the static linker, so the dynamic
-/// linker will never see them.
-/// GlobalRelocations: This entry may have arbitrary relocations.
-///
-/// FIXME: This really should not be in IR.
-Constant::PossibleRelocationsTy Constant::getRelocationInfo() const {
- if (const GlobalValue *GV = dyn_cast<GlobalValue>(this)) {
- if (GV->hasLocalLinkage() || GV->hasHiddenVisibility())
- return LocalRelocation; // Local to this file/library.
- return GlobalRelocations; // Global reference.
- }
-
if (const BlockAddress *BA = dyn_cast<BlockAddress>(this))
- return BA->getFunction()->getRelocationInfo();
-
+ return BA->getFunction()->needsRelocation();
+
// While raw uses of blockaddress need to be relocated, differences between
// two of them don't when they are for labels in the same function. This is a
// common idiom when creating a table for the indirect goto extension, so we
if (CE->getOpcode() == Instruction::Sub) {
ConstantExpr *LHS = dyn_cast<ConstantExpr>(CE->getOperand(0));
ConstantExpr *RHS = dyn_cast<ConstantExpr>(CE->getOperand(1));
- if (LHS && RHS &&
- LHS->getOpcode() == Instruction::PtrToInt &&
+ if (LHS && RHS && LHS->getOpcode() == Instruction::PtrToInt &&
RHS->getOpcode() == Instruction::PtrToInt &&
isa<BlockAddress>(LHS->getOperand(0)) &&
isa<BlockAddress>(RHS->getOperand(0)) &&
cast<BlockAddress>(LHS->getOperand(0))->getFunction() ==
- cast<BlockAddress>(RHS->getOperand(0))->getFunction())
- return NoRelocation;
+ cast<BlockAddress>(RHS->getOperand(0))->getFunction())
+ return false;
}
- PossibleRelocationsTy Result = NoRelocation;
+ bool Result = false;
for (unsigned i = 0, e = getNumOperands(); i != e; ++i)
- Result = std::max(Result,
- cast<Constant>(getOperand(i))->getRelocationInfo());
+ Result |= cast<Constant>(getOperand(i))->needsRelocation();
return Result;
}
return get(Ty->getContext(), APInt(Ty->getBitWidth(), Str, radix));
}
+/// Remove the constant from the constant table.
+void ConstantInt::destroyConstantImpl() {
+ llvm_unreachable("You can't ConstantInt->destroyConstantImpl()!");
+}
+
//===----------------------------------------------------------------------===//
// ConstantFP
//===----------------------------------------------------------------------===//
return Val.bitwiseIsEqual(V);
}
+/// Remove the constant from the constant table.
+void ConstantFP::destroyConstantImpl() {
+ llvm_unreachable("You can't ConstantInt->destroyConstantImpl()!");
+}
+
//===----------------------------------------------------------------------===//
// ConstantAggregateZero Implementation
//===----------------------------------------------------------------------===//
}
unsigned ConstantAggregateZero::getNumElements() const {
- const Type *Ty = getType();
- if (const auto *AT = dyn_cast<ArrayType>(Ty))
+ Type *Ty = getType();
+ if (auto *AT = dyn_cast<ArrayType>(Ty))
return AT->getNumElements();
- if (const auto *VT = dyn_cast<VectorType>(Ty))
+ if (auto *VT = dyn_cast<VectorType>(Ty))
return VT->getNumElements();
return Ty->getStructNumElements();
}
}
unsigned UndefValue::getNumElements() const {
- const Type *Ty = getType();
- if (const auto *AT = dyn_cast<ArrayType>(Ty))
+ Type *Ty = getType();
+ if (auto *AT = dyn_cast<ArrayType>(Ty))
return AT->getNumElements();
- if (const auto *VT = dyn_cast<VectorType>(Ty))
+ if (auto *VT = dyn_cast<VectorType>(Ty))
return VT->getNumElements();
return Ty->getStructNumElements();
}
return true;
}
+template <typename SequentialTy, typename ElementTy>
+static Constant *getIntSequenceIfElementsMatch(ArrayRef<Constant *> V) {
+ assert(!V.empty() && "Cannot get empty int sequence.");
+
+ SmallVector<ElementTy, 16> Elts;
+ for (Constant *C : V)
+ if (auto *CI = dyn_cast<ConstantInt>(C))
+ Elts.push_back(CI->getZExtValue());
+ else
+ return nullptr;
+ return SequentialTy::get(V[0]->getContext(), Elts);
+}
+
+template <typename SequentialTy, typename ElementTy>
+static Constant *getFPSequenceIfElementsMatch(ArrayRef<Constant *> V) {
+ assert(!V.empty() && "Cannot get empty FP sequence.");
+
+ SmallVector<ElementTy, 16> Elts;
+ for (Constant *C : V)
+ if (auto *CFP = dyn_cast<ConstantFP>(C))
+ Elts.push_back(CFP->getValueAPF().bitcastToAPInt().getLimitedValue());
+ else
+ return nullptr;
+ return SequentialTy::getFP(V[0]->getContext(), Elts);
+}
+
+template <typename SequenceTy>
+static Constant *getSequenceIfElementsMatch(Constant *C,
+ ArrayRef<Constant *> V) {
+ // We speculatively build the elements here even if it turns out that there is
+ // a constantexpr or something else weird, since it is so uncommon for that to
+ // happen.
+ if (ConstantInt *CI = dyn_cast<ConstantInt>(C)) {
+ if (CI->getType()->isIntegerTy(8))
+ return getIntSequenceIfElementsMatch<SequenceTy, uint8_t>(V);
+ else if (CI->getType()->isIntegerTy(16))
+ return getIntSequenceIfElementsMatch<SequenceTy, uint16_t>(V);
+ else if (CI->getType()->isIntegerTy(32))
+ return getIntSequenceIfElementsMatch<SequenceTy, uint32_t>(V);
+ else if (CI->getType()->isIntegerTy(64))
+ return getIntSequenceIfElementsMatch<SequenceTy, uint64_t>(V);
+ } else if (ConstantFP *CFP = dyn_cast<ConstantFP>(C)) {
+ if (CFP->getType()->isHalfTy())
+ return getFPSequenceIfElementsMatch<SequenceTy, uint16_t>(V);
+ else if (CFP->getType()->isFloatTy())
+ return getFPSequenceIfElementsMatch<SequenceTy, uint32_t>(V);
+ else if (CFP->getType()->isDoubleTy())
+ return getFPSequenceIfElementsMatch<SequenceTy, uint64_t>(V);
+ }
+
+ return nullptr;
+}
+
ConstantArray::ConstantArray(ArrayType *T, ArrayRef<Constant *> V)
: Constant(T, ConstantArrayVal,
OperandTraits<ConstantArray>::op_end(this) - V.size(),
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())
// Check to see if all of the elements are ConstantFP or ConstantInt and if
// the element type is compatible with ConstantDataVector. If so, use it.
- if (ConstantDataSequential::isElementTypeCompatible(C->getType())) {
- // We speculatively build the elements here even if it turns out that there
- // is a constantexpr or something else weird in the array, since it is so
- // uncommon for that to happen.
- if (ConstantInt *CI = dyn_cast<ConstantInt>(C)) {
- if (CI->getType()->isIntegerTy(8)) {
- SmallVector<uint8_t, 16> Elts;
- for (unsigned i = 0, e = V.size(); i != e; ++i)
- if (ConstantInt *CI = dyn_cast<ConstantInt>(V[i]))
- Elts.push_back(CI->getZExtValue());
- else
- break;
- if (Elts.size() == V.size())
- return ConstantDataArray::get(C->getContext(), Elts);
- } else if (CI->getType()->isIntegerTy(16)) {
- SmallVector<uint16_t, 16> Elts;
- for (unsigned i = 0, e = V.size(); i != e; ++i)
- if (ConstantInt *CI = dyn_cast<ConstantInt>(V[i]))
- Elts.push_back(CI->getZExtValue());
- else
- break;
- if (Elts.size() == V.size())
- return ConstantDataArray::get(C->getContext(), Elts);
- } else if (CI->getType()->isIntegerTy(32)) {
- SmallVector<uint32_t, 16> Elts;
- for (unsigned i = 0, e = V.size(); i != e; ++i)
- if (ConstantInt *CI = dyn_cast<ConstantInt>(V[i]))
- Elts.push_back(CI->getZExtValue());
- else
- break;
- if (Elts.size() == V.size())
- return ConstantDataArray::get(C->getContext(), Elts);
- } else if (CI->getType()->isIntegerTy(64)) {
- SmallVector<uint64_t, 16> Elts;
- for (unsigned i = 0, e = V.size(); i != e; ++i)
- if (ConstantInt *CI = dyn_cast<ConstantInt>(V[i]))
- Elts.push_back(CI->getZExtValue());
- else
- break;
- if (Elts.size() == V.size())
- return ConstantDataArray::get(C->getContext(), Elts);
- }
- }
-
- if (ConstantFP *CFP = dyn_cast<ConstantFP>(C)) {
- if (CFP->getType()->isFloatTy()) {
- SmallVector<uint32_t, 16> Elts;
- for (unsigned i = 0, e = V.size(); i != e; ++i)
- if (ConstantFP *CFP = dyn_cast<ConstantFP>(V[i]))
- Elts.push_back(
- CFP->getValueAPF().bitcastToAPInt().getLimitedValue());
- else
- break;
- if (Elts.size() == V.size())
- return ConstantDataArray::getFP(C->getContext(), Elts);
- } else if (CFP->getType()->isDoubleTy()) {
- SmallVector<uint64_t, 16> Elts;
- for (unsigned i = 0, e = V.size(); i != e; ++i)
- if (ConstantFP *CFP = dyn_cast<ConstantFP>(V[i]))
- Elts.push_back(
- CFP->getValueAPF().bitcastToAPInt().getLimitedValue());
- else
- break;
- if (Elts.size() == V.size())
- return ConstantDataArray::getFP(C->getContext(), Elts);
- }
- }
- }
+ if (ConstantDataSequential::isElementTypeCompatible(C->getType()))
+ return getSequenceIfElementsMatch<ConstantDataArray>(C, V);
// Otherwise, we really do want to create a ConstantArray.
return nullptr;
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());
// Check to see if all of the elements are ConstantFP or ConstantInt and if
// the element type is compatible with ConstantDataVector. If so, use it.
- if (ConstantDataSequential::isElementTypeCompatible(C->getType())) {
- // We speculatively build the elements here even if it turns out that there
- // is a constantexpr or something else weird in the array, since it is so
- // uncommon for that to happen.
- if (ConstantInt *CI = dyn_cast<ConstantInt>(C)) {
- if (CI->getType()->isIntegerTy(8)) {
- SmallVector<uint8_t, 16> Elts;
- for (unsigned i = 0, e = V.size(); i != e; ++i)
- if (ConstantInt *CI = dyn_cast<ConstantInt>(V[i]))
- Elts.push_back(CI->getZExtValue());
- else
- break;
- if (Elts.size() == V.size())
- return ConstantDataVector::get(C->getContext(), Elts);
- } else if (CI->getType()->isIntegerTy(16)) {
- SmallVector<uint16_t, 16> Elts;
- for (unsigned i = 0, e = V.size(); i != e; ++i)
- if (ConstantInt *CI = dyn_cast<ConstantInt>(V[i]))
- Elts.push_back(CI->getZExtValue());
- else
- break;
- if (Elts.size() == V.size())
- return ConstantDataVector::get(C->getContext(), Elts);
- } else if (CI->getType()->isIntegerTy(32)) {
- SmallVector<uint32_t, 16> Elts;
- for (unsigned i = 0, e = V.size(); i != e; ++i)
- if (ConstantInt *CI = dyn_cast<ConstantInt>(V[i]))
- Elts.push_back(CI->getZExtValue());
- else
- break;
- if (Elts.size() == V.size())
- return ConstantDataVector::get(C->getContext(), Elts);
- } else if (CI->getType()->isIntegerTy(64)) {
- SmallVector<uint64_t, 16> Elts;
- for (unsigned i = 0, e = V.size(); i != e; ++i)
- if (ConstantInt *CI = dyn_cast<ConstantInt>(V[i]))
- Elts.push_back(CI->getZExtValue());
- else
- break;
- if (Elts.size() == V.size())
- return ConstantDataVector::get(C->getContext(), Elts);
- }
- }
-
- if (ConstantFP *CFP = dyn_cast<ConstantFP>(C)) {
- if (CFP->getType()->isFloatTy()) {
- SmallVector<uint32_t, 16> Elts;
- for (unsigned i = 0, e = V.size(); i != e; ++i)
- if (ConstantFP *CFP = dyn_cast<ConstantFP>(V[i]))
- Elts.push_back(
- CFP->getValueAPF().bitcastToAPInt().getLimitedValue());
- else
- break;
- if (Elts.size() == V.size())
- return ConstantDataVector::getFP(C->getContext(), Elts);
- } else if (CFP->getType()->isDoubleTy()) {
- SmallVector<uint64_t, 16> Elts;
- for (unsigned i = 0, e = V.size(); i != e; ++i)
- if (ConstantFP *CFP = dyn_cast<ConstantFP>(V[i]))
- Elts.push_back(
- CFP->getValueAPF().bitcastToAPInt().getLimitedValue());
- else
- break;
- if (Elts.size() == V.size())
- return ConstantDataVector::getFP(C->getContext(), Elts);
- }
- }
- }
+ if (ConstantDataSequential::isElementTypeCompatible(C->getType()))
+ return getSequenceIfElementsMatch<ConstantDataVector>(C, V);
// Otherwise, the element type isn't compatible with ConstantDataVector, or
// the operand list constants a ConstantExpr or something else strange.
return get(Elts);
}
+ConstantTokenNone *ConstantTokenNone::get(LLVMContext &Context) {
+ LLVMContextImpl *pImpl = Context.pImpl;
+ if (!pImpl->TheNoneToken)
+ pImpl->TheNoneToken.reset(new ConstantTokenNone(Context));
+ return pImpl->TheNoneToken.get();
+}
+
+/// Remove the constant from the constant table.
+void ConstantTokenNone::destroyConstantImpl() {
+ llvm_unreachable("You can't ConstantTokenNone->destroyConstantImpl()!");
+}
// Utility function for determining if a ConstantExpr is a CastOp or not. This
// can't be inline because we don't want to #include Instruction.h into
}
unsigned ConstantExpr::getPredicate() const {
- assert(isCompare());
- return ((const CompareConstantExpr*)this)->predicate;
+ return cast<CompareConstantExpr>(this)->predicate;
}
/// getWithOperandReplaced - Return a constant expression identical to this
/// operands replaced with the specified values. The specified array must
/// have the same number of operands as our current one.
Constant *ConstantExpr::getWithOperands(ArrayRef<Constant *> Ops, Type *Ty,
- bool OnlyIfReduced) const {
+ bool OnlyIfReduced, Type *SrcTy) const {
assert(Ops.size() == getNumOperands() && "Operand count mismatch!");
// If no operands changed return self.
case Instruction::ShuffleVector:
return ConstantExpr::getShuffleVector(Ops[0], Ops[1], Ops[2],
OnlyIfReducedTy);
- case Instruction::GetElementPtr:
- return ConstantExpr::getGetElementPtr(nullptr, Ops[0], Ops.slice(1),
- cast<GEPOperator>(this)->isInBounds(),
- OnlyIfReducedTy);
+ case Instruction::GetElementPtr: {
+ auto *GEPO = cast<GEPOperator>(this);
+ assert(SrcTy || (Ops[0]->getType() == getOperand(0)->getType()));
+ return ConstantExpr::getGetElementPtr(
+ SrcTy ? SrcTy : GEPO->getSourceElementType(), Ops[0], Ops.slice(1),
+ GEPO->isInBounds(), OnlyIfReducedTy);
+ }
case Instruction::ICmp:
case Instruction::FCmp:
return ConstantExpr::getCompare(getPredicate(), Ops[0], Ops[1],
/// destroyConstant - Remove the constant from the constant table.
///
-void ConstantAggregateZero::destroyConstant() {
+void ConstantAggregateZero::destroyConstantImpl() {
getContext().pImpl->CAZConstants.erase(getType());
- destroyConstantImpl();
}
/// destroyConstant - Remove the constant from the constant table...
///
-void ConstantArray::destroyConstant() {
+void ConstantArray::destroyConstantImpl() {
getType()->getContext().pImpl->ArrayConstants.remove(this);
- destroyConstantImpl();
}
// destroyConstant - Remove the constant from the constant table...
//
-void ConstantStruct::destroyConstant() {
+void ConstantStruct::destroyConstantImpl() {
getType()->getContext().pImpl->StructConstants.remove(this);
- destroyConstantImpl();
}
// destroyConstant - Remove the constant from the constant table...
//
-void ConstantVector::destroyConstant() {
+void ConstantVector::destroyConstantImpl() {
getType()->getContext().pImpl->VectorConstants.remove(this);
- destroyConstantImpl();
}
/// getSplatValue - If this is a splat vector constant, meaning that all of
return cast<ConstantInt>(C)->getValue();
}
-
//---- ConstantPointerNull::get() implementation.
//
// destroyConstant - Remove the constant from the constant table...
//
-void ConstantPointerNull::destroyConstant() {
+void ConstantPointerNull::destroyConstantImpl() {
getContext().pImpl->CPNConstants.erase(getType());
- // Free the constant and any dangling references to it.
- destroyConstantImpl();
}
// destroyConstant - Remove the constant from the constant table.
//
-void UndefValue::destroyConstant() {
+void UndefValue::destroyConstantImpl() {
// Free the constant and any dangling references to it.
getContext().pImpl->UVConstants.erase(getType());
- destroyConstantImpl();
}
//---- BlockAddress::get() implementation.
// destroyConstant - Remove the constant from the constant table.
//
-void BlockAddress::destroyConstant() {
+void BlockAddress::destroyConstantImpl() {
getFunction()->getType()->getContext().pImpl
->BlockAddresses.erase(std::make_pair(getFunction(), getBasicBlock()));
getBasicBlock()->AdjustBlockAddressRefCount(-1);
- destroyConstantImpl();
}
-void BlockAddress::replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U) {
+Value *BlockAddress::handleOperandChangeImpl(Value *From, Value *To, Use *U) {
// This could be replacing either the Basic Block or the Function. In either
// case, we have to remove the map entry.
Function *NewF = getFunction();
// and return early.
BlockAddress *&NewBA =
getContext().pImpl->BlockAddresses[std::make_pair(NewF, NewBB)];
- if (NewBA) {
- replaceUsesOfWithOnConstantImpl(NewBA);
- return;
- }
+ if (NewBA)
+ return NewBA;
getBasicBlock()->AdjustBlockAddressRefCount(-1);
setOperand(0, NewF);
setOperand(1, NewBB);
getBasicBlock()->AdjustBlockAddressRefCount(1);
+
+ // If we just want to keep the existing value, then return null.
+ // Callers know that this means we shouldn't delete this value.
+ return nullptr;
}
//---- ConstantExpr::get() implementations.
// destroyConstant - Remove the constant from the constant table...
//
-void ConstantExpr::destroyConstant() {
+void ConstantExpr::destroyConstantImpl() {
getType()->getContext().pImpl->ExprConstants.remove(this);
- destroyConstantImpl();
}
const char *ConstantExpr::getOpcodeName() const {
/// formed with a vector or array of the specified element type.
/// ConstantDataArray only works with normal float and int types that are
/// stored densely in memory, not with things like i42 or x86_f80.
-bool ConstantDataSequential::isElementTypeCompatible(const Type *Ty) {
- if (Ty->isFloatTy() || Ty->isDoubleTy()) return true;
- if (const IntegerType *IT = dyn_cast<IntegerType>(Ty)) {
+bool ConstantDataSequential::isElementTypeCompatible(Type *Ty) {
+ if (Ty->isHalfTy() || Ty->isFloatTy() || Ty->isDoubleTy()) return true;
+ if (auto *IT = dyn_cast<IntegerType>(Ty)) {
switch (IT->getBitWidth()) {
case 8:
case 16:
return *Entry = new ConstantDataVector(Ty, Slot.first().data());
}
-void ConstantDataSequential::destroyConstant() {
+void ConstantDataSequential::destroyConstantImpl() {
// Remove the constant from the StringMap.
StringMap<ConstantDataSequential*> &CDSConstants =
getType()->getContext().pImpl->CDSConstants;
// If we were part of a list, make sure that we don't delete the list that is
// still owned by the uniquing map.
Next = nullptr;
-
- // Finally, actually delete it.
- destroyConstantImpl();
}
/// get() constructors - Return a constant with array type with an element
/// object.
Constant *ConstantDataArray::getFP(LLVMContext &Context,
ArrayRef<uint16_t> Elts) {
- Type *Ty = VectorType::get(Type::getHalfTy(Context), Elts.size());
+ Type *Ty = ArrayType::get(Type::getHalfTy(Context), Elts.size());
const char *Data = reinterpret_cast<const char *>(Elts.data());
return getImpl(StringRef(const_cast<char *>(Data), Elts.size() * 2), Ty);
}
}
if (ConstantFP *CFP = dyn_cast<ConstantFP>(V)) {
+ if (CFP->getType()->isHalfTy()) {
+ SmallVector<uint16_t, 16> Elts(
+ NumElts, CFP->getValueAPF().bitcastToAPInt().getLimitedValue());
+ return getFP(V->getContext(), Elts);
+ }
if (CFP->getType()->isFloatTy()) {
SmallVector<uint32_t, 16> Elts(
NumElts, CFP->getValueAPF().bitcastToAPInt().getLimitedValue());
switch (getElementType()->getTypeID()) {
default:
llvm_unreachable("Accessor can only be used when element is float/double!");
+ case Type::HalfTyID: {
+ auto EltVal = *reinterpret_cast<const uint16_t *>(EltPtr);
+ return APFloat(APFloat::IEEEhalf, APInt(16, EltVal));
+ }
case Type::FloatTyID: {
auto EltVal = *reinterpret_cast<const uint32_t *>(EltPtr);
return APFloat(APFloat::IEEEsingle, APInt(32, EltVal));
/// Note that this has to compute a new constant to return, so it isn't as
/// efficient as getElementAsInteger/Float/Double.
Constant *ConstantDataSequential::getElementAsConstant(unsigned Elt) const {
- if (getElementType()->isFloatTy() || getElementType()->isDoubleTy())
+ if (getElementType()->isHalfTy() || getElementType()->isFloatTy() ||
+ getElementType()->isDoubleTy())
return ConstantFP::get(getContext(), getElementAsAPFloat(Elt));
return ConstantInt::get(getElementType(), getElementAsInteger(Elt));
}
//===----------------------------------------------------------------------===//
-// replaceUsesOfWithOnConstant implementations
+// handleOperandChange implementations
-/// replaceUsesOfWithOnConstant - Update this constant array to change uses of
+/// Update this constant array to change uses of
/// 'From' to be uses of 'To'. This must update the uniquing data structures
/// etc.
///
/// Note that we intentionally replace all uses of From with To here. Consider
/// a large array that uses 'From' 1000 times. By handling this case all here,
-/// ConstantArray::replaceUsesOfWithOnConstant is only invoked once, and that
+/// ConstantArray::handleOperandChange is only invoked once, and that
/// single invocation handles all 1000 uses. Handling them one at a time would
/// work, but would be really slow because it would have to unique each updated
/// array instance.
///
-void Constant::replaceUsesOfWithOnConstantImpl(Constant *Replacement) {
+void Constant::handleOperandChange(Value *From, Value *To, Use *U) {
+ Value *Replacement = nullptr;
+ switch (getValueID()) {
+ default:
+ llvm_unreachable("Not a constant!");
+#define HANDLE_CONSTANT(Name) \
+ case Value::Name##Val: \
+ Replacement = cast<Name>(this)->handleOperandChangeImpl(From, To, U); \
+ break;
+#include "llvm/IR/Value.def"
+ }
+
+ // If handleOperandChangeImpl returned nullptr, then it handled
+ // replacing itself and we don't want to delete or replace anything else here.
+ if (!Replacement)
+ return;
+
// I do need to replace this with an existing value.
assert(Replacement != this && "I didn't contain From!");
destroyConstant();
}
-void ConstantArray::replaceUsesOfWithOnConstant(Value *From, Value *To,
- Use *U) {
+Value *ConstantInt::handleOperandChangeImpl(Value *From, Value *To, Use *U) {
+ llvm_unreachable("Unsupported class for handleOperandChange()!");
+}
+
+Value *ConstantFP::handleOperandChangeImpl(Value *From, Value *To, Use *U) {
+ llvm_unreachable("Unsupported class for handleOperandChange()!");
+}
+
+Value *ConstantTokenNone::handleOperandChangeImpl(Value *From, Value *To,
+ Use *U) {
+ llvm_unreachable("Unsupported class for handleOperandChange()!");
+}
+
+Value *UndefValue::handleOperandChangeImpl(Value *From, Value *To, Use *U) {
+ llvm_unreachable("Unsupported class for handleOperandChange()!");
+}
+
+Value *ConstantPointerNull::handleOperandChangeImpl(Value *From, Value *To,
+ Use *U) {
+ llvm_unreachable("Unsupported class for handleOperandChange()!");
+}
+
+Value *ConstantAggregateZero::handleOperandChangeImpl(Value *From, Value *To,
+ Use *U) {
+ llvm_unreachable("Unsupported class for handleOperandChange()!");
+}
+
+Value *ConstantDataSequential::handleOperandChangeImpl(Value *From, Value *To,
+ Use *U) {
+ llvm_unreachable("Unsupported class for handleOperandChange()!");
+}
+
+Value *ConstantArray::handleOperandChangeImpl(Value *From, Value *To, Use *U) {
assert(isa<Constant>(To) && "Cannot make Constant refer to non-constant!");
Constant *ToC = cast<Constant>(To);
AllSame &= Val == ToC;
}
- if (AllSame && ToC->isNullValue()) {
- replaceUsesOfWithOnConstantImpl(ConstantAggregateZero::get(getType()));
- return;
- }
- if (AllSame && isa<UndefValue>(ToC)) {
- replaceUsesOfWithOnConstantImpl(UndefValue::get(getType()));
- return;
- }
+ if (AllSame && ToC->isNullValue())
+ return ConstantAggregateZero::get(getType());
+
+ if (AllSame && isa<UndefValue>(ToC))
+ return UndefValue::get(getType());
// Check for any other type of constant-folding.
- if (Constant *C = getImpl(getType(), Values)) {
- replaceUsesOfWithOnConstantImpl(C);
- return;
- }
+ if (Constant *C = getImpl(getType(), Values))
+ return C;
// Update to the new value.
- if (Constant *C = getContext().pImpl->ArrayConstants.replaceOperandsInPlace(
- Values, this, From, ToC, NumUpdated, U - OperandList))
- replaceUsesOfWithOnConstantImpl(C);
+ return getContext().pImpl->ArrayConstants.replaceOperandsInPlace(
+ Values, this, From, ToC, NumUpdated, U - OperandList);
}
-void ConstantStruct::replaceUsesOfWithOnConstant(Value *From, Value *To,
- Use *U) {
+Value *ConstantStruct::handleOperandChangeImpl(Value *From, Value *To, Use *U) {
assert(isa<Constant>(To) && "Cannot make Constant refer to non-constant!");
Constant *ToC = cast<Constant>(To);
}
Values[OperandToUpdate] = ToC;
- if (isAllZeros) {
- replaceUsesOfWithOnConstantImpl(ConstantAggregateZero::get(getType()));
- return;
- }
- if (isAllUndef) {
- replaceUsesOfWithOnConstantImpl(UndefValue::get(getType()));
- return;
- }
+ if (isAllZeros)
+ return ConstantAggregateZero::get(getType());
+
+ if (isAllUndef)
+ return UndefValue::get(getType());
// Update to the new value.
- if (Constant *C = getContext().pImpl->StructConstants.replaceOperandsInPlace(
- Values, this, From, ToC))
- replaceUsesOfWithOnConstantImpl(C);
+ return getContext().pImpl->StructConstants.replaceOperandsInPlace(
+ Values, this, From, ToC);
}
-void ConstantVector::replaceUsesOfWithOnConstant(Value *From, Value *To,
- Use *U) {
+Value *ConstantVector::handleOperandChangeImpl(Value *From, Value *To, Use *U) {
assert(isa<Constant>(To) && "Cannot make Constant refer to non-constant!");
Constant *ToC = cast<Constant>(To);
Values.push_back(Val);
}
- if (Constant *C = getImpl(Values)) {
- replaceUsesOfWithOnConstantImpl(C);
- return;
- }
+ if (Constant *C = getImpl(Values))
+ return C;
// Update to the new value.
Use *OperandList = getOperandList();
- if (Constant *C = getContext().pImpl->VectorConstants.replaceOperandsInPlace(
- Values, this, From, ToC, NumUpdated, U - OperandList))
- replaceUsesOfWithOnConstantImpl(C);
+ return getContext().pImpl->VectorConstants.replaceOperandsInPlace(
+ Values, this, From, ToC, NumUpdated, U - OperandList);
}
-void ConstantExpr::replaceUsesOfWithOnConstant(Value *From, Value *ToV,
- Use *U) {
+Value *ConstantExpr::handleOperandChangeImpl(Value *From, Value *ToV, Use *U) {
assert(isa<Constant>(ToV) && "Cannot make Constant refer to non-constant!");
Constant *To = cast<Constant>(ToV);
}
assert(NumUpdated && "I didn't contain From!");
- if (Constant *C = getWithOperands(NewOps, getType(), true)) {
- replaceUsesOfWithOnConstantImpl(C);
- return;
- }
+ if (Constant *C = getWithOperands(NewOps, getType(), true))
+ return C;
// Update to the new value.
Use *OperandList = getOperandList();
- if (Constant *C = getContext().pImpl->ExprConstants.replaceOperandsInPlace(
- NewOps, this, From, To, NumUpdated, U - OperandList))
- replaceUsesOfWithOnConstantImpl(C);
+ return getContext().pImpl->ExprConstants.replaceOperandsInPlace(
+ NewOps, this, From, To, NumUpdated, U - OperandList);
}
Instruction *ConstantExpr::getAsInstruction() {
case Instruction::ICmp:
case Instruction::FCmp:
return CmpInst::Create((Instruction::OtherOps)getOpcode(),
- getPredicate(), Ops[0], Ops[1]);
+ (CmpInst::Predicate)getPredicate(), Ops[0], Ops[1]);
default:
assert(getNumOperands() == 2 && "Must be binary operator?");