diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h @@ -384,6 +384,8 @@ void printVType(unsigned VType, raw_ostream &OS); +static constexpr unsigned RVVBitsPerBlock = 64; + } // namespace RISCVVType namespace RISCVVPseudosTable { 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 @@ -278,6 +278,13 @@ Value *NewVal, Value *Mask, AtomicOrdering Ord) const override; + /// Returns true if the target allows unaligned memory accesses of the + /// specified type. + bool allowsMisalignedMemoryAccesses( + EVT VT, unsigned AddrSpace = 0, unsigned Align = 1, + MachineMemOperand::Flags Flags = MachineMemOperand::MONone, + bool *Fast = nullptr) const override; + private: void analyzeInputArgs(MachineFunction &MF, CCState &CCInfo, const SmallVectorImpl &Ins, 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 @@ -4545,6 +4545,54 @@ return false; } +bool RISCVTargetLowering::allowsMisalignedMemoryAccesses( + EVT VT, unsigned AddrSpace, unsigned Align, MachineMemOperand::Flags Flags, + bool *Fast) const { + if (VT == RISCVVMVTs::vint8mf8_t || VT == RISCVVMVTs::vint8mf4_t || + VT == RISCVVMVTs::vint8mf2_t || VT == RISCVVMVTs::vint8m1_t || + VT == RISCVVMVTs::vint8m2_t || VT == RISCVVMVTs::vint8m4_t || + VT == RISCVVMVTs::vint8m8_t) { + if (Align == 1) { + if (Fast) + *Fast = true; + return true; + } + } else if (VT == RISCVVMVTs::vint16mf4_t || VT == RISCVVMVTs::vint16mf2_t || + VT == RISCVVMVTs::vint16m1_t || VT == RISCVVMVTs::vint16m2_t || + VT == RISCVVMVTs::vint16m4_t || VT == RISCVVMVTs::vint16m8_t || + VT == RISCVVMVTs::vfloat16mf4_t || + VT == RISCVVMVTs::vfloat16mf2_t || + VT == RISCVVMVTs::vfloat16m1_t || VT == RISCVVMVTs::vfloat16m2_t || + VT == RISCVVMVTs::vfloat16m4_t || VT == RISCVVMVTs::vfloat16m8_t) { + if (Align == 2) { + if (Fast) + *Fast = true; + return true; + } + } else if (VT == RISCVVMVTs::vint32mf2_t || VT == RISCVVMVTs::vint32m1_t || + VT == RISCVVMVTs::vint32m2_t || VT == RISCVVMVTs::vint32m4_t || + VT == RISCVVMVTs::vint32m8_t || VT == RISCVVMVTs::vfloat32mf2_t || + VT == RISCVVMVTs::vfloat32m1_t || VT == RISCVVMVTs::vfloat32m2_t || + VT == RISCVVMVTs::vfloat32m4_t || VT == RISCVVMVTs::vfloat32m8_t) { + if (Align == 4) { + if (Fast) + *Fast = true; + return true; + } + } else if (VT == RISCVVMVTs::vint64m1_t || VT == RISCVVMVTs::vint64m2_t || + VT == RISCVVMVTs::vint64m4_t || VT == RISCVVMVTs::vint64m8_t || + VT == RISCVVMVTs::vfloat64m1_t || VT == RISCVVMVTs::vfloat64m2_t || + VT == RISCVVMVTs::vfloat64m4_t || VT == RISCVVMVTs::vfloat64m8_t) { + if (Align == 8) { + if (Fast) + *Fast = true; + return true; + } + } + + return false; +} + #define GET_REGISTER_MATCHER #include "RISCVGenAsmMatcher.inc" diff --git a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.h b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.h --- a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.h +++ b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.h @@ -47,6 +47,19 @@ Instruction *Inst = nullptr); int getIntImmCostIntrin(Intrinsic::ID IID, unsigned Idx, const APInt &Imm, Type *Ty, TTI::TargetCostKind CostKind); + + bool supportsScalableVectors() const { return ST->hasStdExtV(); } + unsigned getRegisterBitWidth(bool Vector) const { + if (Vector) { + if (ST->hasStdExtV()) + return RISCVVType::RVVBitsPerBlock; + return 0; + } + if (ST->is64Bit()) + return 64; + return 32; + } + Optional getMaxVScale() const; }; } // end namespace llvm diff --git a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp --- a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp +++ b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp @@ -15,6 +15,11 @@ #define DEBUG_TYPE "riscvtti" +static cl::opt MaxVectorLen( + "riscv-vector-bits-max", + cl::desc("The assumed maximum vector bits."), + cl::init(0), cl::Hidden); + int RISCVTTIImpl::getIntImmCost(const APInt &Imm, Type *Ty, TTI::TargetCostKind CostKind) { assert(Ty->isIntegerTy() && @@ -94,3 +99,9 @@ // Prevent hoisting in unknown cases. return TTI::TCC_Free; } + +Optional RISCVTTIImpl::getMaxVScale() const { + if (ST->hasStdExtV()) + return MaxVectorLen / RISCVVType::RVVBitsPerBlock; + return BaseT::getMaxVScale(); +} diff --git a/llvm/test/Transforms/LoopVectorize/RISCV/scalable-vf-hint.ll b/llvm/test/Transforms/LoopVectorize/RISCV/scalable-vf-hint.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/LoopVectorize/RISCV/scalable-vf-hint.ll @@ -0,0 +1,44 @@ +; RUN: opt -mtriple=riscv64 -mattr=+m,+experimental-v -loop-vectorize \ +; RUN: -riscv-vector-bits-max=512 -S < %s 2>&1 \ +; RUN: | llc -mattr=+m,+experimental-v | FileCheck %s + +; void test(int *a, int *b, int N) { +; #pragma clang loop vectorize(enable) vectorize_width(2, scalable) +; for (int i=0; i