Skip to content

Commit

Permalink
[PowerPC][llvm-exegesis] Add a PowerPC target
Browse files Browse the repository at this point in the history
This is patch to add PowerPC target to llvm-exegesis.
The target does just enough to be able to run llvm-exegesis in latency mode for at least some opcodes.

Differential Revision: https://reviews.llvm.org/D54185

llvm-svn: 346411
  • Loading branch information
Jinsong Ji committed Nov 8, 2018
1 parent ac8279a commit 5fd3e75
Show file tree
Hide file tree
Showing 8 changed files with 318 additions and 0 deletions.
4 changes: 4 additions & 0 deletions llvm/tools/llvm-exegesis/lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ if (LLVM_TARGETS_TO_BUILD MATCHES "AArch64")
add_subdirectory(AArch64)
set(TARGETS_TO_APPEND "${TARGETS_TO_APPEND} AArch64")
endif()
if (LLVM_TARGETS_TO_BUILD MATCHES "PowerPC")
add_subdirectory(PowerPC)
set(TARGETS_TO_APPEND "${TARGETS_TO_APPEND} PowerPC")
endif()

set(LLVM_EXEGESIS_TARGETS "${LLVM_EXEGESIS_TARGETS} ${TARGETS_TO_APPEND}" PARENT_SCOPE)

Expand Down
18 changes: 18 additions & 0 deletions llvm/tools/llvm-exegesis/lib/PowerPC/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
include_directories(
${LLVM_MAIN_SRC_DIR}/lib/Target/PowerPC
${LLVM_BINARY_DIR}/lib/Target/PowerPC
)

add_library(LLVMExegesisPowerPC
STATIC
Target.cpp
)

llvm_update_compile_flags(LLVMExegesisPowerPC)
llvm_map_components_to_libnames(libs
PowerPC
Exegesis
)

target_link_libraries(LLVMExegesisPowerPC ${libs})
set_target_properties(LLVMExegesisPowerPC PROPERTIES FOLDER "Libraries")
22 changes: 22 additions & 0 deletions llvm/tools/llvm-exegesis/lib/PowerPC/LLVMBuild.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
;===- ./tools/llvm-exegesis/lib/PowerPC/LLVMBuild.txt ---------------*- Conf -*--===;
;
; The LLVM Compiler Infrastructure
;
; This file is distributed under the University of Illinois Open Source
; License. See LICENSE.TXT for details.
;
;===------------------------------------------------------------------------===;
;
; This is an LLVMBuild description file for the components in this subdirectory.
;
; For more information on the LLVMBuild system, please see:
;
; http://llvm.org/docs/LLVMBuild.html
;
;===------------------------------------------------------------------------===;

[component_0]
type = Library
name = ExegesisPowerPC
parent = Libraries
required_libraries = PowerPC
92 changes: 92 additions & 0 deletions llvm/tools/llvm-exegesis/lib/PowerPC/Target.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
//===-- Target.cpp ----------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
// The PowerPC ExegesisTarget.
//===----------------------------------------------------------------------===//
#include "../Target.h"
#include "../Latency.h"
#include "PPC.h"
#include "PPCRegisterInfo.h"

namespace llvm {
namespace exegesis {

namespace {
class PowerPCLatencyBenchmarkRunner : public LatencyBenchmarkRunner {
public:
PowerPCLatencyBenchmarkRunner(const LLVMState &State)
: LatencyBenchmarkRunner(State) {}

private:
const char *getCounterName() const override {
// All PowerPC subtargets have CYCLES as the cycle counter name
return "CYCLES";
}
};
} // end anonymous namespace

namespace {
class ExegesisPowerPCTarget : public ExegesisTarget {
public:
ExegesisPowerPCTarget() : ExegesisTarget({}) {}

private:
std::vector<llvm::MCInst> setRegTo(const llvm::MCSubtargetInfo &STI,
unsigned Reg,
const llvm::APInt &Value) const override;
bool matchesArch(llvm::Triple::ArchType Arch) const override {
return Arch == llvm::Triple::ppc64le;
}
std::unique_ptr<BenchmarkRunner>
createLatencyBenchmarkRunner(const LLVMState &State) const override {
return llvm::make_unique<PowerPCLatencyBenchmarkRunner>(State);
}
};
} // end anonymous namespace

static unsigned getLoadImmediateOpcode(unsigned RegBitWidth) {
switch (RegBitWidth) {
case 32:
return llvm::PPC::LI;
case 64:
return llvm::PPC::LI8;
}
llvm_unreachable("Invalid Value Width");
}

// Generates instruction to load an immediate value into a register.
static llvm::MCInst loadImmediate(unsigned Reg, unsigned RegBitWidth,
const llvm::APInt &Value) {
if (Value.getBitWidth() > RegBitWidth)
llvm_unreachable("Value must fit in the Register");
return llvm::MCInstBuilder(getLoadImmediateOpcode(RegBitWidth))
.addReg(Reg)
.addImm(Value.getZExtValue());
}

std::vector<llvm::MCInst>
ExegesisPowerPCTarget::setRegTo(const llvm::MCSubtargetInfo &STI, unsigned Reg,
const llvm::APInt &Value) const {
if (llvm::PPC::GPRCRegClass.contains(Reg))
return {loadImmediate(Reg, 32, Value)};
if (llvm::PPC::G8RCRegClass.contains(Reg))
return {loadImmediate(Reg, 64, Value)};
llvm::errs() << "setRegTo is not implemented, results will be unreliable\n";
return {};
}

static ExegesisTarget *getTheExegesisPowerPCTarget() {
static ExegesisPowerPCTarget Target;
return &Target;
}

void InitializePowerPCExegesisTarget() {
ExegesisTarget::registerTarget(getTheExegesisPowerPCTarget());
}

} // namespace exegesis
} // namespace llvm
3 changes: 3 additions & 0 deletions llvm/unittests/tools/llvm-exegesis/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,6 @@ endif()
if(LLVM_TARGETS_TO_BUILD MATCHES "AArch64")
add_subdirectory(AArch64)
endif()
if(LLVM_TARGETS_TO_BUILD MATCHES "PowerPC")
add_subdirectory(PowerPC)
endif()
93 changes: 93 additions & 0 deletions llvm/unittests/tools/llvm-exegesis/PowerPC/AnalysisTest.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
//===-- AnalysisTest.cpp ---------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "Analysis.h"

#include <cassert>
#include <memory>

#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"

namespace llvm{
namespace exegesis {
namespace {

using testing::Pair;
using testing::UnorderedElementsAre;

class AnalysisTest : public ::testing::Test {
protected:
AnalysisTest() {
const std::string TT = "powerpc64le-unknown-linux";
std::string error;
const llvm::Target *const TheTarget =
llvm::TargetRegistry::lookupTarget(TT, error);
if (!TheTarget) {
llvm::errs() << error << "\n";
return;
}
STI.reset(TheTarget->createMCSubtargetInfo(TT, "pwr9", ""));

// Compute the ProxResIdx of ports uses in tests.
const auto &SM = STI->getSchedModel();
for (unsigned I = 0, E = SM.getNumProcResourceKinds(); I < E; ++I) {
const std::string Name = SM.getProcResource(I)->Name;
if (Name == "ALU") {
ALUIdx = I;
} else if (Name == "ALUE") {
ALUEIdx = I;
} else if (Name == "ALUO") {
ALUOIdx = I;
} else if (Name == "IP_AGEN") {
IPAGENIdx = I;
}
}
EXPECT_NE(ALUIdx, 0);
EXPECT_NE(ALUEIdx, 0);
EXPECT_NE(ALUOIdx, 0);
EXPECT_NE(IPAGENIdx, 0);
}

static void SetUpTestCase() {
LLVMInitializePowerPCTargetInfo();
LLVMInitializePowerPCTarget();
LLVMInitializePowerPCTargetMC();
}

protected:
std::unique_ptr<const llvm::MCSubtargetInfo> STI;
uint16_t ALUIdx = 0;
uint16_t ALUEIdx = 0;
uint16_t ALUOIdx = 0;
uint16_t IPAGENIdx = 0;
};

TEST_F(AnalysisTest, ComputeIdealizedProcResPressure_2ALU) {
const auto Pressure =
computeIdealizedProcResPressure(STI->getSchedModel(), {{ALUIdx, 2}});
EXPECT_THAT(Pressure, UnorderedElementsAre(Pair(ALUIdx, 2.0)));
}

TEST_F(AnalysisTest, ComputeIdealizedProcResPressure_1ALUE) {
const auto Pressure =
computeIdealizedProcResPressure(STI->getSchedModel(), {{ALUEIdx, 2}});
EXPECT_THAT(Pressure, UnorderedElementsAre(Pair(ALUEIdx, 2.0)));
}

TEST_F(AnalysisTest, ComputeIdealizedProcResPressure_1ALU1IPAGEN) {
const auto Pressure =
computeIdealizedProcResPressure(STI->getSchedModel(), {{ALUIdx, 1}, {IPAGENIdx, 1}});
EXPECT_THAT(Pressure, UnorderedElementsAre(Pair(ALUIdx, 1.0),Pair(IPAGENIdx, 1)));
}
} // namespace
} // namespace exegesis
} // namespace llvm
22 changes: 22 additions & 0 deletions llvm/unittests/tools/llvm-exegesis/PowerPC/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
include_directories(
${LLVM_MAIN_SRC_DIR}/lib/Target/PowerPC
${LLVM_BINARY_DIR}/lib/Target/PowerPC
${LLVM_MAIN_SRC_DIR}/tools/llvm-exegesis/lib
)

set(LLVM_LINK_COMPONENTS
MC
MCParser
Object
Support
Symbolize
PowerPC
)

add_llvm_unittest(LLVMExegesisPowerPCTests
AnalysisTest.cpp
TargetTest.cpp
)
target_link_libraries(LLVMExegesisPowerPCTests PRIVATE
LLVMExegesis
LLVMExegesisPowerPC)
64 changes: 64 additions & 0 deletions llvm/unittests/tools/llvm-exegesis/PowerPC/TargetTest.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
//===-- TargetTest.cpp ---------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "Target.h"

#include <cassert>
#include <memory>

#include "MCTargetDesc/PPCMCTargetDesc.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"

namespace llvm{
namespace exegesis {

void InitializePowerPCExegesisTarget();

namespace {

using testing::NotNull;
using testing::IsEmpty;
using testing::Not;

constexpr const char kTriple[] = "powerpc64le-unknown-linux";

class PowerPCTargetTest : public ::testing::Test {
protected:
PowerPCTargetTest()
: ExegesisTarget_(ExegesisTarget::lookup(llvm::Triple(kTriple))) {
EXPECT_THAT(ExegesisTarget_, NotNull());
std::string error;
Target_ = llvm::TargetRegistry::lookupTarget(kTriple, error);
EXPECT_THAT(Target_, NotNull());
}
static void SetUpTestCase() {
LLVMInitializePowerPCTargetInfo();
LLVMInitializePowerPCTarget();
LLVMInitializePowerPCTargetMC();
InitializePowerPCExegesisTarget();
}

const llvm::Target *Target_;
const ExegesisTarget *const ExegesisTarget_;
};

TEST_F(PowerPCTargetTest, SetRegToConstant) {
const std::unique_ptr<llvm::MCSubtargetInfo> STI(
Target_->createMCSubtargetInfo(kTriple, "generic", ""));
const auto Insts =
ExegesisTarget_->setRegTo(*STI, llvm::PPC::X0, llvm::APInt());
EXPECT_THAT(Insts, Not(IsEmpty()));
}

} // namespace
} // namespace exegesis
} // namespace llvm

0 comments on commit 5fd3e75

Please sign in to comment.