From c96caf47d53abb03d8c915f63857210e2bdca1db Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Mon, 6 Jan 2025 15:31:54 -0800 Subject: [PATCH 1/4] [RISCV][llvm-exegesis] Add unittests. NFC This is largely a copy paste from Mips or PowerPC. --- .../tools/llvm-exegesis/CMakeLists.txt | 3 + .../tools/llvm-exegesis/RISCV/CMakeLists.txt | 21 +++ .../RISCV/SnippetGeneratorTest.cpp | 122 ++++++++++++++++++ .../tools/llvm-exegesis/RISCV/TargetTest.cpp | 62 +++++++++ .../tools/llvm-exegesis/RISCV/TestBase.h | 43 ++++++ 5 files changed, 251 insertions(+) create mode 100644 llvm/unittests/tools/llvm-exegesis/RISCV/CMakeLists.txt create mode 100644 llvm/unittests/tools/llvm-exegesis/RISCV/SnippetGeneratorTest.cpp create mode 100644 llvm/unittests/tools/llvm-exegesis/RISCV/TargetTest.cpp create mode 100644 llvm/unittests/tools/llvm-exegesis/RISCV/TestBase.h diff --git a/llvm/unittests/tools/llvm-exegesis/CMakeLists.txt b/llvm/unittests/tools/llvm-exegesis/CMakeLists.txt index 3ee3a0dc6b5d0..735f17ab03e61 100644 --- a/llvm/unittests/tools/llvm-exegesis/CMakeLists.txt +++ b/llvm/unittests/tools/llvm-exegesis/CMakeLists.txt @@ -53,6 +53,9 @@ endif() if(LLVM_TARGETS_TO_BUILD MATCHES "Mips") include(Mips/CMakeLists.txt) endif() +if(LLVM_TARGETS_TO_BUILD MATCHES "RISCV") + include(RISCV/CMakeLists.txt) +endif() include_directories(${exegesis_includes}) diff --git a/llvm/unittests/tools/llvm-exegesis/RISCV/CMakeLists.txt b/llvm/unittests/tools/llvm-exegesis/RISCV/CMakeLists.txt new file mode 100644 index 0000000000000..1984819be7738 --- /dev/null +++ b/llvm/unittests/tools/llvm-exegesis/RISCV/CMakeLists.txt @@ -0,0 +1,21 @@ +add_llvm_exegesis_unittest_includes( + ${LLVM_MAIN_SRC_DIR}/lib/Target/RISCV + ${LLVM_BINARY_DIR}/lib/Target/RISCV + ${LLVM_MAIN_SRC_DIR}/tools/llvm-exegesis/lib + ) + +add_llvm_exegesis_unittest_link_components( + MC + MCParser + Object + Support + Symbolize + RISCV + ) + +add_llvm_exegesis_unittest_sources( + SnippetGeneratorTest.cpp + TargetTest.cpp + ) +add_llvm_exegesis_unittest_link_libraries( + LLVMExegesisRISCV) diff --git a/llvm/unittests/tools/llvm-exegesis/RISCV/SnippetGeneratorTest.cpp b/llvm/unittests/tools/llvm-exegesis/RISCV/SnippetGeneratorTest.cpp new file mode 100644 index 0000000000000..8ea8623e0d373 --- /dev/null +++ b/llvm/unittests/tools/llvm-exegesis/RISCV/SnippetGeneratorTest.cpp @@ -0,0 +1,122 @@ +//===-- SnippetGeneratorTest.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 "../Common/AssemblerUtils.h" +#include "LlvmState.h" +#include "MCInstrDescView.h" +#include "RISCVInstrInfo.h" +#include "ParallelSnippetGenerator.h" +#include "RegisterAliasing.h" +#include "SerialSnippetGenerator.h" +#include "TestBase.h" + +namespace llvm { +namespace exegesis { +namespace { + +using testing::AnyOf; +using testing::ElementsAre; +using testing::HasSubstr; +using testing::SizeIs; + +MATCHER(IsInvalid, "") { return !arg.isValid(); } +MATCHER(IsReg, "") { return arg.isReg(); } + +template +class RISCVSnippetGeneratorTest : public RISCVTestBase { +protected: + RISCVSnippetGeneratorTest() : Generator(State, SnippetGenerator::Options()) {} + + std::vector checkAndGetCodeTemplates(unsigned Opcode) { + randomGenerator().seed(0); // Initialize seed. + const Instruction &Instr = State.getIC().getInstr(Opcode); + auto CodeTemplateOrError = Generator.generateCodeTemplates( + &Instr, State.getRATC().emptyRegisters()); + EXPECT_FALSE(CodeTemplateOrError.takeError()); // Valid configuration. + return std::move(CodeTemplateOrError.get()); + } + + SnippetGeneratorT Generator; +}; + +using RISCVSerialSnippetGeneratorTest = RISCVSnippetGeneratorTest; + +using RISCVParallelSnippetGeneratorTest = + RISCVSnippetGeneratorTest; + +TEST_F(RISCVSerialSnippetGeneratorTest, ImplicitSelfDependencyThroughExplicitRegs) { + // - ADD + // - Op0 Explicit Def RegClass(GPR) + // - Op1 Explicit Use RegClass(GPR) + // - Op2 Explicit Use RegClass(GPR) + // - Var0 [Op0] + // - Var1 [Op1] + // - Var2 [Op2] + // - hasAliasingRegisters + const unsigned Opcode = RISCV::ADD; + const auto CodeTemplates = checkAndGetCodeTemplates(Opcode); + ASSERT_THAT(CodeTemplates, SizeIs(1)); + const auto &CT = CodeTemplates[0]; + EXPECT_THAT(CT.Execution, ExecutionMode::SERIAL_VIA_EXPLICIT_REGS); + ASSERT_THAT(CT.Instructions, SizeIs(1)); + const InstructionTemplate &IT = CT.Instructions[0]; + EXPECT_THAT(IT.getOpcode(), Opcode); + ASSERT_THAT(IT.getVariableValues(), SizeIs(3)); + EXPECT_THAT(IT.getVariableValues(), + AnyOf(ElementsAre(IsReg(), IsInvalid(), IsReg()), + ElementsAre(IsReg(), IsReg(), IsInvalid()))) + << "Op0 is either set to Op1 or to Op2"; +} + +TEST_F(RISCVSerialSnippetGeneratorTest, + ImplicitSelfDependencyThroughExplicitRegsForbidAll) { + // - XOR + // - Op0 Explicit Def RegClass(GPR) + // - Op1 Explicit Use RegClass(GPR) + // - Op2 Explicit Use RegClass(GPR) + // - Var0 [Op0] + // - Var1 [Op1] + // - Var2 [Op2] + // - hasAliasingRegisters + randomGenerator().seed(0); // Initialize seed. + const Instruction &Instr = State.getIC().getInstr(RISCV::XOR); + auto AllRegisters = State.getRATC().emptyRegisters(); + AllRegisters.flip(); + auto Error = + Generator.generateCodeTemplates(&Instr, AllRegisters).takeError(); + EXPECT_TRUE((bool)Error); + consumeError(std::move(Error)); +} + +TEST_F(RISCVParallelSnippetGeneratorTest, MemoryUse) { + // LB reads from memory. + // - LB + // - Op0 Explicit Def RegClass(GPR) + // - Op1 Explicit Use Memory RegClass(GPR) + // - Op2 Explicit Use Memory + // - Var0 [Op0] + // - Var1 [Op1] + // - Var2 [Op2] + // - hasMemoryOperands + const unsigned Opcode = RISCV::LB; + const auto CodeTemplates = checkAndGetCodeTemplates(Opcode); + ASSERT_THAT(CodeTemplates, SizeIs(1)); + const auto &CT = CodeTemplates[0]; + EXPECT_THAT(CT.Info, HasSubstr("instruction has no tied variables")); + EXPECT_THAT(CT.Execution, ExecutionMode::UNKNOWN); + ASSERT_THAT(CT.Instructions, + SizeIs(ParallelSnippetGenerator::kMinNumDifferentAddresses)); + const InstructionTemplate &IT = CT.Instructions[0]; + EXPECT_THAT(IT.getOpcode(), Opcode); + ASSERT_THAT(IT.getVariableValues(), SizeIs(3)); + EXPECT_EQ(IT.getVariableValues()[1].getReg(), RISCV::X10); +} + +} // namespace +} // namespace exegesis +} // namespace llvm diff --git a/llvm/unittests/tools/llvm-exegesis/RISCV/TargetTest.cpp b/llvm/unittests/tools/llvm-exegesis/RISCV/TargetTest.cpp new file mode 100644 index 0000000000000..db4a73d994259 --- /dev/null +++ b/llvm/unittests/tools/llvm-exegesis/RISCV/TargetTest.cpp @@ -0,0 +1,62 @@ +//===-- TargetTest.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 +#include + +#include "MCTargetDesc/RISCVMCTargetDesc.h" +#include "llvm/MC/TargetRegistry.h" +#include "llvm/Support/TargetSelect.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +namespace llvm{ +namespace exegesis { + +void InitializeRISCVExegesisTarget(); + +namespace { + +using testing::NotNull; +using testing::IsEmpty; +using testing::Not; + +constexpr const char kTriple[] = "riscv64-unknown-linux"; + +class RISCVTargetTest : public ::testing::Test { +protected: + RISCVTargetTest() + : ExegesisTarget_(ExegesisTarget::lookup(Triple(kTriple))) { + EXPECT_THAT(ExegesisTarget_, NotNull()); + std::string error; + Target_ = TargetRegistry::lookupTarget(kTriple, error); + EXPECT_THAT(Target_, NotNull()); + } + static void SetUpTestCase() { + LLVMInitializeRISCVTargetInfo(); + LLVMInitializeRISCVTarget(); + LLVMInitializeRISCVTargetMC(); + InitializeRISCVExegesisTarget(); + } + + const Target *Target_; + const ExegesisTarget *const ExegesisTarget_; +}; + +TEST_F(RISCVTargetTest, SetRegToConstant) { + const std::unique_ptr STI( + Target_->createMCSubtargetInfo(kTriple, "generic", "")); + const auto Insts = ExegesisTarget_->setRegTo(*STI, RISCV::X10, APInt()); + EXPECT_THAT(Insts, Not(IsEmpty())); +} + +} // namespace +} // namespace exegesis +} // namespace llvm diff --git a/llvm/unittests/tools/llvm-exegesis/RISCV/TestBase.h b/llvm/unittests/tools/llvm-exegesis/RISCV/TestBase.h new file mode 100644 index 0000000000000..a5a32819ecdf2 --- /dev/null +++ b/llvm/unittests/tools/llvm-exegesis/RISCV/TestBase.h @@ -0,0 +1,43 @@ +//===-- TestBase.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 +// +//===----------------------------------------------------------------------===// +// Test fixture common to all RISC-V tests. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_UNITTESTS_TOOLS_LLVMEXEGESIS_RISCV_TESTBASE_H +#define LLVM_UNITTESTS_TOOLS_LLVMEXEGESIS_RISCV_TESTBASE_H + +#include "LlvmState.h" +#include "llvm/MC/TargetRegistry.h" +#include "llvm/Support/TargetSelect.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +namespace llvm { +namespace exegesis { + +void InitializeRISCVExegesisTarget(); + +class RISCVTestBase : public ::testing::Test { +protected: + RISCVTestBase() + : State(cantFail(LLVMState::Create("riscv64-unknown-linux", "generic-rv64"))) {} + + static void SetUpTestCase() { + LLVMInitializeRISCVTargetInfo(); + LLVMInitializeRISCVTargetMC(); + LLVMInitializeRISCVTarget(); + InitializeRISCVExegesisTarget(); + } + + const LLVMState State; +}; + +} // namespace exegesis +} // namespace llvm + +#endif From 4dd0cc4aaaff7ece1fccd7363039bca188af61b7 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Mon, 6 Jan 2025 17:33:03 -0800 Subject: [PATCH 2/4] fixup! clang-format --- .../tools/llvm-exegesis/RISCV/SnippetGeneratorTest.cpp | 8 +++++--- llvm/unittests/tools/llvm-exegesis/RISCV/TargetTest.cpp | 7 +++---- llvm/unittests/tools/llvm-exegesis/RISCV/TestBase.h | 3 ++- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/llvm/unittests/tools/llvm-exegesis/RISCV/SnippetGeneratorTest.cpp b/llvm/unittests/tools/llvm-exegesis/RISCV/SnippetGeneratorTest.cpp index 8ea8623e0d373..22c25d92dfd3e 100644 --- a/llvm/unittests/tools/llvm-exegesis/RISCV/SnippetGeneratorTest.cpp +++ b/llvm/unittests/tools/llvm-exegesis/RISCV/SnippetGeneratorTest.cpp @@ -9,8 +9,8 @@ #include "../Common/AssemblerUtils.h" #include "LlvmState.h" #include "MCInstrDescView.h" -#include "RISCVInstrInfo.h" #include "ParallelSnippetGenerator.h" +#include "RISCVInstrInfo.h" #include "RegisterAliasing.h" #include "SerialSnippetGenerator.h" #include "TestBase.h" @@ -44,12 +44,14 @@ class RISCVSnippetGeneratorTest : public RISCVTestBase { SnippetGeneratorT Generator; }; -using RISCVSerialSnippetGeneratorTest = RISCVSnippetGeneratorTest; +using RISCVSerialSnippetGeneratorTest = + RISCVSnippetGeneratorTest; using RISCVParallelSnippetGeneratorTest = RISCVSnippetGeneratorTest; -TEST_F(RISCVSerialSnippetGeneratorTest, ImplicitSelfDependencyThroughExplicitRegs) { +TEST_F(RISCVSerialSnippetGeneratorTest, + ImplicitSelfDependencyThroughExplicitRegs) { // - ADD // - Op0 Explicit Def RegClass(GPR) // - Op1 Explicit Use RegClass(GPR) diff --git a/llvm/unittests/tools/llvm-exegesis/RISCV/TargetTest.cpp b/llvm/unittests/tools/llvm-exegesis/RISCV/TargetTest.cpp index db4a73d994259..06fa553ea5a9c 100644 --- a/llvm/unittests/tools/llvm-exegesis/RISCV/TargetTest.cpp +++ b/llvm/unittests/tools/llvm-exegesis/RISCV/TargetTest.cpp @@ -17,23 +17,22 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" -namespace llvm{ +namespace llvm { namespace exegesis { void InitializeRISCVExegesisTarget(); namespace { -using testing::NotNull; using testing::IsEmpty; using testing::Not; +using testing::NotNull; constexpr const char kTriple[] = "riscv64-unknown-linux"; class RISCVTargetTest : public ::testing::Test { protected: - RISCVTargetTest() - : ExegesisTarget_(ExegesisTarget::lookup(Triple(kTriple))) { + RISCVTargetTest() : ExegesisTarget_(ExegesisTarget::lookup(Triple(kTriple))) { EXPECT_THAT(ExegesisTarget_, NotNull()); std::string error; Target_ = TargetRegistry::lookupTarget(kTriple, error); diff --git a/llvm/unittests/tools/llvm-exegesis/RISCV/TestBase.h b/llvm/unittests/tools/llvm-exegesis/RISCV/TestBase.h index a5a32819ecdf2..66748fb9a2ce1 100644 --- a/llvm/unittests/tools/llvm-exegesis/RISCV/TestBase.h +++ b/llvm/unittests/tools/llvm-exegesis/RISCV/TestBase.h @@ -25,7 +25,8 @@ void InitializeRISCVExegesisTarget(); class RISCVTestBase : public ::testing::Test { protected: RISCVTestBase() - : State(cantFail(LLVMState::Create("riscv64-unknown-linux", "generic-rv64"))) {} + : State(cantFail( + LLVMState::Create("riscv64-unknown-linux", "generic-rv64"))) {} static void SetUpTestCase() { LLVMInitializeRISCVTargetInfo(); From a43d447206c8b06d8699144508f036fbfad80685 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Mon, 6 Jan 2025 21:52:27 -0800 Subject: [PATCH 3/4] fixup! inherit from RISCVTestBase --- .../tools/llvm-exegesis/RISCV/TargetTest.cpp | 26 +++++-------------- 1 file changed, 6 insertions(+), 20 deletions(-) diff --git a/llvm/unittests/tools/llvm-exegesis/RISCV/TargetTest.cpp b/llvm/unittests/tools/llvm-exegesis/RISCV/TargetTest.cpp index 06fa553ea5a9c..745a6c68c9a0e 100644 --- a/llvm/unittests/tools/llvm-exegesis/RISCV/TargetTest.cpp +++ b/llvm/unittests/tools/llvm-exegesis/RISCV/TargetTest.cpp @@ -12,6 +12,7 @@ #include #include "MCTargetDesc/RISCVMCTargetDesc.h" +#include "TestBase.h" #include "llvm/MC/TargetRegistry.h" #include "llvm/Support/TargetSelect.h" #include "gmock/gmock.h" @@ -28,31 +29,16 @@ using testing::IsEmpty; using testing::Not; using testing::NotNull; -constexpr const char kTriple[] = "riscv64-unknown-linux"; - -class RISCVTargetTest : public ::testing::Test { +class RISCVTargetTest : public RISCVTestBase { protected: - RISCVTargetTest() : ExegesisTarget_(ExegesisTarget::lookup(Triple(kTriple))) { - EXPECT_THAT(ExegesisTarget_, NotNull()); - std::string error; - Target_ = TargetRegistry::lookupTarget(kTriple, error); - EXPECT_THAT(Target_, NotNull()); - } - static void SetUpTestCase() { - LLVMInitializeRISCVTargetInfo(); - LLVMInitializeRISCVTarget(); - LLVMInitializeRISCVTargetMC(); - InitializeRISCVExegesisTarget(); + std::vector setRegTo(unsigned Reg, const APInt &Value) { + return State.getExegesisTarget().setRegTo(State.getSubtargetInfo(), Reg, + Value); } - - const Target *Target_; - const ExegesisTarget *const ExegesisTarget_; }; TEST_F(RISCVTargetTest, SetRegToConstant) { - const std::unique_ptr STI( - Target_->createMCSubtargetInfo(kTriple, "generic", "")); - const auto Insts = ExegesisTarget_->setRegTo(*STI, RISCV::X10, APInt()); + const auto Insts = setRegTo(RISCV::X10, APInt()); EXPECT_THAT(Insts, Not(IsEmpty())); } From 6048ecb08b376667199f62c331ace9301bc8f7cb Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Mon, 6 Jan 2025 22:17:37 -0800 Subject: [PATCH 4/4] fixup! Use errorToBool --- .../tools/llvm-exegesis/RISCV/SnippetGeneratorTest.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/llvm/unittests/tools/llvm-exegesis/RISCV/SnippetGeneratorTest.cpp b/llvm/unittests/tools/llvm-exegesis/RISCV/SnippetGeneratorTest.cpp index 22c25d92dfd3e..5920b79da9d3e 100644 --- a/llvm/unittests/tools/llvm-exegesis/RISCV/SnippetGeneratorTest.cpp +++ b/llvm/unittests/tools/llvm-exegesis/RISCV/SnippetGeneratorTest.cpp @@ -89,10 +89,8 @@ TEST_F(RISCVSerialSnippetGeneratorTest, const Instruction &Instr = State.getIC().getInstr(RISCV::XOR); auto AllRegisters = State.getRATC().emptyRegisters(); AllRegisters.flip(); - auto Error = - Generator.generateCodeTemplates(&Instr, AllRegisters).takeError(); - EXPECT_TRUE((bool)Error); - consumeError(std::move(Error)); + EXPECT_TRUE(errorToBool( + Generator.generateCodeTemplates(&Instr, AllRegisters).takeError())); } TEST_F(RISCVParallelSnippetGeneratorTest, MemoryUse) {