diff --git a/llvm/lib/Target/RISCV/RISCVGatherScatterLowering.cpp b/llvm/lib/Target/RISCV/RISCVGatherScatterLowering.cpp --- a/llvm/lib/Target/RISCV/RISCVGatherScatterLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVGatherScatterLowering.cpp @@ -63,8 +63,6 @@ } private: - bool isLegalTypeAndAlignment(Type *DataType, Value *AlignOp); - bool tryCreateStridedLoadStore(IntrinsicInst *II, Type *DataType, Value *Ptr, Value *AlignOp); @@ -87,24 +85,6 @@ return new RISCVGatherScatterLowering(); } -bool RISCVGatherScatterLowering::isLegalTypeAndAlignment(Type *DataType, - Value *AlignOp) { - Type *ScalarType = DataType->getScalarType(); - if (!TLI->isLegalElementTypeForRVV(ScalarType)) - return false; - - MaybeAlign MA = cast(AlignOp)->getMaybeAlignValue(); - if (MA && MA->value() < DL->getTypeStoreSize(ScalarType).getFixedValue()) - return false; - - // FIXME: Let the backend type legalize by splitting/widening? - EVT DataVT = TLI->getValueType(*DL, DataType); - if (!TLI->isTypeLegal(DataVT)) - return false; - - return true; -} - // TODO: Should we consider the mask when looking for a stride? static std::pair matchStridedConstant(Constant *StartC) { if (!isa(StartC->getType())) @@ -464,7 +444,12 @@ Value *Ptr, Value *AlignOp) { // Make sure the operation will be supported by the backend. - if (!isLegalTypeAndAlignment(DataType, AlignOp)) + MaybeAlign MA = cast(AlignOp)->getMaybeAlignValue(); + if (!MA || !TLI->isLegalStridedLoadStore(*DL, DataType, *MA)) + return false; + + // FIXME: Let the backend type legalize by splitting/widening? + if (!TLI->isTypeLegal(TLI->getValueType(*DL, DataType))) return false; // Pointer should be a GEP. diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.h b/llvm/lib/Target/RISCV/RISCVISelLowering.h --- a/llvm/lib/Target/RISCV/RISCVISelLowering.h +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.h @@ -704,6 +704,10 @@ bool isLegalInterleavedAccessType(FixedVectorType *, unsigned Factor, const DataLayout &) const; + /// Return true if a stride load store of the given result type and + /// alignment is legal. + bool isLegalStridedLoadStore(const DataLayout &DL, Type *DataType, Align Alignment) const; + unsigned getMaxSupportedInterleaveFactor() const override { return 8; } bool lowerInterleavedLoad(LoadInst *LI, diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -11426,6 +11426,11 @@ if (!TLI.isTypeLegal(WideVecVT)) return SDValue(); + // Check that the operation is legal + Type *WideVecTy = EVT(WideVecVT).getTypeForEVT(*DAG.getContext()); + if (!TLI.isLegalStridedLoadStore(DAG.getDataLayout(), WideVecTy, Align)) + return SDValue(); + MVT ContainerVT = TLI.getContainerForFixedLengthVector(WideVecVT); SDValue VL = getDefaultVLOps(WideVecVT, ContainerVT, DL, DAG, Subtarget).second; @@ -11453,12 +11458,6 @@ BaseLd->getPointerInfo(), BaseLd->getMemOperand()->getFlags(), MemSize, Align); - // Can't do the combine if the common alignment isn't naturally aligned with - // the new element type - if (!TLI.allowsMemoryAccessForAlignment(*DAG.getContext(), - DAG.getDataLayout(), WideVecVT, *MMO)) - return SDValue(); - SDValue StridedLoad = DAG.getMemIntrinsicNode(ISD::INTRINSIC_W_CHAIN, DL, VTs, Ops, WideVecVT, MMO); for (SDValue Ld : N->ops()) @@ -15798,6 +15797,26 @@ return Factor * LMUL <= 8; } +bool RISCVTargetLowering::isLegalStridedLoadStore(const DataLayout &DL, + Type *DataType, + Align Alignment) const { + if (!Subtarget.hasVInstructions()) + return false; + + // Only support fixed vectors if we know the minimum vector size. + if (isa(DataType) && !Subtarget.useRVVForFixedLengthVectors()) + return false; + + Type *ScalarType = DataType->getScalarType(); + if (!isLegalElementTypeForRVV(ScalarType)) + return false; + + if (Alignment < DL.getTypeStoreSize(ScalarType).getFixedValue()) + return false; + + return true; +} + /// Lower an interleaved load into a vlsegN intrinsic. /// /// E.g. Lower an interleaved load (Factor = 2):