if (const ConstantVector *CV = dyn_cast<ConstantVector>(this))
return Elt < CV->getNumOperands() ? CV->getOperand(Elt) : nullptr;
- if (const ConstantAggregateZero *CAZ =dyn_cast<ConstantAggregateZero>(this))
- return CAZ->getElementValue(Elt);
+ if (const ConstantAggregateZero *CAZ = dyn_cast<ConstantAggregateZero>(this))
+ return Elt < CAZ->getNumElements() ? CAZ->getElementValue(Elt) : nullptr;
if (const UndefValue *UV = dyn_cast<UndefValue>(this))
- return UV->getElementValue(Elt);
+ return Elt < UV->getNumElements() ? UV->getElementValue(Elt) : nullptr;
if (const ConstantDataSequential *CDS =dyn_cast<ConstantDataSequential>(this))
return Elt < CDS->getNumElements() ? CDS->getElementAsConstant(Elt)
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");
ConstantInt::getFalse(Ty->getContext()));
}
-
// Get a ConstantInt from an APInt.
ConstantInt *ConstantInt::get(LLVMContext &Context, const APInt &V) {
// get an existing value or the insertion position
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 C;
}
+Constant *ConstantFP::getNaN(Type *Ty, bool Negative, unsigned Type) {
+ const fltSemantics &Semantics = *TypeToFloatSemantics(Ty->getScalarType());
+ APFloat NaN = APFloat::getNaN(Semantics, Negative, Type);
+ Constant *C = get(Ty->getContext(), NaN);
+
+ if (VectorType *VTy = dyn_cast<VectorType>(Ty))
+ return ConstantVector::getSplat(VTy->getNumElements(), C);
+
+ return C;
+}
+
Constant *ConstantFP::getNegativeZero(Type *Ty) {
const fltSemantics &Semantics = *TypeToFloatSemantics(Ty->getScalarType());
APFloat NegZero = APFloat::getZero(Semantics, /*Negative=*/true);
return Val.bitwiseIsEqual(V);
}
+/// Remove the constant from the constant table.
+void ConstantFP::destroyConstantImpl() {
+ llvm_unreachable("You can't ConstantInt->destroyConstantImpl()!");
+}
+
//===----------------------------------------------------------------------===//
// ConstantAggregateZero Implementation
//===----------------------------------------------------------------------===//
return getStructElement(Idx);
}
+unsigned ConstantAggregateZero::getNumElements() const {
+ Type *Ty = getType();
+ if (auto *AT = dyn_cast<ArrayType>(Ty))
+ return AT->getNumElements();
+ if (auto *VT = dyn_cast<VectorType>(Ty))
+ return VT->getNumElements();
+ return Ty->getStructNumElements();
+}
//===----------------------------------------------------------------------===//
// UndefValue Implementation
return getStructElement(Idx);
}
-
+unsigned UndefValue::getNumElements() const {
+ Type *Ty = getType();
+ if (auto *AT = dyn_cast<ArrayType>(Ty))
+ return AT->getNumElements();
+ if (auto *VT = dyn_cast<VectorType>(Ty))
+ return VT->getNumElements();
+ return Ty->getStructNumElements();
+}
//===----------------------------------------------------------------------===//
// ConstantXXX Classes
if (ConstantFP *CFP = dyn_cast<ConstantFP>(C)) {
if (CFP->getType()->isFloatTy()) {
- SmallVector<float, 16> Elts;
+ 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().convertToFloat());
+ Elts.push_back(
+ CFP->getValueAPF().bitcastToAPInt().getLimitedValue());
else
break;
if (Elts.size() == V.size())
- return ConstantDataArray::get(C->getContext(), Elts);
+ return ConstantDataArray::getFP(C->getContext(), Elts);
} else if (CFP->getType()->isDoubleTy()) {
- SmallVector<double, 16> Elts;
+ 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().convertToDouble());
+ Elts.push_back(
+ CFP->getValueAPF().bitcastToAPInt().getLimitedValue());
else
break;
if (Elts.size() == V.size())
- return ConstantDataArray::get(C->getContext(), Elts);
+ return ConstantDataArray::getFP(C->getContext(), Elts);
}
}
}
if (ConstantFP *CFP = dyn_cast<ConstantFP>(C)) {
if (CFP->getType()->isFloatTy()) {
- SmallVector<float, 16> Elts;
+ 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().convertToFloat());
+ Elts.push_back(
+ CFP->getValueAPF().bitcastToAPInt().getLimitedValue());
else
break;
if (Elts.size() == V.size())
- return ConstantDataVector::get(C->getContext(), Elts);
+ return ConstantDataVector::getFP(C->getContext(), Elts);
} else if (CFP->getType()->isDoubleTy()) {
- SmallVector<double, 16> Elts;
+ 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().convertToDouble());
+ Elts.push_back(
+ CFP->getValueAPF().bitcastToAPInt().getLimitedValue());
else
break;
if (Elts.size() == V.size())
- return ConstantDataVector::get(C->getContext(), Elts);
+ return ConstantDataVector::getFP(C->getContext(), Elts);
}
}
}
/// 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!");
- bool AnyChange = Ty != getType();
- for (unsigned i = 0; i != Ops.size(); ++i)
- AnyChange |= Ops[i] != getOperand(i);
- if (!AnyChange) // No operands changed, return self.
+ // If no operands changed return self.
+ if (Ty == getType() && std::equal(Ops.begin(), Ops.end(), op_begin()))
return const_cast<ConstantExpr*>(this);
Type *OnlyIfReducedTy = OnlyIfReduced ? Ty : nullptr;
case Instruction::ShuffleVector:
return ConstantExpr::getShuffleVector(Ops[0], Ops[1], Ops[2],
OnlyIfReducedTy);
- case Instruction::GetElementPtr:
- return ConstantExpr::getGetElementPtr(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.
// Note that a non-inbounds gep is used, as null isn't within any object.
Constant *GEPIdx = ConstantInt::get(Type::getInt32Ty(Ty->getContext()), 1);
Constant *GEP = getGetElementPtr(
- Constant::getNullValue(PointerType::getUnqual(Ty)), GEPIdx);
+ Ty, Constant::getNullValue(PointerType::getUnqual(Ty)), GEPIdx);
return getPtrToInt(GEP,
Type::getInt64Ty(Ty->getContext()));
}
Constant *Zero = ConstantInt::get(Type::getInt64Ty(Ty->getContext()), 0);
Constant *One = ConstantInt::get(Type::getInt32Ty(Ty->getContext()), 1);
Constant *Indices[2] = { Zero, One };
- Constant *GEP = getGetElementPtr(NullPtr, Indices);
+ Constant *GEP = getGetElementPtr(AligningTy, NullPtr, Indices);
return getPtrToInt(GEP,
Type::getInt64Ty(Ty->getContext()));
}
FieldNo
};
Constant *GEP = getGetElementPtr(
- Constant::getNullValue(PointerType::getUnqual(Ty)), GEPIdx);
+ Ty, Constant::getNullValue(PointerType::getUnqual(Ty)), GEPIdx);
return getPtrToInt(GEP,
Type::getInt64Ty(Ty->getContext()));
}
return pImpl->ExprConstants.getOrCreate(V1->getType(), Key);
}
-Constant *ConstantExpr::getGetElementPtr(Constant *C, ArrayRef<Value *> Idxs,
- bool InBounds, Type *OnlyIfReducedTy) {
- assert(C->getType()->isPtrOrPtrVectorTy() &&
- "Non-pointer type for constant GetElementPtr expression");
+Constant *ConstantExpr::getGetElementPtr(Type *Ty, Constant *C,
+ ArrayRef<Value *> Idxs, bool InBounds,
+ Type *OnlyIfReducedTy) {
+ if (!Ty)
+ Ty = cast<PointerType>(C->getType()->getScalarType())->getElementType();
+ else
+ assert(
+ Ty ==
+ cast<PointerType>(C->getType()->getScalarType())->getContainedType(0u));
- if (Constant *FC = ConstantFoldGetElementPtr(C, InBounds, Idxs))
+ if (Constant *FC = ConstantFoldGetElementPtr(Ty, C, InBounds, Idxs))
return FC; // Fold a few common cases.
// Get the result type of the getelementptr!
- Type *Ty = GetElementPtrInst::getIndexedType(C->getType(), Idxs);
- assert(Ty && "GEP indices invalid!");
+ Type *DestTy = GetElementPtrInst::getIndexedType(Ty, Idxs);
+ assert(DestTy && "GEP indices invalid!");
unsigned AS = C->getType()->getPointerAddressSpace();
- Type *ReqTy = Ty->getPointerTo(AS);
+ Type *ReqTy = DestTy->getPointerTo(AS);
if (VectorType *VecTy = dyn_cast<VectorType>(C->getType()))
ReqTy = VectorType::get(ReqTy, VecTy->getNumElements());
ArgVec.push_back(cast<Constant>(Idxs[i]));
}
const ConstantExprKeyType Key(Instruction::GetElementPtr, ArgVec, 0,
- InBounds ? GEPOperator::IsInBounds : 0);
+ InBounds ? GEPOperator::IsInBounds : 0, None,
+ Ty);
LLVMContextImpl *pImpl = C->getContext().pImpl;
return pImpl->ExprConstants.getOrCreate(ReqTy, Key);
// 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 {
return Instruction::getOpcodeName(getOpcode());
}
-
-
-GetElementPtrConstantExpr::
-GetElementPtrConstantExpr(Constant *C, ArrayRef<Constant*> IdxList,
- Type *DestTy)
- : ConstantExpr(DestTy, Instruction::GetElementPtr,
- OperandTraits<GetElementPtrConstantExpr>::op_end(this)
- - (IdxList.size()+1), IdxList.size()+1) {
- OperandList[0] = C;
+GetElementPtrConstantExpr::GetElementPtrConstantExpr(
+ Type *SrcElementTy, Constant *C, ArrayRef<Constant *> IdxList, Type *DestTy)
+ : ConstantExpr(DestTy, Instruction::GetElementPtr,
+ OperandTraits<GetElementPtrConstantExpr>::op_end(this) -
+ (IdxList.size() + 1),
+ IdxList.size() + 1),
+ SrcElementTy(SrcElementTy) {
+ Op<0>() = C;
+ Use *OperandList = getOperandList();
for (unsigned i = 0, E = IdxList.size(); i != E; ++i)
OperandList[i+1] = IdxList[i];
}
+Type *GetElementPtrConstantExpr::getSourceElementType() const {
+ return SrcElementTy;
+}
+
//===----------------------------------------------------------------------===//
// ConstantData* implementations
/// 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) {
+bool ConstantDataSequential::isElementTypeCompatible(Type *Ty) {
if (Ty->isFloatTy() || Ty->isDoubleTy()) return true;
- if (const IntegerType *IT = dyn_cast<IntegerType>(Ty)) {
+ 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
Constant *ConstantDataArray::get(LLVMContext &Context, ArrayRef<double> Elts) {
Type *Ty = ArrayType::get(Type::getDoubleTy(Context), Elts.size());
const char *Data = reinterpret_cast<const char *>(Elts.data());
- return getImpl(StringRef(const_cast<char *>(Data), Elts.size()*8), Ty);
+ return getImpl(StringRef(const_cast<char *>(Data), Elts.size() * 8), Ty);
+}
+
+/// getFP() constructors - Return a constant with array type with an element
+/// count and element type of float with precision matching the number of
+/// bits in the ArrayRef passed in. (i.e. half for 16bits, float for 32bits,
+/// double for 64bits) Note that this can return a ConstantAggregateZero
+/// object.
+Constant *ConstantDataArray::getFP(LLVMContext &Context,
+ ArrayRef<uint16_t> Elts) {
+ Type *Ty = VectorType::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);
+}
+Constant *ConstantDataArray::getFP(LLVMContext &Context,
+ ArrayRef<uint32_t> Elts) {
+ Type *Ty = ArrayType::get(Type::getFloatTy(Context), Elts.size());
+ const char *Data = reinterpret_cast<const char *>(Elts.data());
+ return getImpl(StringRef(const_cast<char *>(Data), Elts.size() * 4), Ty);
+}
+Constant *ConstantDataArray::getFP(LLVMContext &Context,
+ ArrayRef<uint64_t> Elts) {
+ Type *Ty = ArrayType::get(Type::getDoubleTy(Context), Elts.size());
+ const char *Data = reinterpret_cast<const char *>(Elts.data());
+ return getImpl(StringRef(const_cast<char *>(Data), Elts.size() * 8), Ty);
}
/// getString - This method constructs a CDS and initializes it with a text
Constant *ConstantDataVector::get(LLVMContext &Context, ArrayRef<double> Elts) {
Type *Ty = VectorType::get(Type::getDoubleTy(Context), Elts.size());
const char *Data = reinterpret_cast<const char *>(Elts.data());
- return getImpl(StringRef(const_cast<char *>(Data), Elts.size()*8), Ty);
+ return getImpl(StringRef(const_cast<char *>(Data), Elts.size() * 8), Ty);
+}
+
+/// getFP() constructors - Return a constant with vector type with an element
+/// count and element type of float with the precision matching the number of
+/// bits in the ArrayRef passed in. (i.e. half for 16bits, float for 32bits,
+/// double for 64bits) Note that this can return a ConstantAggregateZero
+/// object.
+Constant *ConstantDataVector::getFP(LLVMContext &Context,
+ ArrayRef<uint16_t> Elts) {
+ Type *Ty = VectorType::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);
+}
+Constant *ConstantDataVector::getFP(LLVMContext &Context,
+ ArrayRef<uint32_t> Elts) {
+ Type *Ty = VectorType::get(Type::getFloatTy(Context), Elts.size());
+ const char *Data = reinterpret_cast<const char *>(Elts.data());
+ return getImpl(StringRef(const_cast<char *>(Data), Elts.size() * 4), Ty);
+}
+Constant *ConstantDataVector::getFP(LLVMContext &Context,
+ ArrayRef<uint64_t> Elts) {
+ Type *Ty = VectorType::get(Type::getDoubleTy(Context), Elts.size());
+ const char *Data = reinterpret_cast<const char *>(Elts.data());
+ return getImpl(StringRef(const_cast<char *>(Data), Elts.size() * 8), Ty);
}
Constant *ConstantDataVector::getSplat(unsigned NumElts, Constant *V) {
if (ConstantFP *CFP = dyn_cast<ConstantFP>(V)) {
if (CFP->getType()->isFloatTy()) {
- SmallVector<float, 16> Elts(NumElts, CFP->getValueAPF().convertToFloat());
- return get(V->getContext(), Elts);
+ SmallVector<uint32_t, 16> Elts(
+ NumElts, CFP->getValueAPF().bitcastToAPInt().getLimitedValue());
+ return getFP(V->getContext(), Elts);
}
if (CFP->getType()->isDoubleTy()) {
- SmallVector<double, 16> Elts(NumElts,
- CFP->getValueAPF().convertToDouble());
- return get(V->getContext(), Elts);
+ SmallVector<uint64_t, 16> Elts(
+ NumElts, CFP->getValueAPF().bitcastToAPInt().getLimitedValue());
+ return getFP(V->getContext(), Elts);
}
}
return ConstantVector::getSplat(NumElts, V);
default:
llvm_unreachable("Accessor can only be used when element is float/double!");
case Type::FloatTyID: {
- const float *FloatPrt = reinterpret_cast<const float *>(EltPtr);
- return APFloat(*const_cast<float *>(FloatPrt));
- }
+ auto EltVal = *reinterpret_cast<const uint32_t *>(EltPtr);
+ return APFloat(APFloat::IEEEsingle, APInt(32, EltVal));
+ }
case Type::DoubleTyID: {
- const double *DoublePtr = reinterpret_cast<const double *>(EltPtr);
- return APFloat(*const_cast<double *>(DoublePtr));
- }
+ auto EltVal = *reinterpret_cast<const uint64_t *>(EltPtr);
+ return APFloat(APFloat::IEEEdouble, APInt(64, EltVal));
+ }
}
}
}
//===----------------------------------------------------------------------===//
-// 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 *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);
// Keep track of whether all the values in the array are "ToC".
bool AllSame = true;
+ Use *OperandList = getOperandList();
for (Use *O = OperandList, *E = OperandList+getNumOperands(); O != E; ++O) {
Constant *Val = cast<Constant>(O->get());
if (Val == From) {
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);
+ Use *OperandList = getOperandList();
unsigned OperandToUpdate = U-OperandList;
assert(getOperand(OperandToUpdate) == From && "ReplaceAllUsesWith broken!");
}
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.
- if (Constant *C = getContext().pImpl->VectorConstants.replaceOperandsInPlace(
- Values, this, From, ToC, NumUpdated, U - OperandList))
- replaceUsesOfWithOnConstantImpl(C);
+ Use *OperandList = getOperandList();
+ 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.
- if (Constant *C = getContext().pImpl->ExprConstants.replaceOperandsInPlace(
- NewOps, this, From, To, NumUpdated, U - OperandList))
- replaceUsesOfWithOnConstantImpl(C);
+ Use *OperandList = getOperandList();
+ return getContext().pImpl->ExprConstants.replaceOperandsInPlace(
+ NewOps, this, From, To, NumUpdated, U - OperandList);
}
Instruction *ConstantExpr::getAsInstruction() {
- SmallVector<Value*,4> ValueOperands;
- for (op_iterator I = op_begin(), E = op_end(); I != E; ++I)
- ValueOperands.push_back(cast<Value>(I));
-
+ SmallVector<Value *, 4> ValueOperands(op_begin(), op_end());
ArrayRef<Value*> Ops(ValueOperands);
switch (getOpcode()) {
case Instruction::ShuffleVector:
return new ShuffleVectorInst(Ops[0], Ops[1], Ops[2]);
- case Instruction::GetElementPtr:
- if (cast<GEPOperator>(this)->isInBounds())
- return GetElementPtrInst::CreateInBounds(Ops[0], Ops.slice(1));
- else
- return GetElementPtrInst::Create(Ops[0], Ops.slice(1));
-
+ case Instruction::GetElementPtr: {
+ const auto *GO = cast<GEPOperator>(this);
+ if (GO->isInBounds())
+ return GetElementPtrInst::CreateInBounds(GO->getSourceElementType(),
+ Ops[0], Ops.slice(1));
+ return GetElementPtrInst::Create(GO->getSourceElementType(), Ops[0],
+ Ops.slice(1));
+ }
case Instruction::ICmp:
case Instruction::FCmp:
return CmpInst::Create((Instruction::OtherOps)getOpcode(),