LCOV - code coverage report
Current view: top level - lib/Target/AMDGPU/MCTargetDesc - SIMCCodeEmitter.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 108 137 78.8 %
Date: 2018-10-20 13:21:21 Functions: 10 12 83.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===-- SIMCCodeEmitter.cpp - SI Code Emitter -----------------------------===//
       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             : //
      10             : /// \file
      11             : /// The SI code emitter produces machine code that can be executed
      12             : /// directly on the GPU device.
      13             : //
      14             : //===----------------------------------------------------------------------===//
      15             : 
      16             : #include "AMDGPU.h"
      17             : #include "MCTargetDesc/AMDGPUFixupKinds.h"
      18             : #include "MCTargetDesc/AMDGPUMCCodeEmitter.h"
      19             : #include "MCTargetDesc/AMDGPUMCTargetDesc.h"
      20             : #include "Utils/AMDGPUBaseInfo.h"
      21             : #include "llvm/MC/MCCodeEmitter.h"
      22             : #include "llvm/MC/MCContext.h"
      23             : #include "llvm/MC/MCExpr.h"
      24             : #include "llvm/MC/MCFixup.h"
      25             : #include "llvm/MC/MCInst.h"
      26             : #include "llvm/MC/MCInstrDesc.h"
      27             : #include "llvm/MC/MCInstrInfo.h"
      28             : #include "llvm/MC/MCRegisterInfo.h"
      29             : #include "llvm/MC/MCSubtargetInfo.h"
      30             : #include "llvm/MC/MCSymbol.h"
      31             : #include "llvm/Support/Casting.h"
      32             : #include "llvm/Support/ErrorHandling.h"
      33             : #include "llvm/Support/MathExtras.h"
      34             : #include "llvm/Support/raw_ostream.h"
      35             : #include <cassert>
      36             : #include <cstdint>
      37             : #include <cstdlib>
      38             : 
      39             : using namespace llvm;
      40             : 
      41             : namespace {
      42             : 
      43             : class SIMCCodeEmitter : public  AMDGPUMCCodeEmitter {
      44             :   const MCRegisterInfo &MRI;
      45             : 
      46             :   /// Encode an fp or int literal
      47             :   uint32_t getLitEncoding(const MCOperand &MO, const MCOperandInfo &OpInfo,
      48             :                           const MCSubtargetInfo &STI) const;
      49             : 
      50             : public:
      51           0 :   SIMCCodeEmitter(const MCInstrInfo &mcii, const MCRegisterInfo &mri,
      52             :                   MCContext &ctx)
      53         479 :       : AMDGPUMCCodeEmitter(mcii), MRI(mri) {}
      54             :   SIMCCodeEmitter(const SIMCCodeEmitter &) = delete;
      55             :   SIMCCodeEmitter &operator=(const SIMCCodeEmitter &) = delete;
      56             : 
      57             :   /// Encode the instruction and write it to the OS.
      58             :   void encodeInstruction(const MCInst &MI, raw_ostream &OS,
      59             :                          SmallVectorImpl<MCFixup> &Fixups,
      60             :                          const MCSubtargetInfo &STI) const override;
      61             : 
      62             :   /// \returns the encoding for an MCOperand.
      63             :   uint64_t getMachineOpValue(const MCInst &MI, const MCOperand &MO,
      64             :                              SmallVectorImpl<MCFixup> &Fixups,
      65             :                              const MCSubtargetInfo &STI) const override;
      66             : 
      67             :   /// Use a fixup to encode the simm16 field for SOPP branch
      68             :   ///        instructions.
      69             :   unsigned getSOPPBrEncoding(const MCInst &MI, unsigned OpNo,
      70             :                              SmallVectorImpl<MCFixup> &Fixups,
      71             :                              const MCSubtargetInfo &STI) const override;
      72             : 
      73             :   unsigned getSDWASrcEncoding(const MCInst &MI, unsigned OpNo,
      74             :                               SmallVectorImpl<MCFixup> &Fixups,
      75             :                               const MCSubtargetInfo &STI) const override;
      76             : 
      77             :   unsigned getSDWAVopcDstEncoding(const MCInst &MI, unsigned OpNo,
      78             :                                   SmallVectorImpl<MCFixup> &Fixups,
      79             :                                   const MCSubtargetInfo &STI) const override;
      80             : };
      81             : 
      82             : } // end anonymous namespace
      83             : 
      84         479 : MCCodeEmitter *llvm::createSIMCCodeEmitter(const MCInstrInfo &MCII,
      85             :                                            const MCRegisterInfo &MRI,
      86             :                                            MCContext &Ctx) {
      87         479 :   return new SIMCCodeEmitter(MCII, MRI, Ctx);
      88             : }
      89             : 
      90             : // Returns the encoding value to use if the given integer is an integer inline
      91             : // immediate value, or 0 if it is not.
      92             : template <typename IntTy>
      93             : static uint32_t getIntInlineImmEncoding(IntTy Imm) {
      94       64766 :   if (Imm >= 0 && Imm <= 64)
      95       15373 :     return 128 + Imm;
      96             : 
      97       49393 :   if (Imm >= -16 && Imm <= -1)
      98       12461 :     return 192 + std::abs(Imm);
      99             : 
     100             :   return 0;
     101             : }
     102             : 
     103       12634 : static uint32_t getLit16Encoding(uint16_t Val, const MCSubtargetInfo &STI) {
     104       12634 :   uint16_t IntImm = getIntInlineImmEncoding(static_cast<int16_t>(Val));
     105       12634 :   if (IntImm != 0)
     106        5218 :     return IntImm;
     107             : 
     108        7416 :   if (Val == 0x3800) // 0.5
     109             :     return 240;
     110             : 
     111        4793 :   if (Val == 0xB800) // -0.5
     112             :     return 241;
     113             : 
     114        4783 :   if (Val == 0x3C00) // 1.0
     115             :     return 242;
     116             : 
     117        4773 :   if (Val == 0xBC00) // -1.0
     118             :     return 243;
     119             : 
     120        4761 :   if (Val == 0x4000) // 2.0
     121             :     return 244;
     122             : 
     123        4753 :   if (Val == 0xC000) // -2.0
     124             :     return 245;
     125             : 
     126        4743 :   if (Val == 0x4400) // 4.0
     127             :     return 246;
     128             : 
     129        4733 :   if (Val == 0xC400) // -4.0
     130             :     return 247;
     131             : 
     132        2146 :   if (Val == 0x3118 && // 1.0 / (2.0 * pi)
     133             :       STI.getFeatureBits()[AMDGPU::FeatureInv2PiInlineImm])
     134          18 :     return 248;
     135             : 
     136             :   return 255;
     137             : }
     138             : 
     139       37066 : static uint32_t getLit32Encoding(uint32_t Val, const MCSubtargetInfo &STI) {
     140       37066 :   uint32_t IntImm = getIntInlineImmEncoding(static_cast<int32_t>(Val));
     141       16776 :   if (IntImm != 0)
     142             :     return IntImm;
     143             : 
     144       20290 :   if (Val == FloatToBits(0.5f))
     145             :     return 240;
     146             : 
     147       13917 :   if (Val == FloatToBits(-0.5f))
     148             :     return 241;
     149             : 
     150       13914 :   if (Val == FloatToBits(1.0f))
     151             :     return 242;
     152             : 
     153       13851 :   if (Val == FloatToBits(-1.0f))
     154             :     return 243;
     155             : 
     156       13785 :   if (Val == FloatToBits(2.0f))
     157             :     return 244;
     158             : 
     159       13779 :   if (Val == FloatToBits(-2.0f))
     160             :     return 245;
     161             : 
     162       13762 :   if (Val == FloatToBits(4.0f))
     163             :     return 246;
     164             : 
     165       13711 :   if (Val == FloatToBits(-4.0f))
     166             :     return 247;
     167             : 
     168        7401 :   if (Val == 0x3e22f983 && // 1.0 / (2.0 * pi)
     169             :       STI.getFeatureBits()[AMDGPU::FeatureInv2PiInlineImm])
     170          42 :     return 248;
     171             : 
     172             :   return 255;
     173             : }
     174             : 
     175       15066 : static uint32_t getLit64Encoding(uint64_t Val, const MCSubtargetInfo &STI) {
     176       15066 :   uint32_t IntImm = getIntInlineImmEncoding(static_cast<int64_t>(Val));
     177        5840 :   if (IntImm != 0)
     178             :     return IntImm;
     179             : 
     180        9226 :   if (Val == DoubleToBits(0.5))
     181             :     return 240;
     182             : 
     183        6409 :   if (Val == DoubleToBits(-0.5))
     184             :     return 241;
     185             : 
     186        6408 :   if (Val == DoubleToBits(1.0))
     187             :     return 242;
     188             : 
     189        6404 :   if (Val == DoubleToBits(-1.0))
     190             :     return 243;
     191             : 
     192        6369 :   if (Val == DoubleToBits(2.0))
     193             :     return 244;
     194             : 
     195        6367 :   if (Val == DoubleToBits(-2.0))
     196             :     return 245;
     197             : 
     198        6366 :   if (Val == DoubleToBits(4.0))
     199             :     return 246;
     200             : 
     201        6334 :   if (Val == DoubleToBits(-4.0))
     202             :     return 247;
     203             : 
     204        3563 :   if (Val == 0x3fc45f306dc9c882 && // 1.0 / (2.0 * pi)
     205             :       STI.getFeatureBits()[AMDGPU::FeatureInv2PiInlineImm])
     206          21 :     return 248;
     207             : 
     208             :   return 255;
     209             : }
     210             : 
     211           0 : uint32_t SIMCCodeEmitter::getLitEncoding(const MCOperand &MO,
     212             :                                          const MCOperandInfo &OpInfo,
     213             :                                          const MCSubtargetInfo &STI) const {
     214             :   int64_t Imm;
     215           0 :   if (MO.isExpr()) {
     216           0 :     const auto *C = dyn_cast<MCConstantExpr>(MO.getExpr());
     217             :     if (!C)
     218           0 :       return 255;
     219             : 
     220           0 :     Imm = C->getValue();
     221             :   } else {
     222             : 
     223             :     assert(!MO.isFPImm());
     224             : 
     225           0 :     if (!MO.isImm())
     226           0 :       return ~0;
     227             : 
     228           0 :     Imm = MO.getImm();
     229             :   }
     230             : 
     231           0 :   switch (OpInfo.OperandType) {
     232           0 :   case AMDGPU::OPERAND_REG_IMM_INT32:
     233             :   case AMDGPU::OPERAND_REG_IMM_FP32:
     234             :   case AMDGPU::OPERAND_REG_INLINE_C_INT32:
     235             :   case AMDGPU::OPERAND_REG_INLINE_C_FP32:
     236           0 :     return getLit32Encoding(static_cast<uint32_t>(Imm), STI);
     237             : 
     238           0 :   case AMDGPU::OPERAND_REG_IMM_INT64:
     239             :   case AMDGPU::OPERAND_REG_IMM_FP64:
     240             :   case AMDGPU::OPERAND_REG_INLINE_C_INT64:
     241             :   case AMDGPU::OPERAND_REG_INLINE_C_FP64:
     242           0 :     return getLit64Encoding(static_cast<uint64_t>(Imm), STI);
     243             : 
     244           0 :   case AMDGPU::OPERAND_REG_IMM_INT16:
     245             :   case AMDGPU::OPERAND_REG_IMM_FP16:
     246             :   case AMDGPU::OPERAND_REG_INLINE_C_INT16:
     247             :   case AMDGPU::OPERAND_REG_INLINE_C_FP16:
     248             :     // FIXME Is this correct? What do inline immediates do on SI for f16 src
     249             :     // which does not have f16 support?
     250           0 :     return getLit16Encoding(static_cast<uint16_t>(Imm), STI);
     251             : 
     252           0 :   case AMDGPU::OPERAND_REG_INLINE_C_V2INT16:
     253             :   case AMDGPU::OPERAND_REG_INLINE_C_V2FP16: {
     254           0 :     uint16_t Lo16 = static_cast<uint16_t>(Imm);
     255           0 :     uint32_t Encoding = getLit16Encoding(Lo16, STI);
     256           0 :     return Encoding;
     257             :   }
     258           0 :   default:
     259           0 :     llvm_unreachable("invalid operand size");
     260             :   }
     261             : }
     262             : 
     263      245427 : void SIMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
     264             :                                        SmallVectorImpl<MCFixup> &Fixups,
     265             :                                        const MCSubtargetInfo &STI) const {
     266      490854 :   verifyInstructionPredicates(MI,
     267             :                               computeAvailableFeatures(STI.getFeatureBits()));
     268             : 
     269      245427 :   uint64_t Encoding = getBinaryCodeForInstr(MI, Fixups, STI);
     270      245427 :   const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
     271      245427 :   unsigned bytes = Desc.getSize();
     272             : 
     273     1926183 :   for (unsigned i = 0; i < bytes; i++) {
     274     1680756 :     OS.write((uint8_t) ((Encoding >> (8 * i)) & 0xff));
     275             :   }
     276             : 
     277      245427 :   if (bytes > 4)
     278             :     return;
     279             : 
     280             :   // Check for additional literals in SRC0/1/2 (Op 1/2/3)
     281      219911 :   for (unsigned i = 0, e = Desc.getNumOperands(); i < e; ++i) {
     282             : 
     283             :     // Check if this operand should be encoded as [SV]Src
     284      155887 :     if (!AMDGPU::isSISrcOperand(Desc, i))
     285             :       continue;
     286             : 
     287             :     // Is this operand a literal immediate?
     288             :     const MCOperand &Op = MI.getOperand(i);
     289       80499 :     if (getLitEncoding(Op, Desc.OpInfo[i], STI) != 255)
     290             :       continue;
     291             : 
     292             :     // Yes! Encode it
     293             :     int64_t Imm = 0;
     294             : 
     295        6641 :     if (Op.isImm())
     296        6512 :       Imm = Op.getImm();
     297         129 :     else if (Op.isExpr()) {
     298         129 :       if (const auto *C = dyn_cast<MCConstantExpr>(Op.getExpr()))
     299           2 :         Imm = C->getValue();
     300             : 
     301             :     } else if (!Op.isExpr()) // Exprs will be replaced with a fixup value.
     302           0 :       llvm_unreachable("Must be immediate or expr");
     303             : 
     304       33205 :     for (unsigned j = 0; j < 4; j++) {
     305       26564 :       OS.write((uint8_t) ((Imm >> (8 * j)) & 0xff));
     306             :     }
     307             : 
     308             :     // Only one literal value allowed
     309             :     break;
     310             :   }
     311             : }
     312             : 
     313         233 : unsigned SIMCCodeEmitter::getSOPPBrEncoding(const MCInst &MI, unsigned OpNo,
     314             :                                             SmallVectorImpl<MCFixup> &Fixups,
     315             :                                             const MCSubtargetInfo &STI) const {
     316             :   const MCOperand &MO = MI.getOperand(OpNo);
     317             : 
     318         233 :   if (MO.isExpr()) {
     319          59 :     const MCExpr *Expr = MO.getExpr();
     320             :     MCFixupKind Kind = (MCFixupKind)AMDGPU::fixup_si_sopp_br;
     321         118 :     Fixups.push_back(MCFixup::create(0, Expr, Kind, MI.getLoc()));
     322          59 :     return 0;
     323             :   }
     324             : 
     325         174 :   return getMachineOpValue(MI, MO, Fixups, STI);
     326             : }
     327             : 
     328             : unsigned
     329       66749 : SIMCCodeEmitter::getSDWASrcEncoding(const MCInst &MI, unsigned OpNo,
     330             :                                     SmallVectorImpl<MCFixup> &Fixups,
     331             :                                     const MCSubtargetInfo &STI) const {
     332             :   using namespace AMDGPU::SDWA;
     333             : 
     334             :   uint64_t RegEnc = 0;
     335             : 
     336             :   const MCOperand &MO = MI.getOperand(OpNo);
     337             : 
     338       66749 :   if (MO.isReg()) {
     339       63804 :     unsigned Reg = MO.getReg();
     340       63804 :     RegEnc |= MRI.getEncodingValue(Reg);
     341       63804 :     RegEnc &= SDWA9EncValues::SRC_VGPR_MASK;
     342       63804 :     if (AMDGPU::isSGPR(AMDGPU::mc2PseudoReg(Reg), &MRI)) {
     343        6313 :       RegEnc |= SDWA9EncValues::SRC_SGPR_MASK;
     344             :     }
     345       63804 :     return RegEnc;
     346             :   } else {
     347        2945 :     const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
     348        2945 :     uint32_t Enc = getLitEncoding(MO, Desc.OpInfo[OpNo], STI);
     349        2945 :     if (Enc != ~0U && Enc != 255) {
     350        2945 :       return Enc | SDWA9EncValues::SRC_SGPR_MASK;
     351             :     }
     352             :   }
     353             : 
     354           0 :   llvm_unreachable("Unsupported operand kind");
     355             :   return 0;
     356             : }
     357             : 
     358             : unsigned
     359       14478 : SIMCCodeEmitter::getSDWAVopcDstEncoding(const MCInst &MI, unsigned OpNo,
     360             :                                         SmallVectorImpl<MCFixup> &Fixups,
     361             :                                         const MCSubtargetInfo &STI) const {
     362             :   using namespace AMDGPU::SDWA;
     363             : 
     364             :   uint64_t RegEnc = 0;
     365             : 
     366             :   const MCOperand &MO = MI.getOperand(OpNo);
     367             : 
     368       14478 :   unsigned Reg = MO.getReg();
     369       14478 :   if (Reg != AMDGPU::VCC) {
     370       14028 :     RegEnc |= MRI.getEncodingValue(Reg);
     371             :     RegEnc &= SDWA9EncValues::VOPC_DST_SGPR_MASK;
     372       14028 :     RegEnc |= SDWA9EncValues::VOPC_DST_VCC_MASK;
     373             :   }
     374       14478 :   return RegEnc;
     375             : }
     376             : 
     377         161 : static bool needsPCRel(const MCExpr *Expr) {
     378         161 :   switch (Expr->getKind()) {
     379             :   case MCExpr::SymbolRef:
     380             :     return true;
     381             :   case MCExpr::Binary: {
     382             :     auto *BE = cast<MCBinaryExpr>(Expr);
     383          51 :     if (BE->getOpcode() == MCBinaryExpr::Sub)
     384             :       return false;
     385          34 :     return needsPCRel(BE->getLHS()) || needsPCRel(BE->getRHS());
     386             :   }
     387             :   case MCExpr::Unary:
     388           0 :     return needsPCRel(cast<MCUnaryExpr>(Expr)->getSubExpr());
     389           0 :   case MCExpr::Target:
     390             :   case MCExpr::Constant:
     391           0 :     return false;
     392             :   }
     393           0 :   llvm_unreachable("invalid kind");
     394             : }
     395             : 
     396     1141814 : uint64_t SIMCCodeEmitter::getMachineOpValue(const MCInst &MI,
     397             :                                             const MCOperand &MO,
     398             :                                        SmallVectorImpl<MCFixup> &Fixups,
     399             :                                        const MCSubtargetInfo &STI) const {
     400     1141814 :   if (MO.isReg())
     401     1083518 :     return MRI.getEncodingValue(MO.getReg());
     402             : 
     403      600055 :   if (MO.isExpr() && MO.getExpr()->getKind() != MCExpr::Constant) {
     404             :     // FIXME: If this is expression is PCRel or not should not depend on what
     405             :     // the expression looks like. Given that this is just a general expression,
     406             :     // it should probably be FK_Data_4 and whatever is producing
     407             :     //
     408             :     //    s_add_u32 s2, s2, (extern_const_addrspace+16
     409             :     //
     410             :     // And expecting a PCRel should instead produce
     411             :     //
     412             :     // .Ltmp1:
     413             :     //   s_add_u32 s2, s2, (extern_const_addrspace+16)-.Ltmp1
     414             :     MCFixupKind Kind;
     415         127 :     if (needsPCRel(MO.getExpr()))
     416             :       Kind = FK_PCRel_4;
     417             :     else
     418             :       Kind = FK_Data_4;
     419         254 :     Fixups.push_back(MCFixup::create(4, MO.getExpr(), Kind, MI.getLoc()));
     420             :   }
     421             : 
     422             :   // Figure out the operand number, needed for isSrcOperand check
     423             :   unsigned OpNo = 0;
     424     3152606 :   for (unsigned e = MI.getNumOperands(); OpNo < e; ++OpNo) {
     425     3152606 :     if (&MO == &MI.getOperand(OpNo))
     426             :       break;
     427             :   }
     428             : 
     429      600055 :   const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
     430      600055 :   if (AMDGPU::isSISrcOperand(Desc, OpNo)) {
     431       41681 :     uint32_t Enc = getLitEncoding(MO, Desc.OpInfo[OpNo], STI);
     432       41681 :     if (Enc != ~0U && (Enc != 255 || Desc.getSize() == 4))
     433       41681 :       return Enc;
     434             : 
     435      558374 :   } else if (MO.isImm())
     436      558374 :     return MO.getImm();
     437             : 
     438           0 :   llvm_unreachable("Encoding of this operand type is not supported yet.");
     439             :   return 0;
     440             : }
     441             : 
     442             : #define ENABLE_INSTR_PREDICATE_VERIFIER
     443             : #include "AMDGPUGenMCCodeEmitter.inc"

Generated by: LCOV version 1.13