diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp --- a/clang/lib/CodeGen/CGExprConstant.cpp +++ b/clang/lib/CodeGen/CGExprConstant.cpp @@ -318,12 +318,17 @@ CharUnits Offset = Offsets[Index]; if (auto *CA = dyn_cast(C)) { + // Expand the sequence into its contained elements. + // FIXME: This assumes vector elements are byte-sized. replace(Elems, Index, Index + 1, llvm::map_range(llvm::seq(0u, CA->getNumOperands()), [&](unsigned Op) { return CA->getOperand(Op); })); - if (auto *Seq = dyn_cast(CA->getType())) { + if (isa(CA->getType()) || + isa(CA->getType())) { // Array or vector. - CharUnits ElemSize = getSize(Seq->getElementType()); + llvm::Type *ElemTy = + llvm::GetElementPtrInst::getTypeAtIndex(CA->getType(), (uint64_t)0); + CharUnits ElemSize = getSize(ElemTy); replace( Offsets, Index, Index + 1, llvm::map_range(llvm::seq(0u, CA->getNumOperands()), @@ -344,6 +349,8 @@ } if (auto *CDS = dyn_cast(C)) { + // Expand the sequence into its contained elements. + // FIXME: This assumes vector elements are byte-sized. // FIXME: If possible, split into two ConstantDataSequentials at Hint. CharUnits ElemSize = getSize(CDS->getElementType()); replace(Elems, Index, Index + 1, @@ -359,6 +366,7 @@ } if (isa(C)) { + // Split into two zeros at the hinted offset. CharUnits ElemSize = getSize(C); assert(Hint > Offset && Hint < Offset + ElemSize && "nothing to split"); replace(Elems, Index, Index + 1, @@ -368,6 +376,7 @@ } if (isa(C)) { + // Drop undef; it doesn't contribute to the final layout. replace(Elems, Index, Index + 1, {}); replace(Offsets, Index, Index + 1, {}); return true; diff --git a/llvm/include/llvm/IR/Constants.h b/llvm/include/llvm/IR/Constants.h --- a/llvm/include/llvm/IR/Constants.h +++ b/llvm/include/llvm/IR/Constants.h @@ -44,7 +44,6 @@ class ArrayType; class IntegerType; class PointerType; -class SequentialType; class StructType; class VectorType; template struct ConstantAggrKeyType; @@ -631,12 +630,6 @@ /// efficient as getElementAsInteger/Float/Double. Constant *getElementAsConstant(unsigned i) const; - /// Specialize the getType() method to always return a SequentialType, which - /// reduces the amount of casting needed in parts of the compiler. - inline SequentialType *getType() const { - return cast(Value::getType()); - } - /// Return the element type of the array/vector. Type *getElementType() const; diff --git a/llvm/include/llvm/IR/DerivedTypes.h b/llvm/include/llvm/IR/DerivedTypes.h --- a/llvm/include/llvm/IR/DerivedTypes.h +++ b/llvm/include/llvm/IR/DerivedTypes.h @@ -354,47 +354,22 @@ return cast(this)->getElementType(N); } -/// This is the superclass of the array and vector type classes. Both of these -/// represent "arrays" in memory. The array type represents a specifically sized -/// array, and the vector type represents a specifically sized array that allows -/// for use of SIMD instructions. SequentialType holds the common features of -/// both, which stem from the fact that both lay their components out in memory -/// identically. -class SequentialType : public Type { - Type *ContainedType; ///< Storage for the single contained type. +/// Class to represent array types. +class ArrayType : public Type { + /// The element type of the array. + Type *ContainedType; + /// Number of elements in the array. uint64_t NumElements; -protected: - SequentialType(TypeID TID, Type *ElType, uint64_t NumElements) - : Type(ElType->getContext(), TID), ContainedType(ElType), - NumElements(NumElements) { - ContainedTys = &ContainedType; - NumContainedTys = 1; - } - -public: - SequentialType(const SequentialType &) = delete; - SequentialType &operator=(const SequentialType &) = delete; - - /// For scalable vectors, this will return the minimum number of elements - /// in the vector. - uint64_t getNumElements() const { return NumElements; } - Type *getElementType() const { return ContainedType; } - - /// Methods for support type inquiry through isa, cast, and dyn_cast. - static bool classof(const Type *T) { - return T->getTypeID() == ArrayTyID || T->getTypeID() == VectorTyID; - } -}; - -/// Class to represent array types. -class ArrayType : public SequentialType { ArrayType(Type *ElType, uint64_t NumEl); public: ArrayType(const ArrayType &) = delete; ArrayType &operator=(const ArrayType &) = delete; + uint64_t getNumElements() const { return NumElements; } + Type *getElementType() const { return ContainedType; } + /// This static method is the primary way to construct an ArrayType static ArrayType *get(Type *ElementType, uint64_t NumElements); @@ -412,7 +387,7 @@ } /// Class to represent vector types. -class VectorType : public SequentialType { +class VectorType : public Type { /// A fully specified VectorType is of the form . 'n' is the /// minimum number of elements of type Ty contained within the vector, and /// 'vscale x' indicates that the total element count is an integer multiple @@ -426,18 +401,28 @@ /// - a vector containing an unknown integer multiple /// of 4 i32s + /// The element type of the vector. + Type *ContainedType; + /// Minumum number of elements in the vector. + uint64_t NumElements; + VectorType(Type *ElType, unsigned NumEl, bool Scalable = false); VectorType(Type *ElType, ElementCount EC); // If true, the total number of elements is an unknown multiple of the - // minimum 'NumElements' from SequentialType. Otherwise the total number - // of elements is exactly equal to 'NumElements'. + // minimum 'NumElements'. Otherwise the total number of elements is exactly + // equal to 'NumElements'. bool Scalable; public: VectorType(const VectorType &) = delete; VectorType &operator=(const VectorType &) = delete; + /// For scalable vectors, this will return the minimum number of elements + /// in the vector. + uint64_t getNumElements() const { return NumElements; } + Type *getElementType() const { return ContainedType; } + /// This static method is the primary way to construct an VectorType. static VectorType *get(Type *ElementType, ElementCount EC); static VectorType *get(Type *ElementType, unsigned NumElements, diff --git a/llvm/include/llvm/IR/GetElementPtrTypeIterator.h b/llvm/include/llvm/IR/GetElementPtrTypeIterator.h --- a/llvm/include/llvm/IR/GetElementPtrTypeIterator.h +++ b/llvm/include/llvm/IR/GetElementPtrTypeIterator.h @@ -75,9 +75,15 @@ generic_gep_type_iterator& operator++() { // Preincrement Type *Ty = getIndexedType(); - if (auto *STy = dyn_cast(Ty)) { - CurTy = STy->getElementType(); - NumElements = STy->getNumElements(); + if (auto *ATy = dyn_cast(Ty)) { + CurTy = ATy->getElementType(); + NumElements = ATy->getNumElements(); + } else if (auto *VTy = dyn_cast(Ty)) { + CurTy = VTy->getElementType(); + if (VTy->isScalable()) + NumElements = Unbounded; + else + NumElements = VTy->getNumElements(); } else CurTy = dyn_cast(Ty); ++OpIt; diff --git a/llvm/include/llvm/IR/Type.h b/llvm/include/llvm/IR/Type.h --- a/llvm/include/llvm/IR/Type.h +++ b/llvm/include/llvm/IR/Type.h @@ -110,10 +110,6 @@ /// Float). Type * const *ContainedTys = nullptr; - static bool isSequentialType(TypeID TyID) { - return TyID == ArrayTyID || TyID == VectorTyID; - } - public: /// Print the current type. /// Omit the type details if \p NoDetails == true. @@ -358,11 +354,6 @@ inline unsigned getStructNumElements() const; inline Type *getStructElementType(unsigned N) const; - inline Type *getSequentialElementType() const { - assert(isSequentialType(getTypeID()) && "Not a sequential type!"); - return ContainedTys[0]; - } - inline uint64_t getArrayNumElements() const; Type *getArrayElementType() const { diff --git a/llvm/lib/Analysis/BasicAliasAnalysis.cpp b/llvm/lib/Analysis/BasicAliasAnalysis.cpp --- a/llvm/lib/Analysis/BasicAliasAnalysis.cpp +++ b/llvm/lib/Analysis/BasicAliasAnalysis.cpp @@ -1145,11 +1145,11 @@ GEP1->getSourceElementType(), IntermediateIndices); StructType *LastIndexedStruct = dyn_cast(Ty); - if (isa(Ty)) { + if (isa(Ty) || isa(Ty)) { // We know that: // - both GEPs begin indexing from the exact same pointer; // - the last indices in both GEPs are constants, indexing into a sequential - // type (array or pointer); + // type (array or vector); // - both GEPs only index through arrays prior to that. // // Because array indices greater than the number of elements are valid in @@ -1157,8 +1157,8 @@ // GEP1 and GEP2 we cannot guarantee that the last indexed arrays don't // partially overlap. We also need to check that the loaded size matches // the element size, otherwise we could still have overlap. - const uint64_t ElementSize = - DL.getTypeStoreSize(cast(Ty)->getElementType()); + Type *LastElementTy = GetElementPtrInst::getTypeAtIndex(Ty, (uint64_t)0); + const uint64_t ElementSize = DL.getTypeStoreSize(LastElementTy); if (V1Size != ElementSize || V2Size != ElementSize) return MayAlias; diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp --- a/llvm/lib/Analysis/ConstantFolding.cpp +++ b/llvm/lib/Analysis/ConstantFolding.cpp @@ -462,15 +462,18 @@ if (isa(C) || isa(C) || isa(C)) { - Type *EltTy = C->getType()->getSequentialElementType(); - uint64_t EltSize = DL.getTypeAllocSize(EltTy); - uint64_t Index = ByteOffset / EltSize; - uint64_t Offset = ByteOffset - Index * EltSize; uint64_t NumElts; - if (auto *AT = dyn_cast(C->getType())) + Type *EltTy; + if (auto *AT = dyn_cast(C->getType())) { NumElts = AT->getNumElements(); - else + EltTy = AT->getElementType(); + } else { NumElts = C->getType()->getVectorNumElements(); + EltTy = C->getType()->getVectorElementType(); + } + uint64_t EltSize = DL.getTypeAllocSize(EltTy); + uint64_t Index = ByteOffset / EltSize; + uint64_t Offset = ByteOffset - Index * EltSize; for (; Index != NumElts; ++Index) { if (!ReadDataFromGlobal(C->getAggregateElement(Index), Offset, CurPtr, @@ -935,11 +938,11 @@ // Only handle pointers to sized types, not pointers to functions. if (!Ty->isSized()) return nullptr; - } else if (auto *ATy = dyn_cast(Ty)) { - Ty = ATy->getElementType(); } else { - // We've reached some non-indexable type. - break; + Type *NextTy = GetElementPtrInst::getTypeAtIndex(Ty, (uint64_t)0); + if (!NextTy) + break; + Ty = NextTy; } // Determine which element of the array the offset points into. diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp --- a/llvm/lib/Analysis/ScalarEvolution.cpp +++ b/llvm/lib/Analysis/ScalarEvolution.cpp @@ -3555,7 +3555,7 @@ CurTy = GEP->getSourceElementType(); FirstIter = false; } else { - CurTy = cast(CurTy)->getElementType(); + CurTy = GetElementPtrInst::getTypeAtIndex(CurTy, (uint64_t)0); } // For an array, add the element offset, explicitly scaled. const SCEV *ElementSize = getSizeOfExpr(IntIdxTy, CurTy); diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -2473,7 +2473,11 @@ if (Record.empty()) return error("Invalid record"); - Type *EltTy = cast(CurTy)->getElementType(); + Type *EltTy; + if (auto *Array = dyn_cast(CurTy)) + EltTy = Array->getElementType(); + else + EltTy = cast(CurTy)->getElementType(); if (EltTy->isIntegerTy(8)) { SmallVector Elts(Record.begin(), Record.end()); if (isa(CurTy)) diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -2423,7 +2423,7 @@ } else if (const ConstantDataSequential *CDS = dyn_cast(C)) { Code = bitc::CST_CODE_DATA; - Type *EltTy = CDS->getType()->getElementType(); + Type *EltTy = CDS->getElementType(); if (isa(EltTy)) { for (unsigned i = 0, e = CDS->getNumElements(); i != e; ++i) Record.push_back(CDS->getElementAsInteger(i)); diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -2487,8 +2487,8 @@ } unsigned Size = DL.getTypeAllocSize(CDS->getType()); - unsigned EmittedSize = DL.getTypeAllocSize(CDS->getType()->getElementType()) * - CDS->getNumElements(); + unsigned EmittedSize = + DL.getTypeAllocSize(CDS->getElementType()) * CDS->getNumElements(); assert(EmittedSize <= Size && "Size cannot be less than EmittedSize!"); if (unsigned Padding = Size - EmittedSize) AP.OutStreamer->emitZeros(Padding); diff --git a/llvm/lib/IR/ConstantFold.cpp b/llvm/lib/IR/ConstantFold.cpp --- a/llvm/lib/IR/ConstantFold.cpp +++ b/llvm/lib/IR/ConstantFold.cpp @@ -119,18 +119,9 @@ Constant::getNullValue(Type::getInt32Ty(DPTy->getContext())); IdxList.push_back(Zero); Type *ElTy = PTy->getElementType(); - while (ElTy != DPTy->getElementType()) { - if (StructType *STy = dyn_cast(ElTy)) { - if (STy->getNumElements() == 0) break; - ElTy = STy->getElementType(0); - IdxList.push_back(Zero); - } else if (SequentialType *STy = - dyn_cast(ElTy)) { - ElTy = STy->getElementType(); - IdxList.push_back(Zero); - } else { - break; - } + while (ElTy && ElTy != DPTy->getElementType()) { + ElTy = GetElementPtrInst::getTypeAtIndex(ElTy, (uint64_t)0); + IdxList.push_back(Zero); } if (ElTy == DPTy->getElementType()) @@ -936,7 +927,7 @@ if (StructType *ST = dyn_cast(Agg->getType())) NumElts = ST->getNumElements(); else - NumElts = cast(Agg->getType())->getNumElements(); + NumElts = cast(Agg->getType())->getNumElements(); SmallVector Result; for (unsigned i = 0; i != NumElts; ++i) { @@ -951,9 +942,7 @@ if (StructType *ST = dyn_cast(Agg->getType())) return ConstantStruct::get(ST, Result); - if (ArrayType *AT = dyn_cast(Agg->getType())) - return ConstantArray::get(AT, Result); - return ConstantVector::get(Result); + return ConstantArray::get(cast(Agg->getType()), Result); } Constant *llvm::ConstantFoldUnaryInstruction(unsigned Opcode, Constant *C) { @@ -2412,12 +2401,12 @@ // The verify makes sure that GEPs into a struct are in range. continue; } - auto *STy = cast(Ty); - if (isa(STy)) { + if (isa(Ty)) { // There can be awkward padding in after a non-power of two vector. Unknown = true; continue; } + auto *STy = cast(Ty); if (ConstantInt *CI = dyn_cast(Idxs[i])) { if (isIndexInRangeOfArrayType(STy->getNumElements(), CI)) // It's in range, skip to the next index. diff --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp --- a/llvm/lib/IR/Constants.cpp +++ b/llvm/lib/IR/Constants.cpp @@ -923,7 +923,9 @@ //===----------------------------------------------------------------------===// Constant *ConstantAggregateZero::getSequentialElement() const { - return Constant::getNullValue(getType()->getSequentialElementType()); + if (auto *AT = dyn_cast(getType())) + return Constant::getNullValue(AT->getElementType()); + return Constant::getNullValue(cast(getType())->getElementType()); } Constant *ConstantAggregateZero::getStructElement(unsigned Elt) const { @@ -931,13 +933,13 @@ } Constant *ConstantAggregateZero::getElementValue(Constant *C) const { - if (isa(getType())) + if (isa(getType()) || isa(getType())) return getSequentialElement(); return getStructElement(cast(C)->getZExtValue()); } Constant *ConstantAggregateZero::getElementValue(unsigned Idx) const { - if (isa(getType())) + if (isa(getType()) || isa(getType())) return getSequentialElement(); return getStructElement(Idx); } @@ -956,7 +958,9 @@ //===----------------------------------------------------------------------===// UndefValue *UndefValue::getSequentialElement() const { - return UndefValue::get(getType()->getSequentialElementType()); + if (ArrayType *ATy = dyn_cast(getType())) + return UndefValue::get(ATy->getElementType()); + return UndefValue::get(cast(getType())->getElementType()); } UndefValue *UndefValue::getStructElement(unsigned Elt) const { @@ -964,21 +968,23 @@ } UndefValue *UndefValue::getElementValue(Constant *C) const { - if (isa(getType())) + if (isa(getType()) || isa(getType())) return getSequentialElement(); return getStructElement(cast(C)->getZExtValue()); } UndefValue *UndefValue::getElementValue(unsigned Idx) const { - if (isa(getType())) + if (isa(getType()) || isa(getType())) return getSequentialElement(); return getStructElement(Idx); } unsigned UndefValue::getNumElements() const { Type *Ty = getType(); - if (auto *ST = dyn_cast(Ty)) - return ST->getNumElements(); + if (auto *AT = dyn_cast(Ty)) + return AT->getNumElements(); + if (auto *VT = dyn_cast(Ty)) + return VT->getNumElements(); return Ty->getStructNumElements(); } @@ -2527,7 +2533,9 @@ // ConstantData* implementations Type *ConstantDataSequential::getElementType() const { - return getType()->getElementType(); + if (ArrayType *ATy = dyn_cast(getType())) + return ATy->getElementType(); + return cast(getType())->getElementType(); } StringRef ConstantDataSequential::getRawDataValues() const { @@ -2580,7 +2588,12 @@ /// the correct element type. We take the bytes in as a StringRef because /// we *want* an underlying "char*" to avoid TBAA type punning violations. Constant *ConstantDataSequential::getImpl(StringRef Elements, Type *Ty) { - assert(isElementTypeCompatible(Ty->getSequentialElementType())); +#ifndef NDEBUG + if (ArrayType *ATy = dyn_cast(Ty)) + assert(isElementTypeCompatible(ATy->getElementType())); + else + assert(isElementTypeCompatible(cast(Ty)->getElementType())); +#endif // If the elements are all zero or there are no elements, return a CAZ, which // is more dense and canonical. if (isAllZeros(Elements)) diff --git a/llvm/lib/IR/Core.cpp b/llvm/lib/IR/Core.cpp --- a/llvm/lib/IR/Core.cpp +++ b/llvm/lib/IR/Core.cpp @@ -753,7 +753,9 @@ auto *Ty = unwrap(WrappedTy); if (auto *PTy = dyn_cast(Ty)) return wrap(PTy->getElementType()); - return wrap(cast(Ty)->getElementType()); + if (auto *ATy = dyn_cast(Ty)) + return wrap(ATy->getElementType()); + return wrap(cast(Ty)->getElementType()); } unsigned LLVMGetNumContainedTypes(LLVMTypeRef Tp) { diff --git a/llvm/lib/IR/Type.cpp b/llvm/lib/IR/Type.cpp --- a/llvm/lib/IR/Type.cpp +++ b/llvm/lib/IR/Type.cpp @@ -552,7 +552,11 @@ //===----------------------------------------------------------------------===// ArrayType::ArrayType(Type *ElType, uint64_t NumEl) - : SequentialType(ArrayTyID, ElType, NumEl) {} + : Type(ElType->getContext(), ArrayTyID), ContainedType(ElType), + NumElements(NumEl) { + ContainedTys = &ContainedType; + NumContainedTys = 1; +} ArrayType *ArrayType::get(Type *ElementType, uint64_t NumElements) { assert(isValidElementType(ElementType) && "Invalid type for array element!"); @@ -579,7 +583,11 @@ //===----------------------------------------------------------------------===// VectorType::VectorType(Type *ElType, ElementCount EC) - : SequentialType(VectorTyID, ElType, EC.Min), Scalable(EC.Scalable) {} + : Type(ElType->getContext(), VectorTyID), ContainedType(ElType), + NumElements(EC.Min), Scalable(EC.Scalable) { + ContainedTys = &ContainedType; + NumContainedTys = 1; +} VectorType *VectorType::get(Type *ElementType, ElementCount EC) { assert(EC.Min > 0 && "#Elements of a VectorType must be greater than 0"); diff --git a/llvm/lib/Linker/IRMover.cpp b/llvm/lib/Linker/IRMover.cpp --- a/llvm/lib/Linker/IRMover.cpp +++ b/llvm/lib/Linker/IRMover.cpp @@ -173,9 +173,11 @@ if (DSTy->isLiteral() != SSTy->isLiteral() || DSTy->isPacked() != SSTy->isPacked()) return false; - } else if (auto *DSeqTy = dyn_cast(DstTy)) { - if (DSeqTy->getNumElements() != - cast(SrcTy)->getNumElements()) + } else if (auto *DArrTy = dyn_cast(DstTy)) { + if (DArrTy->getNumElements() != cast(SrcTy)->getNumElements()) + return false; + } else if (auto *DVecTy = dyn_cast(DstTy)) { + if (DVecTy->getElementCount() != cast(SrcTy)->getElementCount()) return false; } diff --git a/llvm/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp b/llvm/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp --- a/llvm/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp @@ -364,8 +364,13 @@ return false; } - Type *AT = Alloca->getAllocatedType(); - SequentialType *AllocaTy = dyn_cast(AT); + Type *AllocaTy = Alloca->getAllocatedType(); + VectorType *VectorTy = dyn_cast(AllocaTy); + if (auto *ArrayTy = dyn_cast(AllocaTy)) { + if (VectorType::isValidElementType(ArrayTy->getElementType()) && + ArrayTy->getNumElements() > 0) + VectorTy = arrayTypeToVecType(ArrayTy); + } LLVM_DEBUG(dbgs() << "Alloca candidate for vectorization\n"); @@ -373,10 +378,8 @@ // are just being conservative for now. // FIXME: We also reject alloca's of the form [ 2 x [ 2 x i32 ]] or equivalent. Potentially these // could also be promoted but we don't currently handle this case - if (!AllocaTy || - AllocaTy->getNumElements() > 16 || - AllocaTy->getNumElements() < 2 || - !VectorType::isValidElementType(AllocaTy->getElementType())) { + if (!VectorTy || VectorTy->getNumElements() > 16 || + VectorTy->getNumElements() < 2) { LLVM_DEBUG(dbgs() << " Cannot convert type to vector\n"); return false; } @@ -412,10 +415,6 @@ } } - VectorType *VectorTy = dyn_cast(AllocaTy); - if (!VectorTy) - VectorTy = arrayTypeToVecType(cast(AllocaTy)); - LLVM_DEBUG(dbgs() << " Converting alloca to vector " << *AllocaTy << " -> " << *VectorTy << '\n'); @@ -424,7 +423,7 @@ IRBuilder<> Builder(Inst); switch (Inst->getOpcode()) { case Instruction::Load: { - if (Inst->getType() == AT) + if (Inst->getType() == AllocaTy) break; Type *VecPtrTy = VectorTy->getPointerTo(AMDGPUAS::PRIVATE_ADDRESS); @@ -440,7 +439,7 @@ } case Instruction::Store: { StoreInst *SI = cast(Inst); - if (SI->getValueOperand()->getType() == AT) + if (SI->getValueOperand()->getType() == AllocaTy) break; Type *VecPtrTy = VectorTy->getPointerTo(AMDGPUAS::PRIVATE_ADDRESS); diff --git a/llvm/lib/Target/Hexagon/HexagonCommonGEP.cpp b/llvm/lib/Target/Hexagon/HexagonCommonGEP.cpp --- a/llvm/lib/Target/Hexagon/HexagonCommonGEP.cpp +++ b/llvm/lib/Target/Hexagon/HexagonCommonGEP.cpp @@ -204,17 +204,7 @@ Type *next_type(Type *Ty, Value *Idx) { if (auto *PTy = dyn_cast(Ty)) return PTy->getElementType(); - // Advance the type. - if (!Ty->isStructTy()) { - Type *NexTy = cast(Ty)->getElementType(); - return NexTy; - } - // Otherwise it is a struct type. - ConstantInt *CI = dyn_cast(Idx); - assert(CI && "Struct type with non-constant index"); - int64_t i = CI->getValue().getSExtValue(); - Type *NextTy = cast(Ty)->getElementType(i); - return NextTy; + return GetElementPtrInst::getTypeAtIndex(Ty, Idx); } raw_ostream &operator<< (raw_ostream &OS, const GepNode &GN) { diff --git a/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp b/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp --- a/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp +++ b/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp @@ -784,13 +784,18 @@ if (DL.getTypeSizeInBits(type) != DL.getTypeAllocSizeInBits(type)) return false; - if (!isa(type) && !isa(type)) - return true; + // FIXME: This isn't the right way to check for padding in vectors with + // non-byte-size elements. + if (VectorType *seqTy = dyn_cast(type)) + return isDenselyPacked(seqTy->getElementType(), DL); - // For homogenous sequential types, check for padding within members. - if (SequentialType *seqTy = dyn_cast(type)) + // For array types, check for padding within members. + if (ArrayType *seqTy = dyn_cast(type)) return isDenselyPacked(seqTy->getElementType(), DL); + if (!isa(type)) + return true; + // Check for padding within and between elements of a struct. StructType *StructTy = cast(type); const StructLayout *Layout = DL.getStructLayout(StructTy); diff --git a/llvm/lib/Transforms/IPO/GlobalOpt.cpp b/llvm/lib/Transforms/IPO/GlobalOpt.cpp --- a/llvm/lib/Transforms/IPO/GlobalOpt.cpp +++ b/llvm/lib/Transforms/IPO/GlobalOpt.cpp @@ -128,13 +128,15 @@ Type *Ty = Types.pop_back_val(); switch (Ty->getTypeID()) { default: break; - case Type::PointerTyID: return true; + case Type::PointerTyID: + return true; + case Type::VectorTyID: + if (cast(Ty)->getElementType()->isPointerTy()) + return true; + break; case Type::ArrayTyID: - case Type::VectorTyID: { - SequentialType *STy = cast(Ty); - Types.push_back(STy->getElementType()); + Types.push_back(cast(Ty)->getElementType()); break; - } case Type::StructTyID: { StructType *STy = cast(Ty); if (STy->isOpaque()) return true; @@ -142,7 +144,8 @@ E = STy->element_end(); I != E; ++I) { Type *InnerTy = *I; if (isa(InnerTy)) return true; - if (isa(InnerTy) || isa(InnerTy)) + if (isa(InnerTy) || isa(InnerTy) || + isa(InnerTy)) Types.push_back(InnerTy); } break; @@ -433,13 +436,27 @@ return true; } +static bool IsSRASequential(Type *T) { + return isa(T) || isa(T); +} +static uint64_t GetSRASequentialNumElements(Type *T) { + if (ArrayType *AT = cast(T)) + return AT->getNumElements(); + return cast(T)->getNumElements(); +} +static Type *GetSRASequentialElementType(Type *T) { + if (ArrayType *AT = cast(T)) + return AT->getElementType(); + return cast(T)->getElementType(); +} static bool CanDoGlobalSRA(GlobalVariable *GV) { Constant *Init = GV->getInitializer(); if (isa(Init->getType())) { // nothing to check - } else if (SequentialType *STy = dyn_cast(Init->getType())) { - if (STy->getNumElements() > 16 && GV->hasNUsesOrMore(16)) + } else if (IsSRASequential(Init->getType())) { + if (GetSRASequentialNumElements(Init->getType()) > 16 && + GV->hasNUsesOrMore(16)) return false; // It's not worth it. } else return false; @@ -509,8 +526,8 @@ Type *ElTy = nullptr; if (StructType *STy = dyn_cast(Ty)) ElTy = STy->getElementType(ElementIdx); - else if (SequentialType *STy = dyn_cast(Ty)) - ElTy = STy->getElementType(); + else + ElTy = GetSRASequentialElementType(Ty); assert(ElTy); Constant *In = Init->getAggregateElement(ElementIdx); @@ -541,7 +558,7 @@ uint64_t FragmentOffsetInBits = Layout.getElementOffsetInBits(ElementIdx); transferSRADebugInfo(GV, NGV, FragmentOffsetInBits, Size, STy->getNumElements()); - } else if (SequentialType *STy = dyn_cast(Ty)) { + } else { uint64_t EltSize = DL.getTypeAllocSize(ElTy); Align EltAlign(DL.getABITypeAlignment(ElTy)); uint64_t FragmentSizeInBits = DL.getTypeAllocSizeInBits(ElTy); @@ -553,7 +570,7 @@ if (NewAlign > EltAlign) NGV->setAlignment(NewAlign); transferSRADebugInfo(GV, NGV, FragmentSizeInBits * ElementIdx, - FragmentSizeInBits, STy->getNumElements()); + FragmentSizeInBits, GetSRASequentialNumElements(Ty)); } } @@ -2424,8 +2441,11 @@ } ConstantInt *CI = cast(Addr->getOperand(OpNo)); - SequentialType *InitTy = cast(Init->getType()); - uint64_t NumElts = InitTy->getNumElements(); + uint64_t NumElts; + if (ArrayType *ATy = dyn_cast(Init->getType())) + NumElts = ATy->getNumElements(); + else + NumElts = cast(Init->getType())->getNumElements(); // Break up the array into elements. for (uint64_t i = 0, e = NumElts; i != e; ++i) @@ -2436,7 +2456,7 @@ EvaluateStoreInto(Elts[CI->getZExtValue()], Val, Addr, OpNo+1); if (Init->getType()->isArrayTy()) - return ConstantArray::get(cast(InitTy), Elts); + return ConstantArray::get(cast(Init->getType()), Elts); return ConstantVector::get(Elts); } @@ -2558,8 +2578,10 @@ unsigned NumElts; if (auto *STy = dyn_cast(Ty)) NumElts = STy->getNumElements(); + else if (auto *ATy = dyn_cast(Ty)) + NumElts = ATy->getNumElements(); else - NumElts = cast(Ty)->getNumElements(); + NumElts = cast(Ty)->getNumElements(); for (unsigned i = 0, e = NumElts; i != e; ++i) Elts.push_back(Init->getAggregateElement(i)); } diff --git a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp --- a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp @@ -2133,7 +2133,7 @@ Type *Ty = ConstArg->getType(); if (Ty->isVectorTy()) { unsigned NumElements = Ty->getVectorNumElements(); - Type *EltTy = Ty->getSequentialElementType(); + Type *EltTy = Ty->getVectorElementType(); SmallVector Elements; for (unsigned Idx = 0; Idx < NumElements; ++Idx) { if (ConstantInt *Elt = diff --git a/llvm/lib/Transforms/Scalar/SROA.cpp b/llvm/lib/Transforms/Scalar/SROA.cpp --- a/llvm/lib/Transforms/Scalar/SROA.cpp +++ b/llvm/lib/Transforms/Scalar/SROA.cpp @@ -3505,17 +3505,31 @@ /// return a type if necessary. static Type *getTypePartition(const DataLayout &DL, Type *Ty, uint64_t Offset, uint64_t Size) { + if (Ty->isVectorTy() && Ty->getVectorIsScalable()) + return nullptr; + if (Offset == 0 && DL.getTypeAllocSize(Ty) == Size) return stripAggregateTypeWrapping(DL, Ty); if (Offset > DL.getTypeAllocSize(Ty) || (DL.getTypeAllocSize(Ty) - Offset) < Size) return nullptr; - if (SequentialType *SeqTy = dyn_cast(Ty)) { - Type *ElementTy = SeqTy->getElementType(); + if (isa(Ty) || isa(Ty)) { + Type *ElementTy; + uint64_t TyNumElements; + if (auto *AT = dyn_cast(Ty)) { + ElementTy = AT->getElementType(); + TyNumElements = AT->getNumElements(); + } else { + // FIXME: This isn't right for vectors with non-byte-sized or + // non-power-of-two sized elements. + auto *VT = cast(Ty); + ElementTy = VT->getElementType(); + TyNumElements = VT->getNumElements(); + } uint64_t ElementSize = DL.getTypeAllocSize(ElementTy); uint64_t NumSkippedElements = Offset / ElementSize; - if (NumSkippedElements >= SeqTy->getNumElements()) + if (NumSkippedElements >= TyNumElements) return nullptr; Offset -= NumSkippedElements * ElementSize; diff --git a/llvm/lib/Transforms/Utils/FunctionComparator.cpp b/llvm/lib/Transforms/Utils/FunctionComparator.cpp --- a/llvm/lib/Transforms/Utils/FunctionComparator.cpp +++ b/llvm/lib/Transforms/Utils/FunctionComparator.cpp @@ -476,14 +476,24 @@ return 0; } - case Type::ArrayTyID: - case Type::VectorTyID: { - auto *STyL = cast(TyL); - auto *STyR = cast(TyR); + case Type::ArrayTyID: { + auto *STyL = cast(TyL); + auto *STyR = cast(TyR); if (STyL->getNumElements() != STyR->getNumElements()) return cmpNumbers(STyL->getNumElements(), STyR->getNumElements()); return cmpTypes(STyL->getElementType(), STyR->getElementType()); } + case Type::VectorTyID: { + auto *STyL = cast(TyL); + auto *STyR = cast(TyR); + if (STyL->getElementCount().Scalable != STyR->getElementCount().Scalable) + return cmpNumbers(STyL->getElementCount().Scalable, + STyR->getElementCount().Scalable); + if (STyL->getElementCount().Min != STyR->getElementCount().Min) + return cmpNumbers(STyL->getElementCount().Min, + STyR->getElementCount().Min); + return cmpTypes(STyL->getElementType(), STyR->getElementType()); + } } } diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp --- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp +++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp @@ -3131,7 +3131,8 @@ unsigned N = 1; Type *EltTy = T; - while (isa(EltTy) || isa(EltTy)) { + while (isa(EltTy) || isa(EltTy) || + isa(EltTy)) { if (auto *ST = dyn_cast(EltTy)) { // Check that struct is homogeneous. for (const auto *Ty : ST->elements()) @@ -3139,10 +3140,13 @@ return 0; N *= ST->getNumElements(); EltTy = *ST->element_begin(); + } else if (auto *AT = dyn_cast(EltTy)) { + N *= AT->getNumElements(); + EltTy = AT->getElementType(); } else { - auto *SeqT = cast(EltTy); - N *= SeqT->getNumElements(); - EltTy = SeqT->getElementType(); + auto *VT = cast(EltTy); + N *= VT->getNumElements(); + EltTy = VT->getElementType(); } }