IR: Introduce ConstantAggregate, NFC

Add a common parent class for ConstantArray, ConstantVector, and
ConstantStruct called ConstantAggregate.  These are the aggregate
subclasses of Constant that take operands.

This is mainly a cleanup, adding common `isa` target and removing
duplicated code.  However, it also simplifies caching which constants
point transitively at `GlobalValue` (a possible future direction).

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@265466 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Duncan P. N. Exon Smith 2016-04-05 21:10:45 +00:00
parent 3444a406d3
commit d7773c0d39
9 changed files with 78 additions and 86 deletions

View File

@ -353,14 +353,43 @@ public:
}
};
/// Base class for aggregate constants (with operands).
///
/// These constants are aggregates of other constants, which are stored as
/// operands.
///
/// Subclasses are \a ConstantStruct, \a ConstantArray, and \a
/// ConstantVector.
///
/// \note Some subclasses of \a ConstantData are semantically aggregates --
/// such as \a ConstantDataArray -- but are not subclasses of this because they
/// use operands.
class ConstantAggregate : public Constant {
protected:
ConstantAggregate(CompositeType *T, ValueTy VT, ArrayRef<Constant *> V);
public:
/// Transparently provide more efficient getOperand methods.
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant);
/// Methods for support type inquiry through isa, cast, and dyn_cast:
static bool classof(const Value *V) {
return V->getValueID() >= ConstantAggregateFirstVal &&
V->getValueID() <= ConstantAggregateLastVal;
}
};
template <>
struct OperandTraits<ConstantAggregate>
: public VariadicOperandTraits<ConstantAggregate> {};
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantAggregate, Constant)
//===----------------------------------------------------------------------===//
/// ConstantArray - Constant Array Declarations
///
class ConstantArray final : public Constant {
class ConstantArray final : public ConstantAggregate {
friend struct ConstantAggrKeyType<ConstantArray>;
ConstantArray(const ConstantArray &) = delete;
friend class Constant;
void destroyConstantImpl();
Value *handleOperandChangeImpl(Value *From, Value *To);
@ -375,9 +404,6 @@ private:
static Constant *getImpl(ArrayType *T, ArrayRef<Constant *> V);
public:
/// Transparently provide more efficient getOperand methods.
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant);
/// Specialize the getType() method to always return an ArrayType,
/// which reduces the amount of casting needed in parts of the compiler.
inline ArrayType *getType() const {
@ -390,20 +416,11 @@ public:
}
};
template <>
struct OperandTraits<ConstantArray> :
public VariadicOperandTraits<ConstantArray> {
};
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantArray, Constant)
//===----------------------------------------------------------------------===//
// Constant Struct Declarations
//
class ConstantStruct final : public Constant {
class ConstantStruct final : public ConstantAggregate {
friend struct ConstantAggrKeyType<ConstantStruct>;
ConstantStruct(const ConstantStruct &) = delete;
friend class Constant;
void destroyConstantImpl();
Value *handleOperandChangeImpl(Value *From, Value *To);
@ -434,9 +451,6 @@ public:
ArrayRef<Constant*> V,
bool Packed = false);
/// Transparently provide more efficient getOperand methods.
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant);
/// Specialization - reduce amount of casting.
inline StructType *getType() const {
return cast<StructType>(Value::getType());
@ -448,21 +462,12 @@ public:
}
};
template <>
struct OperandTraits<ConstantStruct> :
public VariadicOperandTraits<ConstantStruct> {
};
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantStruct, Constant)
//===----------------------------------------------------------------------===//
/// Constant Vector Declarations
///
class ConstantVector final : public Constant {
class ConstantVector final : public ConstantAggregate {
friend struct ConstantAggrKeyType<ConstantVector>;
ConstantVector(const ConstantVector &) = delete;
friend class Constant;
void destroyConstantImpl();
Value *handleOperandChangeImpl(Value *From, Value *To);
@ -480,9 +485,6 @@ public:
/// Return a ConstantVector with the specified constant in each element.
static Constant *getSplat(unsigned NumElts, Constant *Elt);
/// Transparently provide more efficient getOperand methods.
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant);
/// Specialize the getType() method to always return a VectorType,
/// which reduces the amount of casting needed in parts of the compiler.
inline VectorType *getType() const {
@ -499,13 +501,6 @@ public:
}
};
template <>
struct OperandTraits<ConstantVector> :
public VariadicOperandTraits<ConstantVector> {
};
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantVector, Constant)
//===----------------------------------------------------------------------===//
/// A constant pointer value that points to null
///

View File

@ -63,6 +63,8 @@ HANDLE_GLOBAL_VALUE(GlobalAlias)
HANDLE_GLOBAL_VALUE(GlobalVariable)
HANDLE_CONSTANT(BlockAddress)
HANDLE_CONSTANT(ConstantExpr)
// ConstantAggregate.
HANDLE_CONSTANT(ConstantArray)
HANDLE_CONSTANT(ConstantStruct)
HANDLE_CONSTANT(ConstantVector)
@ -88,6 +90,8 @@ HANDLE_CONSTANT_MARKER(ConstantFirstVal, Function)
HANDLE_CONSTANT_MARKER(ConstantLastVal, ConstantTokenNone)
HANDLE_CONSTANT_MARKER(ConstantDataFirstVal, UndefValue)
HANDLE_CONSTANT_MARKER(ConstantDataLastVal, ConstantTokenNone)
HANDLE_CONSTANT_MARKER(ConstantAggregateFirstVal, ConstantArray)
HANDLE_CONSTANT_MARKER(ConstantAggregateLastVal, ConstantVector)
#undef HANDLE_GLOBAL_VALUE
#undef HANDLE_CONSTANT

View File

@ -28,6 +28,7 @@ class AssemblyAnnotationWriter;
class BasicBlock;
class Constant;
class ConstantData;
class ConstantAggregate;
class DataLayout;
class Function;
class GlobalAlias;
@ -701,6 +702,13 @@ template <> struct isa_impl<ConstantData, Value> {
}
};
template <> struct isa_impl<ConstantAggregate, Value> {
static inline bool doit(const Value &Val) {
return Val.getValueID() >= Value::ConstantAggregateFirstVal &&
Val.getValueID() <= Value::ConstantAggregateLastVal;
}
};
template <> struct isa_impl<Argument, Value> {
static inline bool doit (const Value &Val) {
return Val.getValueID() == Value::ArgumentVal;

View File

@ -894,13 +894,12 @@ static bool canSkipAddingToSets(Value *Val) {
// we should filter out the (potentially shared) instance to
// i32* null.
if (isa<Constant>(Val)) {
bool Container = isa<ConstantVector>(Val) || isa<ConstantArray>(Val) ||
isa<ConstantStruct>(Val);
// TODO: Because all of these things are constant, we can determine whether
// the data is *actually* mutable at graph building time. This will probably
// come for free/cheap with offset awareness.
bool CanStoreMutableData =
isa<GlobalValue>(Val) || isa<ConstantExpr>(Val) || Container;
bool CanStoreMutableData = isa<GlobalValue>(Val) ||
isa<ConstantExpr>(Val) ||
isa<ConstantAggregate>(Val);
return !CanStoreMutableData;
}

View File

@ -1708,8 +1708,7 @@ static void WriteConstants(unsigned FirstVal, unsigned LastVal,
Record.push_back(
CDS->getElementAsAPFloat(i).bitcastToAPInt().getLimitedValue());
}
} else if (isa<ConstantArray>(C) || isa<ConstantStruct>(C) ||
isa<ConstantVector>(C)) {
} else if (isa<ConstantAggregate>(C)) {
Code = bitc::CST_CODE_AGGREGATE;
for (const Value *Op : C->operands())
Record.push_back(VE.getValueID(Op));

View File

@ -270,14 +270,8 @@ Constant *Constant::getAllOnesValue(Type *Ty) {
/// not. This can return null if the element index is a ConstantExpr, or if
/// 'this' is a constant expr.
Constant *Constant::getAggregateElement(unsigned Elt) const {
if (const ConstantStruct *CS = dyn_cast<ConstantStruct>(this))
return Elt < CS->getNumOperands() ? CS->getOperand(Elt) : nullptr;
if (const ConstantArray *CA = dyn_cast<ConstantArray>(this))
return Elt < CA->getNumOperands() ? CA->getOperand(Elt) : nullptr;
if (const ConstantVector *CV = dyn_cast<ConstantVector>(this))
return Elt < CV->getNumOperands() ? CV->getOperand(Elt) : nullptr;
if (const ConstantAggregate *CC = dyn_cast<ConstantAggregate>(this))
return Elt < CC->getNumOperands() ? CC->getOperand(Elt) : nullptr;
if (const ConstantAggregateZero *CAZ = dyn_cast<ConstantAggregateZero>(this))
return Elt < CAZ->getNumElements() ? CAZ->getElementValue(Elt) : nullptr;
@ -912,16 +906,25 @@ static Constant *getSequenceIfElementsMatch(Constant *C,
return nullptr;
}
ConstantArray::ConstantArray(ArrayType *T, ArrayRef<Constant *> V)
: Constant(T, ConstantArrayVal,
OperandTraits<ConstantArray>::op_end(this) - V.size(),
ConstantAggregate::ConstantAggregate(CompositeType *T, ValueTy VT,
ArrayRef<Constant *> V)
: Constant(T, VT, OperandTraits<ConstantAggregate>::op_end(this) - V.size(),
V.size()) {
assert(V.size() == T->getNumElements() &&
"Invalid initializer vector for constant array");
for (unsigned i = 0, e = V.size(); i != e; ++i)
assert(V[i]->getType() == T->getElementType() &&
"Initializer for array element doesn't match array element type!");
std::copy(V.begin(), V.end(), op_begin());
// Check that types match, unless this is an opaque struct.
if (auto *ST = dyn_cast<StructType>(T))
if (ST->isOpaque())
return;
for (unsigned I = 0, E = V.size(); I != E; ++I)
assert(V[I]->getType() == T->getTypeAtIndex(I) &&
"Initializer for composite element doesn't match!");
}
ConstantArray::ConstantArray(ArrayType *T, ArrayRef<Constant *> V)
: ConstantAggregate(T, ConstantArrayVal, V) {
assert(V.size() == T->getNumElements() &&
"Invalid initializer for constant array");
}
Constant *ConstantArray::get(ArrayType *Ty, ArrayRef<Constant*> V) {
@ -980,17 +983,10 @@ StructType *ConstantStruct::getTypeForElements(ArrayRef<Constant*> V,
return getTypeForElements(V[0]->getContext(), V, Packed);
}
ConstantStruct::ConstantStruct(StructType *T, ArrayRef<Constant *> V)
: Constant(T, ConstantStructVal,
OperandTraits<ConstantStruct>::op_end(this) - V.size(),
V.size()) {
assert(V.size() == T->getNumElements() &&
"Invalid initializer vector for constant structure");
for (unsigned i = 0, e = V.size(); i != e; ++i)
assert((T->isOpaque() || V[i]->getType() == T->getElementType(i)) &&
"Initializer for struct element doesn't match struct element type!");
std::copy(V.begin(), V.end(), op_begin());
: ConstantAggregate(T, ConstantStructVal, V) {
assert((T->isOpaque() || V.size() == T->getNumElements()) &&
"Invalid initializer for constant struct");
}
// ConstantStruct accessors.
@ -1033,15 +1029,9 @@ Constant *ConstantStruct::get(StructType *T, ...) {
}
ConstantVector::ConstantVector(VectorType *T, ArrayRef<Constant *> V)
: Constant(T, ConstantVectorVal,
OperandTraits<ConstantVector>::op_end(this) - V.size(),
V.size()) {
: ConstantAggregate(T, ConstantVectorVal, V) {
assert(V.size() == T->getNumElements() &&
"Invalid initializer vector for constant vector");
for (size_t i = 0, e = V.size(); i != e; i++)
assert(V[i]->getType() == T->getElementType() &&
"Initializer for vector element doesn't match vector element type!");
std::copy(V.begin(), V.end(), op_begin());
"Invalid initializer for constant vector");
}
// ConstantVector accessors.

View File

@ -1910,8 +1910,7 @@ void NVPTXAsmPrinter::bufferLEByte(const Constant *CPV, int Bytes,
case Type::ArrayTyID:
case Type::VectorTyID:
case Type::StructTyID: {
if (isa<ConstantArray>(CPV) || isa<ConstantVector>(CPV) ||
isa<ConstantStruct>(CPV) || isa<ConstantDataSequential>(CPV)) {
if (isa<ConstantAggregate>(CPV) || isa<ConstantDataSequential>(CPV)) {
int ElementSize = DL.getTypeAllocSize(CPV->getType());
bufferAggregateConstant(CPV, aggBuffer);
if (Bytes > ElementSize)

View File

@ -230,8 +230,7 @@ Value *GenericToNVVM::remapConstant(Module *M, Function *F, Constant *C,
if (I != GVMap.end()) {
NewValue = getOrInsertCVTA(M, F, I->second, Builder);
}
} else if (isa<ConstantVector>(C) || isa<ConstantArray>(C) ||
isa<ConstantStruct>(C)) {
} else if (isa<ConstantAggregate>(C)) {
// If any element in the constant vector or aggregate C is or uses a global
// variable in GVMap, the constant C needs to be reconstructed, using a set
// of instructions.

View File

@ -56,8 +56,7 @@ isSimpleEnoughValueToCommitHelper(Constant *C,
return true;
// Aggregate values are safe if all their elements are.
if (isa<ConstantArray>(C) || isa<ConstantStruct>(C) ||
isa<ConstantVector>(C)) {
if (isa<ConstantAggregate>(C)) {
for (Value *Op : C->operands())
if (!isSimpleEnoughValueToCommit(cast<Constant>(Op), SimpleConstants, DL))
return false;