10b57cec5SDimitry Andric //===- AMDGPUMCInstLower.cpp - Lower AMDGPU MachineInstr to an MCInst -----===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric /// \file 100b57cec5SDimitry Andric /// Code to lower AMDGPU MachineInstrs to their corresponding MCInst. 110b57cec5SDimitry Andric // 120b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 130b57cec5SDimitry Andric // 140b57cec5SDimitry Andric 150b57cec5SDimitry Andric #include "AMDGPUAsmPrinter.h" 160b57cec5SDimitry Andric #include "AMDGPUSubtarget.h" 170b57cec5SDimitry Andric #include "AMDGPUTargetMachine.h" 180b57cec5SDimitry Andric #include "MCTargetDesc/AMDGPUInstPrinter.h" 190b57cec5SDimitry Andric #include "MCTargetDesc/AMDGPUMCTargetDesc.h" 200b57cec5SDimitry Andric #include "R600AsmPrinter.h" 210b57cec5SDimitry Andric #include "SIInstrInfo.h" 220b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h" 230b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h" 240b57cec5SDimitry Andric #include "llvm/IR/Constants.h" 250b57cec5SDimitry Andric #include "llvm/IR/Function.h" 260b57cec5SDimitry Andric #include "llvm/IR/GlobalVariable.h" 270b57cec5SDimitry Andric #include "llvm/MC/MCCodeEmitter.h" 280b57cec5SDimitry Andric #include "llvm/MC/MCContext.h" 290b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h" 300b57cec5SDimitry Andric #include "llvm/MC/MCInst.h" 310b57cec5SDimitry Andric #include "llvm/MC/MCObjectStreamer.h" 320b57cec5SDimitry Andric #include "llvm/MC/MCStreamer.h" 330b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 340b57cec5SDimitry Andric #include "llvm/Support/Format.h" 350b57cec5SDimitry Andric #include <algorithm> 360b57cec5SDimitry Andric 370b57cec5SDimitry Andric using namespace llvm; 380b57cec5SDimitry Andric 390b57cec5SDimitry Andric namespace { 400b57cec5SDimitry Andric 410b57cec5SDimitry Andric class AMDGPUMCInstLower { 420b57cec5SDimitry Andric MCContext &Ctx; 430b57cec5SDimitry Andric const TargetSubtargetInfo &ST; 440b57cec5SDimitry Andric const AsmPrinter &AP; 450b57cec5SDimitry Andric 460b57cec5SDimitry Andric const MCExpr *getLongBranchBlockExpr(const MachineBasicBlock &SrcBB, 470b57cec5SDimitry Andric const MachineOperand &MO) const; 480b57cec5SDimitry Andric 490b57cec5SDimitry Andric public: 500b57cec5SDimitry Andric AMDGPUMCInstLower(MCContext &ctx, const TargetSubtargetInfo &ST, 510b57cec5SDimitry Andric const AsmPrinter &AP); 520b57cec5SDimitry Andric 530b57cec5SDimitry Andric bool lowerOperand(const MachineOperand &MO, MCOperand &MCOp) const; 540b57cec5SDimitry Andric 550b57cec5SDimitry Andric /// Lower a MachineInstr to an MCInst 560b57cec5SDimitry Andric void lower(const MachineInstr *MI, MCInst &OutMI) const; 570b57cec5SDimitry Andric 580b57cec5SDimitry Andric }; 590b57cec5SDimitry Andric 600b57cec5SDimitry Andric class R600MCInstLower : public AMDGPUMCInstLower { 610b57cec5SDimitry Andric public: 620b57cec5SDimitry Andric R600MCInstLower(MCContext &ctx, const R600Subtarget &ST, 630b57cec5SDimitry Andric const AsmPrinter &AP); 640b57cec5SDimitry Andric 650b57cec5SDimitry Andric /// Lower a MachineInstr to an MCInst 660b57cec5SDimitry Andric void lower(const MachineInstr *MI, MCInst &OutMI) const; 670b57cec5SDimitry Andric }; 680b57cec5SDimitry Andric 690b57cec5SDimitry Andric 700b57cec5SDimitry Andric } // End anonymous namespace 710b57cec5SDimitry Andric 720b57cec5SDimitry Andric #include "AMDGPUGenMCPseudoLowering.inc" 730b57cec5SDimitry Andric 740b57cec5SDimitry Andric AMDGPUMCInstLower::AMDGPUMCInstLower(MCContext &ctx, 750b57cec5SDimitry Andric const TargetSubtargetInfo &st, 760b57cec5SDimitry Andric const AsmPrinter &ap): 770b57cec5SDimitry Andric Ctx(ctx), ST(st), AP(ap) { } 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric static MCSymbolRefExpr::VariantKind getVariantKind(unsigned MOFlags) { 800b57cec5SDimitry Andric switch (MOFlags) { 810b57cec5SDimitry Andric default: 820b57cec5SDimitry Andric return MCSymbolRefExpr::VK_None; 830b57cec5SDimitry Andric case SIInstrInfo::MO_GOTPCREL: 840b57cec5SDimitry Andric return MCSymbolRefExpr::VK_GOTPCREL; 850b57cec5SDimitry Andric case SIInstrInfo::MO_GOTPCREL32_LO: 860b57cec5SDimitry Andric return MCSymbolRefExpr::VK_AMDGPU_GOTPCREL32_LO; 870b57cec5SDimitry Andric case SIInstrInfo::MO_GOTPCREL32_HI: 880b57cec5SDimitry Andric return MCSymbolRefExpr::VK_AMDGPU_GOTPCREL32_HI; 890b57cec5SDimitry Andric case SIInstrInfo::MO_REL32_LO: 900b57cec5SDimitry Andric return MCSymbolRefExpr::VK_AMDGPU_REL32_LO; 910b57cec5SDimitry Andric case SIInstrInfo::MO_REL32_HI: 920b57cec5SDimitry Andric return MCSymbolRefExpr::VK_AMDGPU_REL32_HI; 930b57cec5SDimitry Andric case SIInstrInfo::MO_ABS32_LO: 940b57cec5SDimitry Andric return MCSymbolRefExpr::VK_AMDGPU_ABS32_LO; 950b57cec5SDimitry Andric case SIInstrInfo::MO_ABS32_HI: 960b57cec5SDimitry Andric return MCSymbolRefExpr::VK_AMDGPU_ABS32_HI; 970b57cec5SDimitry Andric } 980b57cec5SDimitry Andric } 990b57cec5SDimitry Andric 1000b57cec5SDimitry Andric const MCExpr *AMDGPUMCInstLower::getLongBranchBlockExpr( 1010b57cec5SDimitry Andric const MachineBasicBlock &SrcBB, 1020b57cec5SDimitry Andric const MachineOperand &MO) const { 1030b57cec5SDimitry Andric const MCExpr *DestBBSym 1040b57cec5SDimitry Andric = MCSymbolRefExpr::create(MO.getMBB()->getSymbol(), Ctx); 1050b57cec5SDimitry Andric const MCExpr *SrcBBSym = MCSymbolRefExpr::create(SrcBB.getSymbol(), Ctx); 1060b57cec5SDimitry Andric 1070b57cec5SDimitry Andric // FIXME: The first half of this assert should be removed. This should 1080b57cec5SDimitry Andric // probably be PC relative instead of using the source block symbol, and 1090b57cec5SDimitry Andric // therefore the indirect branch expansion should use a bundle. 1100b57cec5SDimitry Andric assert( 1110b57cec5SDimitry Andric skipDebugInstructionsForward(SrcBB.begin(), SrcBB.end())->getOpcode() == 1120b57cec5SDimitry Andric AMDGPU::S_GETPC_B64 && 1130b57cec5SDimitry Andric ST.getInstrInfo()->get(AMDGPU::S_GETPC_B64).Size == 4); 1140b57cec5SDimitry Andric 1150b57cec5SDimitry Andric // s_getpc_b64 returns the address of next instruction. 1160b57cec5SDimitry Andric const MCConstantExpr *One = MCConstantExpr::create(4, Ctx); 1170b57cec5SDimitry Andric SrcBBSym = MCBinaryExpr::createAdd(SrcBBSym, One, Ctx); 1180b57cec5SDimitry Andric 1190b57cec5SDimitry Andric if (MO.getTargetFlags() == SIInstrInfo::MO_LONG_BRANCH_FORWARD) 1200b57cec5SDimitry Andric return MCBinaryExpr::createSub(DestBBSym, SrcBBSym, Ctx); 1210b57cec5SDimitry Andric 1220b57cec5SDimitry Andric assert(MO.getTargetFlags() == SIInstrInfo::MO_LONG_BRANCH_BACKWARD); 1230b57cec5SDimitry Andric return MCBinaryExpr::createSub(SrcBBSym, DestBBSym, Ctx); 1240b57cec5SDimitry Andric } 1250b57cec5SDimitry Andric 1260b57cec5SDimitry Andric bool AMDGPUMCInstLower::lowerOperand(const MachineOperand &MO, 1270b57cec5SDimitry Andric MCOperand &MCOp) const { 1280b57cec5SDimitry Andric switch (MO.getType()) { 1290b57cec5SDimitry Andric default: 1300b57cec5SDimitry Andric llvm_unreachable("unknown operand type"); 1310b57cec5SDimitry Andric case MachineOperand::MO_Immediate: 1320b57cec5SDimitry Andric MCOp = MCOperand::createImm(MO.getImm()); 1330b57cec5SDimitry Andric return true; 1340b57cec5SDimitry Andric case MachineOperand::MO_Register: 1350b57cec5SDimitry Andric MCOp = MCOperand::createReg(AMDGPU::getMCReg(MO.getReg(), ST)); 1360b57cec5SDimitry Andric return true; 1370b57cec5SDimitry Andric case MachineOperand::MO_MachineBasicBlock: { 1380b57cec5SDimitry Andric if (MO.getTargetFlags() != 0) { 1390b57cec5SDimitry Andric MCOp = MCOperand::createExpr( 1400b57cec5SDimitry Andric getLongBranchBlockExpr(*MO.getParent()->getParent(), MO)); 1410b57cec5SDimitry Andric } else { 1420b57cec5SDimitry Andric MCOp = MCOperand::createExpr( 1430b57cec5SDimitry Andric MCSymbolRefExpr::create(MO.getMBB()->getSymbol(), Ctx)); 1440b57cec5SDimitry Andric } 1450b57cec5SDimitry Andric 1460b57cec5SDimitry Andric return true; 1470b57cec5SDimitry Andric } 1480b57cec5SDimitry Andric case MachineOperand::MO_GlobalAddress: { 1490b57cec5SDimitry Andric const GlobalValue *GV = MO.getGlobal(); 1500b57cec5SDimitry Andric SmallString<128> SymbolName; 1510b57cec5SDimitry Andric AP.getNameWithPrefix(SymbolName, GV); 1520b57cec5SDimitry Andric MCSymbol *Sym = Ctx.getOrCreateSymbol(SymbolName); 1530b57cec5SDimitry Andric const MCExpr *Expr = 1540b57cec5SDimitry Andric MCSymbolRefExpr::create(Sym, getVariantKind(MO.getTargetFlags()),Ctx); 1550b57cec5SDimitry Andric int64_t Offset = MO.getOffset(); 1560b57cec5SDimitry Andric if (Offset != 0) { 1570b57cec5SDimitry Andric Expr = MCBinaryExpr::createAdd(Expr, 1580b57cec5SDimitry Andric MCConstantExpr::create(Offset, Ctx), Ctx); 1590b57cec5SDimitry Andric } 1600b57cec5SDimitry Andric MCOp = MCOperand::createExpr(Expr); 1610b57cec5SDimitry Andric return true; 1620b57cec5SDimitry Andric } 1630b57cec5SDimitry Andric case MachineOperand::MO_ExternalSymbol: { 1640b57cec5SDimitry Andric MCSymbol *Sym = Ctx.getOrCreateSymbol(StringRef(MO.getSymbolName())); 1650b57cec5SDimitry Andric Sym->setExternal(true); 1660b57cec5SDimitry Andric const MCSymbolRefExpr *Expr = MCSymbolRefExpr::create(Sym, Ctx); 1670b57cec5SDimitry Andric MCOp = MCOperand::createExpr(Expr); 1680b57cec5SDimitry Andric return true; 1690b57cec5SDimitry Andric } 1700b57cec5SDimitry Andric case MachineOperand::MO_RegisterMask: 1710b57cec5SDimitry Andric // Regmasks are like implicit defs. 1720b57cec5SDimitry Andric return false; 1730b57cec5SDimitry Andric } 1740b57cec5SDimitry Andric } 1750b57cec5SDimitry Andric 1760b57cec5SDimitry Andric void AMDGPUMCInstLower::lower(const MachineInstr *MI, MCInst &OutMI) const { 1770b57cec5SDimitry Andric unsigned Opcode = MI->getOpcode(); 1780b57cec5SDimitry Andric const auto *TII = static_cast<const SIInstrInfo*>(ST.getInstrInfo()); 1790b57cec5SDimitry Andric 1800b57cec5SDimitry Andric // FIXME: Should be able to handle this with emitPseudoExpansionLowering. We 1810b57cec5SDimitry Andric // need to select it to the subtarget specific version, and there's no way to 1820b57cec5SDimitry Andric // do that with a single pseudo source operation. 1830b57cec5SDimitry Andric if (Opcode == AMDGPU::S_SETPC_B64_return) 1840b57cec5SDimitry Andric Opcode = AMDGPU::S_SETPC_B64; 1850b57cec5SDimitry Andric else if (Opcode == AMDGPU::SI_CALL) { 1860b57cec5SDimitry Andric // SI_CALL is just S_SWAPPC_B64 with an additional operand to track the 1870b57cec5SDimitry Andric // called function (which we need to remove here). 1880b57cec5SDimitry Andric OutMI.setOpcode(TII->pseudoToMCOpcode(AMDGPU::S_SWAPPC_B64)); 1890b57cec5SDimitry Andric MCOperand Dest, Src; 1900b57cec5SDimitry Andric lowerOperand(MI->getOperand(0), Dest); 1910b57cec5SDimitry Andric lowerOperand(MI->getOperand(1), Src); 1920b57cec5SDimitry Andric OutMI.addOperand(Dest); 1930b57cec5SDimitry Andric OutMI.addOperand(Src); 1940b57cec5SDimitry Andric return; 1950b57cec5SDimitry Andric } else if (Opcode == AMDGPU::SI_TCRETURN) { 1960b57cec5SDimitry Andric // TODO: How to use branch immediate and avoid register+add? 1970b57cec5SDimitry Andric Opcode = AMDGPU::S_SETPC_B64; 1980b57cec5SDimitry Andric } 1990b57cec5SDimitry Andric 2000b57cec5SDimitry Andric int MCOpcode = TII->pseudoToMCOpcode(Opcode); 2010b57cec5SDimitry Andric if (MCOpcode == -1) { 2020b57cec5SDimitry Andric LLVMContext &C = MI->getParent()->getParent()->getFunction().getContext(); 2030b57cec5SDimitry Andric C.emitError("AMDGPUMCInstLower::lower - Pseudo instruction doesn't have " 2040b57cec5SDimitry Andric "a target-specific version: " + Twine(MI->getOpcode())); 2050b57cec5SDimitry Andric } 2060b57cec5SDimitry Andric 2070b57cec5SDimitry Andric OutMI.setOpcode(MCOpcode); 2080b57cec5SDimitry Andric 2090b57cec5SDimitry Andric for (const MachineOperand &MO : MI->explicit_operands()) { 2100b57cec5SDimitry Andric MCOperand MCOp; 2110b57cec5SDimitry Andric lowerOperand(MO, MCOp); 2120b57cec5SDimitry Andric OutMI.addOperand(MCOp); 2130b57cec5SDimitry Andric } 2148bcb0991SDimitry Andric 2158bcb0991SDimitry Andric int FIIdx = AMDGPU::getNamedOperandIdx(MCOpcode, AMDGPU::OpName::fi); 2168bcb0991SDimitry Andric if (FIIdx >= (int)OutMI.getNumOperands()) 2178bcb0991SDimitry Andric OutMI.addOperand(MCOperand::createImm(0)); 2180b57cec5SDimitry Andric } 2190b57cec5SDimitry Andric 2200b57cec5SDimitry Andric bool AMDGPUAsmPrinter::lowerOperand(const MachineOperand &MO, 2210b57cec5SDimitry Andric MCOperand &MCOp) const { 2220b57cec5SDimitry Andric const GCNSubtarget &STI = MF->getSubtarget<GCNSubtarget>(); 2230b57cec5SDimitry Andric AMDGPUMCInstLower MCInstLowering(OutContext, STI, *this); 2240b57cec5SDimitry Andric return MCInstLowering.lowerOperand(MO, MCOp); 2250b57cec5SDimitry Andric } 2260b57cec5SDimitry Andric 2270b57cec5SDimitry Andric static const MCExpr *lowerAddrSpaceCast(const TargetMachine &TM, 2280b57cec5SDimitry Andric const Constant *CV, 2290b57cec5SDimitry Andric MCContext &OutContext) { 2300b57cec5SDimitry Andric // TargetMachine does not support llvm-style cast. Use C++-style cast. 2310b57cec5SDimitry Andric // This is safe since TM is always of type AMDGPUTargetMachine or its 2320b57cec5SDimitry Andric // derived class. 2330b57cec5SDimitry Andric auto &AT = static_cast<const AMDGPUTargetMachine&>(TM); 2340b57cec5SDimitry Andric auto *CE = dyn_cast<ConstantExpr>(CV); 2350b57cec5SDimitry Andric 2360b57cec5SDimitry Andric // Lower null pointers in private and local address space. 2370b57cec5SDimitry Andric // Clang generates addrspacecast for null pointers in private and local 2380b57cec5SDimitry Andric // address space, which needs to be lowered. 2390b57cec5SDimitry Andric if (CE && CE->getOpcode() == Instruction::AddrSpaceCast) { 2400b57cec5SDimitry Andric auto Op = CE->getOperand(0); 2410b57cec5SDimitry Andric auto SrcAddr = Op->getType()->getPointerAddressSpace(); 2420b57cec5SDimitry Andric if (Op->isNullValue() && AT.getNullPointerValue(SrcAddr) == 0) { 2430b57cec5SDimitry Andric auto DstAddr = CE->getType()->getPointerAddressSpace(); 2440b57cec5SDimitry Andric return MCConstantExpr::create(AT.getNullPointerValue(DstAddr), 2450b57cec5SDimitry Andric OutContext); 2460b57cec5SDimitry Andric } 2470b57cec5SDimitry Andric } 2480b57cec5SDimitry Andric return nullptr; 2490b57cec5SDimitry Andric } 2500b57cec5SDimitry Andric 2510b57cec5SDimitry Andric const MCExpr *AMDGPUAsmPrinter::lowerConstant(const Constant *CV) { 2520b57cec5SDimitry Andric if (const MCExpr *E = lowerAddrSpaceCast(TM, CV, OutContext)) 2530b57cec5SDimitry Andric return E; 2540b57cec5SDimitry Andric return AsmPrinter::lowerConstant(CV); 2550b57cec5SDimitry Andric } 2560b57cec5SDimitry Andric 257*5ffd83dbSDimitry Andric void AMDGPUAsmPrinter::emitInstruction(const MachineInstr *MI) { 2580b57cec5SDimitry Andric if (emitPseudoExpansionLowering(*OutStreamer, MI)) 2590b57cec5SDimitry Andric return; 2600b57cec5SDimitry Andric 2610b57cec5SDimitry Andric const GCNSubtarget &STI = MF->getSubtarget<GCNSubtarget>(); 2620b57cec5SDimitry Andric AMDGPUMCInstLower MCInstLowering(OutContext, STI, *this); 2630b57cec5SDimitry Andric 2640b57cec5SDimitry Andric StringRef Err; 2650b57cec5SDimitry Andric if (!STI.getInstrInfo()->verifyInstruction(*MI, Err)) { 2660b57cec5SDimitry Andric LLVMContext &C = MI->getParent()->getParent()->getFunction().getContext(); 2670b57cec5SDimitry Andric C.emitError("Illegal instruction detected: " + Err); 2680b57cec5SDimitry Andric MI->print(errs()); 2690b57cec5SDimitry Andric } 2700b57cec5SDimitry Andric 2710b57cec5SDimitry Andric if (MI->isBundle()) { 2720b57cec5SDimitry Andric const MachineBasicBlock *MBB = MI->getParent(); 2730b57cec5SDimitry Andric MachineBasicBlock::const_instr_iterator I = ++MI->getIterator(); 2740b57cec5SDimitry Andric while (I != MBB->instr_end() && I->isInsideBundle()) { 275*5ffd83dbSDimitry Andric emitInstruction(&*I); 2760b57cec5SDimitry Andric ++I; 2770b57cec5SDimitry Andric } 2780b57cec5SDimitry Andric } else { 2790b57cec5SDimitry Andric // We don't want SI_MASK_BRANCH/SI_RETURN_TO_EPILOG encoded. They are 2800b57cec5SDimitry Andric // placeholder terminator instructions and should only be printed as 2810b57cec5SDimitry Andric // comments. 2820b57cec5SDimitry Andric if (MI->getOpcode() == AMDGPU::SI_MASK_BRANCH) { 2830b57cec5SDimitry Andric if (isVerbose()) { 2840b57cec5SDimitry Andric SmallVector<char, 16> BBStr; 2850b57cec5SDimitry Andric raw_svector_ostream Str(BBStr); 2860b57cec5SDimitry Andric 2870b57cec5SDimitry Andric const MachineBasicBlock *MBB = MI->getOperand(0).getMBB(); 2880b57cec5SDimitry Andric const MCSymbolRefExpr *Expr 2890b57cec5SDimitry Andric = MCSymbolRefExpr::create(MBB->getSymbol(), OutContext); 2900b57cec5SDimitry Andric Expr->print(Str, MAI); 2910b57cec5SDimitry Andric OutStreamer->emitRawComment(Twine(" mask branch ") + BBStr); 2920b57cec5SDimitry Andric } 2930b57cec5SDimitry Andric 2940b57cec5SDimitry Andric return; 2950b57cec5SDimitry Andric } 2960b57cec5SDimitry Andric 2970b57cec5SDimitry Andric if (MI->getOpcode() == AMDGPU::SI_RETURN_TO_EPILOG) { 2980b57cec5SDimitry Andric if (isVerbose()) 2990b57cec5SDimitry Andric OutStreamer->emitRawComment(" return to shader part epilog"); 3000b57cec5SDimitry Andric return; 3010b57cec5SDimitry Andric } 3020b57cec5SDimitry Andric 3030b57cec5SDimitry Andric if (MI->getOpcode() == AMDGPU::WAVE_BARRIER) { 3040b57cec5SDimitry Andric if (isVerbose()) 3050b57cec5SDimitry Andric OutStreamer->emitRawComment(" wave barrier"); 3060b57cec5SDimitry Andric return; 3070b57cec5SDimitry Andric } 3080b57cec5SDimitry Andric 3090b57cec5SDimitry Andric if (MI->getOpcode() == AMDGPU::SI_MASKED_UNREACHABLE) { 3100b57cec5SDimitry Andric if (isVerbose()) 3110b57cec5SDimitry Andric OutStreamer->emitRawComment(" divergent unreachable"); 3120b57cec5SDimitry Andric return; 3130b57cec5SDimitry Andric } 3140b57cec5SDimitry Andric 3150b57cec5SDimitry Andric MCInst TmpInst; 3160b57cec5SDimitry Andric MCInstLowering.lower(MI, TmpInst); 3170b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, TmpInst); 3180b57cec5SDimitry Andric 3190b57cec5SDimitry Andric #ifdef EXPENSIVE_CHECKS 3200b57cec5SDimitry Andric // Sanity-check getInstSizeInBytes on explicitly specified CPUs (it cannot 3210b57cec5SDimitry Andric // work correctly for the generic CPU). 3220b57cec5SDimitry Andric // 3230b57cec5SDimitry Andric // The isPseudo check really shouldn't be here, but unfortunately there are 3240b57cec5SDimitry Andric // some negative lit tests that depend on being able to continue through 3250b57cec5SDimitry Andric // here even when pseudo instructions haven't been lowered. 3260b57cec5SDimitry Andric if (!MI->isPseudo() && STI.isCPUStringValid(STI.getCPU())) { 3270b57cec5SDimitry Andric SmallVector<MCFixup, 4> Fixups; 3280b57cec5SDimitry Andric SmallVector<char, 16> CodeBytes; 3290b57cec5SDimitry Andric raw_svector_ostream CodeStream(CodeBytes); 3300b57cec5SDimitry Andric 3310b57cec5SDimitry Andric std::unique_ptr<MCCodeEmitter> InstEmitter(createSIMCCodeEmitter( 3320b57cec5SDimitry Andric *STI.getInstrInfo(), *OutContext.getRegisterInfo(), OutContext)); 3330b57cec5SDimitry Andric InstEmitter->encodeInstruction(TmpInst, CodeStream, Fixups, STI); 3340b57cec5SDimitry Andric 3350b57cec5SDimitry Andric assert(CodeBytes.size() == STI.getInstrInfo()->getInstSizeInBytes(*MI)); 3360b57cec5SDimitry Andric } 3370b57cec5SDimitry Andric #endif 3380b57cec5SDimitry Andric 3390b57cec5SDimitry Andric if (DumpCodeInstEmitter) { 3400b57cec5SDimitry Andric // Disassemble instruction/operands to text 3410b57cec5SDimitry Andric DisasmLines.resize(DisasmLines.size() + 1); 3420b57cec5SDimitry Andric std::string &DisasmLine = DisasmLines.back(); 3430b57cec5SDimitry Andric raw_string_ostream DisasmStream(DisasmLine); 3440b57cec5SDimitry Andric 3450b57cec5SDimitry Andric AMDGPUInstPrinter InstPrinter(*TM.getMCAsmInfo(), *STI.getInstrInfo(), 3460b57cec5SDimitry Andric *STI.getRegisterInfo()); 347480093f4SDimitry Andric InstPrinter.printInst(&TmpInst, 0, StringRef(), STI, DisasmStream); 3480b57cec5SDimitry Andric 3490b57cec5SDimitry Andric // Disassemble instruction/operands to hex representation. 3500b57cec5SDimitry Andric SmallVector<MCFixup, 4> Fixups; 3510b57cec5SDimitry Andric SmallVector<char, 16> CodeBytes; 3520b57cec5SDimitry Andric raw_svector_ostream CodeStream(CodeBytes); 3530b57cec5SDimitry Andric 3540b57cec5SDimitry Andric DumpCodeInstEmitter->encodeInstruction( 3550b57cec5SDimitry Andric TmpInst, CodeStream, Fixups, MF->getSubtarget<MCSubtargetInfo>()); 3560b57cec5SDimitry Andric HexLines.resize(HexLines.size() + 1); 3570b57cec5SDimitry Andric std::string &HexLine = HexLines.back(); 3580b57cec5SDimitry Andric raw_string_ostream HexStream(HexLine); 3590b57cec5SDimitry Andric 3600b57cec5SDimitry Andric for (size_t i = 0; i < CodeBytes.size(); i += 4) { 3610b57cec5SDimitry Andric unsigned int CodeDWord = *(unsigned int *)&CodeBytes[i]; 3620b57cec5SDimitry Andric HexStream << format("%s%08X", (i > 0 ? " " : ""), CodeDWord); 3630b57cec5SDimitry Andric } 3640b57cec5SDimitry Andric 3650b57cec5SDimitry Andric DisasmStream.flush(); 3660b57cec5SDimitry Andric DisasmLineMaxLen = std::max(DisasmLineMaxLen, DisasmLine.size()); 3670b57cec5SDimitry Andric } 3680b57cec5SDimitry Andric } 3690b57cec5SDimitry Andric } 3700b57cec5SDimitry Andric 3710b57cec5SDimitry Andric R600MCInstLower::R600MCInstLower(MCContext &Ctx, const R600Subtarget &ST, 3720b57cec5SDimitry Andric const AsmPrinter &AP) : 3730b57cec5SDimitry Andric AMDGPUMCInstLower(Ctx, ST, AP) { } 3740b57cec5SDimitry Andric 3750b57cec5SDimitry Andric void R600MCInstLower::lower(const MachineInstr *MI, MCInst &OutMI) const { 3760b57cec5SDimitry Andric OutMI.setOpcode(MI->getOpcode()); 3770b57cec5SDimitry Andric for (const MachineOperand &MO : MI->explicit_operands()) { 3780b57cec5SDimitry Andric MCOperand MCOp; 3790b57cec5SDimitry Andric lowerOperand(MO, MCOp); 3800b57cec5SDimitry Andric OutMI.addOperand(MCOp); 3810b57cec5SDimitry Andric } 3820b57cec5SDimitry Andric } 3830b57cec5SDimitry Andric 384*5ffd83dbSDimitry Andric void R600AsmPrinter::emitInstruction(const MachineInstr *MI) { 3850b57cec5SDimitry Andric const R600Subtarget &STI = MF->getSubtarget<R600Subtarget>(); 3860b57cec5SDimitry Andric R600MCInstLower MCInstLowering(OutContext, STI, *this); 3870b57cec5SDimitry Andric 3880b57cec5SDimitry Andric StringRef Err; 3890b57cec5SDimitry Andric if (!STI.getInstrInfo()->verifyInstruction(*MI, Err)) { 3900b57cec5SDimitry Andric LLVMContext &C = MI->getParent()->getParent()->getFunction().getContext(); 3910b57cec5SDimitry Andric C.emitError("Illegal instruction detected: " + Err); 3920b57cec5SDimitry Andric MI->print(errs()); 3930b57cec5SDimitry Andric } 3940b57cec5SDimitry Andric 3950b57cec5SDimitry Andric if (MI->isBundle()) { 3960b57cec5SDimitry Andric const MachineBasicBlock *MBB = MI->getParent(); 3970b57cec5SDimitry Andric MachineBasicBlock::const_instr_iterator I = ++MI->getIterator(); 3980b57cec5SDimitry Andric while (I != MBB->instr_end() && I->isInsideBundle()) { 399*5ffd83dbSDimitry Andric emitInstruction(&*I); 4000b57cec5SDimitry Andric ++I; 4010b57cec5SDimitry Andric } 4020b57cec5SDimitry Andric } else { 4030b57cec5SDimitry Andric MCInst TmpInst; 4040b57cec5SDimitry Andric MCInstLowering.lower(MI, TmpInst); 4050b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, TmpInst); 4060b57cec5SDimitry Andric } 4070b57cec5SDimitry Andric } 4080b57cec5SDimitry Andric 4090b57cec5SDimitry Andric const MCExpr *R600AsmPrinter::lowerConstant(const Constant *CV) { 4100b57cec5SDimitry Andric if (const MCExpr *E = lowerAddrSpaceCast(TM, CV, OutContext)) 4110b57cec5SDimitry Andric return E; 4120b57cec5SDimitry Andric return AsmPrinter::lowerConstant(CV); 4130b57cec5SDimitry Andric } 414