LCOV - code coverage report
Current view: top level - lib/Target/AMDGPU - AMDGPUMCInstLower.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 125 142 88.0 %
Date: 2018-06-17 00:07:59 Functions: 10 10 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- AMDGPUMCInstLower.cpp - Lower AMDGPU MachineInstr to an MCInst -----===//
       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             : /// Code to lower AMDGPU MachineInstrs to their corresponding MCInst.
      12             : //
      13             : //===----------------------------------------------------------------------===//
      14             : //
      15             : 
      16             : #include "AMDGPUAsmPrinter.h"
      17             : #include "AMDGPUSubtarget.h"
      18             : #include "AMDGPUTargetMachine.h"
      19             : #include "InstPrinter/AMDGPUInstPrinter.h"
      20             : #include "MCTargetDesc/AMDGPUMCTargetDesc.h"
      21             : #include "R600AsmPrinter.h"
      22             : #include "SIInstrInfo.h"
      23             : #include "llvm/CodeGen/MachineBasicBlock.h"
      24             : #include "llvm/CodeGen/MachineInstr.h"
      25             : #include "llvm/IR/Constants.h"
      26             : #include "llvm/IR/Function.h"
      27             : #include "llvm/IR/GlobalVariable.h"
      28             : #include "llvm/MC/MCCodeEmitter.h"
      29             : #include "llvm/MC/MCContext.h"
      30             : #include "llvm/MC/MCExpr.h"
      31             : #include "llvm/MC/MCInst.h"
      32             : #include "llvm/MC/MCObjectStreamer.h"
      33             : #include "llvm/MC/MCStreamer.h"
      34             : #include "llvm/Support/ErrorHandling.h"
      35             : #include "llvm/Support/Format.h"
      36             : #include <algorithm>
      37             : 
      38             : using namespace llvm;
      39             : 
      40             : namespace {
      41             : 
      42             : class AMDGPUMCInstLower {
      43             :   MCContext &Ctx;
      44             :   const TargetSubtargetInfo &ST;
      45             :   const AsmPrinter &AP;
      46             : 
      47             :   const MCExpr *getLongBranchBlockExpr(const MachineBasicBlock &SrcBB,
      48             :                                        const MachineOperand &MO) const;
      49             : 
      50             : public:
      51             :   AMDGPUMCInstLower(MCContext &ctx, const TargetSubtargetInfo &ST,
      52             :                     const AsmPrinter &AP);
      53             : 
      54             :   bool lowerOperand(const MachineOperand &MO, MCOperand &MCOp) const;
      55             : 
      56             :   /// Lower a MachineInstr to an MCInst
      57             :   void lower(const MachineInstr *MI, MCInst &OutMI) const;
      58             : 
      59             : };
      60             : 
      61             : class R600MCInstLower : public AMDGPUMCInstLower {
      62             : public:
      63             :   R600MCInstLower(MCContext &ctx, const R600Subtarget &ST,
      64             :                   const AsmPrinter &AP);
      65             : 
      66             :   /// Lower a MachineInstr to an MCInst
      67             :   void lower(const MachineInstr *MI, MCInst &OutMI) const;
      68             : };
      69             : 
      70             : 
      71             : } // End anonymous namespace
      72             : 
      73             : #include "AMDGPUGenMCPseudoLowering.inc"
      74             : 
      75             : AMDGPUMCInstLower::AMDGPUMCInstLower(MCContext &ctx,
      76             :                                      const TargetSubtargetInfo &st,
      77      413892 :                                      const AsmPrinter &ap):
      78      413892 :   Ctx(ctx), ST(st), AP(ap) { }
      79             : 
      80             : static MCSymbolRefExpr::VariantKind getVariantKind(unsigned MOFlags) {
      81             :   switch (MOFlags) {
      82             :   default:
      83             :     return MCSymbolRefExpr::VK_None;
      84             :   case SIInstrInfo::MO_GOTPCREL:
      85             :     return MCSymbolRefExpr::VK_GOTPCREL;
      86             :   case SIInstrInfo::MO_GOTPCREL32_LO:
      87             :     return MCSymbolRefExpr::VK_AMDGPU_GOTPCREL32_LO;
      88             :   case SIInstrInfo::MO_GOTPCREL32_HI:
      89             :     return MCSymbolRefExpr::VK_AMDGPU_GOTPCREL32_HI;
      90             :   case SIInstrInfo::MO_REL32_LO:
      91             :     return MCSymbolRefExpr::VK_AMDGPU_REL32_LO;
      92             :   case SIInstrInfo::MO_REL32_HI:
      93             :     return MCSymbolRefExpr::VK_AMDGPU_REL32_HI;
      94             :   }
      95             : }
      96             : 
      97          31 : const MCExpr *AMDGPUMCInstLower::getLongBranchBlockExpr(
      98             :   const MachineBasicBlock &SrcBB,
      99             :   const MachineOperand &MO) const {
     100             :   const MCExpr *DestBBSym
     101          31 :     = MCSymbolRefExpr::create(MO.getMBB()->getSymbol(), Ctx);
     102          31 :   const MCExpr *SrcBBSym = MCSymbolRefExpr::create(SrcBB.getSymbol(), Ctx);
     103             : 
     104             :   assert(SrcBB.front().getOpcode() == AMDGPU::S_GETPC_B64 &&
     105             :          ST.getInstrInfo()->get(AMDGPU::S_GETPC_B64).Size == 4);
     106             : 
     107             :   // s_getpc_b64 returns the address of next instruction.
     108          31 :   const MCConstantExpr *One = MCConstantExpr::create(4, Ctx);
     109          31 :   SrcBBSym = MCBinaryExpr::createAdd(SrcBBSym, One, Ctx);
     110             : 
     111          31 :   if (MO.getTargetFlags() == AMDGPU::TF_LONG_BRANCH_FORWARD)
     112          23 :     return MCBinaryExpr::createSub(DestBBSym, SrcBBSym, Ctx);
     113             : 
     114             :   assert(MO.getTargetFlags() == AMDGPU::TF_LONG_BRANCH_BACKWARD);
     115           8 :   return MCBinaryExpr::createSub(SrcBBSym, DestBBSym, Ctx);
     116             : }
     117             : 
     118     2038472 : bool AMDGPUMCInstLower::lowerOperand(const MachineOperand &MO,
     119             :                                      MCOperand &MCOp) const {
     120     2038472 :   switch (MO.getType()) {
     121           0 :   default:
     122           0 :     llvm_unreachable("unknown operand type");
     123     1257287 :   case MachineOperand::MO_Immediate:
     124     2514574 :     MCOp = MCOperand::createImm(MO.getImm());
     125     1257287 :     return true;
     126      778316 :   case MachineOperand::MO_Register:
     127     1556632 :     MCOp = MCOperand::createReg(AMDGPU::getMCReg(MO.getReg(), ST));
     128      778316 :     return true;
     129             :   case MachineOperand::MO_MachineBasicBlock: {
     130         904 :     if (MO.getTargetFlags() != 0) {
     131          31 :       MCOp = MCOperand::createExpr(
     132          31 :         getLongBranchBlockExpr(*MO.getParent()->getParent(), MO));
     133             :     } else {
     134         873 :       MCOp = MCOperand::createExpr(
     135         873 :         MCSymbolRefExpr::create(MO.getMBB()->getSymbol(), Ctx));
     136             :     }
     137             : 
     138             :     return true;
     139             :   }
     140        1081 :   case MachineOperand::MO_GlobalAddress: {
     141        1081 :     const GlobalValue *GV = MO.getGlobal();
     142             :     SmallString<128> SymbolName;
     143        1081 :     AP.getNameWithPrefix(SymbolName, GV);
     144        2162 :     MCSymbol *Sym = Ctx.getOrCreateSymbol(SymbolName);
     145             :     const MCExpr *SymExpr =
     146        2162 :       MCSymbolRefExpr::create(Sym, getVariantKind(MO.getTargetFlags()),Ctx);
     147        1081 :     const MCExpr *Expr = MCBinaryExpr::createAdd(SymExpr,
     148        2162 :       MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);
     149        1081 :     MCOp = MCOperand::createExpr(Expr);
     150             :     return true;
     151             :   }
     152         884 :   case MachineOperand::MO_ExternalSymbol: {
     153        1768 :     MCSymbol *Sym = Ctx.getOrCreateSymbol(StringRef(MO.getSymbolName()));
     154             :     Sym->setExternal(true);
     155         884 :     const MCSymbolRefExpr *Expr = MCSymbolRefExpr::create(Sym, Ctx);
     156         884 :     MCOp = MCOperand::createExpr(Expr);
     157         884 :     return true;
     158             :   }
     159             :   case MachineOperand::MO_RegisterMask:
     160             :     // Regmasks are like implicit defs.
     161             :     return false;
     162             :   }
     163             : }
     164             : 
     165      330761 : void AMDGPUMCInstLower::lower(const MachineInstr *MI, MCInst &OutMI) const {
     166      330761 :   unsigned Opcode = MI->getOpcode();
     167      330761 :   const auto *TII = static_cast<const SIInstrInfo*>(ST.getInstrInfo());
     168             : 
     169             :   // FIXME: Should be able to handle this with emitPseudoExpansionLowering. We
     170             :   // need to select it to the subtarget specific version, and there's no way to
     171             :   // do that with a single pseudo source operation.
     172      330761 :   if (Opcode == AMDGPU::S_SETPC_B64_return)
     173             :     Opcode = AMDGPU::S_SETPC_B64;
     174      329400 :   else if (Opcode == AMDGPU::SI_CALL) {
     175             :     // SI_CALL is just S_SWAPPC_B64 with an additional operand to track the
     176             :     // called function (which we need to remove here).
     177         453 :     OutMI.setOpcode(TII->pseudoToMCOpcode(AMDGPU::S_SWAPPC_B64));
     178             :     MCOperand Dest, Src;
     179         453 :     lowerOperand(MI->getOperand(0), Dest);
     180         906 :     lowerOperand(MI->getOperand(1), Src);
     181             :     OutMI.addOperand(Dest);
     182             :     OutMI.addOperand(Src);
     183             :     return;
     184      328947 :   } else if (Opcode == AMDGPU::SI_TCRETURN) {
     185             :     // TODO: How to use branch immediate and avoid register+add?
     186             :     Opcode = AMDGPU::S_SETPC_B64;
     187             :   }
     188             : 
     189      330308 :   int MCOpcode = TII->pseudoToMCOpcode(Opcode);
     190      330308 :   if (MCOpcode == -1) {
     191           0 :     LLVMContext &C = MI->getParent()->getParent()->getFunction().getContext();
     192           0 :     C.emitError("AMDGPUMCInstLower::lower - Pseudo instruction doesn't have "
     193           0 :                 "a target-specific version: " + Twine(MI->getOpcode()));
     194             :   }
     195             : 
     196      330308 :   OutMI.setOpcode(MCOpcode);
     197             : 
     198     2395094 :   for (const MachineOperand &MO : MI->explicit_operands()) {
     199             :     MCOperand MCOp;
     200     1032393 :     lowerOperand(MO, MCOp);
     201             :     OutMI.addOperand(MCOp);
     202             :   }
     203             : }
     204             : 
     205          48 : bool AMDGPUAsmPrinter::lowerOperand(const MachineOperand &MO,
     206             :                                     MCOperand &MCOp) const {
     207          48 :   const AMDGPUSubtarget &STI = MF->getSubtarget<AMDGPUSubtarget>();
     208          48 :   AMDGPUMCInstLower MCInstLowering(OutContext, STI, *this);
     209          48 :   return MCInstLowering.lowerOperand(MO, MCOp);
     210             : }
     211             : 
     212          56 : static const MCExpr *lowerAddrSpaceCast(const TargetMachine &TM,
     213             :                                         const Constant *CV,
     214             :                                         MCContext &OutContext) {
     215             :   // TargetMachine does not support llvm-style cast. Use C++-style cast.
     216             :   // This is safe since TM is always of type AMDGPUTargetMachine or its
     217             :   // derived class.
     218             :   auto &AT = static_cast<const AMDGPUTargetMachine&>(TM);
     219             :   auto *CE = dyn_cast<ConstantExpr>(CV);
     220             : 
     221             :   // Lower null pointers in private and local address space.
     222             :   // Clang generates addrspacecast for null pointers in private and local
     223             :   // address space, which needs to be lowered.
     224          56 :   if (CE && CE->getOpcode() == Instruction::AddrSpaceCast) {
     225             :     auto Op = CE->getOperand(0);
     226          56 :     auto SrcAddr = Op->getType()->getPointerAddressSpace();
     227          56 :     if (Op->isNullValue() && AT.getNullPointerValue(SrcAddr) == 0) {
     228          56 :       auto DstAddr = CE->getType()->getPointerAddressSpace();
     229          56 :       return MCConstantExpr::create(AT.getNullPointerValue(DstAddr),
     230          56 :         OutContext);
     231             :     }
     232             :   }
     233             :   return nullptr;
     234             : }
     235             : 
     236          28 : const MCExpr *AMDGPUAsmPrinter::lowerConstant(const Constant *CV) {
     237          28 :   if (const MCExpr *E = lowerAddrSpaceCast(TM, CV, OutContext))
     238             :     return E;
     239           0 :   return AsmPrinter::lowerConstant(CV);
     240             : }
     241             : 
     242      332334 : void AMDGPUAsmPrinter::EmitInstruction(const MachineInstr *MI) {
     243      332334 :   if (emitPseudoExpansionLowering(*OutStreamer, MI))
     244        1052 :     return;
     245             : 
     246      332310 :   const AMDGPUSubtarget &STI = MF->getSubtarget<AMDGPUSubtarget>();
     247      332310 :   AMDGPUMCInstLower MCInstLowering(OutContext, STI, *this);
     248             : 
     249      332310 :   StringRef Err;
     250      332310 :   if (!STI.getInstrInfo()->verifyInstruction(*MI, Err)) {
     251           0 :     LLVMContext &C = MI->getParent()->getParent()->getFunction().getContext();
     252           0 :     C.emitError("Illegal instruction detected: " + Err);
     253           0 :     MI->print(errs());
     254             :   }
     255             : 
     256      332310 :   if (MI->isBundle()) {
     257         521 :     const MachineBasicBlock *MBB = MI->getParent();
     258         521 :     MachineBasicBlock::const_instr_iterator I = ++MI->getIterator();
     259        4168 :     while (I != MBB->instr_end() && I->isInsideBundle()) {
     260        1563 :       EmitInstruction(&*I);
     261             :       ++I;
     262             :     }
     263             :   } else {
     264             :     // We don't want SI_MASK_BRANCH/SI_RETURN_TO_EPILOG encoded. They are
     265             :     // placeholder terminator instructions and should only be printed as
     266             :     // comments.
     267      331789 :     if (MI->getOpcode() == AMDGPU::SI_MASK_BRANCH) {
     268         401 :       if (isVerbose()) {
     269             :         SmallVector<char, 16> BBStr;
     270             :         raw_svector_ostream Str(BBStr);
     271             : 
     272         397 :         const MachineBasicBlock *MBB = MI->getOperand(0).getMBB();
     273             :         const MCSymbolRefExpr *Expr
     274         397 :           = MCSymbolRefExpr::create(MBB->getSymbol(), OutContext);
     275         397 :         Expr->print(Str, MAI);
     276         794 :         OutStreamer->emitRawComment(Twine(" mask branch ") + BBStr);
     277             :       }
     278             : 
     279        1028 :       return;
     280             :     }
     281             : 
     282      331388 :     if (MI->getOpcode() == AMDGPU::SI_RETURN_TO_EPILOG) {
     283         600 :       if (isVerbose())
     284        1200 :         OutStreamer->emitRawComment(" return to shader part epilog");
     285             :       return;
     286             :     }
     287             : 
     288      330788 :     if (MI->getOpcode() == AMDGPU::WAVE_BARRIER) {
     289          13 :       if (isVerbose())
     290          26 :         OutStreamer->emitRawComment(" wave barrier");
     291             :       return;
     292             :     }
     293             : 
     294      330775 :     if (MI->getOpcode() == AMDGPU::SI_MASKED_UNREACHABLE) {
     295          14 :       if (isVerbose())
     296          26 :         OutStreamer->emitRawComment(" divergent unreachable");
     297             :       return;
     298             :     }
     299             : 
     300             :     MCInst TmpInst;
     301      330761 :     MCInstLowering.lower(MI, TmpInst);
     302      330761 :     EmitToStreamer(*OutStreamer, TmpInst);
     303             : 
     304      330761 :     if (STI.dumpCode()) {
     305             :       // Disassemble instruction/operands to text.
     306          28 :       DisasmLines.resize(DisasmLines.size() + 1);
     307             :       std::string &DisasmLine = DisasmLines.back();
     308          14 :       raw_string_ostream DisasmStream(DisasmLine);
     309             : 
     310          14 :       AMDGPUInstPrinter InstPrinter(*TM.getMCAsmInfo(),
     311          14 :                                     *STI.getInstrInfo(),
     312          28 :                                     *STI.getRegisterInfo());
     313          14 :       InstPrinter.printInst(&TmpInst, DisasmStream, StringRef(), STI);
     314             : 
     315             :       // Disassemble instruction/operands to hex representation.
     316             :       SmallVector<MCFixup, 4> Fixups;
     317             :       SmallVector<char, 16> CodeBytes;
     318             :       raw_svector_ostream CodeStream(CodeBytes);
     319             : 
     320             :       auto &ObjStreamer = static_cast<MCObjectStreamer&>(*OutStreamer);
     321             :       MCCodeEmitter &InstEmitter = ObjStreamer.getAssembler().getEmitter();
     322          14 :       InstEmitter.encodeInstruction(TmpInst, CodeStream, Fixups,
     323          14 :                                     MF->getSubtarget<MCSubtargetInfo>());
     324          28 :       HexLines.resize(HexLines.size() + 1);
     325             :       std::string &HexLine = HexLines.back();
     326          14 :       raw_string_ostream HexStream(HexLine);
     327             : 
     328          50 :       for (size_t i = 0; i < CodeBytes.size(); i += 4) {
     329          18 :         unsigned int CodeDWord = *(unsigned int *)&CodeBytes[i];
     330          36 :         HexStream << format("%s%08X", (i > 0 ? " " : ""), CodeDWord);
     331             :       }
     332             : 
     333             :       DisasmStream.flush();
     334          28 :       DisasmLineMaxLen = std::max(DisasmLineMaxLen, DisasmLine.size());
     335             :     }
     336             :   }
     337             : }
     338             : 
     339             : R600MCInstLower::R600MCInstLower(MCContext &Ctx, const R600Subtarget &ST,
     340             :                                  const AsmPrinter &AP) :
     341       81534 :         AMDGPUMCInstLower(Ctx, ST, AP) { }
     342             : 
     343       81534 : void R600MCInstLower::lower(const MachineInstr *MI, MCInst &OutMI) const {
     344       81534 :   OutMI.setOpcode(MI->getOpcode());
     345     2091784 :   for (const MachineOperand &MO : MI->explicit_operands()) {
     346             :     MCOperand MCOp;
     347     1005125 :     lowerOperand(MO, MCOp);
     348             :     OutMI.addOperand(MCOp);
     349             :   }
     350       81534 : }
     351             : 
     352       81534 : void R600AsmPrinter::EmitInstruction(const MachineInstr *MI) {
     353       81534 :   const R600Subtarget &STI = MF->getSubtarget<R600Subtarget>();
     354       81534 :   R600MCInstLower MCInstLowering(OutContext, STI, *this);
     355             : 
     356       81534 :   StringRef Err;
     357       81534 :   if (!STI.getInstrInfo()->verifyInstruction(*MI, Err)) {
     358           0 :     LLVMContext &C = MI->getParent()->getParent()->getFunction().getContext();
     359           0 :     C.emitError("Illegal instruction detected: " + Err);
     360           0 :     MI->print(errs());
     361             :   }
     362             : 
     363       81534 :   if (MI->isBundle()) {
     364           0 :     const MachineBasicBlock *MBB = MI->getParent();
     365           0 :     MachineBasicBlock::const_instr_iterator I = ++MI->getIterator();
     366           0 :     while (I != MBB->instr_end() && I->isInsideBundle()) {
     367           0 :       EmitInstruction(&*I);
     368             :       ++I;
     369             :     }
     370             :   } else {
     371             :     MCInst TmpInst;
     372       81534 :     MCInstLowering.lower(MI, TmpInst);
     373       81534 :     EmitToStreamer(*OutStreamer, TmpInst);
     374             :  }
     375       81534 : }
     376             : 
     377          28 : const MCExpr *R600AsmPrinter::lowerConstant(const Constant *CV) {
     378          28 :   if (const MCExpr *E = lowerAddrSpaceCast(TM, CV, OutContext))
     379             :     return E;
     380           0 :   return AsmPrinter::lowerConstant(CV);
     381             : }

Generated by: LCOV version 1.13