From 92344afd6177fe0a29e3f04d9d9b6332f1f68843 Mon Sep 17 00:00:00 2001 From: Anastasiya Chernikova Date: Thu, 4 Apr 2024 14:52:53 +0300 Subject: [PATCH 01/33] [Exegesis][RISCV] Add RISCV support for llvm-exegesis This patch also makes following amendments to core exegesis: * Added distinction between regular registers aliasing check and registers used as memory address in instruction. * Added scratch memory space pointer register. * Added ability for targets to define register name to register number mapping (findRegisterByName). * General exegesis options were amended: * mattr - new option to pass a list of enabled target features * opcode-name - this option is amended to accept range of opcodes at once Llvm-exegesis RISCV port is a result of team effort. Below everyone involved listed. Co-authored-by: Konstantin Vladimirov Co-authored-by: Dmitrii Petrov Co-authored-by: Dmitry Bushev Co-authored-by: Mark Goncharov Co-authored-by: Anastasiya Chernikova --- llvm/lib/Target/RISCV/RISCVInstrInfo.td | 4 +- .../RISCV/latency-by-extension-A.s | 59 +++ .../RISCV/latency-by-extension-C.s | 65 +++ .../llvm-exegesis/RISCV/latency-by-load.s | 60 +++ .../RISCV/latency-by-opcode-name-FADD_D.s | 11 + .../llvm-exegesis/lib/AArch64/Target.cpp | 4 + llvm/tools/llvm-exegesis/lib/Assembler.cpp | 10 +- llvm/tools/llvm-exegesis/lib/BenchmarkCode.h | 5 + llvm/tools/llvm-exegesis/lib/CMakeLists.txt | 3 + llvm/tools/llvm-exegesis/lib/CodeTemplate.cpp | 8 + llvm/tools/llvm-exegesis/lib/CodeTemplate.h | 6 + llvm/tools/llvm-exegesis/lib/LlvmState.cpp | 6 + .../llvm-exegesis/lib/MCInstrDescView.cpp | 33 +- .../tools/llvm-exegesis/lib/MCInstrDescView.h | 13 +- llvm/tools/llvm-exegesis/lib/Mips/Target.cpp | 6 +- llvm/tools/llvm-exegesis/lib/PerfHelper.h | 2 +- .../llvm-exegesis/lib/PowerPC/Target.cpp | 7 + .../llvm-exegesis/lib/RISCV/CMakeLists.txt | 22 + .../llvm-exegesis/lib/RISCV/RISCVCounters.cpp | 66 +++ .../llvm-exegesis/lib/RISCV/RISCVCounters.h | 31 ++ llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp | 414 ++++++++++++++++++ .../lib/SerialSnippetGenerator.cpp | 62 ++- llvm/tools/llvm-exegesis/lib/SnippetFile.cpp | 14 +- .../llvm-exegesis/lib/SnippetGenerator.cpp | 13 +- llvm/tools/llvm-exegesis/lib/Target.cpp | 4 + llvm/tools/llvm-exegesis/lib/Target.h | 19 + llvm/tools/llvm-exegesis/lib/X86/Target.cpp | 6 + llvm/tools/llvm-exegesis/llvm-exegesis.cpp | 68 ++- 28 files changed, 977 insertions(+), 44 deletions(-) create mode 100644 llvm/test/tools/llvm-exegesis/RISCV/latency-by-extension-A.s create mode 100644 llvm/test/tools/llvm-exegesis/RISCV/latency-by-extension-C.s create mode 100644 llvm/test/tools/llvm-exegesis/RISCV/latency-by-load.s create mode 100644 llvm/test/tools/llvm-exegesis/RISCV/latency-by-opcode-name-FADD_D.s create mode 100644 llvm/tools/llvm-exegesis/lib/RISCV/CMakeLists.txt create mode 100644 llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp create mode 100644 llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.h create mode 100644 llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td index 5747f05ffafd4..e558d3e15a7a0 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td @@ -524,7 +524,7 @@ class BranchCC_rri 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 funct3, string opcodestr, DAGOperand rty = GPR> : RVInstI; @@ -539,7 +539,7 @@ class HLoad_r 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 funct3, string opcodestr, DAGOperand rty = GPR> : RVInstS&1 | 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' diff --git a/llvm/test/tools/llvm-exegesis/RISCV/latency-by-opcode-name-FADD_D.s b/llvm/test/tools/llvm-exegesis/RISCV/latency-by-opcode-name-FADD_D.s new file mode 100644 index 0000000000000..fd58bfb7c1a84 --- /dev/null +++ b/llvm/test/tools/llvm-exegesis/RISCV/latency-by-opcode-name-FADD_D.s @@ -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: ... diff --git a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp index 51846862f0a73..6a3eba2459556 100644 --- a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp +++ b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp @@ -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 setRegTo(const MCSubtargetInfo &STI, unsigned Reg, const APInt &Value) const override { if (AArch64::GPR32RegClass.contains(Reg)) diff --git a/llvm/tools/llvm-exegesis/lib/Assembler.cpp b/llvm/tools/llvm-exegesis/lib/Assembler.cpp index 13c8c2048a5c0..1e2a324cc8fc6 100644 --- a/llvm/tools/llvm-exegesis/lib/Assembler.cpp +++ b/llvm/tools/llvm-exegesis/lib/Assembler.cpp @@ -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(OperandInfo.OperandType); + report_fatal_error(Twine(Message)); } else { llvm_unreachable("Not yet implemented"); } diff --git a/llvm/tools/llvm-exegesis/lib/BenchmarkCode.h b/llvm/tools/llvm-exegesis/lib/BenchmarkCode.h index 1db8472e99f7c..4d5fc241fde0d 100644 --- a/llvm/tools/llvm-exegesis/lib/BenchmarkCode.h +++ b/llvm/tools/llvm-exegesis/lib/BenchmarkCode.h @@ -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; diff --git a/llvm/tools/llvm-exegesis/lib/CMakeLists.txt b/llvm/tools/llvm-exegesis/lib/CMakeLists.txt index 414b49e5e021c..d95c37ff5426b 100644 --- a/llvm/tools/llvm-exegesis/lib/CMakeLists.txt +++ b/llvm/tools/llvm-exegesis/lib/CMakeLists.txt @@ -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) diff --git a/llvm/tools/llvm-exegesis/lib/CodeTemplate.cpp b/llvm/tools/llvm-exegesis/lib/CodeTemplate.cpp index fd156ee01e7ce..9b5bfe3196dcd 100644 --- a/llvm/tools/llvm-exegesis/lib/CodeTemplate.cpp +++ b/llvm/tools/llvm-exegesis/lib/CodeTemplate.cpp @@ -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(); diff --git a/llvm/tools/llvm-exegesis/lib/CodeTemplate.h b/llvm/tools/llvm-exegesis/lib/CodeTemplate.h index 7aca224302a1f..85fcb4e908f01 100644 --- a/llvm/tools/llvm-exegesis/lib/CodeTemplate.h +++ b/llvm/tools/llvm-exegesis/lib/CodeTemplate.h @@ -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 getVariableValues() const { return VariableValues; } @@ -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, 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: diff --git a/llvm/tools/llvm-exegesis/lib/LlvmState.cpp b/llvm/tools/llvm-exegesis/lib/LlvmState.cpp index 4c44c59286ccf..713b09937d57a 100644 --- a/llvm/tools/llvm-exegesis/lib/LlvmState.cpp +++ b/llvm/tools/llvm-exegesis/lib/LlvmState.cpp @@ -45,6 +45,12 @@ Expected LLVMState::Create(std::string TripleName, if (CpuName == "native") CpuName = std::string(sys::getHostCPUName()); + if (CpuName.empty()) { + std::unique_ptr Empty_STI( + TheTarget->createMCSubtargetInfo(TripleName, "", "")); + CpuName = Empty_STI->getAllProcessorDescriptions().begin()->Key; + } + std::unique_ptr STI( TheTarget->createMCSubtargetInfo(TripleName, CpuName, "")); assert(STI && "Unable to create subtarget info!"); diff --git a/llvm/tools/llvm-exegesis/lib/MCInstrDescView.cpp b/llvm/tools/llvm-exegesis/lib/MCInstrDescView.cpp index 9c926d1fc6112..7705d9af4057e 100644 --- a/llvm/tools/llvm-exegesis/lib/MCInstrDescView.cpp +++ b/llvm/tools/llvm-exegesis/lib/MCInstrDescView.cpp @@ -89,17 +89,17 @@ const BitVector *BitVectorCache::getUnique(BitVector &&BV) const { return Entry.get(); } -Instruction::Instruction(const MCInstrDesc *Description, StringRef Name, - SmallVector Operands, - SmallVector Variables, - const BitVector *ImplDefRegs, - const BitVector *ImplUseRegs, - const BitVector *AllDefRegs, - const BitVector *AllUseRegs) +Instruction::Instruction( + const MCInstrDesc *Description, StringRef Name, + SmallVector Operands, SmallVector Variables, + const BitVector *ImplDefRegs, const BitVector *ImplUseRegs, + const BitVector *AllDefRegs, const BitVector *AllUseRegs, + const BitVector *MemoryRegs, const BitVector *NotMemoryRegs) : Description(*Description), Name(Name), Operands(std::move(Operands)), Variables(std::move(Variables)), ImplDefRegs(*ImplDefRegs), ImplUseRegs(*ImplUseRegs), AllDefRegs(*AllDefRegs), - AllUseRegs(*AllUseRegs) {} + AllUseRegs(*AllUseRegs), MemoryRegs(*MemoryRegs), + NotMemoryRegs(*NotMemoryRegs) {} std::unique_ptr Instruction::create(const MCInstrInfo &InstrInfo, @@ -166,6 +166,9 @@ Instruction::create(const MCInstrInfo &InstrInfo, BitVector ImplUseRegs = RATC.emptyRegisters(); BitVector AllDefRegs = RATC.emptyRegisters(); BitVector AllUseRegs = RATC.emptyRegisters(); + BitVector MemoryRegs = RATC.emptyRegisters(); + BitVector NotMemoryRegs = RATC.emptyRegisters(); + for (const auto &Op : Operands) { if (Op.isReg()) { const auto &AliasingBits = Op.getRegisterAliasing().aliasedBits(); @@ -177,6 +180,10 @@ Instruction::create(const MCInstrInfo &InstrInfo, ImplDefRegs |= AliasingBits; if (Op.isUse() && Op.isImplicit()) ImplUseRegs |= AliasingBits; + if (Op.isUse() && Op.isMemory()) + MemoryRegs |= AliasingBits; + if (Op.isUse() && !Op.isMemory()) + NotMemoryRegs |= AliasingBits; } } // Can't use make_unique because constructor is private. @@ -185,7 +192,9 @@ Instruction::create(const MCInstrInfo &InstrInfo, std::move(Variables), BVC.getUnique(std::move(ImplDefRegs)), BVC.getUnique(std::move(ImplUseRegs)), BVC.getUnique(std::move(AllDefRegs)), - BVC.getUnique(std::move(AllUseRegs)))); + BVC.getUnique(std::move(AllUseRegs)), + BVC.getUnique(std::move(MemoryRegs)), + BVC.getUnique(std::move(NotMemoryRegs)))); } const Operand &Instruction::getPrimaryOperand(const Variable &Var) const { @@ -240,6 +249,12 @@ bool Instruction::hasAliasingRegisters( ForbiddenRegisters); } +bool Instruction::hasAliasingNotMemoryRegisters( + const BitVector &ForbiddenRegisters) const { + return anyCommonExcludingForbidden(AllDefRegs, NotMemoryRegs, + ForbiddenRegisters); +} + bool Instruction::hasOneUseOrOneDef() const { return AllDefRegs.count() || AllUseRegs.count(); } diff --git a/llvm/tools/llvm-exegesis/lib/MCInstrDescView.h b/llvm/tools/llvm-exegesis/lib/MCInstrDescView.h index f8ebc07d01f35..edc1a341b27ce 100644 --- a/llvm/tools/llvm-exegesis/lib/MCInstrDescView.h +++ b/llvm/tools/llvm-exegesis/lib/MCInstrDescView.h @@ -133,6 +133,12 @@ struct Instruction { // aliasing Use and Def registers. bool hasAliasingRegisters(const BitVector &ForbiddenRegisters) const; + // Whether this instruction is self aliasing through some registers. + // Repeating this instruction may execute sequentially by picking aliasing + // Def and Not Memory Use registers. It may also execute in parallel by + // picking non aliasing Def and Not Memory Use registers. + bool hasAliasingNotMemoryRegisters(const BitVector &ForbiddenRegisters) const; + // Whether this instruction's registers alias with OtherInstr's registers. bool hasAliasingRegistersThrough(const Instruction &OtherInstr, const BitVector &ForbiddenRegisters) const; @@ -160,12 +166,17 @@ struct Instruction { const BitVector &ImplUseRegs; // The set of aliased implicit use registers. const BitVector &AllDefRegs; // The set of all aliased def registers. const BitVector &AllUseRegs; // The set of all aliased use registers. + const BitVector &MemoryRegs; // The set of all aliased memory use registers. + const BitVector + &NotMemoryRegs; // The set of all aliased not memory use registers. + private: Instruction(const MCInstrDesc *Description, StringRef Name, SmallVector Operands, SmallVector Variables, const BitVector *ImplDefRegs, const BitVector *ImplUseRegs, const BitVector *AllDefRegs, - const BitVector *AllUseRegs); + const BitVector *AllUseRegs, const BitVector *MemoryRegs, + const BitVector *NotMemoryRegs); }; // Instructions are expensive to instantiate. This class provides a cache of diff --git a/llvm/tools/llvm-exegesis/lib/Mips/Target.cpp b/llvm/tools/llvm-exegesis/lib/Mips/Target.cpp index 731e037c240df..917c055e29d8f 100644 --- a/llvm/tools/llvm-exegesis/lib/Mips/Target.cpp +++ b/llvm/tools/llvm-exegesis/lib/Mips/Target.cpp @@ -62,7 +62,7 @@ class ExegesisMipsTarget : public ExegesisTarget { unsigned getMaxMemoryAccessSize() const override { return 64; } void fillMemoryOperands(InstructionTemplate &IT, unsigned Reg, unsigned Offset) const override; - + unsigned findRegisterByName(const StringRef RegName) const override; std::vector setRegTo(const MCSubtargetInfo &STI, unsigned Reg, const APInt &Value) const override; bool matchesArch(Triple::ArchType Arch) const override { @@ -148,6 +148,10 @@ void ExegesisMipsTarget::fillMemoryOperands(InstructionTemplate &IT, setMemOp(IT, 2, MCOperand::createImm(Offset)); // Disp } +unsigned ExegesisMipsTarget::findRegisterByName(const StringRef RegName) const { + return Mips::NoRegister; +} + std::vector ExegesisMipsTarget::setRegTo(const MCSubtargetInfo &STI, unsigned Reg, const APInt &Value) const { diff --git a/llvm/tools/llvm-exegesis/lib/PerfHelper.h b/llvm/tools/llvm-exegesis/lib/PerfHelper.h index 4a825b293b716..1e0fca7380863 100644 --- a/llvm/tools/llvm-exegesis/lib/PerfHelper.h +++ b/llvm/tools/llvm-exegesis/lib/PerfHelper.h @@ -119,7 +119,7 @@ class CounterGroup { virtual void start(); /// Stops the measurement of the event. - void stop(); + virtual void stop(); /// Returns the current value of the counter or error if it cannot be read. /// FunctionBytes: The benchmark function being executed. diff --git a/llvm/tools/llvm-exegesis/lib/PowerPC/Target.cpp b/llvm/tools/llvm-exegesis/lib/PowerPC/Target.cpp index 5c944c90384e3..0031fb89118dd 100644 --- a/llvm/tools/llvm-exegesis/lib/PowerPC/Target.cpp +++ b/llvm/tools/llvm-exegesis/lib/PowerPC/Target.cpp @@ -33,6 +33,8 @@ class ExegesisPowerPCTarget : public ExegesisTarget { : ExegesisTarget(PPCCpuPfmCounters, PPC_MC::isOpcodeAvailable) {} private: + unsigned findRegisterByName(const StringRef RegName) const override; + std::vector setRegTo(const MCSubtargetInfo &STI, unsigned Reg, const APInt &Value) const override; bool matchesArch(Triple::ArchType Arch) const override { @@ -92,6 +94,11 @@ void ExegesisPowerPCTarget::fillMemoryOperands(InstructionTemplate &IT, setMemOp(IT, MemOpIdx + 2, MCOperand::createReg(Reg)); // BaseReg } +unsigned +ExegesisPowerPCTarget::findRegisterByName(const StringRef RegName) const { + return PPC::NoRegister; +} + std::vector ExegesisPowerPCTarget::setRegTo(const MCSubtargetInfo &STI, unsigned Reg, const APInt &Value) const { diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/CMakeLists.txt b/llvm/tools/llvm-exegesis/lib/RISCV/CMakeLists.txt new file mode 100644 index 0000000000000..ea0ced1786a0c --- /dev/null +++ b/llvm/tools/llvm-exegesis/lib/RISCV/CMakeLists.txt @@ -0,0 +1,22 @@ +include_directories( + ${LLVM_MAIN_SRC_DIR}/lib/Target/RISCV + ${LLVM_BINARY_DIR}/lib/Target/RISCV +) + +set(LLVM_LINK_COMPONENTS + RISCV + Exegesis + Core + Support + ) + +add_llvm_library(LLVMExegesisRISCV + DISABLE_LLVM_LINK_LLVM_DYLIB + STATIC + Target.cpp + RISCVCounters.cpp + + DEPENDS + intrinsics_gen + RISCVCommonTableGen + ) diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp b/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp new file mode 100644 index 0000000000000..1d421b3c31c36 --- /dev/null +++ b/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp @@ -0,0 +1,66 @@ +//===-- RISCVCounters.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 "RISCVCounters.h" + +namespace llvm { +namespace exegesis { + +// This implementation of RISCV target for Exegesis doesn't use libpfm +// and provides manual implementation of performance counters. + +inline uint64_t getRISCVCpuCyclesCount() { +#ifdef __riscv + uint64_t Counter; + asm("csrr %0, cycle" : "=r"(Counter)::"memory"); + return Counter; +#else + return 0; +#endif +} + +class RISCVCpuCyclesCounter : public pfm::CounterGroup { + uint64_t StartValue; + uint64_t EndValue; + uint64_t MeasurementCycles; + +public: + explicit RISCVCpuCyclesCounter(pfm::PerfEvent &&Event); + + void start() override { StartValue = getRISCVCpuCyclesCount(); } + + void stop() override { EndValue = getRISCVCpuCyclesCount(); } + + Expected> + readOrError(StringRef FunctionBytes) const override; +}; + +RISCVCpuCyclesCounter::RISCVCpuCyclesCounter(pfm::PerfEvent &&Event) + : CounterGroup(std::move(Event), {}) { + StartValue = getRISCVCpuCyclesCount(); + EndValue = getRISCVCpuCyclesCount(); + MeasurementCycles = EndValue - StartValue; + if (MeasurementCycles == 0) { + report_fatal_error("MeasurementCycles == 0, " + "performance counters are not configured."); + } + StartValue = EndValue = 0; +} + +Expected> +RISCVCpuCyclesCounter::readOrError(StringRef FunctionBytes) const { + uint64_t Counter = EndValue - StartValue - MeasurementCycles; + return SmallVector({static_cast(Counter)}); +} +std::unique_ptr +createRISCVCpuCyclesCounter(pfm::PerfEvent &&Event) { + return std::make_unique(std::move(Event)); +} + +} // namespace exegesis +} // namespace llvm diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.h b/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.h new file mode 100644 index 0000000000000..203f6af76aaaf --- /dev/null +++ b/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.h @@ -0,0 +1,31 @@ +//===-- RISCVCounters.h -----------------------------------------*- 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 +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// RISC-V perf counters. +/// +/// More info at: https://lwn.net/Articles/680985 +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TOOLS_LLVM_EXEGESIS_LIB_RISCV_RISCVCOUNTERS_H +#define LLVM_TOOLS_LLVM_EXEGESIS_LIB_RISCV_RISCVCOUNTERS_H + +#include "../PerfHelper.h" +#include "../Target.h" +#include + +namespace llvm { +namespace exegesis { + +std::unique_ptr +createRISCVCpuCyclesCounter(pfm::PerfEvent &&Event); + +} // namespace exegesis +} // namespace llvm + +#endif // LLVM_TOOLS_LLVM_EXEGESIS_LIB_RISCV_RISCVCOUNTERS_H diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp new file mode 100644 index 0000000000000..c6d392b3b6d7a --- /dev/null +++ b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp @@ -0,0 +1,414 @@ +//===-- 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 "RISCVCounters.h" + +#include "MCTargetDesc/RISCVBaseInfo.h" +#include "MCTargetDesc/RISCVMCTargetDesc.h" +#include "MCTargetDesc/RISCVMatInt.h" +#include "RISCVInstrInfo.h" + +// include computeAvailableFeatures and computeRequiredFeatures. +#define GET_COMPUTE_FEATURES +#define GET_AVAILABLE_OPCODE_CHECKER +#include "RISCVGenInstrInfo.inc" +#undef GET_COMPUTE_FEATURES +#undef GET_AVAILABLE_OPCODE_CHECKER + +#include "llvm/CodeGen/MachineInstrBuilder.h" + +#include + +namespace llvm { +namespace exegesis { + +namespace { + +// TODO move perf counter data to td files (although it looks like an overkill +// of sorts) + +static const char *RISCVPfmCounterNames[] = { + "CPU_CYCLES", // 0 +}; + +static const PfmCountersInfo RISCVDefaultPfmCounters = { + RISCVPfmCounterNames[0], // Cycle counter + nullptr, // No uops counter. + nullptr, // No issue counters. + 0}; + +static const CpuAndPfmCounters RISCVCpuPfmCounters[] = { + {"", &RISCVDefaultPfmCounters}, +}; + +class ExegesisRISCVTarget : public ExegesisTarget { +public: + ExegesisRISCVTarget(); + + Expected> + createCounter(StringRef CounterName, const LLVMState &State, + ArrayRef ValidationCounters, + const pid_t ProcessID) const override; + + bool checkOpcodeSupported(int Opcode, + const MCSubtargetInfo &SI) const override; + + unsigned findRegisterByName(const StringRef RegName) const override; + + bool matchesArch(Triple::ArchType Arch) const override; + + std::vector 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; + + virtual std::vector + storeRegValueToScratch(const MCSubtargetInfo &STI, unsigned Reg, + unsigned Offset) const override; + ArrayRef getUnavailableRegisters() const override; + + Error randomizeTargetMCOperand(const Instruction &Instr, const Variable &Var, + MCOperand &AssignedValue, + const BitVector &ForbiddenRegs) const override; + + void processInstructionReservedRegs(InstructionTemplate &IT) const override; + + std::vector + generateInstructionVariants(const Instruction &Instr, + unsigned MaxConfigsPerOpcode) const override; +}; + +ExegesisRISCVTarget::ExegesisRISCVTarget() + : ExegesisTarget(RISCVCpuPfmCounters, RISCV_MC::isOpcodeAvailable) {} + +Expected> ExegesisRISCVTarget::createCounter( + StringRef CounterName, const LLVMState &State, + ArrayRef ValidationCounters, const pid_t ProcessID) const { + if (CounterName == RISCVPfmCounterNames[0]) { + return createRISCVCpuCyclesCounter(pfm::PerfEvent(CounterName)); + } + return make_error(Twine("Unsupported performance counter '") + .concat(CounterName) + .concat("'")); +} + +bool ExegesisRISCVTarget::checkOpcodeSupported( + int Opcode, const MCSubtargetInfo &SI) const { + auto Features = SI.getFeatureBits(); + FeatureBitset AvailableFeatures = + RISCV_MC::computeAvailableFeatures(Features); + FeatureBitset RequiredFeatures = RISCV_MC::computeRequiredFeatures(Opcode); + FeatureBitset MissingFeatures = + (AvailableFeatures & RequiredFeatures) ^ RequiredFeatures; + return MissingFeatures.none(); +} + +#define GET_REGISTER_MATCHER +#include "RISCVGenAsmMatcher.inc" + +unsigned +ExegesisRISCVTarget::findRegisterByName(const StringRef RegName) const { + unsigned Reg; + if ((Reg = MatchRegisterName(RegName))) + return Reg; + if ((Reg = MatchRegisterAltName(RegName))) + return Reg; + return RISCV::NoRegister; +} + +bool ExegesisRISCVTarget::matchesArch(Triple::ArchType Arch) const { + return Arch == Triple::riscv32 || Arch == Triple::riscv64; +} + +// Stores constant value to a general-purpose (integer) register. +static std::vector loadIntReg(const MCSubtargetInfo &STI, unsigned Reg, + const APInt &Value) { + RISCVMatInt::InstSeq InstSeq = + RISCVMatInt::generateInstSeq(Value.getSExtValue(), STI); + // First instruction has form 'Op DestReg, X0, Imm' + MCRegister SrcReg = RISCV::X0; + MCRegister DestReg = Reg; + std::vector MatIntInstrs; + MatIntInstrs.reserve(InstSeq.size()); + for (const RISCVMatInt::Inst &Inst : InstSeq) { + switch (Inst.getOpndKind()) { + case RISCVMatInt::Imm: + MatIntInstrs.push_back( + MCInstBuilder(RISCV::LUI).addReg(DestReg).addImm(Inst.getImm())); + break; + case RISCVMatInt::RegX0: + MatIntInstrs.push_back(MCInstBuilder(RISCV::ADD_UW) + .addReg(DestReg) + .addReg(SrcReg) + .addReg(RISCV::X0)); + break; + case RISCVMatInt::RegReg: + MatIntInstrs.push_back(MCInstBuilder(Inst.getOpcode()) + .addReg(DestReg) + .addReg(SrcReg) + .addReg(SrcReg)); + break; + case RISCVMatInt::RegImm: + MatIntInstrs.push_back(MCInstBuilder(Inst.getOpcode()) + .addReg(DestReg) + .addReg(SrcReg) + .addImm(Inst.getImm())); + break; + default: + llvm_unreachable("Unexpected kind!"); + } + // Further instructions have form 'Op DestReg, DestReg, Imm' + SrcReg = DestReg; + } + return MatIntInstrs; +} + +const unsigned ScratchIntReg = RISCV::X30; // t5 + +// Stores constant bits to a floating-point register. +static std::vector loadFPRegBits(const MCSubtargetInfo &STI, + unsigned Reg, const APInt &Bits, + unsigned FmvOpcode) { + std::vector 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 have 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 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::epsilon()) { + errs() << "loadFP64RegBits32 is not implemented for doubles like " << D + << ", please remove fractional part\n"; + return {}; + } + + std::vector 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); +} + +std::vector ExegesisRISCVTarget::setRegTo(const MCSubtargetInfo &STI, + unsigned Reg, + const APInt &Value) const { + if (RISCV::GPRRegClass.contains(Reg)) + return loadIntReg(STI, Reg, Value); + if (RISCV::FPR16RegClass.contains(Reg)) + return loadFPRegBits(STI, Reg, Value, RISCV::FMV_H_X); + if (RISCV::FPR32RegClass.contains(Reg)) + return loadFPRegBits(STI, Reg, Value, RISCV::FMV_W_X); + if (RISCV::FPR64RegClass.contains(Reg)) { + if (STI.hasFeature(RISCV::Feature64Bit)) + return loadFPRegBits(STI, Reg, Value, RISCV::FMV_D_X); + else + return loadFP64RegBits32(STI, Reg, Value); + } + if (Reg == RISCV::FRM || Reg == RISCV::VL || Reg == RISCV::VLENB || + Reg == RISCV::VTYPE || RISCV::GPRPairRegClass.contains(Reg) || + RISCV::VRRegClass.contains(Reg) || isVectorRegList(Reg)) { + // Don't initialize: + // - FRM + // - VL, VLENB, VTYPE + // - vector registers (and vector register lists) + // - Zfinx registers + // Generate 'NOP' so that exegesis treats such registers as initialized + // (it tries to initialize them with '0' anyway). + return {nop()}; + } + errs() << "setRegTo is not implemented for Reg " << Reg + << ", results will be unreliable\n"; + return {}; +} + +const unsigned DefaultLoopCounterReg = RISCV::X31; // t6 +const unsigned ScratchMemoryReg = RISCV::X10; // a0 + +unsigned +ExegesisRISCVTarget::getDefaultLoopCounterRegister(const Triple &) const { + return DefaultLoopCounterReg; +} + +void ExegesisRISCVTarget::decrementLoopCounterAndJump( + MachineBasicBlock &MBB, MachineBasicBlock &TargetMBB, + const MCInstrInfo &MII, unsigned LoopRegister) const { + BuildMI(&MBB, DebugLoc(), MII.get(RISCV::ADDI)) + .addDef(LoopRegister) + .addUse(LoopRegister) + .addImm(-1); + BuildMI(&MBB, DebugLoc(), MII.get(RISCV::BNE)) + .addUse(LoopRegister) + .addUse(RISCV::X0) + .addMBB(&TargetMBB); +} + +unsigned ExegesisRISCVTarget::getScratchMemoryRegister(const Triple &TT) const { + return ScratchMemoryReg; // a0 +} + +void ExegesisRISCVTarget::fillMemoryOperands(InstructionTemplate &IT, + unsigned Reg, + unsigned Offset) const { + // TODO: for now we ignore Offset because have no way + // to detect it in instruction. + auto &I = IT.getInstr(); + + auto MemOpIt = + find_if(I.Operands, [](Operand const &Op) { return Op.isMemory(); }); + assert(MemOpIt != I.Operands.end() && + "Instruction must have memory operands"); + + auto &MemOp = *MemOpIt; + + assert(MemOp.isReg() && "Memory operand expected to be register"); + + IT.getValueFor(MemOp) = MCOperand::createReg(Reg); +} + +std::vector ExegesisRISCVTarget::storeRegValueToScratch( + const MCSubtargetInfo &STI, unsigned Reg, unsigned Offset) const { + std::vector Ret; + + if (RISCV::GPRRegClass.contains(Reg)) { + Ret.push_back(MCInstBuilder(RISCV::SW) + .addReg(Reg) + .addReg(ScratchMemoryReg) + .addImm(Offset)); + return Ret; + } + + errs() << "Failed to store value of " << Reg << " register to scratch memory"; + return {nop()}; +} + +const unsigned UnavailableRegisters[4] = {RISCV::X0, DefaultLoopCounterReg, + ScratchIntReg, ScratchMemoryReg}; + +ArrayRef ExegesisRISCVTarget::getUnavailableRegisters() const { + return ArrayRef(UnavailableRegisters); +} + +Error ExegesisRISCVTarget::randomizeTargetMCOperand( + const Instruction &Instr, const Variable &Var, MCOperand &AssignedValue, + const BitVector &ForbiddenRegs) const { + uint8_t OperandType = + Instr.getPrimaryOperand(Var).getExplicitOperandInfo().OperandType; + + switch (OperandType) { + case RISCVOp::OPERAND_FRMARG: + AssignedValue = MCOperand::createImm(RISCVFPRndMode::DYN); + break; + case RISCVOp::OPERAND_SIMM10_LSB0000_NONZERO: + AssignedValue = MCOperand::createImm(0b1 << 4); + break; + case RISCVOp::OPERAND_SIMM6_NONZERO: + case RISCVOp::OPERAND_UIMMLOG2XLEN_NONZERO: + AssignedValue = MCOperand::createImm(1); + break; + default: + if (OperandType >= RISCVOp::OPERAND_FIRST_RISCV_IMM && + OperandType <= RISCVOp::OPERAND_LAST_RISCV_IMM) + AssignedValue = MCOperand::createImm(0); + } + return Error::success(); +} + +// Process instructions that used ReservedRegisters. +// We must not create instructions that used rd=x0. But for some of them in C +// extension we use registers in which we are really not going to write to. +// Registers were reserved in RISCVRegisterInfo.cpp using markSuperRegs function +// and should not be redeclared. Thus we must set appropriate register +// explicitly for each instruction according to RVC spec. +void ExegesisRISCVTarget::processInstructionReservedRegs( + InstructionTemplate &IT) const { + MCOperand &AssignedValue = IT.getValueFor(0); + + switch (IT.getOpcode()) { + case RISCV::C_ADDI16SP: + AssignedValue = MCOperand::createReg(RISCV::X2); + break; + case RISCV::C_ADDI_NOP: + case RISCV::C_ADD_HINT: + case RISCV::C_SLLI_HINT: + AssignedValue = MCOperand::createReg(RISCV::X0); + break; + default: + break; + } +} + +std::vector +ExegesisRISCVTarget::generateInstructionVariants( + const Instruction &Instr, unsigned int MaxConfigsPerOpcode) const { + InstructionTemplate IT{&Instr}; + for (const Operand &Op : Instr.Operands) { + if (Op.isMemory()) { + IT.getValueFor(Op) = MCOperand::createReg(ScratchMemoryReg); + } + } + return {IT}; +} + +} // anonymous namespace + +static ExegesisTarget *getTheRISCVExegesisTarget() { + static ExegesisRISCVTarget Target; + return &Target; +} + +void InitializeRISCVExegesisTarget() { + ExegesisTarget::registerTarget(getTheRISCVExegesisTarget()); +} + +} // namespace exegesis +} // namespace llvm diff --git a/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp b/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp index 7100b51bbb729..4971c5b609725 100644 --- a/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp +++ b/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp @@ -52,13 +52,16 @@ computeAliasingInstructions(const LLVMState &State, const Instruction *Instr, continue; if (OtherOpcode == Instr->Description.getOpcode()) continue; + if (!State.getExegesisTarget().checkOpcodeSupported( + OtherOpcode, State.getSubtargetInfo())) + continue; const Instruction &OtherInstr = State.getIC().getInstr(OtherOpcode); const MCInstrDesc &OtherInstrDesc = OtherInstr.Description; // Ignore instructions that we cannot run. if (OtherInstrDesc.isPseudo() || OtherInstrDesc.usesCustomInsertionHook() || OtherInstrDesc.isBranch() || OtherInstrDesc.isIndirectBranch() || OtherInstrDesc.isCall() || OtherInstrDesc.isReturn()) { - continue; + continue; } if (OtherInstr.hasMemoryOperands()) continue; @@ -81,12 +84,10 @@ static ExecutionMode getExecutionModes(const Instruction &Instr, EM |= ExecutionMode::ALWAYS_SERIAL_TIED_REGS_ALIAS; if (Instr.hasMemoryOperands()) EM |= ExecutionMode::SERIAL_VIA_MEMORY_INSTR; - else { - if (Instr.hasAliasingRegisters(ForbiddenRegisters)) - EM |= ExecutionMode::SERIAL_VIA_EXPLICIT_REGS; - if (Instr.hasOneUseOrOneDef()) - EM |= ExecutionMode::SERIAL_VIA_NON_MEMORY_INSTR; - } + if (Instr.hasAliasingNotMemoryRegisters(ForbiddenRegisters)) + EM |= ExecutionMode::SERIAL_VIA_EXPLICIT_REGS; + if (Instr.hasOneUseOrOneDef()) + EM |= ExecutionMode::SERIAL_VIA_NON_MEMORY_INSTR; return EM; } @@ -104,6 +105,7 @@ static void appendCodeTemplates(const LLVMState &State, case ExecutionMode::ALWAYS_SERIAL_TIED_REGS_ALIAS: { // Picking whatever value for the tied variable will make the instruction // serial. + State.getExegesisTarget().processInstructionReservedRegs(Variant); CodeTemplate CT; CT.Execution = ExecutionModeBit; CT.Info = std::string(ExecutionClassDescription); @@ -113,7 +115,51 @@ static void appendCodeTemplates(const LLVMState &State, } case ExecutionMode::SERIAL_VIA_MEMORY_INSTR: { // Select back-to-back memory instruction. - // TODO: Implement me. + + auto &I = Variant.getInstr(); + if (I.Description.mayLoad()) { + // If instruction is load, we can self-alias it in case when instruction + // overrides whole address register. For that we use provided scratch + // memory. + + // TODO: now it is not checked if load writes the whole register. + + auto DefOpIt = find_if(I.Operands, [](Operand const &op) { + return op.isDef() && op.isReg(); + }); + + if (DefOpIt == I.Operands.end()) + return; + + auto &DefOp = *DefOpIt; + auto &ET = State.getExegesisTarget(); + auto ScratchMemoryRegister = ET.getScratchMemoryRegister( + State.getTargetMachine().getTargetTriple()); + auto &RegClass = + State.getTargetMachine().getMCRegisterInfo()->getRegClass( + DefOp.getExplicitOperandInfo().RegClass); + + // Register classes of def operand and memory operand must be the same + // to perform aliasing. + if (!RegClass.contains(ScratchMemoryRegister)) + return; + + ET.fillMemoryOperands(Variant, ScratchMemoryRegister, 0); + Variant.getValueFor(DefOp) = MCOperand::createReg(ScratchMemoryRegister); + + CodeTemplate CT; + CT.Execution = ExecutionModeBit; + if (CT.ScratchSpacePointerInReg == 0) + CT.ScratchSpacePointerInReg = ScratchMemoryRegister; + + CT.Info = std::string(ExecutionClassDescription); + CT.Instructions.push_back(std::move(Variant)); + CT.PreinitScratchMemory.emplace_back(ScratchMemoryRegister, + /* Offset */ 0); + CodeTemplates.push_back(std::move(CT)); + } + + // TODO: implement more cases return; } case ExecutionMode::SERIAL_VIA_EXPLICIT_REGS: { diff --git a/llvm/tools/llvm-exegesis/lib/SnippetFile.cpp b/llvm/tools/llvm-exegesis/lib/SnippetFile.cpp index b37999ab017f5..d674b87a425cd 100644 --- a/llvm/tools/llvm-exegesis/lib/SnippetFile.cpp +++ b/llvm/tools/llvm-exegesis/lib/SnippetFile.cpp @@ -37,10 +37,11 @@ namespace { // An MCStreamer that reads a BenchmarkCode definition from a file. class BenchmarkCodeStreamer : public MCStreamer, public AsmCommentConsumer { public: - explicit BenchmarkCodeStreamer(MCContext *Context, const LLVMState &State, - BenchmarkCode *Result) - : MCStreamer(*Context), State(State), Result(Result) {} - + explicit BenchmarkCodeStreamer( + const ExegesisTarget &Target, MCContext *Context, + const LLVMState &State, BenchmarkCode *Result) + : MCStreamer(*Context), Target(Target), State(State), + Result(Result) {} // Implementation of the MCStreamer interface. We only care about // instructions. void emitInstruction(const MCInst &Instruction, @@ -208,6 +209,8 @@ class BenchmarkCodeStreamer : public MCStreamer, public AsmCommentConsumer { Align ByteAlignment, SMLoc Loc) override {} unsigned findRegisterByName(const StringRef RegName) const { + if (unsigned Reg = Target.findRegisterByName(RegName)) + return Reg; std::optional RegisterNumber = State.getRegisterNumberFromName(RegName); if (!RegisterNumber.has_value()) { @@ -218,6 +221,7 @@ class BenchmarkCodeStreamer : public MCStreamer, public AsmCommentConsumer { return *RegisterNumber; } + const ExegesisTarget &Target; const LLVMState &State; BenchmarkCode *const Result; unsigned InvalidComments = 0; @@ -251,7 +255,7 @@ Expected> readSnippets(const LLVMState &State, TM.getTarget().createMCObjectFileInfo(Context, /*PIC=*/false)); Context.setObjectFileInfo(ObjectFileInfo.get()); Context.initInlineSourceManager(); - BenchmarkCodeStreamer Streamer(&Context, State, &Result); + BenchmarkCodeStreamer Streamer(State.getExegesisTarget(), &Context, State, &Result); std::string Error; raw_string_ostream ErrorStream(Error); diff --git a/llvm/tools/llvm-exegesis/lib/SnippetGenerator.cpp b/llvm/tools/llvm-exegesis/lib/SnippetGenerator.cpp index 7dcff60a8fd11..8eaf83044e0dd 100644 --- a/llvm/tools/llvm-exegesis/lib/SnippetGenerator.cpp +++ b/llvm/tools/llvm-exegesis/lib/SnippetGenerator.cpp @@ -73,6 +73,9 @@ Error SnippetGenerator::generateConfigurations( for (CodeTemplate &CT : Templates) { // TODO: Generate as many BenchmarkCode as needed. { + CT.ScratchSpacePointerInReg = + State.getExegesisTarget().getScratchMemoryRegister( + State.getTargetMachine().getTargetTriple()); BenchmarkCode BC; BC.Info = CT.Info; BC.Key.Instructions.reserve(CT.Instructions.size()); @@ -108,6 +111,12 @@ std::vector SnippetGenerator::computeRegisterInitialValues( // Loop invariant: DefinedRegs[i] is true iif it has been set at least once // before the current instruction. BitVector DefinedRegs = State.getRATC().emptyRegisters(); + // If target always expects a scratch memory register as live input, + // mark it as defined. + const ExegesisTarget &Target = State.getExegesisTarget(); + unsigned ScratchMemoryReg = Target.getScratchMemoryRegister( + State.getTargetMachine().getTargetTriple()); + DefinedRegs.set(ScratchMemoryReg); std::vector RIV; for (const InstructionTemplate &IT : Instructions) { // Returns the register that this Operand sets or uses, or 0 if this is not @@ -200,7 +209,9 @@ static void setRegisterOperandValue(const RegisterOperandAssignment &ROV, if (ROV.Op->isExplicit()) { auto &AssignedValue = IB.getValueFor(*ROV.Op); if (AssignedValue.isValid()) { - assert(AssignedValue.isReg() && AssignedValue.getReg() == ROV.Reg); + // TODO don't re-assign register operands which are already "locked" + // by Target in corresponding InstructionTemplate + // assert(AssignedValue.isReg() && AssignedValue.getReg() == ROV.Reg); return; } AssignedValue = MCOperand::createReg(ROV.Reg); diff --git a/llvm/tools/llvm-exegesis/lib/Target.cpp b/llvm/tools/llvm-exegesis/lib/Target.cpp index 29e58692f0e92..533f709147eb6 100644 --- a/llvm/tools/llvm-exegesis/lib/Target.cpp +++ b/llvm/tools/llvm-exegesis/lib/Target.cpp @@ -212,6 +212,10 @@ class ExegesisDefaultTarget : public ExegesisTarget { ExegesisDefaultTarget() : ExegesisTarget({}, opcodeIsNotAvailable) {} private: + unsigned findRegisterByName(const StringRef RegName) const override { + llvm_unreachable("Not yet implemented"); + } + std::vector setRegTo(const MCSubtargetInfo &STI, unsigned Reg, const APInt &Value) const override { llvm_unreachable("Not yet implemented"); diff --git a/llvm/tools/llvm-exegesis/lib/Target.h b/llvm/tools/llvm-exegesis/lib/Target.h index 92cc1cb248a1c..e8dd2757f64c0 100644 --- a/llvm/tools/llvm-exegesis/lib/Target.h +++ b/llvm/tools/llvm-exegesis/lib/Target.h @@ -86,6 +86,14 @@ class ExegesisTarget { ArrayRef ValidationCounters, const pid_t ProcessID = 0) const; + virtual bool checkOpcodeSupported(int Opcode, + const MCSubtargetInfo &SI) const { + return true; + } + + // Find register by name, NoRegister if not found. + virtual unsigned findRegisterByName(const StringRef RegName) const = 0; + // Targets can use this to add target-specific passes in assembleToStream(); virtual void addTargetSpecificPasses(PassManagerBase &PM) const {} @@ -201,6 +209,14 @@ class ExegesisTarget { "fillMemoryOperands() requires getScratchMemoryRegister() > 0"); } + // Generates code to store register into scratch memory with offset. + virtual std::vector storeRegValueToScratch(const MCSubtargetInfo &STI, + unsigned Reg, + unsigned Offset) const { + llvm_unreachable( + "storeRegValueToScratch() requires getScratchMemoryRegister() > 0"); + } + // Returns a counter usable as a loop counter. virtual unsigned getDefaultLoopCounterRegister(const Triple &) const { return 0; @@ -238,6 +254,9 @@ class ExegesisTarget { "targets with target-specific operands should implement this"); } + // Process instructions that used reserved registers. + virtual void processInstructionReservedRegs(InstructionTemplate &IT) const {} + // Returns true if this instruction is supported as a back-to-back // instructions. // FIXME: Eventually we should discover this dynamically. diff --git a/llvm/tools/llvm-exegesis/lib/X86/Target.cpp b/llvm/tools/llvm-exegesis/lib/X86/Target.cpp index 3c3bff76fb681..92cfc64e4173e 100644 --- a/llvm/tools/llvm-exegesis/lib/X86/Target.cpp +++ b/llvm/tools/llvm-exegesis/lib/X86/Target.cpp @@ -747,6 +747,8 @@ class ExegesisX86Target : public ExegesisTarget { const MCInstrInfo &MII, unsigned LoopRegister) const override; + unsigned findRegisterByName(const StringRef RegName) const override; + std::vector setRegTo(const MCSubtargetInfo &STI, unsigned Reg, const APInt &Value) const override; @@ -1020,6 +1022,10 @@ static std::vector loadImmediateSegmentRegister(unsigned Reg, #endif // defined(__x86_64__) && defined(__linux__) } +unsigned ExegesisX86Target::findRegisterByName(const StringRef RegName) const { + return X86::NoRegister; +} + std::vector ExegesisX86Target::setRegTo(const MCSubtargetInfo &STI, unsigned Reg, const APInt &Value) const { diff --git a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp index 546ec770a8d22..1e6e6d8dff904 100644 --- a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp +++ b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp @@ -57,7 +57,9 @@ static cl::opt OpcodeIndex( static cl::opt OpcodeNames("opcode-name", - cl::desc("comma-separated list of opcodes to measure, by name"), + cl::desc("comma-separated list of opcodes to measure, " + "each item is either opcode name ('OP') " + "or opcode range ('OP1..OP2', ends are inclusive)"), cl::cat(BenchmarkOptions), cl::init("")); static cl::opt SnippetsFile("snippets-file", @@ -235,7 +237,7 @@ static cl::opt static cl::opt MCPU("mcpu", cl::desc("Target a specific cpu type (-mcpu=help for details)"), - cl::value_desc("cpu-name"), cl::cat(Options), cl::init("native")); + cl::value_desc("cpu-name"), cl::cat(Options), cl::init("")); static cl::opt DumpObjectToDisk("dump-object-to-disk", @@ -274,6 +276,10 @@ static cl::opt BenchmarkProcessCPU( cl::desc("The CPU number that the benchmarking process should executon on"), cl::cat(BenchmarkOptions), cl::init(-1)); +static cl::opt MAttr( + "mattr", cl::desc("comma-separated list of target architecture features"), + cl::value_desc("+feature1,-feature2,..."), cl::cat(Options), cl::init("")); + static ExitOnError ExitOnErr("llvm-exegesis error: "); // Helper function that logs the error(s) and exits. @@ -296,6 +302,22 @@ T ExitOnFileError(const Twine &FileName, Expected &&E) { return std::move(*E); } +static const char *getIgnoredOpcodeReasonOrNull(const LLVMState &State, + unsigned Opcode) { + const MCInstrDesc &InstrDesc = State.getIC().getInstr(Opcode).Description; + if (InstrDesc.isPseudo() || InstrDesc.usesCustomInsertionHook()) + return "Unsupported opcode: isPseudo/usesCustomInserter"; + if (InstrDesc.isBranch() || InstrDesc.isIndirectBranch()) + return "Unsupported opcode: isBranch/isIndirectBranch"; + if (InstrDesc.isCall() || InstrDesc.isReturn()) + return "Unsupported opcode: isCall/isReturn"; + return nullptr; +} + +static bool isIgnoredOpcode(const LLVMState &State, unsigned Opcode) { + return getIgnoredOpcodeReasonOrNull(State, Opcode) != nullptr; +} + // Checks that only one of OpcodeNames, OpcodeIndex or SnippetsFile is provided, // and returns the opcode indices or {} if snippets should be read from // `SnippetsFile`. @@ -340,10 +362,32 @@ static std::vector getOpcodesOrDie(const LLVMState &State) { std::vector Result; Result.reserve(Pieces.size()); for (const StringRef &OpcodeName : Pieces) { - if (unsigned Opcode = ResolveName(OpcodeName)) + if (unsigned Opcode = ResolveName(OpcodeName)) { Result.push_back(Opcode); - else + continue; + } + // Not a known opcode name; should be an opcode name range. + size_t DotDotPos = OpcodeName.find(".."); + if (DotDotPos == StringRef::npos) { ExitWithError(Twine("unknown opcode ").concat(OpcodeName)); + } + StringRef BeginOpcodeName = OpcodeName.substr(0, DotDotPos); + unsigned BeginOpcode = + BeginOpcodeName.empty() ? 1 : ResolveName(BeginOpcodeName); + if (BeginOpcode == 0) { + ExitWithError(Twine("unknown opcode ").concat(BeginOpcodeName)); + } + StringRef EndOpcodeName = OpcodeName.substr(DotDotPos + 2); + unsigned EndOpcode = EndOpcodeName.empty() + ? State.getInstrInfo().getNumOpcodes() - 1 + : ResolveName(EndOpcodeName); + if (EndOpcode == 0) { + ExitWithError(Twine("unknown opcode ").concat(EndOpcodeName)); + } + for (unsigned I = BeginOpcode; I <= EndOpcode; ++I) { + if (!isIgnoredOpcode(State, I)) + Result.push_back(I); + } } return Result; } @@ -352,17 +396,11 @@ static std::vector getOpcodesOrDie(const LLVMState &State) { static Expected> generateSnippets(const LLVMState &State, unsigned Opcode, const BitVector &ForbiddenRegs) { - const Instruction &Instr = State.getIC().getInstr(Opcode); - const MCInstrDesc &InstrDesc = Instr.Description; // Ignore instructions that we cannot run. - if (InstrDesc.isPseudo() || InstrDesc.usesCustomInsertionHook()) - return make_error( - "Unsupported opcode: isPseudo/usesCustomInserter"); - if (InstrDesc.isBranch() || InstrDesc.isIndirectBranch()) - return make_error("Unsupported opcode: isBranch/isIndirectBranch"); - if (InstrDesc.isCall() || InstrDesc.isReturn()) - return make_error("Unsupported opcode: isCall/isReturn"); + if (const char *Reason = getIgnoredOpcodeReasonOrNull(State, Opcode)) + return make_error(Reason); + const Instruction &Instr = State.getIC().getInstr(Opcode); const std::vector InstructionVariants = State.getExegesisTarget().generateInstructionVariants( Instr, MaxConfigsPerOpcode); @@ -485,8 +523,8 @@ void benchmarkMain() { LLVMInitialize##TargetName##AsmParser(); #include "llvm/Config/TargetExegesis.def" - const LLVMState State = - ExitOnErr(LLVMState::Create(TripleName, MCPU, "", UseDummyPerfCounters)); + const LLVMState State = ExitOnErr( + LLVMState::Create(TripleName, MCPU, MAttr, UseDummyPerfCounters)); // Preliminary check to ensure features needed for requested // benchmark mode are present on target CPU and/or OS. From 68bef562d3d41b18ff9ca6bcdc5e43f7a5ec1d1d Mon Sep 17 00:00:00 2001 From: Anastasiya Chernikova Date: Thu, 16 May 2024 20:11:54 +0300 Subject: [PATCH 02/33] Addressing review comments --- llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp | 4 ++++ llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp | 6 ------ 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp index c6d392b3b6d7a..0909c4d3250f7 100644 --- a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp +++ b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp @@ -375,9 +375,13 @@ void ExegesisRISCVTarget::processInstructionReservedRegs( switch (IT.getOpcode()) { case RISCV::C_ADDI16SP: + case RISCV::C_ADDI4SPN: AssignedValue = MCOperand::createReg(RISCV::X2); break; case RISCV::C_ADDI_NOP: + case RISCV::C_LI_HINT: + case RISCV::C_LUI_HINT: + case RISCV::C_MV_HINT: case RISCV::C_ADD_HINT: case RISCV::C_SLLI_HINT: AssignedValue = MCOperand::createReg(RISCV::X0); diff --git a/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp b/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp index 4971c5b609725..9739b48b2b97e 100644 --- a/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp +++ b/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp @@ -57,12 +57,6 @@ computeAliasingInstructions(const LLVMState &State, const Instruction *Instr, continue; const Instruction &OtherInstr = State.getIC().getInstr(OtherOpcode); const MCInstrDesc &OtherInstrDesc = OtherInstr.Description; - // Ignore instructions that we cannot run. - if (OtherInstrDesc.isPseudo() || OtherInstrDesc.usesCustomInsertionHook() || - OtherInstrDesc.isBranch() || OtherInstrDesc.isIndirectBranch() || - OtherInstrDesc.isCall() || OtherInstrDesc.isReturn()) { - continue; - } if (OtherInstr.hasMemoryOperands()) continue; if (!ET.allowAsBackToBack(OtherInstr)) From 22dc529585a7121f1df34c54327b1514712c97cf Mon Sep 17 00:00:00 2001 From: Anastasiya Chernikova Date: Tue, 21 May 2024 16:29:05 +0300 Subject: [PATCH 03/33] Addressing review comments --- .../RISCV/latency-by-extension-A.s | 118 +++++++++--------- .../RISCV/latency-by-extension-C.s | 98 +++++++-------- .../llvm-exegesis/RISCV/latency-by-load.s | 88 ++++++------- .../RISCV/latency-by-opcode-name-FADD_D.s | 2 +- llvm/tools/llvm-exegesis/lib/Assembler.cpp | 10 +- llvm/tools/llvm-exegesis/lib/LlvmState.cpp | 6 - .../tools/llvm-exegesis/lib/MCInstrDescView.h | 4 +- llvm/tools/llvm-exegesis/llvm-exegesis.cpp | 2 +- 8 files changed, 157 insertions(+), 171 deletions(-) diff --git a/llvm/test/tools/llvm-exegesis/RISCV/latency-by-extension-A.s b/llvm/test/tools/llvm-exegesis/RISCV/latency-by-extension-A.s index 8cd11ffc3c1f6..a0b5932e83467 100644 --- a/llvm/test/tools/llvm-exegesis/RISCV/latency-by-extension-A.s +++ b/llvm/test/tools/llvm-exegesis/RISCV/latency-by-extension-A.s @@ -1,59 +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: ... +# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=AMOAND_D -mattr="+a" | FileCheck --check-prefix=AMOAND_D %s + +AMOAND_D: --- +AMOAND_D-NEXT: mode: latency +AMOAND_D-NEXT: key: +AMOAND_D-NEXT: instructions: +AMOAND_D-NEXT: - 'AMOAND_D [[RE01:X[0-9]+]] X10 [[RE01:X[0-9]+]]' +AMOAND_D-NEXT: config: '' +AMOAND_D-NEXT: register_initial_values: +AMOAND_D-NEXT: - '[[RE01:X[0-9]+]]=0x0' +AMOAND_D-LAST: ... + +# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=AMOADD_W -mattr="+a" | FileCheck --check-prefix=AMOADD_W %s + +AMOADD_W: --- +AMOADD_W-NEXT: mode: latency +AMOADD_W-NEXT: key: +AMOADD_W-NEXT: instructions: +AMOADD_W-NEXT: - 'AMOADD_W [[RE02:X[0-9]+]] X10 [[RE02:X[0-9]+]]' +AMOADD_W-NEXT: config: '' +AMOADD_W-NEXT: register_initial_values: +AMOADD_W-NEXT: - '[[RE02:X[0-9]+]]=0x0' +AMOADD_W-LAST: ... + +# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=AMOMAXU_D -mattr="+a" | FileCheck --check-prefix=AMOMAXU_D %s + +AMOMAXU_D: --- +AMOMAXU_D-NEXT: mode: latency +AMOMAXU_D-NEXT: key: +AMOMAXU_D-NEXT: instructions: +AMOMAXU_D-NEXT: - 'AMOMAXU_D [[RE03:X[0-9]+]] X10 [[RE03:X[0-9]+]]' +AMOMAXU_D-NEXT: config: '' +AMOMAXU_D-NEXT: register_initial_values: +AMOMAXU_D-NEXT: - '[[RE03:X[0-9]+]]=0x0' +AMOMAXU_D-LAST: ... + +# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=AMOMIN_W -mattr="+a" | FileCheck --check-prefix=AMOMIN_W %s + +AMOMIN_W: --- +AMOMIN_W-NEXT: mode: latency +AMOMIN_W-NEXT: key: +AMOMIN_W-NEXT: instructions: +AMOMIN_W-NEXT: - 'AMOMIN_W [[RE04:X[0-9]+]] X10 [[RE04:X[0-9]+]]' +AMOMIN_W-NEXT: config: '' +AMOMIN_W-NEXT: register_initial_values: +AMOMIN_W-NEXT: - '[[RE04:X[0-9]+]]=0x0' +AMOMIN_W-LAST: ... + +# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=AMOXOR_D -mattr="+a" | FileCheck --check-prefix=AMOXOR_D %s + +AMOXOR_D: --- +AMOXOR_D-NEXT: mode: latency +AMOXOR_D-NEXT: key: +AMOXOR_D-NEXT: instructions: +AMOXOR_D-NEXT: - 'AMOXOR_D [[RE05:X[0-9]+]] X10 [[RE05:X[0-9]+]]' +AMOXOR_D-NEXT: config: '' +AMOXOR_D-NEXT: register_initial_values: +AMOXOR_D-NEXT: - '[[RE05:X[0-9]+]]=0x0' +AMOXOR_D-LAST: ... diff --git a/llvm/test/tools/llvm-exegesis/RISCV/latency-by-extension-C.s b/llvm/test/tools/llvm-exegesis/RISCV/latency-by-extension-C.s index e22ddc2d76955..108e1cb411d61 100644 --- a/llvm/test/tools/llvm-exegesis/RISCV/latency-by-extension-C.s +++ b/llvm/test/tools/llvm-exegesis/RISCV/latency-by-extension-C.s @@ -1,65 +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 +# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=C_ADDI -mattr=+c | FileCheck --check-prefix=C_ADDI %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]+]]' +C_ADDI: --- +C_ADDI-NEXT: mode: latency +C_ADDI-NEXT: key: +C_ADDI-NEXT: instructions: +C_ADDI-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 +# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=C_ADDIW -mattr=+c | FileCheck --check-prefix=C_ADDIW %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]+]]' +C_ADDIW: --- +C_ADDIW-NEXT: mode: latency +C_ADDIW-NEXT: key: +C_ADDIW-NEXT: instructions: +C_ADDIW-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 +# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=C_ANDI -mattr=+c | FileCheck --check-prefix=C_ANDI %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]+]]' +C_ANDI: --- +C_ANDI-NEXT: mode: latency +C_ANDI-NEXT: key: +C_ANDI-NEXT: instructions: +C_ANDI-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 +# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=C_SLLI -mattr=+c | FileCheck --check-prefix=C_SLLI %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]+]]' +C_SLLI: --- +C_SLLI-NEXT: mode: latency +C_SLLI-NEXT: key: +C_SLLI-NEXT: instructions: +C_SLLI-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 +# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=C_SRAI -mattr=+c | FileCheck --check-prefix=C_SRAI %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]+]]' +C_SRAI: --- +C_SRAI-NEXT: mode: latency +C_SRAI-NEXT: key: +C_SRAI-NEXT: instructions: +C_SRAI-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 +# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=C_SRLI -mattr=+c | FileCheck --check-prefix=C_SRLI %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: ... +C_SRLI: --- +C_SRLI-NEXT: mode: latency +C_SRLI-NEXT: key: +C_SRLI-NEXT: instructions: +C_SRLI-NEXT: - 'C_SRLI [[REG101:X[0-9]+]] [[REG102:X[0-9]+]] [[IMM10:i_0x[0-9]+]]' +C_SRLI-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 +# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=C_LD -mattr=+c | FileCheck --check-prefix=C_LD %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]+]]' +C_LD: --- +C_LD-NEXT: mode: latency +C_LD-NEXT: key: +C_LD-NEXT: instructions: +C_LD-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 +# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=C_LW -mattr=+c | FileCheck --check-prefix=C_LW %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]+]]' +C_LW: --- +C_LW-NEXT: mode: latency +C_LW-NEXT: key: +C_LW-NEXT: instructions: +C_LW-NEXT: - 'C_LW [[REG71:X[0-9]+]] [[REG72:X[0-9]+]] [[IMM7:i_0x[0-9]+]]' diff --git a/llvm/test/tools/llvm-exegesis/RISCV/latency-by-load.s b/llvm/test/tools/llvm-exegesis/RISCV/latency-by-load.s index b685d8759c27c..ba985e231e5ce 100644 --- a/llvm/test/tools/llvm-exegesis/RISCV/latency-by-load.s +++ b/llvm/test/tools/llvm-exegesis/RISCV/latency-by-load.s @@ -1,60 +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 +# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=LD | FileCheck --check-prefix=LD %s -TEST1: --- -TEST1-NEXT: mode: latency -TEST1-NEXT: key: -TEST1-NEXT: instructions: -TEST1-NEXT: - 'LD X10 X10 i_0x0' +LD: --- +LD-NEXT: mode: latency +LD-NEXT: key: +LD-NEXT: instructions: +LD-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 +# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=LW | FileCheck --check-prefix=LW %s -TEST2: --- -TEST2-NEXT: mode: latency -TEST2-NEXT: key: -TEST2-NEXT: instructions: -TEST2-NEXT: - 'LW X10 X10 i_0x0' +LW: --- +LW-NEXT: mode: latency +LW-NEXT: key: +LW-NEXT: instructions: +LW-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 +# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=LH | FileCheck --check-prefix=LH %s -TEST3: --- -TEST3-NEXT: mode: latency -TEST3-NEXT: key: -TEST3-NEXT: instructions: -TEST3-NEXT: - 'LH X10 X10 i_0x0' +LH: --- +LH-NEXT: mode: latency +LH-NEXT: key: +LH-NEXT: instructions: +LH-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 +# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=LWU | FileCheck --check-prefix=LWU %s -TEST4: --- -TEST4-NEXT: mode: latency -TEST4-NEXT: key: -TEST4-NEXT: instructions: -TEST4-NEXT: - 'LWU X10 X10 i_0x0' +LWU: --- +LWU-NEXT: mode: latency +LWU-NEXT: key: +LWU-NEXT: instructions: +LWU-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 +# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=LBU | FileCheck --check-prefix=LBU %s -TEST5: --- -TEST5-NEXT: mode: latency -TEST5-NEXT: key: -TEST5-NEXT: instructions: -TEST5-NEXT: - 'LBU X10 X10 i_0x0' +LBU: --- +LBU-NEXT: mode: latency +LBU-NEXT: key: +LBU-NEXT: instructions: +LBU-NEXT: - 'LBU X10 X10 i_0x0' -# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --benchmark-phase=assemble-measured-code -opcode-name=LUI 2>&1 | FileCheck --check-prefix=TEST6 %s +# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=LUI 2>&1 | FileCheck --check-prefix=LUI %s -TEST6: LUI: No strategy found to make the execution serial +LUI: 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 +# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=LB | FileCheck --check-prefix=LB %s -TEST7: --- -TEST7-NEXT: mode: latency -TEST7-NEXT: key: -TEST7-NEXT: instructions: -TEST7-NEXT: - 'LB X10 X10 i_0x0' +LB: --- +LB-NEXT: mode: latency +LB-NEXT: key: +LB-NEXT: instructions: +LB-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 +# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=LR_W_RL -mattr="+a" | FileCheck --check-prefix=LR_W_RL %s -TEST8: --- -TEST8-NEXT: mode: latency -TEST8-NEXT: key: -TEST8-NEXT: instructions: -TEST8-NEXT: - 'LR_W_RL X10 X10' +LR_W_RL: --- +LR_W_RL-NEXT: mode: latency +LR_W_RL-NEXT: key: +LR_W_RL-NEXT: instructions: +LR_W_RL-NEXT: - 'LR_W_RL X10 X10' diff --git a/llvm/test/tools/llvm-exegesis/RISCV/latency-by-opcode-name-FADD_D.s b/llvm/test/tools/llvm-exegesis/RISCV/latency-by-opcode-name-FADD_D.s index fd58bfb7c1a84..0a4cca1ffc1c1 100644 --- a/llvm/test/tools/llvm-exegesis/RISCV/latency-by-opcode-name-FADD_D.s +++ b/llvm/test/tools/llvm-exegesis/RISCV/latency-by-opcode-name-FADD_D.s @@ -1,4 +1,4 @@ -# RUN: llvm-exegesis -mtriple=riscv64-unknown-linux-gnu -mode=latency --benchmark-phase=assemble-measured-code -mattr=+d -opcode-name=FADD_D | FileCheck %s +# RUN: llvm-exegesis -mtriple=riscv64-unknown-linux-gnu --mcpu=generic -mode=latency --benchmark-phase=assemble-measured-code -mattr=+d -opcode-name=FADD_D | FileCheck %s CHECK: --- CHECK-NEXT: mode: latency diff --git a/llvm/tools/llvm-exegesis/lib/Assembler.cpp b/llvm/tools/llvm-exegesis/lib/Assembler.cpp index 1e2a324cc8fc6..13c8c2048a5c0 100644 --- a/llvm/tools/llvm-exegesis/lib/Assembler.cpp +++ b/llvm/tools/llvm-exegesis/lib/Assembler.cpp @@ -168,15 +168,7 @@ void BasicBlockFiller::addInstruction(const MCInst &Inst, const DebugLoc &DL) { } else if (Op.isImm()) { Builder.addImm(Op.getImm()); } else if (!Op.isValid()) { - 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(OperandInfo.OperandType); - report_fatal_error(Twine(Message)); + llvm_unreachable("Operand is not set"); } else { llvm_unreachable("Not yet implemented"); } diff --git a/llvm/tools/llvm-exegesis/lib/LlvmState.cpp b/llvm/tools/llvm-exegesis/lib/LlvmState.cpp index 713b09937d57a..4c44c59286ccf 100644 --- a/llvm/tools/llvm-exegesis/lib/LlvmState.cpp +++ b/llvm/tools/llvm-exegesis/lib/LlvmState.cpp @@ -45,12 +45,6 @@ Expected LLVMState::Create(std::string TripleName, if (CpuName == "native") CpuName = std::string(sys::getHostCPUName()); - if (CpuName.empty()) { - std::unique_ptr Empty_STI( - TheTarget->createMCSubtargetInfo(TripleName, "", "")); - CpuName = Empty_STI->getAllProcessorDescriptions().begin()->Key; - } - std::unique_ptr STI( TheTarget->createMCSubtargetInfo(TripleName, CpuName, "")); assert(STI && "Unable to create subtarget info!"); diff --git a/llvm/tools/llvm-exegesis/lib/MCInstrDescView.h b/llvm/tools/llvm-exegesis/lib/MCInstrDescView.h index edc1a341b27ce..da84ce793eb02 100644 --- a/llvm/tools/llvm-exegesis/lib/MCInstrDescView.h +++ b/llvm/tools/llvm-exegesis/lib/MCInstrDescView.h @@ -167,8 +167,8 @@ struct Instruction { const BitVector &AllDefRegs; // The set of all aliased def registers. const BitVector &AllUseRegs; // The set of all aliased use registers. const BitVector &MemoryRegs; // The set of all aliased memory use registers. - const BitVector - &NotMemoryRegs; // The set of all aliased not memory use registers. + // The set of all aliased not memory use registers. + const BitVector &NotMemoryRegs; private: Instruction(const MCInstrDesc *Description, StringRef Name, diff --git a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp index 1e6e6d8dff904..8dc4e4e1eec82 100644 --- a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp +++ b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp @@ -237,7 +237,7 @@ static cl::opt static cl::opt MCPU("mcpu", cl::desc("Target a specific cpu type (-mcpu=help for details)"), - cl::value_desc("cpu-name"), cl::cat(Options), cl::init("")); + cl::value_desc("cpu-name"), cl::cat(Options), cl::init("native")); static cl::opt DumpObjectToDisk("dump-object-to-disk", From 3050772995d1cd118ca788cd05745aef1c6426fc Mon Sep 17 00:00:00 2001 From: Anastasiya Chernikova Date: Tue, 21 May 2024 19:16:19 +0300 Subject: [PATCH 04/33] Addressing review comments --- .../llvm-exegesis/lib/AArch64/Target.cpp | 4 ---- llvm/tools/llvm-exegesis/lib/BenchmarkCode.h | 5 ----- llvm/tools/llvm-exegesis/lib/CodeTemplate.cpp | 5 +++-- llvm/tools/llvm-exegesis/lib/CodeTemplate.h | 4 ++-- .../llvm-exegesis/lib/MCInstrDescView.cpp | 21 ++++++++----------- .../tools/llvm-exegesis/lib/MCInstrDescView.h | 4 +--- llvm/tools/llvm-exegesis/lib/Mips/Target.cpp | 5 ----- .../llvm-exegesis/lib/PowerPC/Target.cpp | 7 ------- llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp | 2 +- .../lib/SerialSnippetGenerator.cpp | 2 +- llvm/tools/llvm-exegesis/lib/Target.cpp | 4 ---- llvm/tools/llvm-exegesis/lib/Target.h | 4 +++- llvm/tools/llvm-exegesis/lib/X86/Target.cpp | 6 ------ 13 files changed, 20 insertions(+), 53 deletions(-) diff --git a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp index 6a3eba2459556..51846862f0a73 100644 --- a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp +++ b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp @@ -45,10 +45,6 @@ class ExegesisAArch64Target : public ExegesisTarget { : ExegesisTarget(AArch64CpuPfmCounters, AArch64_MC::isOpcodeAvailable) {} private: - unsigned findRegisterByName(const StringRef RegName) const override { - return AArch64::NoRegister; - } - std::vector setRegTo(const MCSubtargetInfo &STI, unsigned Reg, const APInt &Value) const override { if (AArch64::GPR32RegClass.contains(Reg)) diff --git a/llvm/tools/llvm-exegesis/lib/BenchmarkCode.h b/llvm/tools/llvm-exegesis/lib/BenchmarkCode.h index 4d5fc241fde0d..1db8472e99f7c 100644 --- a/llvm/tools/llvm-exegesis/lib/BenchmarkCode.h +++ b/llvm/tools/llvm-exegesis/lib/BenchmarkCode.h @@ -17,11 +17,6 @@ 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; diff --git a/llvm/tools/llvm-exegesis/lib/CodeTemplate.cpp b/llvm/tools/llvm-exegesis/lib/CodeTemplate.cpp index 9b5bfe3196dcd..74a78b0f1c56f 100644 --- a/llvm/tools/llvm-exegesis/lib/CodeTemplate.cpp +++ b/llvm/tools/llvm-exegesis/lib/CodeTemplate.cpp @@ -57,11 +57,12 @@ const MCOperand &InstructionTemplate::getValueFor(const Operand &Op) const { return getValueFor(Instr->Variables[Op.getVariableIndex()]); } -MCOperand &InstructionTemplate::getValueFor(unsigned OpIdx) { +MCOperand &InstructionTemplate::getValueForOperandIdx(unsigned OpIdx) { return getValueFor(Instr->Variables[OpIdx]); } -const MCOperand &InstructionTemplate::getValueFor(unsigned OpIdx) const { +const MCOperand & +InstructionTemplate::getValueForOperandIdx(unsigned OpIdx) const { return getValueFor(Instr->Variables[OpIdx]); } diff --git a/llvm/tools/llvm-exegesis/lib/CodeTemplate.h b/llvm/tools/llvm-exegesis/lib/CodeTemplate.h index 85fcb4e908f01..662fd90306a45 100644 --- a/llvm/tools/llvm-exegesis/lib/CodeTemplate.h +++ b/llvm/tools/llvm-exegesis/lib/CodeTemplate.h @@ -35,8 +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; + MCOperand &getValueForOperandIdx(unsigned OpIdx); + const MCOperand &getValueForOperandIdx(unsigned OpIdx) const; bool hasImmediateVariables() const; const Instruction &getInstr() const { return *Instr; } ArrayRef getVariableValues() const { return VariableValues; } diff --git a/llvm/tools/llvm-exegesis/lib/MCInstrDescView.cpp b/llvm/tools/llvm-exegesis/lib/MCInstrDescView.cpp index 7705d9af4057e..f9b3666d36f78 100644 --- a/llvm/tools/llvm-exegesis/lib/MCInstrDescView.cpp +++ b/llvm/tools/llvm-exegesis/lib/MCInstrDescView.cpp @@ -89,17 +89,18 @@ const BitVector *BitVectorCache::getUnique(BitVector &&BV) const { return Entry.get(); } -Instruction::Instruction( - const MCInstrDesc *Description, StringRef Name, - SmallVector Operands, SmallVector Variables, - const BitVector *ImplDefRegs, const BitVector *ImplUseRegs, - const BitVector *AllDefRegs, const BitVector *AllUseRegs, - const BitVector *MemoryRegs, const BitVector *NotMemoryRegs) +Instruction::Instruction(const MCInstrDesc *Description, StringRef Name, + SmallVector Operands, + SmallVector Variables, + const BitVector *ImplDefRegs, + const BitVector *ImplUseRegs, + const BitVector *AllDefRegs, + const BitVector *AllUseRegs, + const BitVector *NotMemoryRegs) : Description(*Description), Name(Name), Operands(std::move(Operands)), Variables(std::move(Variables)), ImplDefRegs(*ImplDefRegs), ImplUseRegs(*ImplUseRegs), AllDefRegs(*AllDefRegs), - AllUseRegs(*AllUseRegs), MemoryRegs(*MemoryRegs), - NotMemoryRegs(*NotMemoryRegs) {} + AllUseRegs(*AllUseRegs), NotMemoryRegs(*NotMemoryRegs) {} std::unique_ptr Instruction::create(const MCInstrInfo &InstrInfo, @@ -166,7 +167,6 @@ Instruction::create(const MCInstrInfo &InstrInfo, BitVector ImplUseRegs = RATC.emptyRegisters(); BitVector AllDefRegs = RATC.emptyRegisters(); BitVector AllUseRegs = RATC.emptyRegisters(); - BitVector MemoryRegs = RATC.emptyRegisters(); BitVector NotMemoryRegs = RATC.emptyRegisters(); for (const auto &Op : Operands) { @@ -180,8 +180,6 @@ Instruction::create(const MCInstrInfo &InstrInfo, ImplDefRegs |= AliasingBits; if (Op.isUse() && Op.isImplicit()) ImplUseRegs |= AliasingBits; - if (Op.isUse() && Op.isMemory()) - MemoryRegs |= AliasingBits; if (Op.isUse() && !Op.isMemory()) NotMemoryRegs |= AliasingBits; } @@ -193,7 +191,6 @@ Instruction::create(const MCInstrInfo &InstrInfo, BVC.getUnique(std::move(ImplUseRegs)), BVC.getUnique(std::move(AllDefRegs)), BVC.getUnique(std::move(AllUseRegs)), - BVC.getUnique(std::move(MemoryRegs)), BVC.getUnique(std::move(NotMemoryRegs)))); } diff --git a/llvm/tools/llvm-exegesis/lib/MCInstrDescView.h b/llvm/tools/llvm-exegesis/lib/MCInstrDescView.h index da84ce793eb02..c6f47a438ad49 100644 --- a/llvm/tools/llvm-exegesis/lib/MCInstrDescView.h +++ b/llvm/tools/llvm-exegesis/lib/MCInstrDescView.h @@ -166,7 +166,6 @@ struct Instruction { const BitVector &ImplUseRegs; // The set of aliased implicit use registers. const BitVector &AllDefRegs; // The set of all aliased def registers. const BitVector &AllUseRegs; // The set of all aliased use registers. - const BitVector &MemoryRegs; // The set of all aliased memory use registers. // The set of all aliased not memory use registers. const BitVector &NotMemoryRegs; @@ -175,8 +174,7 @@ struct Instruction { SmallVector Operands, SmallVector Variables, const BitVector *ImplDefRegs, const BitVector *ImplUseRegs, const BitVector *AllDefRegs, - const BitVector *AllUseRegs, const BitVector *MemoryRegs, - const BitVector *NotMemoryRegs); + const BitVector *AllUseRegs, const BitVector *NotMemoryRegs); }; // Instructions are expensive to instantiate. This class provides a cache of diff --git a/llvm/tools/llvm-exegesis/lib/Mips/Target.cpp b/llvm/tools/llvm-exegesis/lib/Mips/Target.cpp index 917c055e29d8f..6231c971fadb9 100644 --- a/llvm/tools/llvm-exegesis/lib/Mips/Target.cpp +++ b/llvm/tools/llvm-exegesis/lib/Mips/Target.cpp @@ -62,7 +62,6 @@ class ExegesisMipsTarget : public ExegesisTarget { unsigned getMaxMemoryAccessSize() const override { return 64; } void fillMemoryOperands(InstructionTemplate &IT, unsigned Reg, unsigned Offset) const override; - unsigned findRegisterByName(const StringRef RegName) const override; std::vector setRegTo(const MCSubtargetInfo &STI, unsigned Reg, const APInt &Value) const override; bool matchesArch(Triple::ArchType Arch) const override { @@ -148,10 +147,6 @@ void ExegesisMipsTarget::fillMemoryOperands(InstructionTemplate &IT, setMemOp(IT, 2, MCOperand::createImm(Offset)); // Disp } -unsigned ExegesisMipsTarget::findRegisterByName(const StringRef RegName) const { - return Mips::NoRegister; -} - std::vector ExegesisMipsTarget::setRegTo(const MCSubtargetInfo &STI, unsigned Reg, const APInt &Value) const { diff --git a/llvm/tools/llvm-exegesis/lib/PowerPC/Target.cpp b/llvm/tools/llvm-exegesis/lib/PowerPC/Target.cpp index 0031fb89118dd..5c944c90384e3 100644 --- a/llvm/tools/llvm-exegesis/lib/PowerPC/Target.cpp +++ b/llvm/tools/llvm-exegesis/lib/PowerPC/Target.cpp @@ -33,8 +33,6 @@ class ExegesisPowerPCTarget : public ExegesisTarget { : ExegesisTarget(PPCCpuPfmCounters, PPC_MC::isOpcodeAvailable) {} private: - unsigned findRegisterByName(const StringRef RegName) const override; - std::vector setRegTo(const MCSubtargetInfo &STI, unsigned Reg, const APInt &Value) const override; bool matchesArch(Triple::ArchType Arch) const override { @@ -94,11 +92,6 @@ void ExegesisPowerPCTarget::fillMemoryOperands(InstructionTemplate &IT, setMemOp(IT, MemOpIdx + 2, MCOperand::createReg(Reg)); // BaseReg } -unsigned -ExegesisPowerPCTarget::findRegisterByName(const StringRef RegName) const { - return PPC::NoRegister; -} - std::vector ExegesisPowerPCTarget::setRegTo(const MCSubtargetInfo &STI, unsigned Reg, const APInt &Value) const { diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp index 0909c4d3250f7..2583365a3945b 100644 --- a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp +++ b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp @@ -371,7 +371,7 @@ Error ExegesisRISCVTarget::randomizeTargetMCOperand( // explicitly for each instruction according to RVC spec. void ExegesisRISCVTarget::processInstructionReservedRegs( InstructionTemplate &IT) const { - MCOperand &AssignedValue = IT.getValueFor(0); + MCOperand &AssignedValue = IT.getValueForOperandIdx(0); switch (IT.getOpcode()) { case RISCV::C_ADDI16SP: diff --git a/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp b/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp index 9739b48b2b97e..1f1e3983d3014 100644 --- a/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp +++ b/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp @@ -125,7 +125,7 @@ static void appendCodeTemplates(const LLVMState &State, if (DefOpIt == I.Operands.end()) return; - auto &DefOp = *DefOpIt; + const Operand &DefOp = *DefOpIt; auto &ET = State.getExegesisTarget(); auto ScratchMemoryRegister = ET.getScratchMemoryRegister( State.getTargetMachine().getTargetTriple()); diff --git a/llvm/tools/llvm-exegesis/lib/Target.cpp b/llvm/tools/llvm-exegesis/lib/Target.cpp index 533f709147eb6..29e58692f0e92 100644 --- a/llvm/tools/llvm-exegesis/lib/Target.cpp +++ b/llvm/tools/llvm-exegesis/lib/Target.cpp @@ -212,10 +212,6 @@ class ExegesisDefaultTarget : public ExegesisTarget { ExegesisDefaultTarget() : ExegesisTarget({}, opcodeIsNotAvailable) {} private: - unsigned findRegisterByName(const StringRef RegName) const override { - llvm_unreachable("Not yet implemented"); - } - std::vector setRegTo(const MCSubtargetInfo &STI, unsigned Reg, const APInt &Value) const override { llvm_unreachable("Not yet implemented"); diff --git a/llvm/tools/llvm-exegesis/lib/Target.h b/llvm/tools/llvm-exegesis/lib/Target.h index e8dd2757f64c0..2302400800de2 100644 --- a/llvm/tools/llvm-exegesis/lib/Target.h +++ b/llvm/tools/llvm-exegesis/lib/Target.h @@ -92,7 +92,9 @@ class ExegesisTarget { } // Find register by name, NoRegister if not found. - virtual unsigned findRegisterByName(const StringRef RegName) const = 0; + virtual unsigned findRegisterByName(const StringRef RegName) const { + return MCRegister::NoRegister; + } // Targets can use this to add target-specific passes in assembleToStream(); virtual void addTargetSpecificPasses(PassManagerBase &PM) const {} diff --git a/llvm/tools/llvm-exegesis/lib/X86/Target.cpp b/llvm/tools/llvm-exegesis/lib/X86/Target.cpp index 92cfc64e4173e..3c3bff76fb681 100644 --- a/llvm/tools/llvm-exegesis/lib/X86/Target.cpp +++ b/llvm/tools/llvm-exegesis/lib/X86/Target.cpp @@ -747,8 +747,6 @@ class ExegesisX86Target : public ExegesisTarget { const MCInstrInfo &MII, unsigned LoopRegister) const override; - unsigned findRegisterByName(const StringRef RegName) const override; - std::vector setRegTo(const MCSubtargetInfo &STI, unsigned Reg, const APInt &Value) const override; @@ -1022,10 +1020,6 @@ static std::vector loadImmediateSegmentRegister(unsigned Reg, #endif // defined(__x86_64__) && defined(__linux__) } -unsigned ExegesisX86Target::findRegisterByName(const StringRef RegName) const { - return X86::NoRegister; -} - std::vector ExegesisX86Target::setRegTo(const MCSubtargetInfo &STI, unsigned Reg, const APInt &Value) const { From 9c289b8f5f9cb51ae9ec6f08fac3d326dbe64fd9 Mon Sep 17 00:00:00 2001 From: Anastasiya Chernikova Date: Thu, 23 May 2024 20:59:19 +0300 Subject: [PATCH 05/33] Fixed tests --- .../tools/llvm-exegesis/RISCV/latency-by-extension-A.s | 10 +++++----- .../tools/llvm-exegesis/RISCV/latency-by-extension-C.s | 2 +- .../RISCV/latency-by-opcode-name-FADD_D.s | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/llvm/test/tools/llvm-exegesis/RISCV/latency-by-extension-A.s b/llvm/test/tools/llvm-exegesis/RISCV/latency-by-extension-A.s index a0b5932e83467..bdc02d4af2155 100644 --- a/llvm/test/tools/llvm-exegesis/RISCV/latency-by-extension-A.s +++ b/llvm/test/tools/llvm-exegesis/RISCV/latency-by-extension-A.s @@ -8,7 +8,7 @@ AMOAND_D-NEXT: - 'AMOAND_D [[RE01:X[0-9]+]] X10 [[RE01:X[0-9]+]]' AMOAND_D-NEXT: config: '' AMOAND_D-NEXT: register_initial_values: AMOAND_D-NEXT: - '[[RE01:X[0-9]+]]=0x0' -AMOAND_D-LAST: ... +AMOAND_D-DAG: ... # RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=AMOADD_W -mattr="+a" | FileCheck --check-prefix=AMOADD_W %s @@ -20,7 +20,7 @@ AMOADD_W-NEXT: - 'AMOADD_W [[RE02:X[0-9]+]] X10 [[RE02:X[0-9]+]]' AMOADD_W-NEXT: config: '' AMOADD_W-NEXT: register_initial_values: AMOADD_W-NEXT: - '[[RE02:X[0-9]+]]=0x0' -AMOADD_W-LAST: ... +AMOADD_W-DAG: ... # RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=AMOMAXU_D -mattr="+a" | FileCheck --check-prefix=AMOMAXU_D %s @@ -32,7 +32,7 @@ AMOMAXU_D-NEXT: - 'AMOMAXU_D [[RE03:X[0-9]+]] X10 [[RE03:X[0-9]+]]' AMOMAXU_D-NEXT: config: '' AMOMAXU_D-NEXT: register_initial_values: AMOMAXU_D-NEXT: - '[[RE03:X[0-9]+]]=0x0' -AMOMAXU_D-LAST: ... +AMOMAXU_D-DAG: ... # RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=AMOMIN_W -mattr="+a" | FileCheck --check-prefix=AMOMIN_W %s @@ -44,7 +44,7 @@ AMOMIN_W-NEXT: - 'AMOMIN_W [[RE04:X[0-9]+]] X10 [[RE04:X[0-9]+]]' AMOMIN_W-NEXT: config: '' AMOMIN_W-NEXT: register_initial_values: AMOMIN_W-NEXT: - '[[RE04:X[0-9]+]]=0x0' -AMOMIN_W-LAST: ... +AMOMIN_W-DAG: ... # RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=AMOXOR_D -mattr="+a" | FileCheck --check-prefix=AMOXOR_D %s @@ -56,4 +56,4 @@ AMOXOR_D-NEXT: - 'AMOXOR_D [[RE05:X[0-9]+]] X10 [[RE05:X[0-9]+]]' AMOXOR_D-NEXT: config: '' AMOXOR_D-NEXT: register_initial_values: AMOXOR_D-NEXT: - '[[RE05:X[0-9]+]]=0x0' -AMOXOR_D-LAST: ... +AMOXOR_D-DAG: ... diff --git a/llvm/test/tools/llvm-exegesis/RISCV/latency-by-extension-C.s b/llvm/test/tools/llvm-exegesis/RISCV/latency-by-extension-C.s index 108e1cb411d61..00bd79729539f 100644 --- a/llvm/test/tools/llvm-exegesis/RISCV/latency-by-extension-C.s +++ b/llvm/test/tools/llvm-exegesis/RISCV/latency-by-extension-C.s @@ -45,7 +45,7 @@ C_SRLI-NEXT: mode: latency C_SRLI-NEXT: key: C_SRLI-NEXT: instructions: C_SRLI-NEXT: - 'C_SRLI [[REG101:X[0-9]+]] [[REG102:X[0-9]+]] [[IMM10:i_0x[0-9]+]]' -C_SRLI-LAST: ... +C_SRLI-DAG: ... # RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=C_LD -mattr=+c | FileCheck --check-prefix=C_LD %s diff --git a/llvm/test/tools/llvm-exegesis/RISCV/latency-by-opcode-name-FADD_D.s b/llvm/test/tools/llvm-exegesis/RISCV/latency-by-opcode-name-FADD_D.s index 0a4cca1ffc1c1..2dea89cca4d7e 100644 --- a/llvm/test/tools/llvm-exegesis/RISCV/latency-by-opcode-name-FADD_D.s +++ b/llvm/test/tools/llvm-exegesis/RISCV/latency-by-opcode-name-FADD_D.s @@ -8,4 +8,4 @@ CHECK-NEXT: - 'FADD_D [[REG1:F[0-9]+_D]] [[REG2:F[0-9]+_D]] [[REG3:F[0-9]+_D CHECK-NEXT: config: '' CHECK-NEXT: register_initial_values: CHECK-DAG: - '[[REG1]]=0x0' -CHECK-LAST: ... +CHECK-DAG: ... From 1277beb7fc2ce9f8febf2a75378d6817ebd4d45a Mon Sep 17 00:00:00 2001 From: Anastasiya Chernikova Date: Fri, 24 May 2024 18:35:05 +0300 Subject: [PATCH 06/33] Addressing review comments --- llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp | 7 +++++++ llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp | 6 +++--- llvm/tools/llvm-exegesis/lib/SnippetGenerator.cpp | 1 - llvm/tools/llvm-exegesis/lib/Target.h | 2 +- 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp b/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp index 1d421b3c31c36..a9d207fa3d157 100644 --- a/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp +++ b/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp @@ -5,6 +5,10 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// +// +// This file defines RISC-V perf counters. +// +//===----------------------------------------------------------------------===// #include "RISCVCounters.h" @@ -45,6 +49,9 @@ RISCVCpuCyclesCounter::RISCVCpuCyclesCounter(pfm::PerfEvent &&Event) StartValue = getRISCVCpuCyclesCount(); EndValue = getRISCVCpuCyclesCount(); MeasurementCycles = EndValue - StartValue; + // If values of two calls CpuCyclesCounters don`t differ + // it means that counters don`t configured properly, report error. + // MeasurementCycles the smallest interval between two counter calls. if (MeasurementCycles == 0) { report_fatal_error("MeasurementCycles == 0, " "performance counters are not configured."); diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp index 2583365a3945b..77365c5ccadf1 100644 --- a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp +++ b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp @@ -60,7 +60,7 @@ class ExegesisRISCVTarget : public ExegesisTarget { bool checkOpcodeSupported(int Opcode, const MCSubtargetInfo &SI) const override; - unsigned findRegisterByName(const StringRef RegName) const override; + MCRegister findRegisterByName(const StringRef RegName) const override; bool matchesArch(Triple::ArchType Arch) const override; @@ -123,9 +123,9 @@ bool ExegesisRISCVTarget::checkOpcodeSupported( #define GET_REGISTER_MATCHER #include "RISCVGenAsmMatcher.inc" -unsigned +MCRegister ExegesisRISCVTarget::findRegisterByName(const StringRef RegName) const { - unsigned Reg; + MCRegister Reg; if ((Reg = MatchRegisterName(RegName))) return Reg; if ((Reg = MatchRegisterAltName(RegName))) diff --git a/llvm/tools/llvm-exegesis/lib/SnippetGenerator.cpp b/llvm/tools/llvm-exegesis/lib/SnippetGenerator.cpp index 8eaf83044e0dd..48357d443f713 100644 --- a/llvm/tools/llvm-exegesis/lib/SnippetGenerator.cpp +++ b/llvm/tools/llvm-exegesis/lib/SnippetGenerator.cpp @@ -211,7 +211,6 @@ static void setRegisterOperandValue(const RegisterOperandAssignment &ROV, if (AssignedValue.isValid()) { // TODO don't re-assign register operands which are already "locked" // by Target in corresponding InstructionTemplate - // assert(AssignedValue.isReg() && AssignedValue.getReg() == ROV.Reg); return; } AssignedValue = MCOperand::createReg(ROV.Reg); diff --git a/llvm/tools/llvm-exegesis/lib/Target.h b/llvm/tools/llvm-exegesis/lib/Target.h index 2302400800de2..f4edec300e440 100644 --- a/llvm/tools/llvm-exegesis/lib/Target.h +++ b/llvm/tools/llvm-exegesis/lib/Target.h @@ -92,7 +92,7 @@ class ExegesisTarget { } // Find register by name, NoRegister if not found. - virtual unsigned findRegisterByName(const StringRef RegName) const { + virtual MCRegister findRegisterByName(const StringRef RegName) const { return MCRegister::NoRegister; } From 712aa9dec764912ec746c3fce7d62634a0bcf6d4 Mon Sep 17 00:00:00 2001 From: Anastasiya Chernikova Date: Fri, 31 May 2024 19:03:43 +0300 Subject: [PATCH 07/33] Addressing review comments --- llvm/lib/Target/RISCV/CMakeLists.txt | 1 + llvm/lib/Target/RISCV/RISCV.td | 6 ++ llvm/lib/Target/RISCV/RISCVPfmCounters.td | 18 ++++ llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp | 18 +--- llvm/tools/llvm-exegesis/lib/SnippetFile.cpp | 1 + llvm/tools/llvm-exegesis/llvm-exegesis.cpp | 92 ++++++++++++------- .../llvm-project-overlay/llvm/BUILD.bazel | 1 + 7 files changed, 89 insertions(+), 48 deletions(-) create mode 100644 llvm/lib/Target/RISCV/RISCVPfmCounters.td diff --git a/llvm/lib/Target/RISCV/CMakeLists.txt b/llvm/lib/Target/RISCV/CMakeLists.txt index fd049d1a57860..4727e0ca22428 100644 --- a/llvm/lib/Target/RISCV/CMakeLists.txt +++ b/llvm/lib/Target/RISCV/CMakeLists.txt @@ -15,6 +15,7 @@ tablegen(LLVM RISCVGenRegisterBank.inc -gen-register-bank) tablegen(LLVM RISCVGenRegisterInfo.inc -gen-register-info) tablegen(LLVM RISCVGenSearchableTables.inc -gen-searchable-tables) tablegen(LLVM RISCVGenSubtargetInfo.inc -gen-subtarget) +tablegen(LLVM RISCVGenExegesis.inc -gen-exegesis) set(LLVM_TARGET_DEFINITIONS RISCVGISel.td) tablegen(LLVM RISCVGenGlobalISel.inc -gen-global-isel) diff --git a/llvm/lib/Target/RISCV/RISCV.td b/llvm/lib/Target/RISCV/RISCV.td index 00c3d702e12a2..38086e8efe340 100644 --- a/llvm/lib/Target/RISCV/RISCV.td +++ b/llvm/lib/Target/RISCV/RISCV.td @@ -84,3 +84,9 @@ def RISCV : Target { let AssemblyWriters = [RISCVAsmWriter]; let AllowRegisterRenaming = 1; } + +//===----------------------------------------------------------------------===// +// Pfm Counters +//===----------------------------------------------------------------------===// + +include "RISCVPfmCounters.td" diff --git a/llvm/lib/Target/RISCV/RISCVPfmCounters.td b/llvm/lib/Target/RISCV/RISCVPfmCounters.td new file mode 100644 index 0000000000000..33650dc5b0017 --- /dev/null +++ b/llvm/lib/Target/RISCV/RISCVPfmCounters.td @@ -0,0 +1,18 @@ +//===-- RISCVPfmCounters.td - RISC-V Hardware Counters -----*- tablegen -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// This describes the available hardware counters for RISC-V. +// +//===----------------------------------------------------------------------===// + +def CpuCyclesPfmCounter : PfmCounter<"CPU_CYCLES">; + +def DefaultPfmCounters : ProcPfmCounters { + let CycleCounter = CpuCyclesPfmCounter; +} +def : PfmCountersDefaultBinding; diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp index 77365c5ccadf1..84634db285ba6 100644 --- a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp +++ b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp @@ -31,22 +31,7 @@ namespace exegesis { namespace { -// TODO move perf counter data to td files (although it looks like an overkill -// of sorts) - -static const char *RISCVPfmCounterNames[] = { - "CPU_CYCLES", // 0 -}; - -static const PfmCountersInfo RISCVDefaultPfmCounters = { - RISCVPfmCounterNames[0], // Cycle counter - nullptr, // No uops counter. - nullptr, // No issue counters. - 0}; - -static const CpuAndPfmCounters RISCVCpuPfmCounters[] = { - {"", &RISCVDefaultPfmCounters}, -}; +#include "RISCVGenExegesis.inc" class ExegesisRISCVTarget : public ExegesisTarget { public: @@ -102,6 +87,7 @@ Expected> ExegesisRISCVTarget::createCounter( StringRef CounterName, const LLVMState &State, ArrayRef ValidationCounters, const pid_t ProcessID) const { if (CounterName == RISCVPfmCounterNames[0]) { + // TODO add support for Linux perf counters return createRISCVCpuCyclesCounter(pfm::PerfEvent(CounterName)); } return make_error(Twine("Unsupported performance counter '") diff --git a/llvm/tools/llvm-exegesis/lib/SnippetFile.cpp b/llvm/tools/llvm-exegesis/lib/SnippetFile.cpp index d674b87a425cd..f38b233a95d4a 100644 --- a/llvm/tools/llvm-exegesis/lib/SnippetFile.cpp +++ b/llvm/tools/llvm-exegesis/lib/SnippetFile.cpp @@ -209,6 +209,7 @@ class BenchmarkCodeStreamer : public MCStreamer, public AsmCommentConsumer { Align ByteAlignment, SMLoc Loc) override {} unsigned findRegisterByName(const StringRef RegName) const { + // TODO make use of RegNameToRegNo map if (unsigned Reg = Target.findRegisterByName(RegName)) return Reg; std::optional RegisterNumber = diff --git a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp index 8dc4e4e1eec82..c4236820c1462 100644 --- a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp +++ b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp @@ -50,17 +50,27 @@ namespace llvm { namespace exegesis { +struct OpcodeNameParser + : public cl::parser>> { + OpcodeNameParser(cl::Option &O) + : cl::parser>>(O) {} + bool parse(cl::Option &O, StringRef ArgName, const StringRef ArgValue, + std::vector> &Val); +}; + static cl::opt OpcodeIndex( "opcode-index", cl::desc("opcode to measure, by index, or -1 to measure all opcodes"), cl::cat(BenchmarkOptions), cl::init(0)); -static cl::opt +static cl::opt>, false, + OpcodeNameParser> OpcodeNames("opcode-name", cl::desc("comma-separated list of opcodes to measure, " "each item is either opcode name ('OP') " "or opcode range ('OP1..OP2', ends are inclusive)"), - cl::cat(BenchmarkOptions), cl::init("")); + cl::cat(BenchmarkOptions), + cl::init(std::vector>())); static cl::opt SnippetsFile("snippets-file", cl::desc("code snippets to measure"), @@ -318,6 +328,27 @@ static bool isIgnoredOpcode(const LLVMState &State, unsigned Opcode) { return getIgnoredOpcodeReasonOrNull(State, Opcode) != nullptr; } +bool OpcodeNameParser::parse( + cl::Option &O, StringRef ArgName, const StringRef OpcodeNames, + std::vector> &Val) { + SmallVector Pieces; + StringRef(OpcodeNames) + .split(Pieces, ",", /* MaxSplit */ -1, /* KeepEmpty */ false); + for (const StringRef &OpcodeName : Pieces) { + size_t DotDotPos = OpcodeName.find(".."); + if (DotDotPos == StringRef::npos) { + Val.push_back(std::make_pair(OpcodeName, OpcodeName)); + continue; + } + StringRef BeginOpcodeName = OpcodeName.substr(0, DotDotPos); + StringRef EndOpcodeName = OpcodeName.substr(DotDotPos + 2); + Val.push_back(std::make_pair(BeginOpcodeName, EndOpcodeName)); + } + if (Val.empty()) + return O.error("No matching opcode names"); + return false; +} + // Checks that only one of OpcodeNames, OpcodeIndex or SnippetsFile is provided, // and returns the opcode indices or {} if snippets should be read from // `SnippetsFile`. @@ -356,37 +387,34 @@ static std::vector getOpcodesOrDie(const LLVMState &State) { return I->getSecond(); return 0u; }; - SmallVector Pieces; - StringRef(OpcodeNames.getValue()) - .split(Pieces, ",", /* MaxSplit */ -1, /* KeepEmpty */ false); + std::vector Result; - Result.reserve(Pieces.size()); - for (const StringRef &OpcodeName : Pieces) { - if (unsigned Opcode = ResolveName(OpcodeName)) { - Result.push_back(Opcode); - continue; - } - // Not a known opcode name; should be an opcode name range. - size_t DotDotPos = OpcodeName.find(".."); - if (DotDotPos == StringRef::npos) { - ExitWithError(Twine("unknown opcode ").concat(OpcodeName)); - } - StringRef BeginOpcodeName = OpcodeName.substr(0, DotDotPos); - unsigned BeginOpcode = - BeginOpcodeName.empty() ? 1 : ResolveName(BeginOpcodeName); - if (BeginOpcode == 0) { - ExitWithError(Twine("unknown opcode ").concat(BeginOpcodeName)); - } - StringRef EndOpcodeName = OpcodeName.substr(DotDotPos + 2); - unsigned EndOpcode = EndOpcodeName.empty() - ? State.getInstrInfo().getNumOpcodes() - 1 - : ResolveName(EndOpcodeName); - if (EndOpcode == 0) { - ExitWithError(Twine("unknown opcode ").concat(EndOpcodeName)); - } - for (unsigned I = BeginOpcode; I <= EndOpcode; ++I) { - if (!isIgnoredOpcode(State, I)) - Result.push_back(I); + for (const std::pair &OpcodeName : OpcodeNames) { + if (OpcodeName.first == OpcodeName.second) { + if (unsigned Opcode = ResolveName(OpcodeName.first)) { + Result.push_back(Opcode); + continue; + } else { + ExitWithError(Twine("unknown opcode ").concat(OpcodeName.first)); + } + } else { + StringRef BeginOpcodeName = OpcodeName.first; + unsigned BeginOpcode = + BeginOpcodeName.empty() ? 1 : ResolveName(BeginOpcodeName); + if (BeginOpcode == 0) { + ExitWithError(Twine("unknown opcode ").concat(BeginOpcodeName)); + } + StringRef EndOpcodeName = OpcodeName.second; + unsigned EndOpcode = EndOpcodeName.empty() + ? State.getInstrInfo().getNumOpcodes() - 1 + : ResolveName(EndOpcodeName); + if (EndOpcode == 0) { + ExitWithError(Twine("unknown opcode ").concat(EndOpcodeName)); + } + for (unsigned I = BeginOpcode; I <= EndOpcode; ++I) { + if (!isIgnoredOpcode(State, I)) + Result.push_back(I); + } } } return Result; diff --git a/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel b/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel index b3c7108d840d3..d3447b62bb239 100644 --- a/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel @@ -2262,6 +2262,7 @@ llvm_target_lib_list = [lib for lib in [ ("-gen-register-info", "lib/Target/RISCV/RISCVGenRegisterInfo.inc"), ("-gen-subtarget", "lib/Target/RISCV/RISCVGenSubtargetInfo.inc"), ("-gen-searchable-tables", "lib/Target/RISCV/RISCVGenSearchableTables.inc"), + ("-gen-exegesis", "lib/Target/RISCV/RISCVGenExegesis.inc"), ], "tbl_deps": [ ":riscv_isel_target_gen", From 84db7ebf5b94ce0a04ad093bb93707e199cf5f22 Mon Sep 17 00:00:00 2001 From: Anastasiya Chernikova Date: Thu, 13 Jun 2024 17:32:29 +0300 Subject: [PATCH 08/33] Addressing review comments --- llvm/tools/llvm-exegesis/lib/Mips/Target.cpp | 1 + .../llvm-exegesis/lib/RISCV/RISCVCounters.cpp | 20 ++++++++++++++++--- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/llvm/tools/llvm-exegesis/lib/Mips/Target.cpp b/llvm/tools/llvm-exegesis/lib/Mips/Target.cpp index 6231c971fadb9..731e037c240df 100644 --- a/llvm/tools/llvm-exegesis/lib/Mips/Target.cpp +++ b/llvm/tools/llvm-exegesis/lib/Mips/Target.cpp @@ -62,6 +62,7 @@ class ExegesisMipsTarget : public ExegesisTarget { unsigned getMaxMemoryAccessSize() const override { return 64; } void fillMemoryOperands(InstructionTemplate &IT, unsigned Reg, unsigned Offset) const override; + std::vector setRegTo(const MCSubtargetInfo &STI, unsigned Reg, const APInt &Value) const override; bool matchesArch(Triple::ArchType Arch) const override { diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp b/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp index a9d207fa3d157..02a459ad56f6c 100644 --- a/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp +++ b/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp @@ -20,9 +20,23 @@ namespace exegesis { inline uint64_t getRISCVCpuCyclesCount() { #ifdef __riscv - uint64_t Counter; - asm("csrr %0, cycle" : "=r"(Counter)::"memory"); - return Counter; +#if __riscv_xlen == 32 + uint32_t cycles_lo, cycles_hi0, cycles_hi1; + asm volatile("rdtimeh %0\n" + "rdtime %1\n" + "rdtimeh %2\n" + "sub %0, %0, %2\n" + "seqz %0, %0\n" + "sub %0, zero, %0\n" + "and %1, %1, %0\n" + : "=r"(cycles_hi0), "=r"(cycles_lo), "=r"(cycles_hi1)); + return static_cast((static_cast(cycles_hi1) << 32) | + cycles_lo); +#else + uint64_t cycles; + asm volatile("rdtime %0" : "=r"(cycles)); + return static_cast(cycles); +#endif #else return 0; #endif From 99bccddd8e6a84f6521918e957d46c3a1f13a9e5 Mon Sep 17 00:00:00 2001 From: Anastasiya Chernikova Date: Tue, 18 Jun 2024 19:23:55 +0300 Subject: [PATCH 09/33] Addressing review comments --- llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp b/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp index 02a459ad56f6c..9d094f9494f4c 100644 --- a/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp +++ b/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp @@ -22,9 +22,9 @@ inline uint64_t getRISCVCpuCyclesCount() { #ifdef __riscv #if __riscv_xlen == 32 uint32_t cycles_lo, cycles_hi0, cycles_hi1; - asm volatile("rdtimeh %0\n" - "rdtime %1\n" - "rdtimeh %2\n" + asm volatile("rdcycleh %0\n" + "rdcycle %1\n" + "rdcycleh %2\n" "sub %0, %0, %2\n" "seqz %0, %0\n" "sub %0, zero, %0\n" @@ -34,7 +34,7 @@ inline uint64_t getRISCVCpuCyclesCount() { cycles_lo); #else uint64_t cycles; - asm volatile("rdtime %0" : "=r"(cycles)); + asm volatile("rdcycle %0" : "=r"(cycles)); return static_cast(cycles); #endif #else From 9352f6dbba0901146c1098d458d0bf048ae00381 Mon Sep 17 00:00:00 2001 From: Anastasiya Chernikova Date: Fri, 28 Jun 2024 16:12:20 +0300 Subject: [PATCH 10/33] Addressing review comments --- llvm/tools/llvm-exegesis/lib/RISCV/CMakeLists.txt | 1 + llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp | 10 +++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/CMakeLists.txt b/llvm/tools/llvm-exegesis/lib/RISCV/CMakeLists.txt index ea0ced1786a0c..78eec178a456a 100644 --- a/llvm/tools/llvm-exegesis/lib/RISCV/CMakeLists.txt +++ b/llvm/tools/llvm-exegesis/lib/RISCV/CMakeLists.txt @@ -4,6 +4,7 @@ include_directories( ) set(LLVM_LINK_COMPONENTS + CodeGen RISCV Exegesis Core diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp b/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp index 9d094f9494f4c..48e619c762eb4 100644 --- a/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp +++ b/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp @@ -11,6 +11,8 @@ //===----------------------------------------------------------------------===// #include "RISCVCounters.h" +#include +#include namespace llvm { namespace exegesis { @@ -19,7 +21,13 @@ namespace exegesis { // and provides manual implementation of performance counters. inline uint64_t getRISCVCpuCyclesCount() { -#ifdef __riscv +#if defined(__riscv) && defined(__linux__) + uint32_t Cycle; + size_t Length = sizeof(Cycle); + if (!sysctlbyname("kernel.perf_user_access", &Cycle, &Length, NULL, 0) || + Cycle != 1) + report_fatal_error( + "Please write 'sudo echo 1 > /proc/sys/kernel/perf_user_access'"); #if __riscv_xlen == 32 uint32_t cycles_lo, cycles_hi0, cycles_hi1; asm volatile("rdcycleh %0\n" From d52ddc85ddf31767d9adfe6ba71c5408d3768561 Mon Sep 17 00:00:00 2001 From: Anastasiya Chernikova Date: Fri, 28 Jun 2024 16:56:13 +0300 Subject: [PATCH 11/33] Addressing review comments --- .../llvm-exegesis/lib/RISCV/RISCVCounters.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp b/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp index 48e619c762eb4..bcda7da2721fe 100644 --- a/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp +++ b/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp @@ -22,12 +22,6 @@ namespace exegesis { inline uint64_t getRISCVCpuCyclesCount() { #if defined(__riscv) && defined(__linux__) - uint32_t Cycle; - size_t Length = sizeof(Cycle); - if (!sysctlbyname("kernel.perf_user_access", &Cycle, &Length, NULL, 0) || - Cycle != 1) - report_fatal_error( - "Please write 'sudo echo 1 > /proc/sys/kernel/perf_user_access'"); #if __riscv_xlen == 32 uint32_t cycles_lo, cycles_hi0, cycles_hi1; asm volatile("rdcycleh %0\n" @@ -68,6 +62,14 @@ class RISCVCpuCyclesCounter : public pfm::CounterGroup { RISCVCpuCyclesCounter::RISCVCpuCyclesCounter(pfm::PerfEvent &&Event) : CounterGroup(std::move(Event), {}) { + #if defined(__riscv) && defined(__linux__) + uint32_t Cycle; + size_t Length = sizeof(Cycle); + if (!sysctlbyname("kernel.perf_user_access", &Cycle, &Length, NULL, 0) || + Cycle != 1) + report_fatal_error( + "Please write 'sudo echo 1 > /proc/sys/kernel/perf_user_access'"); + #endif StartValue = getRISCVCpuCyclesCount(); EndValue = getRISCVCpuCyclesCount(); MeasurementCycles = EndValue - StartValue; From 49cd4633de1625132c281a70aecdd2569c382a3c Mon Sep 17 00:00:00 2001 From: Anastasiya Chernikova Date: Wed, 10 Jul 2024 14:15:51 +0300 Subject: [PATCH 12/33] Addressing review comments --- .../llvm-exegesis/lib/RISCV/RISCVCounters.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp b/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp index bcda7da2721fe..57c311bb967b1 100644 --- a/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp +++ b/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp @@ -11,8 +11,6 @@ //===----------------------------------------------------------------------===// #include "RISCVCounters.h" -#include -#include namespace llvm { namespace exegesis { @@ -63,12 +61,16 @@ class RISCVCpuCyclesCounter : public pfm::CounterGroup { RISCVCpuCyclesCounter::RISCVCpuCyclesCounter(pfm::PerfEvent &&Event) : CounterGroup(std::move(Event), {}) { #if defined(__riscv) && defined(__linux__) - uint32_t Cycle; - size_t Length = sizeof(Cycle); - if (!sysctlbyname("kernel.perf_user_access", &Cycle, &Length, NULL, 0) || - Cycle != 1) + char Value[2] = "0"; + int File = 0; + std::error_code FileError = sys::fs::openFileForRead("/proc/sys/kernel/watchdog", File); + sys::fs::file_t FileNative = sys::fs::convertFDToNativeFile(File); + Expected ReadBytes = sys::fs::readNativeFile(FileNative, Value); + + if (FileError || !ReadBytes || strcmp(Value, "1") != 0) { report_fatal_error( "Please write 'sudo echo 1 > /proc/sys/kernel/perf_user_access'"); + } #endif StartValue = getRISCVCpuCyclesCount(); EndValue = getRISCVCpuCyclesCount(); From 4004b8a348c4e45c6d56f246238f19f3658f30a6 Mon Sep 17 00:00:00 2001 From: Anastasiya Chernikova Date: Wed, 10 Jul 2024 14:24:30 +0300 Subject: [PATCH 13/33] Fix code format --- llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp b/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp index 57c311bb967b1..6851c1037a461 100644 --- a/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp +++ b/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp @@ -60,10 +60,11 @@ class RISCVCpuCyclesCounter : public pfm::CounterGroup { RISCVCpuCyclesCounter::RISCVCpuCyclesCounter(pfm::PerfEvent &&Event) : CounterGroup(std::move(Event), {}) { - #if defined(__riscv) && defined(__linux__) +#if defined(__riscv) && defined(__linux__) char Value[2] = "0"; int File = 0; - std::error_code FileError = sys::fs::openFileForRead("/proc/sys/kernel/watchdog", File); + std::error_code FileError = + sys::fs::openFileForRead("/proc/sys/kernel/watchdog", File); sys::fs::file_t FileNative = sys::fs::convertFDToNativeFile(File); Expected ReadBytes = sys::fs::readNativeFile(FileNative, Value); @@ -71,7 +72,7 @@ RISCVCpuCyclesCounter::RISCVCpuCyclesCounter(pfm::PerfEvent &&Event) report_fatal_error( "Please write 'sudo echo 1 > /proc/sys/kernel/perf_user_access'"); } - #endif +#endif StartValue = getRISCVCpuCyclesCount(); EndValue = getRISCVCpuCyclesCount(); MeasurementCycles = EndValue - StartValue; From 5c2b1adbda6e79c22dc08be7a727a5aad6eaa02f Mon Sep 17 00:00:00 2001 From: Anastasiya Chernikova Date: Wed, 10 Jul 2024 17:35:08 +0300 Subject: [PATCH 14/33] Addressing review comments --- llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp b/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp index 6851c1037a461..3ca8d742c85ed 100644 --- a/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp +++ b/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp @@ -64,7 +64,7 @@ RISCVCpuCyclesCounter::RISCVCpuCyclesCounter(pfm::PerfEvent &&Event) char Value[2] = "0"; int File = 0; std::error_code FileError = - sys::fs::openFileForRead("/proc/sys/kernel/watchdog", File); + sys::fs::openFileForRead("/proc/sys/kernel/perf_user_access", File); sys::fs::file_t FileNative = sys::fs::convertFDToNativeFile(File); Expected ReadBytes = sys::fs::readNativeFile(FileNative, Value); From 321f0499c2166d2d4fc8d45f5365f3f0d1bd3a80 Mon Sep 17 00:00:00 2001 From: Anastasiya Chernikova Date: Wed, 17 Jul 2024 15:03:13 +0300 Subject: [PATCH 15/33] Addressing review comments --- .../llvm-exegesis/lib/RISCV/RISCVCounters.cpp | 18 ++++++++---------- llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp | 2 +- .../lib/SerialSnippetGenerator.cpp | 2 +- llvm/tools/llvm-exegesis/lib/Target.h | 2 +- 4 files changed, 11 insertions(+), 13 deletions(-) diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp b/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp index 3ca8d742c85ed..8688343036483 100644 --- a/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp +++ b/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp @@ -21,17 +21,15 @@ namespace exegesis { inline uint64_t getRISCVCpuCyclesCount() { #if defined(__riscv) && defined(__linux__) #if __riscv_xlen == 32 - uint32_t cycles_lo, cycles_hi0, cycles_hi1; - asm volatile("rdcycleh %0\n" - "rdcycle %1\n" + uint32_t cycles_x3, cycles_x2, cycles_x4; + asm volatile("again:\n" + "rdcycleh %1\n" + "rdcycle %0\n" "rdcycleh %2\n" - "sub %0, %0, %2\n" - "seqz %0, %0\n" - "sub %0, zero, %0\n" - "and %1, %1, %0\n" - : "=r"(cycles_hi0), "=r"(cycles_lo), "=r"(cycles_hi1)); - return static_cast((static_cast(cycles_hi1) << 32) | - cycles_lo); + "bne %1, %2, again\n" + : "=r"(cycles_x2), "=r"(cycles_x3), "=r"(cycles_x4)); + return static_cast((static_cast(cycles_x3) << 32) | + cycles_x2); #else uint64_t cycles; asm volatile("rdcycle %0" : "=r"(cycles)); diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp index 84634db285ba6..71eda40ff2e60 100644 --- a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp +++ b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp @@ -103,7 +103,7 @@ bool ExegesisRISCVTarget::checkOpcodeSupported( FeatureBitset RequiredFeatures = RISCV_MC::computeRequiredFeatures(Opcode); FeatureBitset MissingFeatures = (AvailableFeatures & RequiredFeatures) ^ RequiredFeatures; - return MissingFeatures.none(); + return !(MissingFeatures.none()); } #define GET_REGISTER_MATCHER diff --git a/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp b/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp index 1f1e3983d3014..ffceb6ac82fac 100644 --- a/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp +++ b/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp @@ -52,7 +52,7 @@ computeAliasingInstructions(const LLVMState &State, const Instruction *Instr, continue; if (OtherOpcode == Instr->Description.getOpcode()) continue; - if (!State.getExegesisTarget().checkOpcodeSupported( + if (State.getExegesisTarget().checkOpcodeSupported( OtherOpcode, State.getSubtargetInfo())) continue; const Instruction &OtherInstr = State.getIC().getInstr(OtherOpcode); diff --git a/llvm/tools/llvm-exegesis/lib/Target.h b/llvm/tools/llvm-exegesis/lib/Target.h index f4edec300e440..1dcef5e51f4e5 100644 --- a/llvm/tools/llvm-exegesis/lib/Target.h +++ b/llvm/tools/llvm-exegesis/lib/Target.h @@ -88,7 +88,7 @@ class ExegesisTarget { virtual bool checkOpcodeSupported(int Opcode, const MCSubtargetInfo &SI) const { - return true; + return false; } // Find register by name, NoRegister if not found. From 78d6a0e9da5f83421ff14ebcce76de793cd7e7e2 Mon Sep 17 00:00:00 2001 From: Anastasiya Chernikova Date: Wed, 17 Jul 2024 18:53:28 +0300 Subject: [PATCH 16/33] Addressing review comments --- llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp | 5 ++--- llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp index 71eda40ff2e60..dcc4895e077f7 100644 --- a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp +++ b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp @@ -101,9 +101,8 @@ bool ExegesisRISCVTarget::checkOpcodeSupported( FeatureBitset AvailableFeatures = RISCV_MC::computeAvailableFeatures(Features); FeatureBitset RequiredFeatures = RISCV_MC::computeRequiredFeatures(Opcode); - FeatureBitset MissingFeatures = - (AvailableFeatures & RequiredFeatures) ^ RequiredFeatures; - return !(MissingFeatures.none()); + FeatureBitset MissingFeatures = RequiredFeatures & ~AvailableFeatures; + return MissingFeatures.none(); } #define GET_REGISTER_MATCHER diff --git a/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp b/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp index ffceb6ac82fac..1f1e3983d3014 100644 --- a/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp +++ b/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp @@ -52,7 +52,7 @@ computeAliasingInstructions(const LLVMState &State, const Instruction *Instr, continue; if (OtherOpcode == Instr->Description.getOpcode()) continue; - if (State.getExegesisTarget().checkOpcodeSupported( + if (!State.getExegesisTarget().checkOpcodeSupported( OtherOpcode, State.getSubtargetInfo())) continue; const Instruction &OtherInstr = State.getIC().getInstr(OtherOpcode); From a650063a1ae8ca35c473d1d50d6ca2cc3bac5f7e Mon Sep 17 00:00:00 2001 From: Anastasiya Chernikova Date: Fri, 19 Jul 2024 15:33:27 +0300 Subject: [PATCH 17/33] Addressing review comments --- llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp b/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp index 1f1e3983d3014..ffceb6ac82fac 100644 --- a/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp +++ b/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp @@ -52,7 +52,7 @@ computeAliasingInstructions(const LLVMState &State, const Instruction *Instr, continue; if (OtherOpcode == Instr->Description.getOpcode()) continue; - if (!State.getExegesisTarget().checkOpcodeSupported( + if (State.getExegesisTarget().checkOpcodeSupported( OtherOpcode, State.getSubtargetInfo())) continue; const Instruction &OtherInstr = State.getIC().getInstr(OtherOpcode); From f35809bfe73b8e67ed7ebdb7ab93ef2afc988f9c Mon Sep 17 00:00:00 2001 From: Dmitry Bushev Date: Fri, 16 Aug 2024 15:45:32 +0300 Subject: [PATCH 18/33] Remove performance counters initial support --- llvm/lib/Target/RISCV/CMakeLists.txt | 1 - llvm/lib/Target/RISCV/RISCV.td | 6 -- llvm/lib/Target/RISCV/RISCVInstrInfo.td | 4 +- llvm/lib/Target/RISCV/RISCVPfmCounters.td | 18 ---- .../llvm-exegesis/lib/RISCV/CMakeLists.txt | 1 - .../llvm-exegesis/lib/RISCV/RISCVCounters.cpp | 98 ------------------- .../llvm-exegesis/lib/RISCV/RISCVCounters.h | 31 ------ llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp | 31 ++---- .../llvm-project-overlay/llvm/BUILD.bazel | 1 - 9 files changed, 8 insertions(+), 183 deletions(-) delete mode 100644 llvm/lib/Target/RISCV/RISCVPfmCounters.td delete mode 100644 llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp delete mode 100644 llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.h diff --git a/llvm/lib/Target/RISCV/CMakeLists.txt b/llvm/lib/Target/RISCV/CMakeLists.txt index 4727e0ca22428..fd049d1a57860 100644 --- a/llvm/lib/Target/RISCV/CMakeLists.txt +++ b/llvm/lib/Target/RISCV/CMakeLists.txt @@ -15,7 +15,6 @@ tablegen(LLVM RISCVGenRegisterBank.inc -gen-register-bank) tablegen(LLVM RISCVGenRegisterInfo.inc -gen-register-info) tablegen(LLVM RISCVGenSearchableTables.inc -gen-searchable-tables) tablegen(LLVM RISCVGenSubtargetInfo.inc -gen-subtarget) -tablegen(LLVM RISCVGenExegesis.inc -gen-exegesis) set(LLVM_TARGET_DEFINITIONS RISCVGISel.td) tablegen(LLVM RISCVGenGlobalISel.inc -gen-global-isel) diff --git a/llvm/lib/Target/RISCV/RISCV.td b/llvm/lib/Target/RISCV/RISCV.td index 38086e8efe340..00c3d702e12a2 100644 --- a/llvm/lib/Target/RISCV/RISCV.td +++ b/llvm/lib/Target/RISCV/RISCV.td @@ -84,9 +84,3 @@ def RISCV : Target { let AssemblyWriters = [RISCVAsmWriter]; let AllowRegisterRenaming = 1; } - -//===----------------------------------------------------------------------===// -// Pfm Counters -//===----------------------------------------------------------------------===// - -include "RISCVPfmCounters.td" diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td index e558d3e15a7a0..5747f05ffafd4 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td @@ -524,7 +524,7 @@ class BranchCC_rri funct3, string opcodestr> let isTerminator = 1; } -let hasSideEffects = 0, mayLoad = 1, mayStore = 0, UseNamedOperandTable = 1 in { +let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in { class Load_ri funct3, string opcodestr, DAGOperand rty = GPR> : RVInstI; @@ -539,7 +539,7 @@ class HLoad_r 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, UseNamedOperandTable = 1 in { +let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in { class Store_rri funct3, string opcodestr, DAGOperand rty = GPR> : RVInstS; - -def DefaultPfmCounters : ProcPfmCounters { - let CycleCounter = CpuCyclesPfmCounter; -} -def : PfmCountersDefaultBinding; diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/CMakeLists.txt b/llvm/tools/llvm-exegesis/lib/RISCV/CMakeLists.txt index 78eec178a456a..489ac6d6e34b3 100644 --- a/llvm/tools/llvm-exegesis/lib/RISCV/CMakeLists.txt +++ b/llvm/tools/llvm-exegesis/lib/RISCV/CMakeLists.txt @@ -15,7 +15,6 @@ add_llvm_library(LLVMExegesisRISCV DISABLE_LLVM_LINK_LLVM_DYLIB STATIC Target.cpp - RISCVCounters.cpp DEPENDS intrinsics_gen diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp b/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp deleted file mode 100644 index 8688343036483..0000000000000 --- a/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp +++ /dev/null @@ -1,98 +0,0 @@ -//===-- RISCVCounters.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 -// -//===----------------------------------------------------------------------===// -// -// This file defines RISC-V perf counters. -// -//===----------------------------------------------------------------------===// - -#include "RISCVCounters.h" - -namespace llvm { -namespace exegesis { - -// This implementation of RISCV target for Exegesis doesn't use libpfm -// and provides manual implementation of performance counters. - -inline uint64_t getRISCVCpuCyclesCount() { -#if defined(__riscv) && defined(__linux__) -#if __riscv_xlen == 32 - uint32_t cycles_x3, cycles_x2, cycles_x4; - asm volatile("again:\n" - "rdcycleh %1\n" - "rdcycle %0\n" - "rdcycleh %2\n" - "bne %1, %2, again\n" - : "=r"(cycles_x2), "=r"(cycles_x3), "=r"(cycles_x4)); - return static_cast((static_cast(cycles_x3) << 32) | - cycles_x2); -#else - uint64_t cycles; - asm volatile("rdcycle %0" : "=r"(cycles)); - return static_cast(cycles); -#endif -#else - return 0; -#endif -} - -class RISCVCpuCyclesCounter : public pfm::CounterGroup { - uint64_t StartValue; - uint64_t EndValue; - uint64_t MeasurementCycles; - -public: - explicit RISCVCpuCyclesCounter(pfm::PerfEvent &&Event); - - void start() override { StartValue = getRISCVCpuCyclesCount(); } - - void stop() override { EndValue = getRISCVCpuCyclesCount(); } - - Expected> - readOrError(StringRef FunctionBytes) const override; -}; - -RISCVCpuCyclesCounter::RISCVCpuCyclesCounter(pfm::PerfEvent &&Event) - : CounterGroup(std::move(Event), {}) { -#if defined(__riscv) && defined(__linux__) - char Value[2] = "0"; - int File = 0; - std::error_code FileError = - sys::fs::openFileForRead("/proc/sys/kernel/perf_user_access", File); - sys::fs::file_t FileNative = sys::fs::convertFDToNativeFile(File); - Expected ReadBytes = sys::fs::readNativeFile(FileNative, Value); - - if (FileError || !ReadBytes || strcmp(Value, "1") != 0) { - report_fatal_error( - "Please write 'sudo echo 1 > /proc/sys/kernel/perf_user_access'"); - } -#endif - StartValue = getRISCVCpuCyclesCount(); - EndValue = getRISCVCpuCyclesCount(); - MeasurementCycles = EndValue - StartValue; - // If values of two calls CpuCyclesCounters don`t differ - // it means that counters don`t configured properly, report error. - // MeasurementCycles the smallest interval between two counter calls. - if (MeasurementCycles == 0) { - report_fatal_error("MeasurementCycles == 0, " - "performance counters are not configured."); - } - StartValue = EndValue = 0; -} - -Expected> -RISCVCpuCyclesCounter::readOrError(StringRef FunctionBytes) const { - uint64_t Counter = EndValue - StartValue - MeasurementCycles; - return SmallVector({static_cast(Counter)}); -} -std::unique_ptr -createRISCVCpuCyclesCounter(pfm::PerfEvent &&Event) { - return std::make_unique(std::move(Event)); -} - -} // namespace exegesis -} // namespace llvm diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.h b/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.h deleted file mode 100644 index 203f6af76aaaf..0000000000000 --- a/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.h +++ /dev/null @@ -1,31 +0,0 @@ -//===-- RISCVCounters.h -----------------------------------------*- 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 -// -//===----------------------------------------------------------------------===// -/// -/// \file -/// RISC-V perf counters. -/// -/// More info at: https://lwn.net/Articles/680985 -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TOOLS_LLVM_EXEGESIS_LIB_RISCV_RISCVCOUNTERS_H -#define LLVM_TOOLS_LLVM_EXEGESIS_LIB_RISCV_RISCVCOUNTERS_H - -#include "../PerfHelper.h" -#include "../Target.h" -#include - -namespace llvm { -namespace exegesis { - -std::unique_ptr -createRISCVCpuCyclesCounter(pfm::PerfEvent &&Event); - -} // namespace exegesis -} // namespace llvm - -#endif // LLVM_TOOLS_LLVM_EXEGESIS_LIB_RISCV_RISCVCOUNTERS_H diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp index dcc4895e077f7..fc6a1e945c67b 100644 --- a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp +++ b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp @@ -8,8 +8,6 @@ #include "../Target.h" -#include "RISCVCounters.h" - #include "MCTargetDesc/RISCVBaseInfo.h" #include "MCTargetDesc/RISCVMCTargetDesc.h" #include "MCTargetDesc/RISCVMatInt.h" @@ -31,17 +29,10 @@ namespace exegesis { namespace { -#include "RISCVGenExegesis.inc" - class ExegesisRISCVTarget : public ExegesisTarget { public: ExegesisRISCVTarget(); - Expected> - createCounter(StringRef CounterName, const LLVMState &State, - ArrayRef ValidationCounters, - const pid_t ProcessID) const override; - bool checkOpcodeSupported(int Opcode, const MCSubtargetInfo &SI) const override; @@ -81,19 +72,8 @@ class ExegesisRISCVTarget : public ExegesisTarget { }; ExegesisRISCVTarget::ExegesisRISCVTarget() - : ExegesisTarget(RISCVCpuPfmCounters, RISCV_MC::isOpcodeAvailable) {} - -Expected> ExegesisRISCVTarget::createCounter( - StringRef CounterName, const LLVMState &State, - ArrayRef ValidationCounters, const pid_t ProcessID) const { - if (CounterName == RISCVPfmCounterNames[0]) { - // TODO add support for Linux perf counters - return createRISCVCpuCyclesCounter(pfm::PerfEvent(CounterName)); - } - return make_error(Twine("Unsupported performance counter '") - .concat(CounterName) - .concat("'")); -} + : ExegesisTarget(ArrayRef{}, + RISCV_MC::isOpcodeAvailable) {} bool ExegesisRISCVTarget::checkOpcodeSupported( int Opcode, const MCSubtargetInfo &SI) const { @@ -135,11 +115,12 @@ static std::vector loadIntReg(const MCSubtargetInfo &STI, unsigned Reg, for (const RISCVMatInt::Inst &Inst : InstSeq) { switch (Inst.getOpndKind()) { case RISCVMatInt::Imm: - MatIntInstrs.push_back( - MCInstBuilder(RISCV::LUI).addReg(DestReg).addImm(Inst.getImm())); + MatIntInstrs.push_back(MCInstBuilder(Inst.getOpcode()) + .addReg(DestReg) + .addImm(Inst.getImm())); break; case RISCVMatInt::RegX0: - MatIntInstrs.push_back(MCInstBuilder(RISCV::ADD_UW) + MatIntInstrs.push_back(MCInstBuilder(Inst.getOpcode()) .addReg(DestReg) .addReg(SrcReg) .addReg(RISCV::X0)); diff --git a/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel b/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel index d3447b62bb239..b3c7108d840d3 100644 --- a/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel @@ -2262,7 +2262,6 @@ llvm_target_lib_list = [lib for lib in [ ("-gen-register-info", "lib/Target/RISCV/RISCVGenRegisterInfo.inc"), ("-gen-subtarget", "lib/Target/RISCV/RISCVGenSubtargetInfo.inc"), ("-gen-searchable-tables", "lib/Target/RISCV/RISCVGenSearchableTables.inc"), - ("-gen-exegesis", "lib/Target/RISCV/RISCVGenExegesis.inc"), ], "tbl_deps": [ ":riscv_isel_target_gen", From 6b6c0af00b7bea04b9c1830d747cb060ad7ff642 Mon Sep 17 00:00:00 2001 From: Anastasiya Chernikova Date: Fri, 27 Sep 2024 17:32:06 +0300 Subject: [PATCH 19/33] Addressing review comments --- .../test/tools/llvm-exegesis/RISCV/latency-by-load.s | 1 - llvm/tools/llvm-exegesis/lib/MCInstrDescView.cpp | 12 ++++++------ llvm/tools/llvm-exegesis/lib/MCInstrDescView.h | 4 ++-- llvm/tools/llvm-exegesis/lib/PerfHelper.h | 2 +- 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/llvm/test/tools/llvm-exegesis/RISCV/latency-by-load.s b/llvm/test/tools/llvm-exegesis/RISCV/latency-by-load.s index ba985e231e5ce..c73c0155ddfa2 100644 --- a/llvm/test/tools/llvm-exegesis/RISCV/latency-by-load.s +++ b/llvm/test/tools/llvm-exegesis/RISCV/latency-by-load.s @@ -42,7 +42,6 @@ LBU-NEXT: - 'LBU X10 X10 i_0x0' LUI: LUI: No strategy found to make the execution serial - # RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=LB | FileCheck --check-prefix=LB %s LB: --- diff --git a/llvm/tools/llvm-exegesis/lib/MCInstrDescView.cpp b/llvm/tools/llvm-exegesis/lib/MCInstrDescView.cpp index f9b3666d36f78..c9225e51213e5 100644 --- a/llvm/tools/llvm-exegesis/lib/MCInstrDescView.cpp +++ b/llvm/tools/llvm-exegesis/lib/MCInstrDescView.cpp @@ -96,11 +96,11 @@ Instruction::Instruction(const MCInstrDesc *Description, StringRef Name, const BitVector *ImplUseRegs, const BitVector *AllDefRegs, const BitVector *AllUseRegs, - const BitVector *NotMemoryRegs) + const BitVector *NonMemoryRegs) : Description(*Description), Name(Name), Operands(std::move(Operands)), Variables(std::move(Variables)), ImplDefRegs(*ImplDefRegs), ImplUseRegs(*ImplUseRegs), AllDefRegs(*AllDefRegs), - AllUseRegs(*AllUseRegs), NotMemoryRegs(*NotMemoryRegs) {} + AllUseRegs(*AllUseRegs), NonMemoryRegs(*NonMemoryRegs) {} std::unique_ptr Instruction::create(const MCInstrInfo &InstrInfo, @@ -167,7 +167,7 @@ Instruction::create(const MCInstrInfo &InstrInfo, BitVector ImplUseRegs = RATC.emptyRegisters(); BitVector AllDefRegs = RATC.emptyRegisters(); BitVector AllUseRegs = RATC.emptyRegisters(); - BitVector NotMemoryRegs = RATC.emptyRegisters(); + BitVector NonMemoryRegs = RATC.emptyRegisters(); for (const auto &Op : Operands) { if (Op.isReg()) { @@ -181,7 +181,7 @@ Instruction::create(const MCInstrInfo &InstrInfo, if (Op.isUse() && Op.isImplicit()) ImplUseRegs |= AliasingBits; if (Op.isUse() && !Op.isMemory()) - NotMemoryRegs |= AliasingBits; + NonMemoryRegs |= AliasingBits; } } // Can't use make_unique because constructor is private. @@ -191,7 +191,7 @@ Instruction::create(const MCInstrInfo &InstrInfo, BVC.getUnique(std::move(ImplUseRegs)), BVC.getUnique(std::move(AllDefRegs)), BVC.getUnique(std::move(AllUseRegs)), - BVC.getUnique(std::move(NotMemoryRegs)))); + BVC.getUnique(std::move(NonMemoryRegs)))); } const Operand &Instruction::getPrimaryOperand(const Variable &Var) const { @@ -248,7 +248,7 @@ bool Instruction::hasAliasingRegisters( bool Instruction::hasAliasingNotMemoryRegisters( const BitVector &ForbiddenRegisters) const { - return anyCommonExcludingForbidden(AllDefRegs, NotMemoryRegs, + return anyCommonExcludingForbidden(AllDefRegs, NonMemoryRegs, ForbiddenRegisters); } diff --git a/llvm/tools/llvm-exegesis/lib/MCInstrDescView.h b/llvm/tools/llvm-exegesis/lib/MCInstrDescView.h index c6f47a438ad49..d7712e21c32c1 100644 --- a/llvm/tools/llvm-exegesis/lib/MCInstrDescView.h +++ b/llvm/tools/llvm-exegesis/lib/MCInstrDescView.h @@ -167,14 +167,14 @@ struct Instruction { const BitVector &AllDefRegs; // The set of all aliased def registers. const BitVector &AllUseRegs; // The set of all aliased use registers. // The set of all aliased not memory use registers. - const BitVector &NotMemoryRegs; + const BitVector &NonMemoryRegs; private: Instruction(const MCInstrDesc *Description, StringRef Name, SmallVector Operands, SmallVector Variables, const BitVector *ImplDefRegs, const BitVector *ImplUseRegs, const BitVector *AllDefRegs, - const BitVector *AllUseRegs, const BitVector *NotMemoryRegs); + const BitVector *AllUseRegs, const BitVector *NonMemoryRegs); }; // Instructions are expensive to instantiate. This class provides a cache of diff --git a/llvm/tools/llvm-exegesis/lib/PerfHelper.h b/llvm/tools/llvm-exegesis/lib/PerfHelper.h index 1e0fca7380863..4a825b293b716 100644 --- a/llvm/tools/llvm-exegesis/lib/PerfHelper.h +++ b/llvm/tools/llvm-exegesis/lib/PerfHelper.h @@ -119,7 +119,7 @@ class CounterGroup { virtual void start(); /// Stops the measurement of the event. - virtual void stop(); + void stop(); /// Returns the current value of the counter or error if it cannot be read. /// FunctionBytes: The benchmark function being executed. From c4244038d3cf53568bb49d33fead0277f4666fae Mon Sep 17 00:00:00 2001 From: Anastasiya Chernikova Date: Mon, 7 Oct 2024 18:16:26 +0300 Subject: [PATCH 20/33] Fix code format --- llvm/tools/llvm-exegesis/lib/SnippetFile.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/llvm/tools/llvm-exegesis/lib/SnippetFile.cpp b/llvm/tools/llvm-exegesis/lib/SnippetFile.cpp index f38b233a95d4a..8534637626f7d 100644 --- a/llvm/tools/llvm-exegesis/lib/SnippetFile.cpp +++ b/llvm/tools/llvm-exegesis/lib/SnippetFile.cpp @@ -37,11 +37,10 @@ namespace { // An MCStreamer that reads a BenchmarkCode definition from a file. class BenchmarkCodeStreamer : public MCStreamer, public AsmCommentConsumer { public: - explicit BenchmarkCodeStreamer( - const ExegesisTarget &Target, MCContext *Context, - const LLVMState &State, BenchmarkCode *Result) - : MCStreamer(*Context), Target(Target), State(State), - Result(Result) {} + explicit BenchmarkCodeStreamer(const ExegesisTarget &Target, + MCContext *Context, const LLVMState &State, + BenchmarkCode *Result) + : MCStreamer(*Context), Target(Target), State(State), Result(Result) {} // Implementation of the MCStreamer interface. We only care about // instructions. void emitInstruction(const MCInst &Instruction, @@ -256,7 +255,8 @@ Expected> readSnippets(const LLVMState &State, TM.getTarget().createMCObjectFileInfo(Context, /*PIC=*/false)); Context.setObjectFileInfo(ObjectFileInfo.get()); Context.initInlineSourceManager(); - BenchmarkCodeStreamer Streamer(State.getExegesisTarget(), &Context, State, &Result); + BenchmarkCodeStreamer Streamer(State.getExegesisTarget(), &Context, State, + &Result); std::string Error; raw_string_ostream ErrorStream(Error); From 68006e5dbc200239f862d2424e887445f368e107 Mon Sep 17 00:00:00 2001 From: Anastasiya Chernikova Date: Tue, 8 Oct 2024 21:47:35 +0300 Subject: [PATCH 21/33] Addressing review comments --- .../lib/SerialSnippetGenerator.cpp | 46 +------------------ llvm/tools/llvm-exegesis/lib/SnippetFile.cpp | 3 -- 2 files changed, 1 insertion(+), 48 deletions(-) diff --git a/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp b/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp index ffceb6ac82fac..08d5cd12f0a6d 100644 --- a/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp +++ b/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp @@ -109,51 +109,7 @@ static void appendCodeTemplates(const LLVMState &State, } case ExecutionMode::SERIAL_VIA_MEMORY_INSTR: { // Select back-to-back memory instruction. - - auto &I = Variant.getInstr(); - if (I.Description.mayLoad()) { - // If instruction is load, we can self-alias it in case when instruction - // overrides whole address register. For that we use provided scratch - // memory. - - // TODO: now it is not checked if load writes the whole register. - - auto DefOpIt = find_if(I.Operands, [](Operand const &op) { - return op.isDef() && op.isReg(); - }); - - if (DefOpIt == I.Operands.end()) - return; - - const Operand &DefOp = *DefOpIt; - auto &ET = State.getExegesisTarget(); - auto ScratchMemoryRegister = ET.getScratchMemoryRegister( - State.getTargetMachine().getTargetTriple()); - auto &RegClass = - State.getTargetMachine().getMCRegisterInfo()->getRegClass( - DefOp.getExplicitOperandInfo().RegClass); - - // Register classes of def operand and memory operand must be the same - // to perform aliasing. - if (!RegClass.contains(ScratchMemoryRegister)) - return; - - ET.fillMemoryOperands(Variant, ScratchMemoryRegister, 0); - Variant.getValueFor(DefOp) = MCOperand::createReg(ScratchMemoryRegister); - - CodeTemplate CT; - CT.Execution = ExecutionModeBit; - if (CT.ScratchSpacePointerInReg == 0) - CT.ScratchSpacePointerInReg = ScratchMemoryRegister; - - CT.Info = std::string(ExecutionClassDescription); - CT.Instructions.push_back(std::move(Variant)); - CT.PreinitScratchMemory.emplace_back(ScratchMemoryRegister, - /* Offset */ 0); - CodeTemplates.push_back(std::move(CT)); - } - - // TODO: implement more cases + // TODO: Implement me. return; } case ExecutionMode::SERIAL_VIA_EXPLICIT_REGS: { diff --git a/llvm/tools/llvm-exegesis/lib/SnippetFile.cpp b/llvm/tools/llvm-exegesis/lib/SnippetFile.cpp index 8534637626f7d..282bc8ca91249 100644 --- a/llvm/tools/llvm-exegesis/lib/SnippetFile.cpp +++ b/llvm/tools/llvm-exegesis/lib/SnippetFile.cpp @@ -208,9 +208,6 @@ class BenchmarkCodeStreamer : public MCStreamer, public AsmCommentConsumer { Align ByteAlignment, SMLoc Loc) override {} unsigned findRegisterByName(const StringRef RegName) const { - // TODO make use of RegNameToRegNo map - if (unsigned Reg = Target.findRegisterByName(RegName)) - return Reg; std::optional RegisterNumber = State.getRegisterNumberFromName(RegName); if (!RegisterNumber.has_value()) { From 2fbe7b923f0313a4d5821e088084de29bbb40419 Mon Sep 17 00:00:00 2001 From: Anastasiya Chernikova Date: Mon, 28 Oct 2024 14:48:20 +0300 Subject: [PATCH 22/33] Fixed consequences of PR https://github.com/llvm/llvm-project/pull/112314. Removed support for load --- .../RISCV/latency-by-extension-C.s | 17 ------ .../llvm-exegesis/RISCV/latency-by-load.s | 59 ------------------- llvm/tools/llvm-exegesis/lib/CodeTemplate.h | 4 -- llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp | 2 +- 4 files changed, 1 insertion(+), 81 deletions(-) delete mode 100644 llvm/test/tools/llvm-exegesis/RISCV/latency-by-load.s diff --git a/llvm/test/tools/llvm-exegesis/RISCV/latency-by-extension-C.s b/llvm/test/tools/llvm-exegesis/RISCV/latency-by-extension-C.s index 00bd79729539f..9e94f024ed116 100644 --- a/llvm/test/tools/llvm-exegesis/RISCV/latency-by-extension-C.s +++ b/llvm/test/tools/llvm-exegesis/RISCV/latency-by-extension-C.s @@ -46,20 +46,3 @@ C_SRLI-NEXT: key: C_SRLI-NEXT: instructions: C_SRLI-NEXT: - 'C_SRLI [[REG101:X[0-9]+]] [[REG102:X[0-9]+]] [[IMM10:i_0x[0-9]+]]' C_SRLI-DAG: ... - - -# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=C_LD -mattr=+c | FileCheck --check-prefix=C_LD %s - -C_LD: --- -C_LD-NEXT: mode: latency -C_LD-NEXT: key: -C_LD-NEXT: instructions: -C_LD-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 --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=C_LW -mattr=+c | FileCheck --check-prefix=C_LW %s - -C_LW: --- -C_LW-NEXT: mode: latency -C_LW-NEXT: key: -C_LW-NEXT: instructions: -C_LW-NEXT: - 'C_LW [[REG71:X[0-9]+]] [[REG72:X[0-9]+]] [[IMM7:i_0x[0-9]+]]' diff --git a/llvm/test/tools/llvm-exegesis/RISCV/latency-by-load.s b/llvm/test/tools/llvm-exegesis/RISCV/latency-by-load.s deleted file mode 100644 index c73c0155ddfa2..0000000000000 --- a/llvm/test/tools/llvm-exegesis/RISCV/latency-by-load.s +++ /dev/null @@ -1,59 +0,0 @@ -# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=LD | FileCheck --check-prefix=LD %s - -LD: --- -LD-NEXT: mode: latency -LD-NEXT: key: -LD-NEXT: instructions: -LD-NEXT: - 'LD X10 X10 i_0x0' - -# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=LW | FileCheck --check-prefix=LW %s - -LW: --- -LW-NEXT: mode: latency -LW-NEXT: key: -LW-NEXT: instructions: -LW-NEXT: - 'LW X10 X10 i_0x0' - -# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=LH | FileCheck --check-prefix=LH %s - -LH: --- -LH-NEXT: mode: latency -LH-NEXT: key: -LH-NEXT: instructions: -LH-NEXT: - 'LH X10 X10 i_0x0' - -# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=LWU | FileCheck --check-prefix=LWU %s - -LWU: --- -LWU-NEXT: mode: latency -LWU-NEXT: key: -LWU-NEXT: instructions: -LWU-NEXT: - 'LWU X10 X10 i_0x0' - -# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=LBU | FileCheck --check-prefix=LBU %s - -LBU: --- -LBU-NEXT: mode: latency -LBU-NEXT: key: -LBU-NEXT: instructions: -LBU-NEXT: - 'LBU X10 X10 i_0x0' - -# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=LUI 2>&1 | FileCheck --check-prefix=LUI %s - -LUI: LUI: No strategy found to make the execution serial - -# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=LB | FileCheck --check-prefix=LB %s - -LB: --- -LB-NEXT: mode: latency -LB-NEXT: key: -LB-NEXT: instructions: -LB-NEXT: - 'LB X10 X10 i_0x0' - -# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=LR_W_RL -mattr="+a" | FileCheck --check-prefix=LR_W_RL %s - -LR_W_RL: --- -LR_W_RL-NEXT: mode: latency -LR_W_RL-NEXT: key: -LR_W_RL-NEXT: instructions: -LR_W_RL-NEXT: - 'LR_W_RL X10 X10' diff --git a/llvm/tools/llvm-exegesis/lib/CodeTemplate.h b/llvm/tools/llvm-exegesis/lib/CodeTemplate.h index 662fd90306a45..f565d3d0f1640 100644 --- a/llvm/tools/llvm-exegesis/lib/CodeTemplate.h +++ b/llvm/tools/llvm-exegesis/lib/CodeTemplate.h @@ -135,10 +135,6 @@ 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, 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: diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp index fc6a1e945c67b..1768a263c52e4 100644 --- a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp +++ b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp @@ -344,7 +344,7 @@ void ExegesisRISCVTarget::processInstructionReservedRegs( case RISCV::C_ADDI4SPN: AssignedValue = MCOperand::createReg(RISCV::X2); break; - case RISCV::C_ADDI_NOP: + case RISCV::C_NOP: case RISCV::C_LI_HINT: case RISCV::C_LUI_HINT: case RISCV::C_MV_HINT: From e4fdd4b28bfee99bba525249c1437e41e2cc58be Mon Sep 17 00:00:00 2001 From: Anastasiya Chernikova Date: Thu, 31 Oct 2024 19:54:12 +0300 Subject: [PATCH 23/33] Addressing review comments --- llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp | 32 ------------------- .../lib/SerialSnippetGenerator.cpp | 3 -- llvm/tools/llvm-exegesis/lib/Target.h | 13 -------- llvm/tools/llvm-exegesis/llvm-exegesis.cpp | 6 ++-- 4 files changed, 3 insertions(+), 51 deletions(-) diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp index 1768a263c52e4..80c025ed3fd27 100644 --- a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp +++ b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp @@ -33,9 +33,6 @@ class ExegesisRISCVTarget : public ExegesisTarget { public: ExegesisRISCVTarget(); - bool checkOpcodeSupported(int Opcode, - const MCSubtargetInfo &SI) const override; - MCRegister findRegisterByName(const StringRef RegName) const override; bool matchesArch(Triple::ArchType Arch) const override; @@ -55,9 +52,6 @@ class ExegesisRISCVTarget : public ExegesisTarget { void fillMemoryOperands(InstructionTemplate &IT, unsigned Reg, unsigned Offset) const override; - virtual std::vector - storeRegValueToScratch(const MCSubtargetInfo &STI, unsigned Reg, - unsigned Offset) const override; ArrayRef getUnavailableRegisters() const override; Error randomizeTargetMCOperand(const Instruction &Instr, const Variable &Var, @@ -75,16 +69,6 @@ ExegesisRISCVTarget::ExegesisRISCVTarget() : ExegesisTarget(ArrayRef{}, RISCV_MC::isOpcodeAvailable) {} -bool ExegesisRISCVTarget::checkOpcodeSupported( - int Opcode, const MCSubtargetInfo &SI) const { - auto Features = SI.getFeatureBits(); - FeatureBitset AvailableFeatures = - RISCV_MC::computeAvailableFeatures(Features); - FeatureBitset RequiredFeatures = RISCV_MC::computeRequiredFeatures(Opcode); - FeatureBitset MissingFeatures = RequiredFeatures & ~AvailableFeatures; - return MissingFeatures.none(); -} - #define GET_REGISTER_MATCHER #include "RISCVGenAsmMatcher.inc" @@ -281,22 +265,6 @@ void ExegesisRISCVTarget::fillMemoryOperands(InstructionTemplate &IT, IT.getValueFor(MemOp) = MCOperand::createReg(Reg); } -std::vector ExegesisRISCVTarget::storeRegValueToScratch( - const MCSubtargetInfo &STI, unsigned Reg, unsigned Offset) const { - std::vector Ret; - - if (RISCV::GPRRegClass.contains(Reg)) { - Ret.push_back(MCInstBuilder(RISCV::SW) - .addReg(Reg) - .addReg(ScratchMemoryReg) - .addImm(Offset)); - return Ret; - } - - errs() << "Failed to store value of " << Reg << " register to scratch memory"; - return {nop()}; -} - const unsigned UnavailableRegisters[4] = {RISCV::X0, DefaultLoopCounterReg, ScratchIntReg, ScratchMemoryReg}; diff --git a/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp b/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp index 08d5cd12f0a6d..9b74e3ecdd2b8 100644 --- a/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp +++ b/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp @@ -52,9 +52,6 @@ computeAliasingInstructions(const LLVMState &State, const Instruction *Instr, continue; if (OtherOpcode == Instr->Description.getOpcode()) continue; - if (State.getExegesisTarget().checkOpcodeSupported( - OtherOpcode, State.getSubtargetInfo())) - continue; const Instruction &OtherInstr = State.getIC().getInstr(OtherOpcode); const MCInstrDesc &OtherInstrDesc = OtherInstr.Description; if (OtherInstr.hasMemoryOperands()) diff --git a/llvm/tools/llvm-exegesis/lib/Target.h b/llvm/tools/llvm-exegesis/lib/Target.h index 1dcef5e51f4e5..94a5672ab3cb7 100644 --- a/llvm/tools/llvm-exegesis/lib/Target.h +++ b/llvm/tools/llvm-exegesis/lib/Target.h @@ -86,11 +86,6 @@ class ExegesisTarget { ArrayRef ValidationCounters, const pid_t ProcessID = 0) const; - virtual bool checkOpcodeSupported(int Opcode, - const MCSubtargetInfo &SI) const { - return false; - } - // Find register by name, NoRegister if not found. virtual MCRegister findRegisterByName(const StringRef RegName) const { return MCRegister::NoRegister; @@ -211,14 +206,6 @@ class ExegesisTarget { "fillMemoryOperands() requires getScratchMemoryRegister() > 0"); } - // Generates code to store register into scratch memory with offset. - virtual std::vector storeRegValueToScratch(const MCSubtargetInfo &STI, - unsigned Reg, - unsigned Offset) const { - llvm_unreachable( - "storeRegValueToScratch() requires getScratchMemoryRegister() > 0"); - } - // Returns a counter usable as a loop counter. virtual unsigned getDefaultLoopCounterRegister(const Triple &) const { return 0; diff --git a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp index c4236820c1462..7eaa0bb763be0 100644 --- a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp +++ b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp @@ -333,16 +333,16 @@ bool OpcodeNameParser::parse( std::vector> &Val) { SmallVector Pieces; StringRef(OpcodeNames) - .split(Pieces, ",", /* MaxSplit */ -1, /* KeepEmpty */ false); + .split(Pieces, ",", /*MaxSplit=*/-1, /*KeepEmpty=*/false); for (const StringRef &OpcodeName : Pieces) { size_t DotDotPos = OpcodeName.find(".."); if (DotDotPos == StringRef::npos) { - Val.push_back(std::make_pair(OpcodeName, OpcodeName)); + Val.emplace_back(std::make_pair(OpcodeName, OpcodeName)); continue; } StringRef BeginOpcodeName = OpcodeName.substr(0, DotDotPos); StringRef EndOpcodeName = OpcodeName.substr(DotDotPos + 2); - Val.push_back(std::make_pair(BeginOpcodeName, EndOpcodeName)); + Val.emplace_back(std::make_pair(BeginOpcodeName, EndOpcodeName)); } if (Val.empty()) return O.error("No matching opcode names"); From c2b189edff1075e8f59580e3e7f5b8f272ceec9e Mon Sep 17 00:00:00 2001 From: Anastasiya Chernikova Date: Thu, 31 Oct 2024 20:35:02 +0300 Subject: [PATCH 24/33] Addressing review comments --- llvm/tools/llvm-exegesis/llvm-exegesis.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp index 7eaa0bb763be0..0875155d7120f 100644 --- a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp +++ b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp @@ -337,12 +337,12 @@ bool OpcodeNameParser::parse( for (const StringRef &OpcodeName : Pieces) { size_t DotDotPos = OpcodeName.find(".."); if (DotDotPos == StringRef::npos) { - Val.emplace_back(std::make_pair(OpcodeName, OpcodeName)); + Val.emplace_back(OpcodeName, OpcodeName); continue; } StringRef BeginOpcodeName = OpcodeName.substr(0, DotDotPos); StringRef EndOpcodeName = OpcodeName.substr(DotDotPos + 2); - Val.emplace_back(std::make_pair(BeginOpcodeName, EndOpcodeName)); + Val.emplace_back(BeginOpcodeName, EndOpcodeName); } if (Val.empty()) return O.error("No matching opcode names"); From f36c7e8ce2bdf87ad5e134a4d08f7540f6911f9a Mon Sep 17 00:00:00 2001 From: Anastasiya Chernikova Date: Thu, 31 Oct 2024 21:07:27 +0300 Subject: [PATCH 25/33] Addressing review comments --- llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp index 80c025ed3fd27..7e2b0410be89a 100644 --- a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp +++ b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp @@ -18,7 +18,6 @@ #define GET_AVAILABLE_OPCODE_CHECKER #include "RISCVGenInstrInfo.inc" #undef GET_COMPUTE_FEATURES -#undef GET_AVAILABLE_OPCODE_CHECKER #include "llvm/CodeGen/MachineInstrBuilder.h" @@ -254,11 +253,11 @@ void ExegesisRISCVTarget::fillMemoryOperands(InstructionTemplate &IT, auto &I = IT.getInstr(); auto MemOpIt = - find_if(I.Operands, [](Operand const &Op) { return Op.isMemory(); }); + find_if(I.Operands, [](const Operand &Op) { return Op.isMemory(); }); assert(MemOpIt != I.Operands.end() && "Instruction must have memory operands"); - auto &MemOp = *MemOpIt; + const Operand &MemOp = *MemOpIt; assert(MemOp.isReg() && "Memory operand expected to be register"); @@ -269,7 +268,7 @@ const unsigned UnavailableRegisters[4] = {RISCV::X0, DefaultLoopCounterReg, ScratchIntReg, ScratchMemoryReg}; ArrayRef ExegesisRISCVTarget::getUnavailableRegisters() const { - return ArrayRef(UnavailableRegisters); + return UnavailableRegisters; } Error ExegesisRISCVTarget::randomizeTargetMCOperand( @@ -329,11 +328,10 @@ std::vector ExegesisRISCVTarget::generateInstructionVariants( const Instruction &Instr, unsigned int MaxConfigsPerOpcode) const { InstructionTemplate IT{&Instr}; - for (const Operand &Op : Instr.Operands) { + for (const Operand &Op : Instr.Operands) if (Op.isMemory()) { IT.getValueFor(Op) = MCOperand::createReg(ScratchMemoryReg); } - } return {IT}; } From eb3bd6f9ea789b3683f4fdb5f9f3cbf8befd1b6b Mon Sep 17 00:00:00 2001 From: Anastasiya Chernikova Date: Mon, 18 Nov 2024 16:24:40 +0300 Subject: [PATCH 26/33] Deleted processInstructionReservedRegs --- llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp | 30 ------------------- .../lib/SerialSnippetGenerator.cpp | 1 - llvm/tools/llvm-exegesis/lib/Target.h | 3 -- 3 files changed, 34 deletions(-) diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp index 7e2b0410be89a..70894c04b76ef 100644 --- a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp +++ b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp @@ -57,8 +57,6 @@ class ExegesisRISCVTarget : public ExegesisTarget { MCOperand &AssignedValue, const BitVector &ForbiddenRegs) const override; - void processInstructionReservedRegs(InstructionTemplate &IT) const override; - std::vector generateInstructionVariants(const Instruction &Instr, unsigned MaxConfigsPerOpcode) const override; @@ -296,34 +294,6 @@ Error ExegesisRISCVTarget::randomizeTargetMCOperand( return Error::success(); } -// Process instructions that used ReservedRegisters. -// We must not create instructions that used rd=x0. But for some of them in C -// extension we use registers in which we are really not going to write to. -// Registers were reserved in RISCVRegisterInfo.cpp using markSuperRegs function -// and should not be redeclared. Thus we must set appropriate register -// explicitly for each instruction according to RVC spec. -void ExegesisRISCVTarget::processInstructionReservedRegs( - InstructionTemplate &IT) const { - MCOperand &AssignedValue = IT.getValueForOperandIdx(0); - - switch (IT.getOpcode()) { - case RISCV::C_ADDI16SP: - case RISCV::C_ADDI4SPN: - AssignedValue = MCOperand::createReg(RISCV::X2); - break; - case RISCV::C_NOP: - case RISCV::C_LI_HINT: - case RISCV::C_LUI_HINT: - case RISCV::C_MV_HINT: - case RISCV::C_ADD_HINT: - case RISCV::C_SLLI_HINT: - AssignedValue = MCOperand::createReg(RISCV::X0); - break; - default: - break; - } -} - std::vector ExegesisRISCVTarget::generateInstructionVariants( const Instruction &Instr, unsigned int MaxConfigsPerOpcode) const { diff --git a/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp b/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp index 9b74e3ecdd2b8..9573e2242ad3f 100644 --- a/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp +++ b/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp @@ -96,7 +96,6 @@ static void appendCodeTemplates(const LLVMState &State, case ExecutionMode::ALWAYS_SERIAL_TIED_REGS_ALIAS: { // Picking whatever value for the tied variable will make the instruction // serial. - State.getExegesisTarget().processInstructionReservedRegs(Variant); CodeTemplate CT; CT.Execution = ExecutionModeBit; CT.Info = std::string(ExecutionClassDescription); diff --git a/llvm/tools/llvm-exegesis/lib/Target.h b/llvm/tools/llvm-exegesis/lib/Target.h index 94a5672ab3cb7..c46eb3e1b8aaa 100644 --- a/llvm/tools/llvm-exegesis/lib/Target.h +++ b/llvm/tools/llvm-exegesis/lib/Target.h @@ -243,9 +243,6 @@ class ExegesisTarget { "targets with target-specific operands should implement this"); } - // Process instructions that used reserved registers. - virtual void processInstructionReservedRegs(InstructionTemplate &IT) const {} - // Returns true if this instruction is supported as a back-to-back // instructions. // FIXME: Eventually we should discover this dynamically. From 70541d3be755eaa89c91b1536a992cfc78f07263 Mon Sep 17 00:00:00 2001 From: Anastasiya Chernikova Date: Mon, 18 Nov 2024 16:26:58 +0300 Subject: [PATCH 27/33] Addressing review comments --- llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp index 70894c04b76ef..84e5e3458bb84 100644 --- a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp +++ b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp @@ -139,7 +139,7 @@ static std::vector loadFPRegBits(const MCSubtargetInfo &STI, } // main idea is: -// we support APInt only if (represented as double) it have zero fractional +// 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 @@ -198,8 +198,7 @@ std::vector ExegesisRISCVTarget::setRegTo(const MCSubtargetInfo &STI, if (RISCV::FPR64RegClass.contains(Reg)) { if (STI.hasFeature(RISCV::Feature64Bit)) return loadFPRegBits(STI, Reg, Value, RISCV::FMV_D_X); - else - return loadFP64RegBits32(STI, Reg, Value); + return loadFP64RegBits32(STI, Reg, Value); } if (Reg == RISCV::FRM || Reg == RISCV::VL || Reg == RISCV::VLENB || Reg == RISCV::VTYPE || RISCV::GPRPairRegClass.contains(Reg) || From 570fee5113abdc4192258fa762ede58da87ac4c0 Mon Sep 17 00:00:00 2001 From: Anastasiya Chernikova Date: Tue, 19 Nov 2024 01:01:03 +0300 Subject: [PATCH 28/33] Addressing review comments --- llvm/tools/llvm-exegesis/lib/CodeTemplate.cpp | 9 --------- llvm/tools/llvm-exegesis/lib/CodeTemplate.h | 2 -- 2 files changed, 11 deletions(-) diff --git a/llvm/tools/llvm-exegesis/lib/CodeTemplate.cpp b/llvm/tools/llvm-exegesis/lib/CodeTemplate.cpp index 74a78b0f1c56f..fd156ee01e7ce 100644 --- a/llvm/tools/llvm-exegesis/lib/CodeTemplate.cpp +++ b/llvm/tools/llvm-exegesis/lib/CodeTemplate.cpp @@ -57,15 +57,6 @@ const MCOperand &InstructionTemplate::getValueFor(const Operand &Op) const { return getValueFor(Instr->Variables[Op.getVariableIndex()]); } -MCOperand &InstructionTemplate::getValueForOperandIdx(unsigned OpIdx) { - return getValueFor(Instr->Variables[OpIdx]); -} - -const MCOperand & -InstructionTemplate::getValueForOperandIdx(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(); diff --git a/llvm/tools/llvm-exegesis/lib/CodeTemplate.h b/llvm/tools/llvm-exegesis/lib/CodeTemplate.h index f565d3d0f1640..7aca224302a1f 100644 --- a/llvm/tools/llvm-exegesis/lib/CodeTemplate.h +++ b/llvm/tools/llvm-exegesis/lib/CodeTemplate.h @@ -35,8 +35,6 @@ struct InstructionTemplate { const MCOperand &getValueFor(const Variable &Var) const; MCOperand &getValueFor(const Operand &Op); const MCOperand &getValueFor(const Operand &Op) const; - MCOperand &getValueForOperandIdx(unsigned OpIdx); - const MCOperand &getValueForOperandIdx(unsigned OpIdx) const; bool hasImmediateVariables() const; const Instruction &getInstr() const { return *Instr; } ArrayRef getVariableValues() const { return VariableValues; } From c56a94b5af1df3846028f8dd1ae12668083cbd2c Mon Sep 17 00:00:00 2001 From: Anastasiya Chernikova Date: Thu, 21 Nov 2024 22:46:11 +0300 Subject: [PATCH 29/33] Addressing review comments --- llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp | 43 +++---------------- 1 file changed, 6 insertions(+), 37 deletions(-) diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp index 84e5e3458bb84..0c27edf032ad3 100644 --- a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp +++ b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp @@ -86,44 +86,13 @@ bool ExegesisRISCVTarget::matchesArch(Triple::ArchType Arch) const { // Stores constant value to a general-purpose (integer) register. static std::vector loadIntReg(const MCSubtargetInfo &STI, unsigned Reg, const APInt &Value) { - RISCVMatInt::InstSeq InstSeq = - RISCVMatInt::generateInstSeq(Value.getSExtValue(), STI); - // First instruction has form 'Op DestReg, X0, Imm' - MCRegister SrcReg = RISCV::X0; - MCRegister DestReg = Reg; + SmallVector MCInstSeq; std::vector MatIntInstrs; - MatIntInstrs.reserve(InstSeq.size()); - for (const RISCVMatInt::Inst &Inst : InstSeq) { - switch (Inst.getOpndKind()) { - case RISCVMatInt::Imm: - MatIntInstrs.push_back(MCInstBuilder(Inst.getOpcode()) - .addReg(DestReg) - .addImm(Inst.getImm())); - break; - case RISCVMatInt::RegX0: - MatIntInstrs.push_back(MCInstBuilder(Inst.getOpcode()) - .addReg(DestReg) - .addReg(SrcReg) - .addReg(RISCV::X0)); - break; - case RISCVMatInt::RegReg: - MatIntInstrs.push_back(MCInstBuilder(Inst.getOpcode()) - .addReg(DestReg) - .addReg(SrcReg) - .addReg(SrcReg)); - break; - case RISCVMatInt::RegImm: - MatIntInstrs.push_back(MCInstBuilder(Inst.getOpcode()) - .addReg(DestReg) - .addReg(SrcReg) - .addImm(Inst.getImm())); - break; - default: - llvm_unreachable("Unexpected kind!"); - } - // Further instructions have form 'Op DestReg, DestReg, Imm' - SrcReg = DestReg; - } + MCRegister DestReg = Reg; + + RISCVMatInt::generateMCInstSeq(Value.getSExtValue(), STI, DestReg, MCInstSeq); + std::copy(MCInstSeq.begin(), MCInstSeq.end(), MatIntInstrs.begin()); + return MatIntInstrs; } From a0130eab5937bd3ebdb5bc682222090301c87877 Mon Sep 17 00:00:00 2001 From: Anastasiya Chernikova Date: Mon, 25 Nov 2024 17:40:50 +0300 Subject: [PATCH 30/33] Addressing review comments --- llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp index 0c27edf032ad3..e280c5dd784f6 100644 --- a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp +++ b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp @@ -91,6 +91,7 @@ static std::vector loadIntReg(const MCSubtargetInfo &STI, unsigned Reg, MCRegister DestReg = Reg; RISCVMatInt::generateMCInstSeq(Value.getSExtValue(), STI, DestReg, MCInstSeq); + MatIntInstrs.resize(MCInstSeq.size()); std::copy(MCInstSeq.begin(), MCInstSeq.end(), MatIntInstrs.begin()); return MatIntInstrs; From 9859fb6f378798d98a16849b8b5377d461758c48 Mon Sep 17 00:00:00 2001 From: Anastasiya Chernikova Date: Tue, 3 Dec 2024 18:52:37 +0300 Subject: [PATCH 31/33] Addressing review comments --- llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp | 100 ++++++++---------- llvm/tools/llvm-exegesis/llvm-exegesis.cpp | 75 +++---------- 2 files changed, 55 insertions(+), 120 deletions(-) diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp index e280c5dd784f6..891818b625fe1 100644 --- a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp +++ b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp @@ -14,10 +14,8 @@ #include "RISCVInstrInfo.h" // include computeAvailableFeatures and computeRequiredFeatures. -#define GET_COMPUTE_FEATURES #define GET_AVAILABLE_OPCODE_CHECKER #include "RISCVGenInstrInfo.inc" -#undef GET_COMPUTE_FEATURES #include "llvm/CodeGen/MachineInstrBuilder.h" @@ -28,61 +26,6 @@ namespace exegesis { namespace { -class ExegesisRISCVTarget : public ExegesisTarget { -public: - ExegesisRISCVTarget(); - - MCRegister findRegisterByName(const StringRef RegName) const override; - - bool matchesArch(Triple::ArchType Arch) const override; - - std::vector 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 getUnavailableRegisters() const override; - - Error randomizeTargetMCOperand(const Instruction &Instr, const Variable &Var, - MCOperand &AssignedValue, - const BitVector &ForbiddenRegs) const override; - - std::vector - generateInstructionVariants(const Instruction &Instr, - unsigned MaxConfigsPerOpcode) const override; -}; - -ExegesisRISCVTarget::ExegesisRISCVTarget() - : ExegesisTarget(ArrayRef{}, - RISCV_MC::isOpcodeAvailable) {} - -#define GET_REGISTER_MATCHER -#include "RISCVGenAsmMatcher.inc" - -MCRegister -ExegesisRISCVTarget::findRegisterByName(const StringRef RegName) const { - MCRegister Reg; - if ((Reg = MatchRegisterName(RegName))) - return Reg; - if ((Reg = MatchRegisterAltName(RegName))) - return Reg; - return RISCV::NoRegister; -} - -bool ExegesisRISCVTarget::matchesArch(Triple::ArchType Arch) const { - return Arch == Triple::riscv32 || Arch == Triple::riscv64; -} - // Stores constant value to a general-purpose (integer) register. static std::vector loadIntReg(const MCSubtargetInfo &STI, unsigned Reg, const APInt &Value) { @@ -156,6 +99,49 @@ static bool isVectorRegList(unsigned Reg) { RISCV::VRN8M1RegClass.contains(Reg); } +class ExegesisRISCVTarget : public ExegesisTarget { +public: + ExegesisRISCVTarget(); + + bool matchesArch(Triple::ArchType Arch) const override; + + std::vector 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 getUnavailableRegisters() const override; + + Error randomizeTargetMCOperand(const Instruction &Instr, const Variable &Var, + MCOperand &AssignedValue, + const BitVector &ForbiddenRegs) const override; + + std::vector + generateInstructionVariants(const Instruction &Instr, + unsigned MaxConfigsPerOpcode) const override; +}; + +ExegesisRISCVTarget::ExegesisRISCVTarget() + : ExegesisTarget(ArrayRef{}, + RISCV_MC::isOpcodeAvailable) {} + +#define GET_REGISTER_MATCHER +#include "RISCVGenAsmMatcher.inc" + +bool ExegesisRISCVTarget::matchesArch(Triple::ArchType Arch) const { + return Arch == Triple::riscv32 || Arch == Triple::riscv64; +} + std::vector ExegesisRISCVTarget::setRegTo(const MCSubtargetInfo &STI, unsigned Reg, const APInt &Value) const { diff --git a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp index 0875155d7120f..fe0b8a0bfda85 100644 --- a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp +++ b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp @@ -50,27 +50,15 @@ namespace llvm { namespace exegesis { -struct OpcodeNameParser - : public cl::parser>> { - OpcodeNameParser(cl::Option &O) - : cl::parser>>(O) {} - bool parse(cl::Option &O, StringRef ArgName, const StringRef ArgValue, - std::vector> &Val); -}; - static cl::opt OpcodeIndex( "opcode-index", cl::desc("opcode to measure, by index, or -1 to measure all opcodes"), cl::cat(BenchmarkOptions), cl::init(0)); -static cl::opt>, false, - OpcodeNameParser> +static cl::opt OpcodeNames("opcode-name", - cl::desc("comma-separated list of opcodes to measure, " - "each item is either opcode name ('OP') " - "or opcode range ('OP1..OP2', ends are inclusive)"), - cl::cat(BenchmarkOptions), - cl::init(std::vector>())); + cl::desc("comma-separated list of opcodes to measure, by name"), + cl::cat(BenchmarkOptions), cl::init("")); static cl::opt SnippetsFile("snippets-file", cl::desc("code snippets to measure"), @@ -328,27 +316,6 @@ static bool isIgnoredOpcode(const LLVMState &State, unsigned Opcode) { return getIgnoredOpcodeReasonOrNull(State, Opcode) != nullptr; } -bool OpcodeNameParser::parse( - cl::Option &O, StringRef ArgName, const StringRef OpcodeNames, - std::vector> &Val) { - SmallVector Pieces; - StringRef(OpcodeNames) - .split(Pieces, ",", /*MaxSplit=*/-1, /*KeepEmpty=*/false); - for (const StringRef &OpcodeName : Pieces) { - size_t DotDotPos = OpcodeName.find(".."); - if (DotDotPos == StringRef::npos) { - Val.emplace_back(OpcodeName, OpcodeName); - continue; - } - StringRef BeginOpcodeName = OpcodeName.substr(0, DotDotPos); - StringRef EndOpcodeName = OpcodeName.substr(DotDotPos + 2); - Val.emplace_back(BeginOpcodeName, EndOpcodeName); - } - if (Val.empty()) - return O.error("No matching opcode names"); - return false; -} - // Checks that only one of OpcodeNames, OpcodeIndex or SnippetsFile is provided, // and returns the opcode indices or {} if snippets should be read from // `SnippetsFile`. @@ -388,34 +355,16 @@ static std::vector getOpcodesOrDie(const LLVMState &State) { return 0u; }; + SmallVector Pieces; + StringRef(OpcodeNames.getValue()) + .split(Pieces, ",", /* MaxSplit */ -1, /* KeepEmpty */ false); std::vector Result; - for (const std::pair &OpcodeName : OpcodeNames) { - if (OpcodeName.first == OpcodeName.second) { - if (unsigned Opcode = ResolveName(OpcodeName.first)) { - Result.push_back(Opcode); - continue; - } else { - ExitWithError(Twine("unknown opcode ").concat(OpcodeName.first)); - } - } else { - StringRef BeginOpcodeName = OpcodeName.first; - unsigned BeginOpcode = - BeginOpcodeName.empty() ? 1 : ResolveName(BeginOpcodeName); - if (BeginOpcode == 0) { - ExitWithError(Twine("unknown opcode ").concat(BeginOpcodeName)); - } - StringRef EndOpcodeName = OpcodeName.second; - unsigned EndOpcode = EndOpcodeName.empty() - ? State.getInstrInfo().getNumOpcodes() - 1 - : ResolveName(EndOpcodeName); - if (EndOpcode == 0) { - ExitWithError(Twine("unknown opcode ").concat(EndOpcodeName)); - } - for (unsigned I = BeginOpcode; I <= EndOpcode; ++I) { - if (!isIgnoredOpcode(State, I)) - Result.push_back(I); - } - } + Result.reserve(Pieces.size()); + for (const StringRef &OpcodeName : Pieces) { + if (unsigned Opcode = ResolveName(OpcodeName)) + Result.push_back(Opcode); + else + ExitWithError(Twine("unknown opcode ").concat(OpcodeName)); } return Result; } From c84e814ffb0d5d1d80718b200e5dfddc628ad906 Mon Sep 17 00:00:00 2001 From: Anastasiya Chernikova Date: Tue, 3 Dec 2024 19:26:21 +0300 Subject: [PATCH 32/33] Addressing review comments --- llvm/tools/llvm-exegesis/lib/Target.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/llvm/tools/llvm-exegesis/lib/Target.h b/llvm/tools/llvm-exegesis/lib/Target.h index c46eb3e1b8aaa..92cc1cb248a1c 100644 --- a/llvm/tools/llvm-exegesis/lib/Target.h +++ b/llvm/tools/llvm-exegesis/lib/Target.h @@ -86,11 +86,6 @@ class ExegesisTarget { ArrayRef ValidationCounters, const pid_t ProcessID = 0) const; - // Find register by name, NoRegister if not found. - virtual MCRegister findRegisterByName(const StringRef RegName) const { - return MCRegister::NoRegister; - } - // Targets can use this to add target-specific passes in assembleToStream(); virtual void addTargetSpecificPasses(PassManagerBase &PM) const {} From 2a8281752eb01d78c88d0890f2f1c0350669a6bf Mon Sep 17 00:00:00 2001 From: Anastasiya Chernikova Date: Sun, 15 Dec 2024 20:01:40 +0300 Subject: [PATCH 33/33] Addressing review comments --- llvm/tools/llvm-exegesis/llvm-exegesis.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp index fe0b8a0bfda85..fa37e05956be8 100644 --- a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp +++ b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp @@ -312,10 +312,6 @@ static const char *getIgnoredOpcodeReasonOrNull(const LLVMState &State, return nullptr; } -static bool isIgnoredOpcode(const LLVMState &State, unsigned Opcode) { - return getIgnoredOpcodeReasonOrNull(State, Opcode) != nullptr; -} - // Checks that only one of OpcodeNames, OpcodeIndex or SnippetsFile is provided, // and returns the opcode indices or {} if snippets should be read from // `SnippetsFile`.