blob: 90c5927ad2939a931d08fc7ed13b08ab1c0e7fc8 [file] [log] [blame]
John Brawnc4ed6002018-07-03 10:10:29 +00001//===-- Target.cpp ----------------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9#include "../Target.h"
10#include "../Latency.h"
11#include "AArch64.h"
Guillaume Chateletc96a97b2018-09-20 12:22:18 +000012#include "AArch64RegisterInfo.h"
John Brawnc4ed6002018-07-03 10:10:29 +000013
14namespace exegesis {
15
16namespace {
17
18class AArch64LatencyBenchmarkRunner : public LatencyBenchmarkRunner {
19public:
20 AArch64LatencyBenchmarkRunner(const LLVMState &State)
21 : LatencyBenchmarkRunner(State) {}
22
23private:
24 const char *getCounterName() const override {
25 // All AArch64 subtargets have CPU_CYCLES as the cycle counter name
26 return "CPU_CYCLES";
27 }
28};
29
Guillaume Chateletc96a97b2018-09-20 12:22:18 +000030namespace {
31
32static unsigned getLoadImmediateOpcode(unsigned RegBitWidth) {
33 switch (RegBitWidth) {
34 case 32:
35 return llvm::AArch64::MOVi32imm;
36 case 64:
37 return llvm::AArch64::MOVi64imm;
38 }
39 llvm_unreachable("Invalid Value Width");
40}
41
42// Generates instruction to load an immediate value into a register.
43static llvm::MCInst loadImmediate(unsigned Reg, unsigned RegBitWidth,
44 const llvm::APInt &Value) {
45 if (Value.getBitWidth() > RegBitWidth)
46 llvm_unreachable("Value must fit in the Register");
47 return llvm::MCInstBuilder(getLoadImmediateOpcode(RegBitWidth))
48 .addReg(Reg)
49 .addImm(Value.getZExtValue());
50}
51
52} // namespace
53
John Brawnc4ed6002018-07-03 10:10:29 +000054class ExegesisAArch64Target : public ExegesisTarget {
Guillaume Chatelet5ad29092018-09-18 11:26:27 +000055 std::vector<llvm::MCInst> setRegTo(const llvm::MCSubtargetInfo &STI,
Guillaume Chateletc96a97b2018-09-20 12:22:18 +000056 unsigned Reg,
57 const llvm::APInt &Value) const override {
58 if (llvm::AArch64::GPR32RegClass.contains(Reg))
59 return {loadImmediate(Reg, 32, Value)};
60 if (llvm::AArch64::GPR64RegClass.contains(Reg))
61 return {loadImmediate(Reg, 64, Value)};
62 llvm::errs() << "setRegTo is not implemented, results will be unreliable\n";
63 return {};
Guillaume Chatelet5ad29092018-09-18 11:26:27 +000064 }
65
John Brawnc4ed6002018-07-03 10:10:29 +000066 bool matchesArch(llvm::Triple::ArchType Arch) const override {
67 return Arch == llvm::Triple::aarch64 || Arch == llvm::Triple::aarch64_be;
68 }
Guillaume Chateletc96a97b2018-09-20 12:22:18 +000069
John Brawnc4ed6002018-07-03 10:10:29 +000070 void addTargetSpecificPasses(llvm::PassManagerBase &PM) const override {
71 // Function return is a pseudo-instruction that needs to be expanded
72 PM.add(llvm::createAArch64ExpandPseudoPass());
73 }
Guillaume Chateletc96a97b2018-09-20 12:22:18 +000074
John Brawnc4ed6002018-07-03 10:10:29 +000075 std::unique_ptr<BenchmarkRunner>
76 createLatencyBenchmarkRunner(const LLVMState &State) const override {
77 return llvm::make_unique<AArch64LatencyBenchmarkRunner>(State);
78 }
79};
80
81} // namespace
82
83static ExegesisTarget *getTheExegesisAArch64Target() {
84 static ExegesisAArch64Target Target;
85 return &Target;
86}
87
88void InitializeAArch64ExegesisTarget() {
89 ExegesisTarget::registerTarget(getTheExegesisAArch64Target());
90}
91
92} // namespace exegesis