xref: /llvm-project/llvm/tools/llvm-exegesis/lib/PowerPC/Target.cpp (revision ff1b01bb7897bf2401540096af775d35b12eb247)
1 //===-- Target.cpp ----------------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 // The PowerPC ExegesisTarget.
8 //===----------------------------------------------------------------------===//
9 #include "../Target.h"
10 #include "PPC.h"
11 #include "PPCRegisterInfo.h"
12 
13 #define GET_AVAILABLE_OPCODE_CHECKER
14 #include "PPCGenInstrInfo.inc"
15 
16 namespace llvm {
17 namespace exegesis {
18 
19 // Helper to fill a memory operand with a value.
20 static void setMemOp(InstructionTemplate &IT, int OpIdx,
21                      const MCOperand &OpVal) {
22   const auto Op = IT.getInstr().Operands[OpIdx];
23   assert(Op.isExplicit() && "invalid memory pattern");
24   IT.getValueFor(Op) = OpVal;
25 }
26 
27 #include "PPCGenExegesis.inc"
28 
29 namespace {
30 class ExegesisPowerPCTarget : public ExegesisTarget {
31 public:
32   ExegesisPowerPCTarget()
33       : ExegesisTarget(PPCCpuPfmCounters, PPC_MC::isOpcodeAvailable) {}
34 
35 private:
36   std::vector<MCInst> setRegTo(const MCSubtargetInfo &STI, MCRegister Reg,
37                                const APInt &Value) const override;
38   bool matchesArch(Triple::ArchType Arch) const override {
39     return Arch == Triple::ppc64le;
40   }
41   MCRegister getScratchMemoryRegister(const Triple &) const override;
42   void fillMemoryOperands(InstructionTemplate &IT, MCRegister Reg,
43                           unsigned Offset) const override;
44 };
45 } // end anonymous namespace
46 
47 static unsigned getLoadImmediateOpcode(unsigned RegBitWidth) {
48   switch (RegBitWidth) {
49   case 32:
50     return PPC::LI;
51   case 64:
52     return PPC::LI8;
53   }
54   llvm_unreachable("Invalid Value Width");
55 }
56 
57 // Generates instruction to load an immediate value into a register.
58 static MCInst loadImmediate(MCRegister Reg, unsigned RegBitWidth,
59                             const APInt &Value) {
60   if (Value.getBitWidth() > RegBitWidth)
61     llvm_unreachable("Value must fit in the Register");
62   // We don't really care the value in reg, ignore the 16 bit
63   // restriction for now.
64   // TODO: make sure we get the exact value in reg if needed.
65   return MCInstBuilder(getLoadImmediateOpcode(RegBitWidth))
66       .addReg(Reg)
67       .addImm(Value.getZExtValue());
68 }
69 
70 MCRegister
71 ExegesisPowerPCTarget::getScratchMemoryRegister(const Triple &TT) const {
72   // R13 is reserved as Thread Pointer, we won't use threading in benchmark, so
73   // use it as scratch memory register
74   return TT.isArch64Bit() ? PPC::X13 : PPC::R13;
75 }
76 
77 void ExegesisPowerPCTarget::fillMemoryOperands(InstructionTemplate &IT,
78                                                MCRegister Reg,
79                                                unsigned Offset) const {
80   int MemOpIdx = 0;
81   if (IT.getInstr().hasTiedRegisters())
82     MemOpIdx = 1;
83   int DispOpIdx = MemOpIdx + 1;
84   const auto DispOp = IT.getInstr().Operands[DispOpIdx];
85   if (DispOp.isReg())
86     // We don't really care about the real address in snippets,
87     // So hardcode X1 for X-form Memory Operations for simplicity.
88     // TODO: materialize the offset into a reggister
89     setMemOp(IT, DispOpIdx, MCOperand::createReg(PPC::X1));
90   else
91     setMemOp(IT, DispOpIdx, MCOperand::createImm(Offset)); // Disp
92   setMemOp(IT, MemOpIdx + 2, MCOperand::createReg(Reg));   // BaseReg
93 }
94 
95 std::vector<MCInst> ExegesisPowerPCTarget::setRegTo(const MCSubtargetInfo &STI,
96                                                     MCRegister Reg,
97                                                     const APInt &Value) const {
98   // X11 is optional use in function linkage, should be the least used one
99   // Use it as scratch reg to load immediate.
100   unsigned ScratchImmReg = PPC::X11;
101 
102   if (PPC::GPRCRegClass.contains(Reg))
103     return {loadImmediate(Reg, 32, Value)};
104   if (PPC::G8RCRegClass.contains(Reg))
105     return {loadImmediate(Reg, 64, Value)};
106   if (PPC::F4RCRegClass.contains(Reg))
107     return {loadImmediate(ScratchImmReg, 64, Value),
108             MCInstBuilder(PPC::MTVSRD).addReg(Reg).addReg(ScratchImmReg)};
109   // We don't care the real value in reg, so set 64 bits or duplicate 64 bits
110   // for simplicity.
111   // TODO: update these if we need a accurate 128 values in registers.
112   if (PPC::VRRCRegClass.contains(Reg))
113     return {loadImmediate(ScratchImmReg, 64, Value),
114             MCInstBuilder(PPC::MTVRD).addReg(Reg).addReg(ScratchImmReg)};
115   if (PPC::VSRCRegClass.contains(Reg))
116     return {loadImmediate(ScratchImmReg, 64, Value),
117             MCInstBuilder(PPC::MTVSRDD)
118                 .addReg(Reg)
119                 .addReg(ScratchImmReg)
120                 .addReg(ScratchImmReg)};
121   if (PPC::VFRCRegClass.contains(Reg))
122     return {loadImmediate(ScratchImmReg, 64, Value),
123             MCInstBuilder(PPC::MTVSRD).addReg(Reg).addReg(ScratchImmReg)};
124   // SPE not supported yet
125   if (PPC::SPERCRegClass.contains(Reg)) {
126     errs() << "Unsupported SPE Reg:" << Reg << "\n";
127     return {};
128   }
129   errs() << "setRegTo is not implemented, results will be unreliable:" << Reg
130          << "\n";
131   return {};
132 }
133 
134 static ExegesisTarget *getTheExegesisPowerPCTarget() {
135   static ExegesisPowerPCTarget Target;
136   return &Target;
137 }
138 
139 void InitializePowerPCExegesisTarget() {
140   ExegesisTarget::registerTarget(getTheExegesisPowerPCTarget());
141 }
142 
143 } // namespace exegesis
144 } // namespace llvm
145