Changeset View
Changeset View
Standalone View
Standalone View
llvm/trunk/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
Show First 20 Lines • Show All 875 Lines • ▼ Show 20 Lines | public: | ||||
bool isCI() const { | bool isCI() const { | ||||
return AMDGPU::isCI(getSTI()); | return AMDGPU::isCI(getSTI()); | ||||
} | } | ||||
bool isVI() const { | bool isVI() const { | ||||
return AMDGPU::isVI(getSTI()); | return AMDGPU::isVI(getSTI()); | ||||
} | } | ||||
bool isGFX9() const { | |||||
return AMDGPU::isGFX9(getSTI()); | |||||
} | |||||
bool hasInv2PiInlineImm() const { | bool hasInv2PiInlineImm() const { | ||||
return getFeatureBits()[AMDGPU::FeatureInv2PiInlineImm]; | return getFeatureBits()[AMDGPU::FeatureInv2PiInlineImm]; | ||||
} | } | ||||
bool hasSGPR102_SGPR103() const { | bool hasSGPR102_SGPR103() const { | ||||
return !isVI(); | return !isVI(); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 92 Lines • ▼ Show 20 Lines | private: | ||||
void errorExpTgt(); | void errorExpTgt(); | ||||
OperandMatchResultTy parseExpTgtImpl(StringRef Str, uint8_t &Val); | OperandMatchResultTy parseExpTgtImpl(StringRef Str, uint8_t &Val); | ||||
bool validateOperandLimitations(const MCInst &Inst); | bool validateOperandLimitations(const MCInst &Inst); | ||||
bool usesConstantBus(const MCInst &Inst, unsigned OpIdx); | bool usesConstantBus(const MCInst &Inst, unsigned OpIdx); | ||||
bool isInlineConstant(const MCInst &Inst, unsigned OpIdx) const; | bool isInlineConstant(const MCInst &Inst, unsigned OpIdx) const; | ||||
unsigned findImplicitSGPRReadInVOP(const MCInst &Inst) const; | unsigned findImplicitSGPRReadInVOP(const MCInst &Inst) const; | ||||
bool isSGPR(unsigned Reg); | |||||
public: | public: | ||||
OperandMatchResultTy parseOptionalOperand(OperandVector &Operands); | OperandMatchResultTy parseOptionalOperand(OperandVector &Operands); | ||||
OperandMatchResultTy parseExpTgt(OperandVector &Operands); | OperandMatchResultTy parseExpTgt(OperandVector &Operands); | ||||
OperandMatchResultTy parseSendMsgOp(OperandVector &Operands); | OperandMatchResultTy parseSendMsgOp(OperandVector &Operands); | ||||
OperandMatchResultTy parseInterpSlot(OperandVector &Operands); | OperandMatchResultTy parseInterpSlot(OperandVector &Operands); | ||||
OperandMatchResultTy parseInterpAttr(OperandVector &Operands); | OperandMatchResultTy parseInterpAttr(OperandVector &Operands); | ||||
Show All 36 Lines | public: | ||||
AMDGPUOperand::Ptr defaultBoundCtrl() const; | AMDGPUOperand::Ptr defaultBoundCtrl() const; | ||||
void cvtDPP(MCInst &Inst, const OperandVector &Operands); | void cvtDPP(MCInst &Inst, const OperandVector &Operands); | ||||
OperandMatchResultTy parseSDWASel(OperandVector &Operands, StringRef Prefix, | OperandMatchResultTy parseSDWASel(OperandVector &Operands, StringRef Prefix, | ||||
AMDGPUOperand::ImmTy Type); | AMDGPUOperand::ImmTy Type); | ||||
OperandMatchResultTy parseSDWADstUnused(OperandVector &Operands); | OperandMatchResultTy parseSDWADstUnused(OperandVector &Operands); | ||||
void cvtSdwaVOP1(MCInst &Inst, const OperandVector &Operands); | void cvtSdwaVOP1(MCInst &Inst, const OperandVector &Operands); | ||||
void cvtSdwaVOP2(MCInst &Inst, const OperandVector &Operands); | void cvtSdwaVOP2(MCInst &Inst, const OperandVector &Operands); | ||||
void cvtSdwaVOP2b(MCInst &Inst, const OperandVector &Operands); | |||||
void cvtSdwaVOPC(MCInst &Inst, const OperandVector &Operands); | void cvtSdwaVOPC(MCInst &Inst, const OperandVector &Operands); | ||||
void cvtSDWA(MCInst &Inst, const OperandVector &Operands, | void cvtSDWA(MCInst &Inst, const OperandVector &Operands, | ||||
uint64_t BasicInstType); | uint64_t BasicInstType, bool skipVcc = false); | ||||
}; | }; | ||||
struct OptionalOperand { | struct OptionalOperand { | ||||
const char *Name; | const char *Name; | ||||
AMDGPUOperand::ImmTy Type; | AMDGPUOperand::ImmTy Type; | ||||
bool IsBit; | bool IsBit; | ||||
bool (*ConvertResult)(int64_t&); | bool (*ConvertResult)(int64_t&); | ||||
}; | }; | ||||
▲ Show 20 Lines • Show All 905 Lines • ▼ Show 20 Lines | ArrayRef<unsigned> AMDGPUAsmParser::getMatchedVariants() const { | ||||
} | } | ||||
if (isForcedVOP3()) { | if (isForcedVOP3()) { | ||||
static const unsigned Variants[] = {AMDGPUAsmVariants::VOP3}; | static const unsigned Variants[] = {AMDGPUAsmVariants::VOP3}; | ||||
return makeArrayRef(Variants); | return makeArrayRef(Variants); | ||||
} | } | ||||
if (isForcedSDWA()) { | if (isForcedSDWA()) { | ||||
static const unsigned Variants[] = {AMDGPUAsmVariants::SDWA}; | static const unsigned Variants[] = {AMDGPUAsmVariants::SDWA, | ||||
AMDGPUAsmVariants::SDWA9}; | |||||
return makeArrayRef(Variants); | return makeArrayRef(Variants); | ||||
} | } | ||||
if (isForcedDPP()) { | if (isForcedDPP()) { | ||||
static const unsigned Variants[] = {AMDGPUAsmVariants::DPP}; | static const unsigned Variants[] = {AMDGPUAsmVariants::DPP}; | ||||
return makeArrayRef(Variants); | return makeArrayRef(Variants); | ||||
} | } | ||||
static const unsigned Variants[] = { | static const unsigned Variants[] = { | ||||
AMDGPUAsmVariants::DEFAULT, AMDGPUAsmVariants::VOP3, | AMDGPUAsmVariants::DEFAULT, AMDGPUAsmVariants::VOP3, | ||||
AMDGPUAsmVariants::SDWA, AMDGPUAsmVariants::DPP | AMDGPUAsmVariants::SDWA, AMDGPUAsmVariants::SDWA9, AMDGPUAsmVariants::DPP | ||||
}; | }; | ||||
return makeArrayRef(Variants); | return makeArrayRef(Variants); | ||||
} | } | ||||
unsigned AMDGPUAsmParser::findImplicitSGPRReadInVOP(const MCInst &Inst) const { | unsigned AMDGPUAsmParser::findImplicitSGPRReadInVOP(const MCInst &Inst) const { | ||||
const MCInstrDesc &Desc = MII.get(Inst.getOpcode()); | const MCInstrDesc &Desc = MII.get(Inst.getOpcode()); | ||||
const unsigned Num = Desc.getNumImplicitUses(); | const unsigned Num = Desc.getNumImplicitUses(); | ||||
for (unsigned i = 0; i < Num; ++i) { | for (unsigned i = 0; i < Num; ++i) { | ||||
unsigned Reg = Desc.ImplicitUses[i]; | unsigned Reg = Desc.ImplicitUses[i]; | ||||
switch (Reg) { | switch (Reg) { | ||||
case AMDGPU::FLAT_SCR: | case AMDGPU::FLAT_SCR: | ||||
case AMDGPU::VCC: | case AMDGPU::VCC: | ||||
case AMDGPU::M0: | case AMDGPU::M0: | ||||
return Reg; | return Reg; | ||||
default: | default: | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
return AMDGPU::NoRegister; | return AMDGPU::NoRegister; | ||||
} | } | ||||
bool AMDGPUAsmParser::isSGPR(unsigned Reg) { | |||||
const MCRegisterInfo *TRI = getContext().getRegisterInfo(); | |||||
const MCRegisterClass SGPRClass = TRI->getRegClass(AMDGPU::SReg_32RegClassID); | |||||
const unsigned FirstSubReg = TRI->getSubReg(Reg, 1); | |||||
return SGPRClass.contains(FirstSubReg != 0 ? FirstSubReg : Reg) || | |||||
Reg == AMDGPU::SCC; | |||||
} | |||||
// NB: This code is correct only when used to check constant | // NB: This code is correct only when used to check constant | ||||
// bus limitations because GFX7 support no f16 inline constants. | // bus limitations because GFX7 support no f16 inline constants. | ||||
// Note that there are no cases when a GFX7 opcode violates | // Note that there are no cases when a GFX7 opcode violates | ||||
// constant bus limitations due to the use of an f16 constant. | // constant bus limitations due to the use of an f16 constant. | ||||
bool AMDGPUAsmParser::isInlineConstant(const MCInst &Inst, | bool AMDGPUAsmParser::isInlineConstant(const MCInst &Inst, | ||||
unsigned OpIdx) const { | unsigned OpIdx) const { | ||||
const MCInstrDesc &Desc = MII.get(Inst.getOpcode()); | const MCInstrDesc &Desc = MII.get(Inst.getOpcode()); | ||||
Show All 25 Lines | bool AMDGPUAsmParser::isInlineConstant(const MCInst &Inst, | ||||
} | } | ||||
} | } | ||||
bool AMDGPUAsmParser::usesConstantBus(const MCInst &Inst, unsigned OpIdx) { | bool AMDGPUAsmParser::usesConstantBus(const MCInst &Inst, unsigned OpIdx) { | ||||
const MCOperand &MO = Inst.getOperand(OpIdx); | const MCOperand &MO = Inst.getOperand(OpIdx); | ||||
if (MO.isImm()) { | if (MO.isImm()) { | ||||
return !isInlineConstant(Inst, OpIdx); | return !isInlineConstant(Inst, OpIdx); | ||||
} | } | ||||
return !MO.isReg() || isSGPR(mc2PseudoReg(MO.getReg())); | return !MO.isReg() || | ||||
isSGPR(mc2PseudoReg(MO.getReg()), getContext().getRegisterInfo()); | |||||
} | } | ||||
bool AMDGPUAsmParser::validateOperandLimitations(const MCInst &Inst) { | bool AMDGPUAsmParser::validateOperandLimitations(const MCInst &Inst) { | ||||
const unsigned Opcode = Inst.getOpcode(); | const unsigned Opcode = Inst.getOpcode(); | ||||
const MCInstrDesc &Desc = MII.get(Opcode); | const MCInstrDesc &Desc = MII.get(Opcode); | ||||
unsigned ConstantBusUseCount = 0; | unsigned ConstantBusUseCount = 0; | ||||
if (Desc.TSFlags & | if (Desc.TSFlags & | ||||
(SIInstrFlags::VOPC | | (SIInstrFlags::VOPC | | ||||
SIInstrFlags::VOP1 | SIInstrFlags::VOP2 | | SIInstrFlags::VOP1 | SIInstrFlags::VOP2 | | ||||
SIInstrFlags::VOP3 | SIInstrFlags::VOP3P)) { | SIInstrFlags::VOP3 | SIInstrFlags::VOP3P | | ||||
SIInstrFlags::SDWA)) { | |||||
// Check special imm operands (used by madmk, etc) | // Check special imm operands (used by madmk, etc) | ||||
if (AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::imm) != -1) { | if (AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::imm) != -1) { | ||||
++ConstantBusUseCount; | ++ConstantBusUseCount; | ||||
} | } | ||||
unsigned SGPRUsed = findImplicitSGPRReadInVOP(Inst); | unsigned SGPRUsed = findImplicitSGPRReadInVOP(Inst); | ||||
if (SGPRUsed != AMDGPU::NoRegister) { | if (SGPRUsed != AMDGPU::NoRegister) { | ||||
▲ Show 20 Lines • Show All 2,074 Lines • ▼ Show 20 Lines | |||||
void AMDGPUAsmParser::cvtSdwaVOP1(MCInst &Inst, const OperandVector &Operands) { | void AMDGPUAsmParser::cvtSdwaVOP1(MCInst &Inst, const OperandVector &Operands) { | ||||
cvtSDWA(Inst, Operands, SIInstrFlags::VOP1); | cvtSDWA(Inst, Operands, SIInstrFlags::VOP1); | ||||
} | } | ||||
void AMDGPUAsmParser::cvtSdwaVOP2(MCInst &Inst, const OperandVector &Operands) { | void AMDGPUAsmParser::cvtSdwaVOP2(MCInst &Inst, const OperandVector &Operands) { | ||||
cvtSDWA(Inst, Operands, SIInstrFlags::VOP2); | cvtSDWA(Inst, Operands, SIInstrFlags::VOP2); | ||||
} | } | ||||
void AMDGPUAsmParser::cvtSdwaVOP2b(MCInst &Inst, const OperandVector &Operands) { | |||||
cvtSDWA(Inst, Operands, SIInstrFlags::VOP2, true); | |||||
} | |||||
void AMDGPUAsmParser::cvtSdwaVOPC(MCInst &Inst, const OperandVector &Operands) { | void AMDGPUAsmParser::cvtSdwaVOPC(MCInst &Inst, const OperandVector &Operands) { | ||||
cvtSDWA(Inst, Operands, SIInstrFlags::VOPC); | cvtSDWA(Inst, Operands, SIInstrFlags::VOPC, isVI()); | ||||
} | } | ||||
void AMDGPUAsmParser::cvtSDWA(MCInst &Inst, const OperandVector &Operands, | void AMDGPUAsmParser::cvtSDWA(MCInst &Inst, const OperandVector &Operands, | ||||
uint64_t BasicInstType) { | uint64_t BasicInstType, bool skipVcc) { | ||||
using namespace llvm::AMDGPU::SDWA; | using namespace llvm::AMDGPU::SDWA; | ||||
OptionalImmIndexMap OptionalIdx; | OptionalImmIndexMap OptionalIdx; | ||||
bool skippedVcc = false; | |||||
unsigned I = 1; | unsigned I = 1; | ||||
const MCInstrDesc &Desc = MII.get(Inst.getOpcode()); | const MCInstrDesc &Desc = MII.get(Inst.getOpcode()); | ||||
for (unsigned J = 0; J < Desc.getNumDefs(); ++J) { | for (unsigned J = 0; J < Desc.getNumDefs(); ++J) { | ||||
((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1); | ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1); | ||||
} | } | ||||
for (unsigned E = Operands.size(); I != E; ++I) { | for (unsigned E = Operands.size(); I != E; ++I) { | ||||
AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]); | AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]); | ||||
// Add the register arguments | if (skipVcc && !skippedVcc && Op.isReg() && Op.Reg.RegNo == AMDGPU::VCC) { | ||||
if ((BasicInstType == SIInstrFlags::VOPC || | // VOP2b (v_add_u32, v_sub_u32 ...) sdwa use "vcc" token as dst. | ||||
BasicInstType == SIInstrFlags::VOP2)&& | // Skip it if it's 2nd (e.g. v_add_i32_sdwa v1, vcc, v2, v3) | ||||
Op.isReg() && | // or 4th (v_addc_u32_sdwa v1, vcc, v2, v3, vcc) operand. | ||||
Op.Reg.RegNo == AMDGPU::VCC) { | // Skip VCC only if we didn't skip it on previous iteration. | ||||
// VOPC and VOP2b (v_add_u32, v_sub_u32 ...) sdwa use "vcc" token as dst. | if (BasicInstType == SIInstrFlags::VOP2 && | ||||
// Skip it. | (Inst.getNumOperands() == 1 || Inst.getNumOperands() == 5)) { | ||||
skippedVcc = true; | |||||
continue; | continue; | ||||
} else if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) { | } else if (BasicInstType == SIInstrFlags::VOPC && | ||||
Inst.getNumOperands() == 0) { | |||||
skippedVcc = true; | |||||
continue; | |||||
} | |||||
} | |||||
if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) { | |||||
Op.addRegWithInputModsOperands(Inst, 2); | Op.addRegWithInputModsOperands(Inst, 2); | ||||
} else if (Op.isImm()) { | } else if (Op.isImm()) { | ||||
// Handle optional arguments | // Handle optional arguments | ||||
OptionalIdx[Op.getImmTy()] = I; | OptionalIdx[Op.getImmTy()] = I; | ||||
} else { | } else { | ||||
llvm_unreachable("Invalid operand type"); | llvm_unreachable("Invalid operand type"); | ||||
} | } | ||||
skippedVcc = false; | |||||
} | } | ||||
addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI, 0); | if (Inst.getOpcode() != AMDGPU::V_NOP_sdwa_gfx9 && | ||||
Inst.getOpcode() != AMDGPU::V_NOP_sdwa_vi) { | |||||
if (Inst.getOpcode() != AMDGPU::V_NOP_sdwa_vi) { | |||||
// V_NOP_sdwa_vi has no optional sdwa arguments | // V_NOP_sdwa_vi has no optional sdwa arguments | ||||
switch (BasicInstType) { | switch (BasicInstType) { | ||||
case SIInstrFlags::VOP1: | case SIInstrFlags::VOP1: | ||||
addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI, 0); | |||||
if (isGFX9() && | |||||
AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::omod) != -1) { | |||||
addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOModSI, 0); | |||||
} | |||||
addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstSel, SdwaSel::DWORD); | addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstSel, SdwaSel::DWORD); | ||||
addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstUnused, DstUnused::UNUSED_PRESERVE); | addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstUnused, DstUnused::UNUSED_PRESERVE); | ||||
addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc0Sel, SdwaSel::DWORD); | addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc0Sel, SdwaSel::DWORD); | ||||
break; | break; | ||||
case SIInstrFlags::VOP2: | case SIInstrFlags::VOP2: | ||||
addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI, 0); | |||||
if (isGFX9() && | |||||
AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::omod) != -1) { | |||||
addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOModSI, 0); | |||||
} | |||||
addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstSel, SdwaSel::DWORD); | addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstSel, SdwaSel::DWORD); | ||||
addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstUnused, DstUnused::UNUSED_PRESERVE); | addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstUnused, DstUnused::UNUSED_PRESERVE); | ||||
addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc0Sel, SdwaSel::DWORD); | addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc0Sel, SdwaSel::DWORD); | ||||
addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc1Sel, SdwaSel::DWORD); | addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc1Sel, SdwaSel::DWORD); | ||||
break; | break; | ||||
case SIInstrFlags::VOPC: | case SIInstrFlags::VOPC: | ||||
if (isVI()) { | |||||
addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI, 0); | |||||
} | |||||
addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc0Sel, SdwaSel::DWORD); | addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc0Sel, SdwaSel::DWORD); | ||||
addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc1Sel, SdwaSel::DWORD); | addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc1Sel, SdwaSel::DWORD); | ||||
break; | break; | ||||
default: | default: | ||||
llvm_unreachable("Invalid instruction type. Only VOP1, VOP2 and VOPC allowed"); | llvm_unreachable("Invalid instruction type. Only VOP1, VOP2 and VOPC allowed"); | ||||
} | } | ||||
} | } | ||||
// special case v_mac_{f16, f32}: | // special case v_mac_{f16, f32}: | ||||
// it has src2 register operand that is tied to dst operand | // it has src2 register operand that is tied to dst operand | ||||
if (Inst.getOpcode() == AMDGPU::V_MAC_F32_sdwa_vi || | if (Inst.getOpcode() == AMDGPU::V_MAC_F32_sdwa_vi || | ||||
Inst.getOpcode() == AMDGPU::V_MAC_F16_sdwa_vi) { | Inst.getOpcode() == AMDGPU::V_MAC_F16_sdwa_vi) { | ||||
auto it = Inst.begin(); | auto it = Inst.begin(); | ||||
std::advance( | std::advance( | ||||
it, AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::src2)); | it, AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::src2)); | ||||
Inst.insert(it, Inst.getOperand(0)); // src2 = dst | Inst.insert(it, Inst.getOperand(0)); // src2 = dst | ||||
} | } | ||||
} | } | ||||
/// Force static initialization. | /// Force static initialization. | ||||
extern "C" void LLVMInitializeAMDGPUAsmParser() { | extern "C" void LLVMInitializeAMDGPUAsmParser() { | ||||
RegisterMCAsmParser<AMDGPUAsmParser> A(getTheAMDGPUTarget()); | RegisterMCAsmParser<AMDGPUAsmParser> A(getTheAMDGPUTarget()); | ||||
RegisterMCAsmParser<AMDGPUAsmParser> B(getTheGCNTarget()); | RegisterMCAsmParser<AMDGPUAsmParser> B(getTheGCNTarget()); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 48 Lines • Show Last 20 Lines |