[llvm] [Exegesis][RISCV] Add initial RVV support (PR #128767)
Craig Topper via llvm-commits
llvm-commits at lists.llvm.org
Thu Feb 27 09:50:57 PST 2025
================
@@ -24,10 +32,574 @@
namespace llvm {
namespace exegesis {
+static cl::opt<bool>
+ OnlyUsesVLMAXForVL("riscv-vlmax-for-vl",
+ cl::desc("Only enumerate VLMAX for VL operand"),
+ cl::init(false), cl::Hidden);
+
+static cl::opt<bool>
+ EnumerateRoundingModes("riscv-enumerate-rounding-modes",
+ cl::desc("Enumerate different FRM and VXRM"),
+ cl::init(true), cl::Hidden);
+
+static cl::opt<std::string>
+ FilterConfig("riscv-filter-config",
+ cl::desc("Show only the configs matching this regex"),
+ cl::init(""), cl::Hidden);
+
#include "RISCVGenExegesis.inc"
namespace {
+template <class BaseT> class RISCVSnippetGenerator : public BaseT {
+ static void printRoundingMode(raw_ostream &OS, unsigned Val, bool UsesVXRM) {
+ if (UsesVXRM) {
+ assert(RISCVVXRndMode::isValidRoundingMode(Val));
+ OS << RISCVVXRndMode::roundingModeToString(
+ static_cast<RISCVVXRndMode::RoundingMode>(Val));
+ } else {
+ assert(RISCVFPRndMode::isValidRoundingMode(Val));
+ OS << RISCVFPRndMode::roundingModeToString(
+ static_cast<RISCVFPRndMode::RoundingMode>(Val));
+ }
+ }
+
+ static constexpr unsigned MinSEW = 8;
+ // ELEN is basically SEW_max.
+ unsigned ELEN = 64;
+
+ // We can't know the real min/max VLEN w/o a Function, so we're
+ // using the VLen from Zvl.
+ unsigned ZvlVLen = 32;
+
+ /// Mask for registers that are NOT standalone registers like X0 and V0
+ BitVector AggregateRegisters;
+
+ // Returns true when opcode is available in any of the FBs.
+ static bool
+ isOpcodeAvailableIn(unsigned Opcode,
+ ArrayRef<RISCV_MC::SubtargetFeatureBits> FBs) {
+ FeatureBitset RequiredFeatures = RISCV_MC::computeRequiredFeatures(Opcode);
+ for (uint8_t FB : FBs) {
+ if (RequiredFeatures[FB])
+ return true;
+ }
+ return false;
+ }
+
+ static bool isRVVFloatingPointOp(unsigned Opcode) {
+ return isOpcodeAvailableIn(Opcode,
+ {RISCV_MC::Feature_HasVInstructionsAnyFBit});
+ }
+
+ // Get the element group width of each vector cryptor extension.
+ static unsigned getZvkEGWSize(unsigned Opcode, unsigned SEW) {
+ using namespace RISCV_MC;
+ if (isOpcodeAvailableIn(Opcode, {Feature_HasStdExtZvkgBit,
+ Feature_HasStdExtZvknedBit,
+ Feature_HasStdExtZvksedBit}))
+ return 128U;
+ if (isOpcodeAvailableIn(Opcode, {Feature_HasStdExtZvkshBit}))
+ return 256U;
+ if (isOpcodeAvailableIn(Opcode, {Feature_HasStdExtZvknhaOrZvknhbBit}))
+ // In Zvknh[ab], when SEW=64 is used (i.e. Zvknhb), EGW is 256.
+ // Otherwise it's 128.
+ return SEW == 64 ? 256U : 128U;
+
+ llvm_unreachable("Unsupported opcode");
+ }
+
+ // A handy utility to multiply or divide an integer by LMUL.
+ template <typename T> static T multiplyLMul(T Val, RISCVVType::VLMUL VLMul) {
+ auto [LMul, IsFractional] = RISCVVType::decodeVLMUL(VLMul);
+ return IsFractional ? Val / LMul : Val * LMul;
+ }
+
+ /// Return the denominator of the fractional (i.e. the `x` in .vfx suffix) or
+ /// nullopt if BaseOpcode is not a vector sext/zext.
+ static std::optional<unsigned> isRVVSignZeroExtend(unsigned BaseOpcode) {
+ switch (BaseOpcode) {
+ case RISCV::VSEXT_VF2:
+ case RISCV::VZEXT_VF2:
+ return 2;
+ case RISCV::VSEXT_VF4:
+ case RISCV::VZEXT_VF4:
+ return 4;
+ case RISCV::VSEXT_VF8:
+ case RISCV::VZEXT_VF8:
+ return 8;
+ default:
+ return std::nullopt;
+ }
+ }
+
+ void annotateWithVType(const CodeTemplate &CT, const Instruction &Instr,
+ unsigned BaseOpcode,
+ const BitVector &ForbiddenRegisters,
+ std::vector<CodeTemplate> &Result) const;
+
+public:
+ RISCVSnippetGenerator(const LLVMState &State,
+ const SnippetGenerator::Options &Opts)
+ : BaseT(State, Opts),
+ AggregateRegisters(State.getRegInfo().getNumRegs(), /*initVal=*/true) {
+ // Initialize standalone registers mask.
+ const MCRegisterInfo &RegInfo = State.getRegInfo();
+ const unsigned StandaloneRegClasses[] = {
+ RISCV::GPRRegClassID, RISCV::FPR16RegClassID, RISCV::VRRegClassID};
+
+ for (unsigned RegClassID : StandaloneRegClasses)
+ for (unsigned Reg : RegInfo.getRegClass(RegClassID))
+ AggregateRegisters.reset(Reg);
+
+ // Initialize ELEN and VLEN.
+ // FIXME: We could have obtained these two constants from RISCVSubtarget
+ // but in order to get that from TargetMachine, we need a Function.
+ const MCSubtargetInfo &STI = State.getSubtargetInfo();
+ ELEN = STI.checkFeatures("+zve64x") ? 64 : 32;
+
+ std::string ZvlQuery;
+ for (unsigned I = 5U, Size = (1 << I); I < 17U; ++I, Size <<= 1) {
----------------
topperc wrote:
Why both with `I`?
```
for (unsigned Size = 32; I <= 65536; Size *= 2)
```
https://github.com/llvm/llvm-project/pull/128767
More information about the llvm-commits
mailing list