LCOV - code coverage report
Current view: top level - lib/Target/AMDGPU/MCTargetDesc - SIMCCodeEmitter.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 135 144 93.8 %
Date: 2017-09-14 15:23:50 Functions: 12 13 92.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             : /// \brief 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         672 : class SIMCCodeEmitter : public  AMDGPUMCCodeEmitter {
      44             :   const MCRegisterInfo &MRI;
      45             : 
      46             :   /// \brief 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             :   SIMCCodeEmitter(const MCInstrInfo &mcii, const MCRegisterInfo &mri,
      52             :                   MCContext &ctx)
      53         672 :       : AMDGPUMCCodeEmitter(mcii), MRI(mri) {}
      54             :   SIMCCodeEmitter(const SIMCCodeEmitter &) = delete;
      55             :   SIMCCodeEmitter &operator=(const SIMCCodeEmitter &) = delete;
      56             : 
      57             :   /// \brief 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             :   /// \brief 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         336 : MCCodeEmitter *llvm::createSIMCCodeEmitter(const MCInstrInfo &MCII,
      85             :                                            const MCRegisterInfo &MRI,
      86             :                                            MCContext &Ctx) {
      87         672 :   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       49603 :   if (Imm >= 0 && Imm <= 64)
      95       11135 :     return 128 + Imm;
      96             : 
      97       38468 :   if (Imm >= -16 && Imm <= -1)
      98        9490 :     return 192 + std::abs(Imm);
      99             : 
     100             :   return 0;
     101             : }
     102             : 
     103        8778 : static uint32_t getLit16Encoding(uint16_t Val, const MCSubtargetInfo &STI) {
     104       17556 :   uint16_t IntImm = getIntInlineImmEncoding(static_cast<int16_t>(Val));
     105        8778 :   if (IntImm != 0)
     106        3501 :     return IntImm;
     107             : 
     108        5277 :   if (Val == 0x3800) // 0.5
     109             :     return 240;
     110             : 
     111        3521 :   if (Val == 0xB800) // -0.5
     112             :     return 241;
     113             : 
     114        3511 :   if (Val == 0x3C00) // 1.0
     115             :     return 242;
     116             : 
     117        3501 :   if (Val == 0xBC00) // -1.0
     118             :     return 243;
     119             : 
     120        3489 :   if (Val == 0x4000) // 2.0
     121             :     return 244;
     122             : 
     123        3481 :   if (Val == 0xC000) // -2.0
     124             :     return 245;
     125             : 
     126        3471 :   if (Val == 0x4400) // 4.0
     127             :     return 246;
     128             : 
     129        3461 :   if (Val == 0xC400) // -4.0
     130             :     return 247;
     131             : 
     132        1744 :   if (Val == 0x3118 && // 1.0 / (2.0 * pi)
     133          36 :       STI.getFeatureBits()[AMDGPU::FeatureInv2PiInlineImm])
     134             :     return 248;
     135             : 
     136             :   return 255;
     137             : }
     138             : 
     139       28113 : static uint32_t getLit32Encoding(uint32_t Val, const MCSubtargetInfo &STI) {
     140       40335 :   uint32_t IntImm = getIntInlineImmEncoding(static_cast<int32_t>(Val));
     141       12222 :   if (IntImm != 0)
     142             :     return IntImm;
     143             : 
     144       15891 :   if (Val == FloatToBits(0.5f))
     145             :     return 240;
     146             : 
     147       11031 :   if (Val == FloatToBits(-0.5f))
     148             :     return 241;
     149             : 
     150       11028 :   if (Val == FloatToBits(1.0f))
     151             :     return 242;
     152             : 
     153       10985 :   if (Val == FloatToBits(-1.0f))
     154             :     return 243;
     155             : 
     156       10919 :   if (Val == FloatToBits(2.0f))
     157             :     return 244;
     158             : 
     159       10917 :   if (Val == FloatToBits(-2.0f))
     160             :     return 245;
     161             : 
     162       10900 :   if (Val == FloatToBits(4.0f))
     163             :     return 246;
     164             : 
     165       10852 :   if (Val == FloatToBits(-4.0f))
     166             :     return 247;
     167             : 
     168        6167 :   if (Val == 0x3e22f983 && // 1.0 / (2.0 * pi)
     169         140 :       STI.getFeatureBits()[AMDGPU::FeatureInv2PiInlineImm])
     170             :     return 248;
     171             : 
     172             :   return 255;
     173             : }
     174             : 
     175       12712 : static uint32_t getLit64Encoding(uint64_t Val, const MCSubtargetInfo &STI) {
     176       17614 :   uint32_t IntImm = getIntInlineImmEncoding(static_cast<int64_t>(Val));
     177        4902 :   if (IntImm != 0)
     178             :     return IntImm;
     179             : 
     180        7810 :   if (Val == DoubleToBits(0.5))
     181             :     return 240;
     182             : 
     183        5433 :   if (Val == DoubleToBits(-0.5))
     184             :     return 241;
     185             : 
     186        5432 :   if (Val == DoubleToBits(1.0))
     187             :     return 242;
     188             : 
     189        5428 :   if (Val == DoubleToBits(-1.0))
     190             :     return 243;
     191             : 
     192        5393 :   if (Val == DoubleToBits(2.0))
     193             :     return 244;
     194             : 
     195        5391 :   if (Val == DoubleToBits(-2.0))
     196             :     return 245;
     197             : 
     198        5390 :   if (Val == DoubleToBits(4.0))
     199             :     return 246;
     200             : 
     201        5358 :   if (Val == DoubleToBits(-4.0))
     202             :     return 247;
     203             : 
     204        3048 :   if (Val == 0x3fc45f306dc9c882 && // 1.0 / (2.0 * pi)
     205          42 :       STI.getFeatureBits()[AMDGPU::FeatureInv2PiInlineImm])
     206             :     return 248;
     207             : 
     208             :   return 255;
     209             : }
     210             : 
     211      100149 : uint32_t SIMCCodeEmitter::getLitEncoding(const MCOperand &MO,
     212             :                                          const MCOperandInfo &OpInfo,
     213             :                                          const MCSubtargetInfo &STI) const {
     214             :   int64_t Imm;
     215      100149 :   if (MO.isExpr()) {
     216         232 :     const auto *C = dyn_cast<MCConstantExpr>(MO.getExpr());
     217             :     if (!C)
     218             :       return 255;
     219             : 
     220           4 :     Imm = C->getValue();
     221             :   } else {
     222             : 
     223             :     assert(!MO.isFPImm());
     224             : 
     225       99921 :     if (!MO.isImm())
     226             :       return ~0;
     227             : 
     228       49599 :     Imm = MO.getImm();
     229             :   }
     230             : 
     231       49603 :   switch (OpInfo.OperandType) {
     232       28113 :   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       28113 :     return getLit32Encoding(static_cast<uint32_t>(Imm), STI);
     237             : 
     238       12712 :   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       12712 :     return getLit64Encoding(static_cast<uint64_t>(Imm), STI);
     243             : 
     244        8625 :   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        8625 :     return getLit16Encoding(static_cast<uint16_t>(Imm), STI);
     251             : 
     252         153 :   case AMDGPU::OPERAND_REG_INLINE_C_V2INT16:
     253             :   case AMDGPU::OPERAND_REG_INLINE_C_V2FP16: {
     254         153 :     uint16_t Lo16 = static_cast<uint16_t>(Imm);
     255         153 :     uint32_t Encoding = getLit16Encoding(Lo16, STI);
     256             :     return Encoding;
     257             :   }
     258           0 :   default:
     259           0 :     llvm_unreachable("invalid operand size");
     260             :   }
     261             : }
     262             : 
     263      186039 : void SIMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
     264             :                                        SmallVectorImpl<MCFixup> &Fixups,
     265             :                                        const MCSubtargetInfo &STI) const {
     266      372078 :   verifyInstructionPredicates(MI,
     267             :                               computeAvailableFeatures(STI.getFeatureBits()));
     268             : 
     269      186039 :   uint64_t Encoding = getBinaryCodeForInstr(MI, Fixups, STI);
     270      372078 :   const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
     271      186039 :   unsigned bytes = Desc.getSize();
     272             : 
     273     1440439 :   for (unsigned i = 0; i < bytes; i++) {
     274     1254400 :     OS.write((uint8_t) ((Encoding >> (8 * i)) & 0xff));
     275             :   }
     276             : 
     277      186039 :   if (bytes > 4)
     278             :     return;
     279             : 
     280             :   // Check for additional literals in SRC0/1/2 (Op 1/2/3)
     281      240284 :   for (unsigned i = 0, e = Desc.getNumOperands(); i < e; ++i) {
     282             : 
     283             :     // Check if this operand should be encoded as [SV]Src
     284      128828 :     if (!AMDGPU::isSISrcOperand(Desc, i))
     285       61979 :       continue;
     286             : 
     287             :     // Is this operand a literal immediate?
     288       66849 :     const MCOperand &Op = MI.getOperand(i);
     289       66849 :     if (getLitEncoding(Op, Desc.OpInfo[i], STI) != 255)
     290       61349 :       continue;
     291             : 
     292             :     // Yes! Encode it
     293        5500 :     int64_t Imm = 0;
     294             : 
     295        5500 :     if (Op.isImm())
     296        5387 :       Imm = Op.getImm();
     297         113 :     else if (Op.isExpr()) {
     298         114 :       if (const auto *C = dyn_cast<MCConstantExpr>(Op.getExpr()))
     299           1 :         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       27500 :     for (unsigned j = 0; j < 4; j++) {
     305       22000 :       OS.write((uint8_t) ((Imm >> (8 * j)) & 0xff));
     306             :     }
     307             : 
     308             :     // Only one literal value allowed
     309             :     break;
     310             :   }
     311             : }
     312             : 
     313         182 : unsigned SIMCCodeEmitter::getSOPPBrEncoding(const MCInst &MI, unsigned OpNo,
     314             :                                             SmallVectorImpl<MCFixup> &Fixups,
     315             :                                             const MCSubtargetInfo &STI) const {
     316         182 :   const MCOperand &MO = MI.getOperand(OpNo);
     317             : 
     318         182 :   if (MO.isExpr()) {
     319          30 :     const MCExpr *Expr = MO.getExpr();
     320          30 :     MCFixupKind Kind = (MCFixupKind)AMDGPU::fixup_si_sopp_br;
     321          60 :     Fixups.push_back(MCFixup::create(0, Expr, Kind, MI.getLoc()));
     322          30 :     return 0;
     323             :   }
     324             : 
     325         152 :   return getMachineOpValue(MI, MO, Fixups, STI);
     326             : }
     327             : 
     328             : unsigned
     329       37299 : SIMCCodeEmitter::getSDWASrcEncoding(const MCInst &MI, unsigned OpNo,
     330             :                                     SmallVectorImpl<MCFixup> &Fixups,
     331             :                                     const MCSubtargetInfo &STI) const {
     332             :   using namespace AMDGPU::SDWA;
     333             : 
     334       37299 :   uint64_t RegEnc = 0;
     335             : 
     336       37299 :   const MCOperand &MO = MI.getOperand(OpNo);
     337             : 
     338       37299 :   unsigned Reg = MO.getReg();
     339       74598 :   RegEnc |= MRI.getEncodingValue(Reg);
     340       37299 :   RegEnc &= SDWA9EncValues::SRC_VGPR_MASK;
     341       37299 :   if (AMDGPU::isSGPR(AMDGPU::mc2PseudoReg(Reg), &MRI)) {
     342        2903 :     RegEnc |= SDWA9EncValues::SRC_SGPR_MASK;
     343             :   }
     344       37299 :   return RegEnc;
     345             : }
     346             : 
     347             : unsigned
     348        4416 : SIMCCodeEmitter::getSDWAVopcDstEncoding(const MCInst &MI, unsigned OpNo,
     349             :                                         SmallVectorImpl<MCFixup> &Fixups,
     350             :                                         const MCSubtargetInfo &STI) const {
     351             :   using namespace AMDGPU::SDWA;
     352             : 
     353        4416 :   uint64_t RegEnc = 0;
     354             : 
     355        4416 :   const MCOperand &MO = MI.getOperand(OpNo);
     356             : 
     357        4416 :   unsigned Reg = MO.getReg();
     358        4416 :   if (Reg != AMDGPU::VCC) {
     359        8466 :     RegEnc |= MRI.getEncodingValue(Reg);
     360        4233 :     RegEnc &= SDWA9EncValues::VOPC_DST_SGPR_MASK;
     361        4233 :     RegEnc |= SDWA9EncValues::VOPC_DST_VCC_MASK;
     362             :   }
     363        4416 :   return RegEnc;
     364             : }
     365             : 
     366         138 : static bool needsPCRel(const MCExpr *Expr) {
     367         138 :   switch (Expr->getKind()) {
     368             :   case MCExpr::SymbolRef:
     369             :     return true;
     370          41 :   case MCExpr::Binary: {
     371          41 :     auto *BE = cast<MCBinaryExpr>(Expr);
     372          41 :     if (BE->getOpcode() == MCBinaryExpr::Sub)
     373             :       return false;
     374          26 :     return needsPCRel(BE->getLHS()) || needsPCRel(BE->getRHS());
     375             :   }
     376           0 :   case MCExpr::Unary:
     377           0 :     return needsPCRel(cast<MCUnaryExpr>(Expr)->getSubExpr());
     378           0 :   case MCExpr::Target:
     379             :   case MCExpr::Constant:
     380           0 :     return false;
     381             :   }
     382           0 :   llvm_unreachable("invalid kind");
     383             : }
     384             : 
     385      840020 : uint64_t SIMCCodeEmitter::getMachineOpValue(const MCInst &MI,
     386             :                                             const MCOperand &MO,
     387             :                                        SmallVectorImpl<MCFixup> &Fixups,
     388             :                                        const MCSubtargetInfo &STI) const {
     389      840020 :   if (MO.isReg())
     390      847912 :     return MRI.getEncodingValue(MO.getReg());
     391             : 
     392      416064 :   if (MO.isExpr() && MO.getExpr()->getKind() != MCExpr::Constant) {
     393             :     // FIXME: If this is expression is PCRel or not should not depend on what
     394             :     // the expression looks like. Given that this is just a general expression,
     395             :     // it should probably be FK_Data_4 and whatever is producing
     396             :     //
     397             :     //    s_add_u32 s2, s2, (extern_const_addrspace+16
     398             :     //
     399             :     // And expecting a PCRel should instead produce
     400             :     //
     401             :     // .Ltmp1:
     402             :     //   s_add_u32 s2, s2, (extern_const_addrspace+16)-.Ltmp1
     403             :     MCFixupKind Kind;
     404         112 :     if (needsPCRel(MO.getExpr()))
     405             :       Kind = FK_PCRel_4;
     406             :     else
     407          15 :       Kind = FK_Data_4;
     408         224 :     Fixups.push_back(MCFixup::create(4, MO.getExpr(), Kind, MI.getLoc()));
     409             :   }
     410             : 
     411             :   // Figure out the operand number, needed for isSrcOperand check
     412      416064 :   unsigned OpNo = 0;
     413     2132801 :   for (unsigned e = MI.getNumOperands(); OpNo < e; ++OpNo) {
     414     2132801 :     if (&MO == &MI.getOperand(OpNo))
     415             :       break;
     416             :   }
     417             : 
     418      832128 :   const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
     419      416064 :   if (AMDGPU::isSISrcOperand(Desc, OpNo)) {
     420       33300 :     uint32_t Enc = getLitEncoding(MO, Desc.OpInfo[OpNo], STI);
     421       33300 :     if (Enc != ~0U && (Enc != 255 || Desc.getSize() == 4))
     422       33300 :       return Enc;
     423             : 
     424      382764 :   } else if (MO.isImm())
     425      382764 :     return MO.getImm();
     426             : 
     427           0 :   llvm_unreachable("Encoding of this operand type is not supported yet.");
     428             :   return 0;
     429             : }

Generated by: LCOV version 1.13