diff --git a/clang/lib/Basic/Targets/RISCV.h b/clang/lib/Basic/Targets/RISCV.h --- a/clang/lib/Basic/Targets/RISCV.h +++ b/clang/lib/Basic/Targets/RISCV.h @@ -111,7 +111,11 @@ DiagnosticsEngine &Diags) override; bool hasExtIntType() const override { return true; } + + Optional> + getVScaleRange(const LangOptions &LangOpts) const override; }; + class LLVM_LIBRARY_VISIBILITY RISCV32TargetInfo : public RISCVTargetInfo { public: RISCV32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) diff --git a/clang/lib/Basic/Targets/RISCV.cpp b/clang/lib/Basic/Targets/RISCV.cpp --- a/clang/lib/Basic/Targets/RISCV.cpp +++ b/clang/lib/Basic/Targets/RISCV.cpp @@ -335,6 +335,20 @@ return true; } +Optional> +RISCVTargetInfo::getVScaleRange(const LangOptions &LangOpts) const { + if (!HasV) + return None; + // VLEN is defined in v0.10 to be at least 128 bits and at most 65536 bits, + // and vscale is VLEN/64. + // FIXME: v1.0 removes the minimum value. + // FIXME: The backend can be told about the more specific minimum/maximum + // VLEN but the frontend can't access this information. + unsigned VLENMin = 128; + unsigned VLENMax = 65536; + return std::make_pair(VLENMin / 64, VLENMax / 64); +} + bool RISCV32TargetInfo::isValidCPUName(StringRef Name) const { return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name), /*Is64Bit=*/false); diff --git a/clang/test/CodeGen/riscv-vscale-range.c b/clang/test/CodeGen/riscv-vscale-range.c new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/riscv-vscale-range.c @@ -0,0 +1,5 @@ +// RUN: %clang_cc1 -triple riscv64 -target-feature +experimental-v -S -emit-llvm -o - %s | FileCheck %s + +// CHECK-LABEL: @func() #0 +// CHECK: attributes #0 = { {{.*}} vscale_range(2,1024) {{.*}} } +void func() {} diff --git a/llvm/lib/Target/RISCV/RISCVSubtarget.h b/llvm/lib/Target/RISCV/RISCVSubtarget.h --- a/llvm/lib/Target/RISCV/RISCVSubtarget.h +++ b/llvm/lib/Target/RISCV/RISCVSubtarget.h @@ -62,6 +62,8 @@ bool EnableSaveRestore = false; unsigned XLen = 32; MVT XLenVT = MVT::i32; + unsigned RVVVectorBitsMin; + unsigned RVVVectorBitsMax; uint8_t MaxInterleaveFactor = 2; RISCVABI::ABI TargetABI = RISCVABI::ABI_Unknown; BitVector UserReservedRegister; @@ -82,7 +84,8 @@ public: // Initializes the data members to match that of the specified triple. RISCVSubtarget(const Triple &TT, StringRef CPU, StringRef TuneCPU, - StringRef FS, StringRef ABIName, const TargetMachine &TM); + StringRef FS, StringRef ABIName, unsigned RVVVectorBitsMin, + unsigned RVVVectorLMULMax, const TargetMachine &TM); // Parses features string setting specified subtarget options. The // definition of this function is auto-generated by tblgen. @@ -155,8 +158,16 @@ // Return the known range for the bit length of RVV data registers. A value // of 0 means nothing is known about that particular limit beyond what's // implied by the architecture. - unsigned getMaxRVVVectorSizeInBits() const; - unsigned getMinRVVVectorSizeInBits() const; + unsigned getMaxRVVVectorSizeInBits() const { + assert(hasStdExtV() && + "Tried to get vector length without V extension support!"); + return RVVVectorBitsMax; + } + unsigned getMinRVVVectorSizeInBits() const { + assert(hasStdExtV() && + "Tried to get vector length without V extension support!"); + return RVVVectorBitsMin; + } unsigned getMaxLMULForFixedLengthVectors() const; bool useRVVForFixedLengthVectors() const; }; diff --git a/llvm/lib/Target/RISCV/RISCVSubtarget.cpp b/llvm/lib/Target/RISCV/RISCVSubtarget.cpp --- a/llvm/lib/Target/RISCV/RISCVSubtarget.cpp +++ b/llvm/lib/Target/RISCV/RISCVSubtarget.cpp @@ -27,18 +27,6 @@ #define GET_SUBTARGETINFO_CTOR #include "RISCVGenSubtargetInfo.inc" -static cl::opt RVVVectorBitsMax( - "riscv-v-vector-bits-max", - cl::desc("Assume V extension vector registers are at most this big, " - "with zero meaning no maximum size is assumed."), - cl::init(0), cl::Hidden); - -static cl::opt RVVVectorBitsMin( - "riscv-v-vector-bits-min", - cl::desc("Assume V extension vector registers are at least this big, " - "with zero meaning no minimum size is assumed."), - cl::init(0), cl::Hidden); - static cl::opt RVVVectorLMULMax( "riscv-v-fixed-length-vector-lmul-max", cl::desc("The maximum LMUL value to use for fixed length vectors. " @@ -75,10 +63,14 @@ RISCVSubtarget::RISCVSubtarget(const Triple &TT, StringRef CPU, StringRef TuneCPU, StringRef FS, - StringRef ABIName, const TargetMachine &TM) + StringRef ABIName, unsigned RVVVectorBitsMin, + unsigned RVVVectorBitsMax, + const TargetMachine &TM) : RISCVGenSubtargetInfo(TT, CPU, TuneCPU, FS), + RVVVectorBitsMin(RVVVectorBitsMin), RVVVectorBitsMax(RVVVectorBitsMax), UserReservedRegister(RISCV::NUM_TARGET_REGS), - FrameLowering(initializeSubtargetDependencies(TT, CPU, TuneCPU, FS, ABIName)), + FrameLowering( + initializeSubtargetDependencies(TT, CPU, TuneCPU, FS, ABIName)), InstrInfo(*this), RegInfo(getHwMode()), TLInfo(TM, *this) { CallLoweringInfo.reset(new RISCVCallLowering(*getTargetLowering())); Legalizer.reset(new RISCVLegalizerInfo(*this)); @@ -105,38 +97,6 @@ return RegBankInfo.get(); } -unsigned RISCVSubtarget::getMaxRVVVectorSizeInBits() const { - assert(hasStdExtV() && "Tried to get vector length without V support!"); - if (RVVVectorBitsMax == 0) - return 0; - assert(RVVVectorBitsMax >= 128 && RVVVectorBitsMax <= 65536 && - isPowerOf2_32(RVVVectorBitsMax) && - "V extension requires vector length to be in the range of 128 to " - "65536 and a power of 2!"); - assert(RVVVectorBitsMax >= RVVVectorBitsMin && - "Minimum V extension vector length should not be larger than its " - "maximum!"); - unsigned Max = std::max(RVVVectorBitsMin, RVVVectorBitsMax); - return PowerOf2Floor((Max < 128 || Max > 65536) ? 0 : Max); -} - -unsigned RISCVSubtarget::getMinRVVVectorSizeInBits() const { - assert(hasStdExtV() && - "Tried to get vector length without V extension support!"); - assert((RVVVectorBitsMin == 0 || - (RVVVectorBitsMin >= 128 && RVVVectorBitsMax <= 65536 && - isPowerOf2_32(RVVVectorBitsMin))) && - "V extension requires vector length to be in the range of 128 to " - "65536 and a power of 2!"); - assert((RVVVectorBitsMax >= RVVVectorBitsMin || RVVVectorBitsMax == 0) && - "Minimum V extension vector length should not be larger than its " - "maximum!"); - unsigned Min = RVVVectorBitsMin; - if (RVVVectorBitsMax != 0) - Min = std::min(RVVVectorBitsMin, RVVVectorBitsMax); - return PowerOf2Floor((Min < 128 || Min > 65536) ? 0 : Min); -} - unsigned RISCVSubtarget::getMaxLMULForFixedLengthVectors() const { assert(hasStdExtV() && "Tried to get maximum LMUL without V extension support!"); diff --git a/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp b/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp --- a/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp +++ b/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp @@ -32,6 +32,18 @@ #include "llvm/Target/TargetOptions.h" using namespace llvm; +static cl::opt RVVVectorBitsMaxOpt( + "riscv-v-vector-bits-max", + cl::desc("Assume V extension vector registers are at most this big, " + "with zero meaning no maximum size is assumed."), + cl::init(0), cl::Hidden); + +static cl::opt RVVVectorBitsMinOpt( + "riscv-v-vector-bits-min", + cl::desc("Assume V extension vector registers are at least this big, " + "with zero meaning no minimum size is assumed."), + cl::init(0), cl::Hidden); + extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVTarget() { RegisterTargetMachine X(getTheRISCV32Target()); RegisterTargetMachine Y(getTheRISCV64Target()); @@ -78,13 +90,50 @@ Attribute TuneAttr = F.getFnAttribute("tune-cpu"); Attribute FSAttr = F.getFnAttribute("target-features"); + unsigned RVVBitsMin = 0; + unsigned RVVBitsMax = 0; + Attribute VScaleRangeAttr = F.getFnAttribute(Attribute::VScaleRange); + if (VScaleRangeAttr.isValid()) { + std::tie(RVVBitsMin, RVVBitsMax) = VScaleRangeAttr.getVScaleRangeArgs(); + RVVBitsMin *= RISCV::RVVBitsPerBlock; + RVVBitsMax *= RISCV::RVVBitsPerBlock; + } else { + RVVBitsMin = RVVVectorBitsMinOpt; + RVVBitsMax = RVVVectorBitsMaxOpt; + } + + assert(RVVBitsMin % 128 == 0 && + "RVV requires vector length in multiples of 128!"); + assert(RVVBitsMax % 128 == 0 && + "RVV requires vector length in multiples of 128!"); + assert(RVVBitsMax <= 65536 && + "RVV vector size must be no larger than 65536!"); + assert((RVVBitsMax >= RVVBitsMin || RVVBitsMax == 0) && + "Minimum RVV vector size should not be larger than its maximum!"); + + // Sanitize user input in case of no asserts. + if (RVVBitsMax != 0) + RVVBitsMin = std::min(RVVBitsMin, RVVBitsMax); + RVVBitsMin = + PowerOf2Floor((RVVBitsMin < 128 || RVVBitsMin > 65536) ? 0 : RVVBitsMin); + + RVVBitsMax = std::max(RVVBitsMin, RVVBitsMax); + RVVBitsMax = + PowerOf2Floor((RVVBitsMax < 128 || RVVBitsMax > 65536) ? 0 : RVVBitsMax); + std::string CPU = CPUAttr.isValid() ? CPUAttr.getValueAsString().str() : TargetCPU; std::string TuneCPU = TuneAttr.isValid() ? TuneAttr.getValueAsString().str() : CPU; std::string FS = FSAttr.isValid() ? FSAttr.getValueAsString().str() : TargetFS; + std::string Key = CPU + TuneCPU + FS; + Key += "RVVMin"; + Key += std::to_string(RVVBitsMin); + Key += "RVVMax"; + Key += std::to_string(RVVBitsMax); + auto &I = SubtargetMap[Key]; if (!I) { // This needs to be done before we create a new subtarget since any @@ -101,7 +150,8 @@ } ABIName = ModuleTargetABI->getString(); } - I = std::make_unique(TargetTriple, CPU, TuneCPU, FS, ABIName, *this); + I = std::make_unique( + TargetTriple, CPU, TuneCPU, FS, ABIName, RVVBitsMin, RVVBitsMax, *this); } return I.get(); }