Skip to content

Commit

Permalink
[Exegesis][RISCV] Add RISCV support for llvm-exegesis
Browse files Browse the repository at this point in the history
Llvm-exegesis RISCV port is a result of team effort. Below everyone involved listed.
Co-authored-by: Konstantin Vladimirov <[email protected]>
Co-authored-by: Dmitrii Petrov <[email protected]>
Co-authored-by: Dmitry Bushev <[email protected]>
Co-authored-by: Mark Goncharov <[email protected]>
Co-authored-by: Anastasiya Chernikova <[email protected]>
  • Loading branch information
AnastasiyaChernikova committed Apr 23, 2024
1 parent 971237d commit e058716
Show file tree
Hide file tree
Showing 31 changed files with 983 additions and 48 deletions.
3 changes: 3 additions & 0 deletions llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,9 @@ enum OperandType : unsigned {
OPERAND_RVKRNUM_2_14,
OPERAND_SPIMM,
OPERAND_LAST_RISCV_IMM = OPERAND_SPIMM,
// Operand is a 3-bit rounding mode, '111' indicates FRM register.
// Represents 'frm' argument passing to floating-point operations.
OPERAND_FRMARG,
// Operand is either a register or uimm5, this is used by V extension pseudo
// instructions to represent a value that be passed as AVL to either vsetvli
// or vsetivli.
Expand Down
4 changes: 2 additions & 2 deletions llvm/lib/Target/RISCV/RISCVInstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -509,7 +509,7 @@ class BranchCC_rri<bits<3> funct3, string opcodestr>
let isTerminator = 1;
}

let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
let hasSideEffects = 0, mayLoad = 1, mayStore = 0, UseNamedOperandTable = 1 in {
class Load_ri<bits<3> funct3, string opcodestr>
: RVInstI<funct3, OPC_LOAD, (outs GPR:$rd), (ins GPRMem:$rs1, simm12:$imm12),
opcodestr, "$rd, ${imm12}(${rs1})">;
Expand All @@ -524,7 +524,7 @@ class HLoad_r<bits<7> funct7, bits<5> funct5, string opcodestr>
// Operands for stores are in the order srcreg, base, offset rather than
// reflecting the order these fields are specified in the instruction
// encoding.
let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in {
let hasSideEffects = 0, mayLoad = 0, mayStore = 1, UseNamedOperandTable = 1 in {
class Store_rri<bits<3> funct3, string opcodestr>
: RVInstS<funct3, OPC_STORE, (outs),
(ins GPR:$rs2, GPRMem:$rs1, simm12:$imm12),
Expand Down
4 changes: 4 additions & 0 deletions llvm/lib/Target/RISCV/RISCVInstrInfoF.td
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,8 @@ def frmarg : Operand<XLenVT> {
let ParserMatchClass = FRMArg;
let PrintMethod = "printFRMArg";
let DecoderMethod = "decodeFRMArg";
let OperandType = "OPERAND_FRMARG";
let OperandNamespace = "RISCVOp";
}

// Variants of the rounding mode operand that default to 'rne'. This is used
Expand All @@ -150,6 +152,8 @@ def frmarglegacy : Operand<XLenVT> {
let ParserMatchClass = FRMArgLegacy;
let PrintMethod = "printFRMArgLegacy";
let DecoderMethod = "decodeFRMArg";
let OperandType = "OPERAND_FRMARG";
let OperandNamespace = "RISCVOp";
}

//===----------------------------------------------------------------------===//
Expand Down
59 changes: 59 additions & 0 deletions llvm/test/tools/llvm-exegesis/RISCV/latency-by-extension-A.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --benchmark-phase=assemble-measured-code -opcode-name=AMOAND_D -mattr="+a" |& FileCheck --check-prefix=TEST1 %s

TEST1: ---
TEST1-NEXT: mode: latency
TEST1-NEXT: key:
TEST1-NEXT: instructions:
TEST1-NEXT: - 'AMOAND_D [[RE01:X[0-9]+]] X10 [[RE01:X[0-9]+]]'
TEST1-NEXT: config: ''
TEST1-NEXT: register_initial_values:
TEST1-NEXT: - '[[RE01:X[0-9]+]]=0x0'
TEST1-LAST: ...

# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --benchmark-phase=assemble-measured-code -opcode-name=AMOADD_W -mattr="+a" |& FileCheck --check-prefix=TEST2 %s

TEST2: ---
TEST2-NEXT: mode: latency
TEST2-NEXT: key:
TEST2-NEXT: instructions:
TEST2-NEXT: - 'AMOADD_W [[RE02:X[0-9]+]] X10 [[RE02:X[0-9]+]]'
TEST2-NEXT: config: ''
TEST2-NEXT: register_initial_values:
TEST2-NEXT: - '[[RE02:X[0-9]+]]=0x0'
TEST2-LAST: ...

# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --benchmark-phase=assemble-measured-code -opcode-name=AMOMAXU_D -mattr="+a" |& FileCheck --check-prefix=TEST3 %s

TEST3: ---
TEST3-NEXT: mode: latency
TEST3-NEXT: key:
TEST3-NEXT: instructions:
TEST3-NEXT: - 'AMOMAXU_D [[RE03:X[0-9]+]] X10 [[RE03:X[0-9]+]]'
TEST3-NEXT: config: ''
TEST3-NEXT: register_initial_values:
TEST3-NEXT: - '[[RE03:X[0-9]+]]=0x0'
TEST3-LAST: ...

# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --benchmark-phase=assemble-measured-code -opcode-name=AMOMIN_W -mattr="+a" |& FileCheck --check-prefix=TEST4 %s

TEST4: ---
TEST4-NEXT: mode: latency
TEST4-NEXT: key:
TEST4-NEXT: instructions:
TEST4-NEXT: - 'AMOMIN_W [[RE04:X[0-9]+]] X10 [[RE04:X[0-9]+]]'
TEST4-NEXT: config: ''
TEST4-NEXT: register_initial_values:
TEST4-NEXT: - '[[RE04:X[0-9]+]]=0x0'
TEST4-LAST: ...

# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --benchmark-phase=assemble-measured-code -opcode-name=AMOXOR_D -mattr="+a" |& FileCheck --check-prefix=TEST5 %s

TEST5: ---
TEST5-NEXT: mode: latency
TEST5-NEXT: key:
TEST5-NEXT: instructions:
TEST5-NEXT: - 'AMOXOR_D [[RE05:X[0-9]+]] X10 [[RE05:X[0-9]+]]'
TEST5-NEXT: config: ''
TEST5-NEXT: register_initial_values:
TEST5-NEXT: - '[[RE05:X[0-9]+]]=0x0'
TEST5-LAST: ...
65 changes: 65 additions & 0 deletions llvm/test/tools/llvm-exegesis/RISCV/latency-by-extension-C.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --benchmark-phase=assemble-measured-code -opcode-name=C_ADDI -mattr=+c |& FileCheck --check-prefix=TEST1 %s

TEST1: ---
TEST1-NEXT: mode: latency
TEST1-NEXT: key:
TEST1-NEXT: instructions:
TEST1-NEXT: - 'C_ADDI [[REG01:X[0-9]+]] [[RE02:X[0-9]+]] [[IMM0:i_0x[0-9]+]]'

# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --benchmark-phase=assemble-measured-code -opcode-name=C_ADDIW -mattr=+c |& FileCheck --check-prefix=TEST2 %s

TEST2: ---
TEST2-NEXT: mode: latency
TEST2-NEXT: key:
TEST2-NEXT: instructions:
TEST2-NEXT: - 'C_ADDIW [[REG11:X[0-9]+]] [[RE12:X[0-9]+]] [[IMM1:i_0x[0-9]+]]'

# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --benchmark-phase=assemble-measured-code -opcode-name=C_ANDI -mattr=+c |& FileCheck --check-prefix=TEST3 %s

TEST3: ---
TEST3-NEXT: mode: latency
TEST3-NEXT: key:
TEST3-NEXT: instructions:
TEST3-NEXT: - 'C_ANDI [[REG31:X[0-9]+]] [[REG32:X[0-9]+]] [[IMM3:i_0x[0-9]+]]'

# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --benchmark-phase=assemble-measured-code -opcode-name=C_SLLI -mattr=+c |& FileCheck --check-prefix=TEST4 %s

TEST4: ---
TEST4-NEXT: mode: latency
TEST4-NEXT: key:
TEST4-NEXT: instructions:
TEST4-NEXT: - 'C_SLLI [[REG81:X[0-9]+]] [[REG82:X[0-9]+]] [[IMM8:i_0x[0-9]+]]'

# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --benchmark-phase=assemble-measured-code -opcode-name=C_SRAI -mattr=+c |& FileCheck --check-prefix=TEST5 %s

TEST5: ---
TEST5-NEXT: mode: latency
TEST5-NEXT: key:
TEST5-NEXT: instructions:
TEST5-NEXT: - 'C_SRAI [[REG91:X[0-9]+]] [[REG92:X[0-9]+]] [[IMM9:i_0x[0-9]+]]'

# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --benchmark-phase=assemble-measured-code -opcode-name=C_SRLI -mattr=+c |& FileCheck --check-prefix=TEST6 %s

TEST6: ---
TEST6-NEXT: mode: latency
TEST6-NEXT: key:
TEST6-NEXT: instructions:
TEST6-NEXT: - 'C_SRLI [[REG101:X[0-9]+]] [[REG102:X[0-9]+]] [[IMM10:i_0x[0-9]+]]'
TEST6-LAST: ...


# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --benchmark-phase=assemble-measured-code -opcode-name=C_LD -mattr=+c |& FileCheck --check-prefix=TEST7 %s

TEST7: ---
TEST7-NEXT: mode: latency
TEST7-NEXT: key:
TEST7-NEXT: instructions:
TEST7-NEXT: - 'C_LD [[REG61:X[0-9]+]] [[REG62:X[0-9]+]] [[IMM6:i_0x[0-9]+]]'

# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --benchmark-phase=assemble-measured-code -opcode-name=C_LW -mattr=+c |& FileCheck --check-prefix=TEST8 %s

TEST8: ---
TEST8-NEXT: mode: latency
TEST8-NEXT: key:
TEST8-NEXT: instructions:
TEST8-NEXT: - 'C_LW [[REG71:X[0-9]+]] [[REG72:X[0-9]+]] [[IMM7:i_0x[0-9]+]]'
60 changes: 60 additions & 0 deletions llvm/test/tools/llvm-exegesis/RISCV/latency-by-load.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --benchmark-phase=assemble-measured-code -opcode-name=LD |& FileCheck --check-prefix=TEST1 %s

TEST1: ---
TEST1-NEXT: mode: latency
TEST1-NEXT: key:
TEST1-NEXT: instructions:
TEST1-NEXT: - 'LD X10 X10 i_0x0'

# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --benchmark-phase=assemble-measured-code -opcode-name=LW |& FileCheck --check-prefix=TEST2 %s

TEST2: ---
TEST2-NEXT: mode: latency
TEST2-NEXT: key:
TEST2-NEXT: instructions:
TEST2-NEXT: - 'LW X10 X10 i_0x0'

# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --benchmark-phase=assemble-measured-code -opcode-name=LH |& FileCheck --check-prefix=TEST3 %s

TEST3: ---
TEST3-NEXT: mode: latency
TEST3-NEXT: key:
TEST3-NEXT: instructions:
TEST3-NEXT: - 'LH X10 X10 i_0x0'

# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --benchmark-phase=assemble-measured-code -opcode-name=LWU |& FileCheck --check-prefix=TEST4 %s

TEST4: ---
TEST4-NEXT: mode: latency
TEST4-NEXT: key:
TEST4-NEXT: instructions:
TEST4-NEXT: - 'LWU X10 X10 i_0x0'

# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --benchmark-phase=assemble-measured-code -opcode-name=LBU |& FileCheck --check-prefix=TEST5 %s

TEST5: ---
TEST5-NEXT: mode: latency
TEST5-NEXT: key:
TEST5-NEXT: instructions:
TEST5-NEXT: - 'LBU X10 X10 i_0x0'

# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --benchmark-phase=assemble-measured-code -opcode-name=LUI |& FileCheck --check-prefix=TEST6 %s

TEST6: LUI: No strategy found to make the execution serial


# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --benchmark-phase=assemble-measured-code -opcode-name=LB |& FileCheck --check-prefix=TEST7 %s

TEST7: ---
TEST7-NEXT: mode: latency
TEST7-NEXT: key:
TEST7-NEXT: instructions:
TEST7-NEXT: - 'LB X10 X10 i_0x0'

# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --benchmark-phase=assemble-measured-code -opcode-name=LR_W_RL -mattr="+a" |& FileCheck --check-prefix=TEST8 %s

TEST8: ---
TEST8-NEXT: mode: latency
TEST8-NEXT: key:
TEST8-NEXT: instructions:
TEST8-NEXT: - 'LR_W_RL X10 X10'
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# RUN: llvm-exegesis -mtriple=riscv64-unknown-linux-gnu -mode=latency --benchmark-phase=assemble-measured-code -mattr=+d -opcode-name=FADD_D |& FileCheck %s

CHECK: ---
CHECK-NEXT: mode: latency
CHECK-NEXT: key:
CHECK-NEXT: instructions:
CHECK-NEXT: - 'FADD_D [[REG1:F[0-9]+_D]] [[REG2:F[0-9]+_D]] [[REG3:F[0-9]+_D]] i_0x7'
CHECK-NEXT: config: ''
CHECK-NEXT: register_initial_values:
CHECK-DAG: - '[[REG1]]=0x0'
CHECK-LAST: ...
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
RUN: llvm-exegesis -mode=latency --benchmark-phase=assemble-measured-code -opcode-name=LB -mtriple=riscv64-unknown-linux-gnu

CHECK: Warning: Pre-assigned register prevented usage of self-aliasing strategy.
4 changes: 4 additions & 0 deletions llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ class ExegesisAArch64Target : public ExegesisTarget {
: ExegesisTarget(AArch64CpuPfmCounters, AArch64_MC::isOpcodeAvailable) {}

private:
unsigned findRegisterByName(const StringRef RegName) const override {
return AArch64::NoRegister;
}

std::vector<MCInst> setRegTo(const MCSubtargetInfo &STI, unsigned Reg,
const APInt &Value) const override {
if (AArch64::GPR32RegClass.contains(Reg))
Expand Down
10 changes: 9 additions & 1 deletion llvm/tools/llvm-exegesis/lib/Assembler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,15 @@ void BasicBlockFiller::addInstruction(const MCInst &Inst, const DebugLoc &DL) {
} else if (Op.isImm()) {
Builder.addImm(Op.getImm());
} else if (!Op.isValid()) {
llvm_unreachable("Operand is not set");
std::string Message;
llvm::raw_string_ostream MessageOut(Message);
MessageOut << "Operand is not set: Instr: ";
Inst.dump_pretty(MessageOut, MCII->getName(Inst.getOpcode()));
MessageOut << "; OpIndex: " << OpIndex;
const MCOperandInfo &OperandInfo = MCID.operands()[OpIndex];
MessageOut << "; OpInfo.OperandType: "
<< static_cast<uint32_t>(OperandInfo.OperandType);
report_fatal_error(Twine(Message));
} else {
llvm_unreachable("Not yet implemented");
}
Expand Down
5 changes: 5 additions & 0 deletions llvm/tools/llvm-exegesis/lib/BenchmarkCode.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@
namespace llvm {
namespace exegesis {

struct ScratchMemoryStore {
unsigned Reg;
unsigned Offset;
};

// A collection of instructions that are to be assembled, executed and measured.
struct BenchmarkCode {
BenchmarkKey Key;
Expand Down
3 changes: 3 additions & 0 deletions llvm/tools/llvm-exegesis/lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ endif()
if (LLVM_TARGETS_TO_BUILD MATCHES "Mips")
list(APPEND LLVM_EXEGESIS_TARGETS "Mips")
endif()
if(LLVM_TARGETS_TO_BUILD MATCHES "RISCV")
list(APPEND LLVM_EXEGESIS_TARGETS "RISCV")
endif()

set(LLVM_EXEGESIS_TARGETS ${LLVM_EXEGESIS_TARGETS} PARENT_SCOPE)

Expand Down
8 changes: 8 additions & 0 deletions llvm/tools/llvm-exegesis/lib/CodeTemplate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,14 @@ const MCOperand &InstructionTemplate::getValueFor(const Operand &Op) const {
return getValueFor(Instr->Variables[Op.getVariableIndex()]);
}

MCOperand &InstructionTemplate::getValueFor(unsigned OpIdx) {
return getValueFor(Instr->Variables[OpIdx]);
}

const MCOperand &InstructionTemplate::getValueFor(unsigned OpIdx) const {
return getValueFor(Instr->Variables[OpIdx]);
}

bool InstructionTemplate::hasImmediateVariables() const {
return any_of(Instr->Variables, [this](const Variable &Var) {
return Instr->getPrimaryOperand(Var).isImmediate();
Expand Down
6 changes: 6 additions & 0 deletions llvm/tools/llvm-exegesis/lib/CodeTemplate.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ struct InstructionTemplate {
const MCOperand &getValueFor(const Variable &Var) const;
MCOperand &getValueFor(const Operand &Op);
const MCOperand &getValueFor(const Operand &Op) const;
MCOperand &getValueFor(unsigned OpIdx);
const MCOperand &getValueFor(unsigned OpIdx) const;
bool hasImmediateVariables() const;
const Instruction &getInstr() const { return *Instr; }
ArrayRef<MCOperand> getVariableValues() const { return VariableValues; }
Expand Down Expand Up @@ -133,6 +135,10 @@ struct CodeTemplate {
// the pointer to this memory is passed in to the function.
unsigned ScratchSpacePointerInReg = 0;

// Require to pre-store value of a given register (fisrt)
// to scratch memory with given offset (second)
SmallVector<std::pair<unsigned, unsigned>, 2> PreinitScratchMemory;

#if defined(__GNUC__) && (defined(__clang__) || LLVM_GNUC_PREREQ(8, 0, 0))
// FIXME: GCC7 bug workaround. Drop #if after GCC7 no longer supported.
private:
Expand Down
6 changes: 6 additions & 0 deletions llvm/tools/llvm-exegesis/lib/LlvmState.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ Expected<LLVMState> LLVMState::Create(std::string TripleName,
if (CpuName == "native")
CpuName = std::string(sys::getHostCPUName());

if (CpuName.empty()) {
std::unique_ptr<MCSubtargetInfo> Empty_STI(
TheTarget->createMCSubtargetInfo(TripleName, "", ""));
CpuName = Empty_STI->getAllProcessorDescriptions().begin()->Key;
}

std::unique_ptr<MCSubtargetInfo> STI(
TheTarget->createMCSubtargetInfo(TripleName, CpuName, ""));
assert(STI && "Unable to create subtarget info!");
Expand Down
Loading

0 comments on commit e058716

Please sign in to comment.