[llvm] Reland (#120419):[Exegesis][RISCV] Add RISCV support for llvm-exegesis (PR #120467)

Aiden Grossman via llvm-commits llvm-commits at lists.llvm.org
Wed Dec 18 11:37:42 PST 2024


================
@@ -0,0 +1,275 @@
+//===-- Target.cpp ----------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "../Target.h"
+
+#include "MCTargetDesc/RISCVBaseInfo.h"
+#include "MCTargetDesc/RISCVMCTargetDesc.h"
+#include "MCTargetDesc/RISCVMatInt.h"
+#include "RISCVInstrInfo.h"
+
+// include computeAvailableFeatures and computeRequiredFeatures.
+#define GET_AVAILABLE_OPCODE_CHECKER
+#include "RISCVGenInstrInfo.inc"
+
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+
+#include <vector>
+
+namespace llvm {
+namespace exegesis {
+
+namespace {
+
+// Stores constant value to a general-purpose (integer) register.
+static std::vector<MCInst> loadIntReg(const MCSubtargetInfo &STI, unsigned Reg,
+                                      const APInt &Value) {
+  SmallVector<MCInst, 8> MCInstSeq;
+  std::vector<MCInst> MatIntInstrs;
+  MCRegister DestReg = Reg;
+
+  RISCVMatInt::generateMCInstSeq(Value.getSExtValue(), STI, DestReg, MCInstSeq);
+  MatIntInstrs.resize(MCInstSeq.size());
+  std::copy(MCInstSeq.begin(), MCInstSeq.end(), MatIntInstrs.begin());
+
+  return MatIntInstrs;
+}
+
+const unsigned ScratchIntReg = RISCV::X30; // t5
+
+// Stores constant bits to a floating-point register.
+static std::vector<MCInst> loadFPRegBits(const MCSubtargetInfo &STI,
+                                         unsigned Reg, const APInt &Bits,
+                                         unsigned FmvOpcode) {
+  std::vector<MCInst> Instrs = loadIntReg(STI, ScratchIntReg, Bits);
+  Instrs.push_back(MCInstBuilder(FmvOpcode).addReg(Reg).addReg(ScratchIntReg));
+  return Instrs;
+}
+
+// main idea is:
+// we support APInt only if (represented as double) it has zero fractional
+// part: 1.0, 2.0, 3.0, etc... then we can do the trick: write int to tmp reg t5
+// and then do FCVT this is only reliable thing in 32-bit mode, otherwise we
+// need to use __floatsidf
+static std::vector<MCInst> loadFP64RegBits32(const MCSubtargetInfo &STI,
+                                             unsigned Reg, const APInt &Bits) {
+  double D = Bits.bitsToDouble();
+  double IPart;
+  double FPart = std::modf(D, &IPart);
+
+  if (std::abs(FPart) > std::numeric_limits<double>::epsilon()) {
+    errs() << "loadFP64RegBits32 is not implemented for doubles like " << D
+           << ", please remove fractional part\n";
+    return {};
+  }
+
+  std::vector<MCInst> Instrs = loadIntReg(STI, ScratchIntReg, Bits);
+  Instrs.push_back(
+      MCInstBuilder(RISCV::FCVT_D_W).addReg(Reg).addReg(ScratchIntReg));
+  return Instrs;
+}
+
+static MCInst nop() {
+  // ADDI X0, X0, 0
+  return MCInstBuilder(RISCV::ADDI)
+      .addReg(RISCV::X0)
+      .addReg(RISCV::X0)
+      .addImm(0);
+}
+
+static bool isVectorRegList(unsigned Reg) {
+  return RISCV::VRM2RegClass.contains(Reg) ||
+         RISCV::VRM4RegClass.contains(Reg) ||
+         RISCV::VRM8RegClass.contains(Reg) ||
+         RISCV::VRN2M1RegClass.contains(Reg) ||
+         RISCV::VRN2M2RegClass.contains(Reg) ||
+         RISCV::VRN2M4RegClass.contains(Reg) ||
+         RISCV::VRN3M1RegClass.contains(Reg) ||
+         RISCV::VRN3M2RegClass.contains(Reg) ||
+         RISCV::VRN4M1RegClass.contains(Reg) ||
+         RISCV::VRN4M2RegClass.contains(Reg) ||
+         RISCV::VRN5M1RegClass.contains(Reg) ||
+         RISCV::VRN6M1RegClass.contains(Reg) ||
+         RISCV::VRN7M1RegClass.contains(Reg) ||
+         RISCV::VRN8M1RegClass.contains(Reg);
+}
+
+class ExegesisRISCVTarget : public ExegesisTarget {
+public:
+  ExegesisRISCVTarget();
+
+  bool matchesArch(Triple::ArchType Arch) const override;
+
+  std::vector<MCInst> setRegTo(const MCSubtargetInfo &STI, unsigned Reg,
+                               const APInt &Value) const override;
+
+  unsigned getDefaultLoopCounterRegister(const Triple &) const override;
+
+  void decrementLoopCounterAndJump(MachineBasicBlock &MBB,
+                                   MachineBasicBlock &TargetMBB,
+                                   const MCInstrInfo &MII,
+                                   unsigned LoopRegister) const override;
+
+  unsigned getScratchMemoryRegister(const Triple &TT) const override;
+
+  void fillMemoryOperands(InstructionTemplate &IT, unsigned Reg,
+                          unsigned Offset) const override;
+
+  ArrayRef<unsigned> getUnavailableRegisters() const override;
+
+  Error randomizeTargetMCOperand(const Instruction &Instr, const Variable &Var,
+                                 MCOperand &AssignedValue,
+                                 const BitVector &ForbiddenRegs) const override;
+
+  std::vector<InstructionTemplate>
+  generateInstructionVariants(const Instruction &Instr,
+                              unsigned MaxConfigsPerOpcode) const override;
+};
+
+ExegesisRISCVTarget::ExegesisRISCVTarget()
+    : ExegesisTarget(ArrayRef<CpuAndPfmCounters>{},
+                     RISCV_MC::isOpcodeAvailable) {}
+
+#define GET_REGISTER_MATCHER
+#include "RISCVGenAsmMatcher.inc"
----------------
boomanaiden154 wrote:

This should be removed before relanding. It doesn't make sense to land with a forward fix already planned.

https://github.com/llvm/llvm-project/pull/120467


More information about the llvm-commits mailing list