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