Home | History | Annotate | Line # | Download | only in PowerPC
      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.
     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:
     29   ExegesisPowerPCTarget() : ExegesisTarget(PPCCpuPfmCounters) {}
     30 
     31 private:
     32   std::vector<MCInst> setRegTo(const MCSubtargetInfo &STI, unsigned Reg,
     33                                const APInt &Value) const override;
     34   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 
     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.
     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
     67 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 
     73 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 
     91 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 
    130 static ExegesisTarget *getTheExegesisPowerPCTarget() {
    131   static ExegesisPowerPCTarget Target;
    132   return &Target;
    133 }
    134 
    135 void InitializePowerPCExegesisTarget() {
    136   ExegesisTarget::registerTarget(getTheExegesisPowerPCTarget());
    137 }
    138 
    139 } // namespace exegesis
    140 } // namespace llvm
    141