blob: be8f0b41ede24fdb57c5f3996fb8db977441acb3 [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
Fangrui Song32401af2018-10-22 17:10:47 +000014namespace llvm {
John Brawnc4ed6002018-07-03 10:10:29 +000015namespace exegesis {
16
17namespace {
18
19class AArch64LatencyBenchmarkRunner : public LatencyBenchmarkRunner {
20public:
21 AArch64LatencyBenchmarkRunner(const LLVMState &State)
22 : LatencyBenchmarkRunner(State) {}
23
24private:
25 const char *getCounterName() const override {
26 // All AArch64 subtargets have CPU_CYCLES as the cycle counter name
27 return "CPU_CYCLES";
28 }
29};
30
Guillaume Chateletc96a97b2018-09-20 12:22:18 +000031namespace {
32
33static unsigned getLoadImmediateOpcode(unsigned RegBitWidth) {
34 switch (RegBitWidth) {
35 case 32:
36 return llvm::AArch64::MOVi32imm;
37 case 64:
38 return llvm::AArch64::MOVi64imm;
39 }
40 llvm_unreachable("Invalid Value Width");
41}
42
43// Generates instruction to load an immediate value into a register.
44static llvm::MCInst loadImmediate(unsigned Reg, unsigned RegBitWidth,
45 const llvm::APInt &Value) {
46 if (Value.getBitWidth() > RegBitWidth)
47 llvm_unreachable("Value must fit in the Register");
48 return llvm::MCInstBuilder(getLoadImmediateOpcode(RegBitWidth))
49 .addReg(Reg)
50 .addImm(Value.getZExtValue());
51}
52
53} // namespace
54
John Brawnc4ed6002018-07-03 10:10:29 +000055class ExegesisAArch64Target : public ExegesisTarget {
Guillaume Chatelet5ad29092018-09-18 11:26:27 +000056 std::vector<llvm::MCInst> setRegTo(const llvm::MCSubtargetInfo &STI,
Guillaume Chateletc96a97b2018-09-20 12:22:18 +000057 unsigned Reg,
58 const llvm::APInt &Value) const override {
59 if (llvm::AArch64::GPR32RegClass.contains(Reg))
60 return {loadImmediate(Reg, 32, Value)};
61 if (llvm::AArch64::GPR64RegClass.contains(Reg))
62 return {loadImmediate(Reg, 64, Value)};
63 llvm::errs() << "setRegTo is not implemented, results will be unreliable\n";
64 return {};
Guillaume Chatelet5ad29092018-09-18 11:26:27 +000065 }
66
John Brawnc4ed6002018-07-03 10:10:29 +000067 bool matchesArch(llvm::Triple::ArchType Arch) const override {
68 return Arch == llvm::Triple::aarch64 || Arch == llvm::Triple::aarch64_be;
69 }
Guillaume Chateletc96a97b2018-09-20 12:22:18 +000070
John Brawnc4ed6002018-07-03 10:10:29 +000071 void addTargetSpecificPasses(llvm::PassManagerBase &PM) const override {
72 // Function return is a pseudo-instruction that needs to be expanded
73 PM.add(llvm::createAArch64ExpandPseudoPass());
74 }
Guillaume Chateletc96a97b2018-09-20 12:22:18 +000075
John Brawnc4ed6002018-07-03 10:10:29 +000076 std::unique_ptr<BenchmarkRunner>
77 createLatencyBenchmarkRunner(const LLVMState &State) const override {
78 return llvm::make_unique<AArch64LatencyBenchmarkRunner>(State);
79 }
80};
81
82} // namespace
83
84static ExegesisTarget *getTheExegesisAArch64Target() {
85 static ExegesisAArch64Target Target;
86 return &Target;
87}
88
89void InitializeAArch64ExegesisTarget() {
90 ExegesisTarget::registerTarget(getTheExegesisAArch64Target());
91}
92
93} // namespace exegesis
Fangrui Song32401af2018-10-22 17:10:47 +000094} // namespace llvm