diff options
Diffstat (limited to 'llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp')
-rw-r--r-- | llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp | 280 |
1 files changed, 220 insertions, 60 deletions
diff --git a/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp b/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp index f3aa1a5823689..013b7a0cf25d1 100644 --- a/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp +++ b/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp @@ -163,6 +163,7 @@ public: ImmTyUNorm, ImmTyDA, ImmTyR128A16, + ImmTyA16, ImmTyLWE, ImmTyExpTgt, ImmTyExpCompr, @@ -277,6 +278,7 @@ public: isRegClass(AMDGPU::VReg_96RegClassID) || isRegClass(AMDGPU::VReg_128RegClassID) || isRegClass(AMDGPU::VReg_160RegClassID) || + isRegClass(AMDGPU::VReg_192RegClassID) || isRegClass(AMDGPU::VReg_256RegClassID) || isRegClass(AMDGPU::VReg_512RegClassID) || isRegClass(AMDGPU::VReg_1024RegClassID); @@ -315,6 +317,7 @@ public: bool isUNorm() const { return isImmTy(ImmTyUNorm); } bool isDA() const { return isImmTy(ImmTyDA); } bool isR128A16() const { return isImmTy(ImmTyR128A16); } + bool isGFX10A16() const { return isImmTy(ImmTyA16); } bool isLWE() const { return isImmTy(ImmTyLWE); } bool isOff() const { return isImmTy(ImmTyOff); } bool isExpTgt() const { return isImmTy(ImmTyExpTgt); } @@ -486,7 +489,7 @@ public: } bool isVSrcB16() const { - return isVCSrcF16() || isLiteralImm(MVT::i16); + return isVCSrcB16() || isLiteralImm(MVT::i16); } bool isVSrcV2B16() const { @@ -654,7 +657,7 @@ public: bool isSendMsg() const; bool isSwizzle() const; bool isSMRDOffset8() const; - bool isSMRDOffset20() const; + bool isSMEMOffset() const; bool isSMRDLiteralOffset() const; bool isDPP8() const; bool isDPPCtrl() const; @@ -847,6 +850,7 @@ public: case ImmTyUNorm: OS << "UNorm"; break; case ImmTyDA: OS << "DA"; break; case ImmTyR128A16: OS << "R128A16"; break; + case ImmTyA16: OS << "A16"; break; case ImmTyLWE: OS << "LWE"; break; case ImmTyOff: OS << "Off"; break; case ImmTyExpTgt: OS << "ExpTgt"; break; @@ -1062,17 +1066,20 @@ private: bool AddNextRegisterToList(unsigned& Reg, unsigned& RegWidth, RegisterKind RegKind, unsigned Reg1); - bool ParseAMDGPURegister(RegisterKind& RegKind, unsigned& Reg, - unsigned& RegNum, unsigned& RegWidth); - unsigned ParseRegularReg(RegisterKind &RegKind, - unsigned &RegNum, - unsigned &RegWidth); - unsigned ParseSpecialReg(RegisterKind &RegKind, - unsigned &RegNum, - unsigned &RegWidth); - unsigned ParseRegList(RegisterKind &RegKind, - unsigned &RegNum, - unsigned &RegWidth); + bool ParseAMDGPURegister(RegisterKind &RegKind, unsigned &Reg, + unsigned &RegNum, unsigned &RegWidth, + bool RestoreOnFailure = false); + bool ParseAMDGPURegister(RegisterKind &RegKind, unsigned &Reg, + unsigned &RegNum, unsigned &RegWidth, + SmallVectorImpl<AsmToken> &Tokens); + unsigned ParseRegularReg(RegisterKind &RegKind, unsigned &RegNum, + unsigned &RegWidth, + SmallVectorImpl<AsmToken> &Tokens); + unsigned ParseSpecialReg(RegisterKind &RegKind, unsigned &RegNum, + unsigned &RegWidth, + SmallVectorImpl<AsmToken> &Tokens); + unsigned ParseRegList(RegisterKind &RegKind, unsigned &RegNum, + unsigned &RegWidth, SmallVectorImpl<AsmToken> &Tokens); bool ParseRegRange(unsigned& Num, unsigned& Width); unsigned getRegularReg(RegisterKind RegKind, unsigned RegNum, @@ -1157,6 +1164,10 @@ public: return AMDGPU::hasPackedD16(getSTI()); } + bool hasGFX10A16() const { + return AMDGPU::hasGFX10A16(getSTI()); + } + bool isSI() const { return AMDGPU::isSI(getSTI()); } @@ -1177,6 +1188,10 @@ public: return AMDGPU::isGFX10(getSTI()); } + bool isGFX10_BEncoding() const { + return AMDGPU::isGFX10_BEncoding(getSTI()); + } + bool hasInv2PiInlineImm() const { return getFeatureBits()[AMDGPU::FeatureInv2PiInlineImm]; } @@ -1226,8 +1241,12 @@ public: bool isForcedSDWA() const { return ForcedSDWA; } ArrayRef<unsigned> getMatchedVariants() const; - std::unique_ptr<AMDGPUOperand> parseRegister(); + std::unique_ptr<AMDGPUOperand> parseRegister(bool RestoreOnFailure = false); + bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc, + bool RestoreOnFailure); bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override; + OperandMatchResultTy tryParseRegister(unsigned &RegNo, SMLoc &StartLoc, + SMLoc &EndLoc) override; unsigned checkTargetMatchPredicate(MCInst &Inst) override; unsigned validateTargetOperandClass(MCParsedAsmOperand &Op, unsigned Kind) override; @@ -1311,9 +1330,11 @@ private: void errorExpTgt(); OperandMatchResultTy parseExpTgtImpl(StringRef Str, uint8_t &Val); SMLoc getFlatOffsetLoc(const OperandVector &Operands) const; + SMLoc getSMEMOffsetLoc(const OperandVector &Operands) const; bool validateInstruction(const MCInst &Inst, const SMLoc &IDLoc, const OperandVector &Operands); bool validateFlatOffset(const MCInst &Inst, const OperandVector &Operands); + bool validateSMEMOffset(const MCInst &Inst, const OperandVector &Operands); bool validateSOPLiteral(const MCInst &Inst) const; bool validateConstantBusLimitations(const MCInst &Inst); bool validateEarlyClobberLimitations(const MCInst &Inst); @@ -1329,6 +1350,7 @@ private: bool validateOpSel(const MCInst &Inst); bool validateVccOperand(unsigned Reg) const; bool validateVOP3Literal(const MCInst &Inst) const; + bool validateMAIAccWrite(const MCInst &Inst); unsigned getConstantBusLimit(unsigned Opcode) const; bool usesConstantBus(const MCInst &Inst, unsigned OpIdx); bool isInlineConstant(const MCInst &Inst, unsigned OpIdx) const; @@ -1390,7 +1412,7 @@ public: AMDGPUOperand::Ptr defaultSLC() const; AMDGPUOperand::Ptr defaultSMRDOffset8() const; - AMDGPUOperand::Ptr defaultSMRDOffset20() const; + AMDGPUOperand::Ptr defaultSMEMOffset() const; AMDGPUOperand::Ptr defaultSMRDLiteralOffset() const; AMDGPUOperand::Ptr defaultFlatOffset() const; @@ -1524,6 +1546,16 @@ static bool isSafeTruncation(int64_t Val, unsigned Size) { return isUIntN(Size, Val) || isIntN(Size, Val); } +static bool isInlineableLiteralOp16(int64_t Val, MVT VT, bool HasInv2Pi) { + if (VT.getScalarType() == MVT::i16) { + // FP immediate values are broken. + return isInlinableIntLiteral(Val); + } + + // f16/v2f16 operands work correctly for all values. + return AMDGPU::isInlinableLiteral16(Val, HasInv2Pi); +} + bool AMDGPUOperand::isInlinableImm(MVT type) const { // This is a hack to enable named inline values like @@ -1555,9 +1587,9 @@ bool AMDGPUOperand::isInlinableImm(MVT type) const { return false; if (type.getScalarSizeInBits() == 16) { - return AMDGPU::isInlinableLiteral16( + return isInlineableLiteralOp16( static_cast<int16_t>(FPLiteral.bitcastToAPInt().getZExtValue()), - AsmParser->hasInv2PiInlineImm()); + type, AsmParser->hasInv2PiInlineImm()); } // Check if single precision literal is inlinable @@ -1577,9 +1609,9 @@ bool AMDGPUOperand::isInlinableImm(MVT type) const { } if (type.getScalarSizeInBits() == 16) { - return AMDGPU::isInlinableLiteral16( + return isInlineableLiteralOp16( static_cast<int16_t>(Literal.getLoBits(16).getSExtValue()), - AsmParser->hasInv2PiInlineImm()); + type, AsmParser->hasInv2PiInlineImm()); } return AMDGPU::isInlinableLiteral32( @@ -1901,6 +1933,7 @@ static int getRegClass(RegisterKind Is, unsigned RegWidth) { case 3: return AMDGPU::VReg_96RegClassID; case 4: return AMDGPU::VReg_128RegClassID; case 5: return AMDGPU::VReg_160RegClassID; + case 6: return AMDGPU::VReg_192RegClassID; case 8: return AMDGPU::VReg_256RegClassID; case 16: return AMDGPU::VReg_512RegClassID; case 32: return AMDGPU::VReg_1024RegClassID; @@ -1919,7 +1952,10 @@ static int getRegClass(RegisterKind Is, unsigned RegWidth) { default: return -1; case 1: return AMDGPU::SGPR_32RegClassID; case 2: return AMDGPU::SGPR_64RegClassID; + case 3: return AMDGPU::SGPR_96RegClassID; case 4: return AMDGPU::SGPR_128RegClassID; + case 5: return AMDGPU::SGPR_160RegClassID; + case 6: return AMDGPU::SGPR_192RegClassID; case 8: return AMDGPU::SGPR_256RegClassID; case 16: return AMDGPU::SGPR_512RegClassID; } @@ -1928,7 +1964,11 @@ static int getRegClass(RegisterKind Is, unsigned RegWidth) { default: return -1; case 1: return AMDGPU::AGPR_32RegClassID; case 2: return AMDGPU::AReg_64RegClassID; + case 3: return AMDGPU::AReg_96RegClassID; case 4: return AMDGPU::AReg_128RegClassID; + case 5: return AMDGPU::AReg_160RegClassID; + case 6: return AMDGPU::AReg_192RegClassID; + case 8: return AMDGPU::AReg_256RegClassID; case 16: return AMDGPU::AReg_512RegClassID; case 32: return AMDGPU::AReg_1024RegClassID; } @@ -1975,12 +2015,13 @@ static unsigned getSpecialRegForName(StringRef RegName) { .Case("tma_hi", AMDGPU::TMA_HI) .Case("tba_lo", AMDGPU::TBA_LO) .Case("tba_hi", AMDGPU::TBA_HI) + .Case("pc", AMDGPU::PC_REG) .Case("null", AMDGPU::SGPR_NULL) .Default(AMDGPU::NoRegister); } bool AMDGPUAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, - SMLoc &EndLoc) { + SMLoc &EndLoc, bool RestoreOnFailure) { auto R = parseRegister(); if (!R) return true; assert(R->isReg()); @@ -1990,6 +2031,25 @@ bool AMDGPUAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, return false; } +bool AMDGPUAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, + SMLoc &EndLoc) { + return ParseRegister(RegNo, StartLoc, EndLoc, /*RestoreOnFailure=*/false); +} + +OperandMatchResultTy AMDGPUAsmParser::tryParseRegister(unsigned &RegNo, + SMLoc &StartLoc, + SMLoc &EndLoc) { + bool Result = + ParseRegister(RegNo, StartLoc, EndLoc, /*RestoreOnFailure=*/true); + bool PendingErrors = getParser().hasPendingError(); + getParser().clearPendingErrors(); + if (PendingErrors) + return MatchOperand_ParseFail; + if (Result) + return MatchOperand_NoMatch; + return MatchOperand_Success; +} + bool AMDGPUAsmParser::AddNextRegisterToList(unsigned &Reg, unsigned &RegWidth, RegisterKind RegKind, unsigned Reg1) { switch (RegKind) { @@ -2166,31 +2226,31 @@ AMDGPUAsmParser::ParseRegRange(unsigned& Num, unsigned& Width) { return true; } -unsigned -AMDGPUAsmParser::ParseSpecialReg(RegisterKind &RegKind, - unsigned &RegNum, - unsigned &RegWidth) { +unsigned AMDGPUAsmParser::ParseSpecialReg(RegisterKind &RegKind, + unsigned &RegNum, unsigned &RegWidth, + SmallVectorImpl<AsmToken> &Tokens) { assert(isToken(AsmToken::Identifier)); unsigned Reg = getSpecialRegForName(getTokenStr()); if (Reg) { RegNum = 0; RegWidth = 1; RegKind = IS_SPECIAL; + Tokens.push_back(getToken()); lex(); // skip register name } return Reg; } -unsigned -AMDGPUAsmParser::ParseRegularReg(RegisterKind &RegKind, - unsigned &RegNum, - unsigned &RegWidth) { +unsigned AMDGPUAsmParser::ParseRegularReg(RegisterKind &RegKind, + unsigned &RegNum, unsigned &RegWidth, + SmallVectorImpl<AsmToken> &Tokens) { assert(isToken(AsmToken::Identifier)); StringRef RegName = getTokenStr(); const RegInfo *RI = getRegularRegInfo(RegName); if (!RI) return AMDGPU::NoRegister; + Tokens.push_back(getToken()); lex(); // skip register name RegKind = RI->Kind; @@ -2209,10 +2269,9 @@ AMDGPUAsmParser::ParseRegularReg(RegisterKind &RegKind, return getRegularReg(RegKind, RegNum, RegWidth); } -unsigned -AMDGPUAsmParser::ParseRegList(RegisterKind &RegKind, - unsigned &RegNum, - unsigned &RegWidth) { +unsigned AMDGPUAsmParser::ParseRegList(RegisterKind &RegKind, unsigned &RegNum, + unsigned &RegWidth, + SmallVectorImpl<AsmToken> &Tokens) { unsigned Reg = AMDGPU::NoRegister; if (!trySkipToken(AsmToken::LBrac)) @@ -2229,7 +2288,8 @@ AMDGPUAsmParser::ParseRegList(RegisterKind &RegKind, RegisterKind NextRegKind; unsigned NextReg, NextRegNum, NextRegWidth; - if (!ParseAMDGPURegister(NextRegKind, NextReg, NextRegNum, NextRegWidth)) + if (!ParseAMDGPURegister(NextRegKind, NextReg, NextRegNum, NextRegWidth, + Tokens)) return AMDGPU::NoRegister; if (NextRegWidth != 1) return AMDGPU::NoRegister; @@ -2248,24 +2308,40 @@ AMDGPUAsmParser::ParseRegList(RegisterKind &RegKind, return Reg; } -bool AMDGPUAsmParser::ParseAMDGPURegister(RegisterKind &RegKind, - unsigned &Reg, - unsigned &RegNum, - unsigned &RegWidth) { +bool AMDGPUAsmParser::ParseAMDGPURegister(RegisterKind &RegKind, unsigned &Reg, + unsigned &RegNum, unsigned &RegWidth, + SmallVectorImpl<AsmToken> &Tokens) { Reg = AMDGPU::NoRegister; if (isToken(AsmToken::Identifier)) { - Reg = ParseSpecialReg(RegKind, RegNum, RegWidth); + Reg = ParseSpecialReg(RegKind, RegNum, RegWidth, Tokens); if (Reg == AMDGPU::NoRegister) - Reg = ParseRegularReg(RegKind, RegNum, RegWidth); + Reg = ParseRegularReg(RegKind, RegNum, RegWidth, Tokens); } else { - Reg = ParseRegList(RegKind, RegNum, RegWidth); + Reg = ParseRegList(RegKind, RegNum, RegWidth, Tokens); } const MCRegisterInfo *TRI = getContext().getRegisterInfo(); return Reg != AMDGPU::NoRegister && subtargetHasRegister(*TRI, Reg); } +bool AMDGPUAsmParser::ParseAMDGPURegister(RegisterKind &RegKind, unsigned &Reg, + unsigned &RegNum, unsigned &RegWidth, + bool RestoreOnFailure) { + Reg = AMDGPU::NoRegister; + + SmallVector<AsmToken, 1> Tokens; + if (ParseAMDGPURegister(RegKind, Reg, RegNum, RegWidth, Tokens)) { + if (RestoreOnFailure) { + while (!Tokens.empty()) { + getLexer().UnLex(Tokens.pop_back_val()); + } + } + return true; + } + return false; +} + Optional<StringRef> AMDGPUAsmParser::getGprCountSymbolName(RegisterKind RegKind) { switch (RegKind) { @@ -2314,7 +2390,8 @@ bool AMDGPUAsmParser::updateGprCountSymbols(RegisterKind RegKind, return true; } -std::unique_ptr<AMDGPUOperand> AMDGPUAsmParser::parseRegister() { +std::unique_ptr<AMDGPUOperand> +AMDGPUAsmParser::parseRegister(bool RestoreOnFailure) { const auto &Tok = Parser.getTok(); SMLoc StartLoc = Tok.getLoc(); SMLoc EndLoc = Tok.getEndLoc(); @@ -2758,16 +2835,22 @@ bool AMDGPUAsmParser::isInlineConstant(const MCInst &Inst, return AMDGPU::isInlinableLiteral32(Val, hasInv2PiInlineImm()); case 2: { const unsigned OperandType = Desc.OpInfo[OpIdx].OperandType; + if (OperandType == AMDGPU::OPERAND_REG_IMM_INT16 || + OperandType == AMDGPU::OPERAND_REG_INLINE_C_INT16 || + OperandType == AMDGPU::OPERAND_REG_INLINE_AC_INT16) + return AMDGPU::isInlinableIntLiteral(Val); + if (OperandType == AMDGPU::OPERAND_REG_INLINE_C_V2INT16 || - OperandType == AMDGPU::OPERAND_REG_INLINE_C_V2FP16 || OperandType == AMDGPU::OPERAND_REG_INLINE_AC_V2INT16 || + OperandType == AMDGPU::OPERAND_REG_IMM_V2INT16) + return AMDGPU::isInlinableIntLiteralV216(Val); + + if (OperandType == AMDGPU::OPERAND_REG_INLINE_C_V2FP16 || OperandType == AMDGPU::OPERAND_REG_INLINE_AC_V2FP16 || - OperandType == AMDGPU::OPERAND_REG_IMM_V2INT16 || - OperandType == AMDGPU::OPERAND_REG_IMM_V2FP16) { + OperandType == AMDGPU::OPERAND_REG_IMM_V2FP16) return AMDGPU::isInlinableLiteralV216(Val, hasInv2PiInlineImm()); - } else { - return AMDGPU::isInlinableLiteral16(Val, hasInv2PiInlineImm()); - } + + return AMDGPU::isInlinableLiteral16(Val, hasInv2PiInlineImm()); } default: llvm_unreachable("invalid operand size"); @@ -3085,6 +3168,30 @@ bool AMDGPUAsmParser::validateMovrels(const MCInst &Inst) { return !isSGPR(mc2PseudoReg(Reg), TRI); } +bool AMDGPUAsmParser::validateMAIAccWrite(const MCInst &Inst) { + + const unsigned Opc = Inst.getOpcode(); + + if (Opc != AMDGPU::V_ACCVGPR_WRITE_B32_vi) + return true; + + const int Src0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0); + assert(Src0Idx != -1); + + const MCOperand &Src0 = Inst.getOperand(Src0Idx); + if (!Src0.isReg()) + return true; + + auto Reg = Src0.getReg(); + const MCRegisterInfo *TRI = getContext().getRegisterInfo(); + if (isSGPR(mc2PseudoReg(Reg), TRI)) { + Error(getLoc(), "source operand must be either a VGPR or an inline constant"); + return false; + } + + return true; +} + bool AMDGPUAsmParser::validateMIMGD16(const MCInst &Inst) { const unsigned Opc = Inst.getOpcode(); @@ -3335,6 +3442,46 @@ bool AMDGPUAsmParser::validateFlatOffset(const MCInst &Inst, return true; } +SMLoc AMDGPUAsmParser::getSMEMOffsetLoc(const OperandVector &Operands) const { + for (unsigned i = 1, e = Operands.size(); i != e; ++i) { + AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]); + if (Op.isSMEMOffset()) + return Op.getStartLoc(); + } + return getLoc(); +} + +bool AMDGPUAsmParser::validateSMEMOffset(const MCInst &Inst, + const OperandVector &Operands) { + if (isCI() || isSI()) + return true; + + uint64_t TSFlags = MII.get(Inst.getOpcode()).TSFlags; + if ((TSFlags & SIInstrFlags::SMRD) == 0) + return true; + + auto Opcode = Inst.getOpcode(); + auto OpNum = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::offset); + if (OpNum == -1) + return true; + + const auto &Op = Inst.getOperand(OpNum); + if (!Op.isImm()) + return true; + + uint64_t Offset = Op.getImm(); + bool IsBuffer = AMDGPU::getSMEMIsBuffer(Opcode); + if (AMDGPU::isLegalSMRDEncodedUnsignedOffset(getSTI(), Offset) || + AMDGPU::isLegalSMRDEncodedSignedOffset(getSTI(), Offset, IsBuffer)) + return true; + + Error(getSMEMOffsetLoc(Operands), + (isVI() || IsBuffer) ? "expected a 20-bit unsigned offset" : + "expected a 21-bit signed offset"); + + return false; +} + bool AMDGPUAsmParser::validateSOPLiteral(const MCInst &Inst) const { unsigned Opcode = Inst.getOpcode(); const MCInstrDesc &Desc = MII.get(Opcode); @@ -3512,6 +3659,12 @@ bool AMDGPUAsmParser::validateInstruction(const MCInst &Inst, if (!validateFlatOffset(Inst, Operands)) { return false; } + if (!validateSMEMOffset(Inst, Operands)) { + return false; + } + if (!validateMAIAccWrite(Inst)) { + return false; + } return true; } @@ -3556,7 +3709,7 @@ bool AMDGPUAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, return true; } Inst.setLoc(IDLoc); - Out.EmitInstruction(Inst, getSTI()); + Out.emitInstruction(Inst, getSTI()); return false; case Match_MissingFeature: @@ -4307,19 +4460,19 @@ bool AMDGPUAsmParser::ParseDirectiveAMDGPULDS() { if (Size > LocalMemorySize) return Error(SizeLoc, "size is too large"); - int64_t Align = 4; + int64_t Alignment = 4; if (getLexer().is(AsmToken::Comma)) { Lex(); SMLoc AlignLoc = getLexer().getLoc(); - if (getParser().parseAbsoluteExpression(Align)) + if (getParser().parseAbsoluteExpression(Alignment)) return true; - if (Align < 0 || !isPowerOf2_64(Align)) + if (Alignment < 0 || !isPowerOf2_64(Alignment)) return Error(AlignLoc, "alignment must be a power of two"); // Alignment larger than the size of LDS is possible in theory, as long // as the linker manages to place to symbol at address 0, but we do want // to make sure the alignment fits nicely into a 32-bit integer. - if (Align >= 1u << 31) + if (Alignment >= 1u << 31) return Error(AlignLoc, "alignment is too large"); } @@ -4331,7 +4484,7 @@ bool AMDGPUAsmParser::ParseDirectiveAMDGPULDS() { if (!Symbol->isUndefined()) return Error(NameLoc, "invalid symbol redefinition"); - getTargetStreamer().emitAMDGPULDS(Symbol, Size, Align); + getTargetStreamer().emitAMDGPULDS(Symbol, Size, Align(Alignment)); return false; } @@ -4650,9 +4803,9 @@ AMDGPUAsmParser::parseNamedBit(const char *Name, OperandVector &Operands, case AsmToken::Identifier: { StringRef Tok = Parser.getTok().getString(); if (Tok == Name) { - if (Tok == "r128" && isGFX9()) + if (Tok == "r128" && !hasMIMG_R128()) Error(S, "r128 modifier is not supported on this GPU"); - if (Tok == "a16" && !isGFX9() && !isGFX10()) + if (Tok == "a16" && !isGFX9() && !hasGFX10A16()) Error(S, "a16 modifier is not supported on this GPU"); Bit = 1; Parser.Lex(); @@ -4672,6 +4825,9 @@ AMDGPUAsmParser::parseNamedBit(const char *Name, OperandVector &Operands, if (!isGFX10() && ImmTy == AMDGPUOperand::ImmTyDLC) return MatchOperand_ParseFail; + if (isGFX9() && ImmTy == AMDGPUOperand::ImmTyA16) + ImmTy = AMDGPUOperand::ImmTyR128A16; + Operands.push_back(AMDGPUOperand::CreateImm(this, Bit, S, ImmTy)); return MatchOperand_Success; } @@ -5987,6 +6143,8 @@ void AMDGPUAsmParser::cvtMIMG(MCInst &Inst, const OperandVector &Operands, addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGLC); addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySLC); addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyR128A16); + if (IsGFX10) + addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyA16); addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyTFE); addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyLWE); if (!IsGFX10) @@ -6006,8 +6164,8 @@ bool AMDGPUOperand::isSMRDOffset8() const { return isImm() && isUInt<8>(getImm()); } -bool AMDGPUOperand::isSMRDOffset20() const { - return isImm() && isUInt<20>(getImm()); +bool AMDGPUOperand::isSMEMOffset() const { + return isImm(); // Offset range is checked later by validator. } bool AMDGPUOperand::isSMRDLiteralOffset() const { @@ -6020,7 +6178,7 @@ AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSMRDOffset8() const { return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyOffset); } -AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSMRDOffset20() const { +AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSMEMOffset() const { return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyOffset); } @@ -6096,7 +6254,7 @@ static const OptionalOperand AMDGPUOptionalOperandTable[] = { {"unorm", AMDGPUOperand::ImmTyUNorm, true, nullptr}, {"da", AMDGPUOperand::ImmTyDA, true, nullptr}, {"r128", AMDGPUOperand::ImmTyR128A16, true, nullptr}, - {"a16", AMDGPUOperand::ImmTyR128A16, true, nullptr}, + {"a16", AMDGPUOperand::ImmTyA16, true, nullptr}, {"lwe", AMDGPUOperand::ImmTyLWE, true, nullptr}, {"d16", AMDGPUOperand::ImmTyD16, true, nullptr}, {"dmask", AMDGPUOperand::ImmTyDMask, false, nullptr}, @@ -6499,7 +6657,7 @@ OperandMatchResultTy AMDGPUAsmParser::parseDim(OperandVector &Operands) { std::string Token; if (getLexer().is(AsmToken::Integer)) { SMLoc Loc = getLexer().getTok().getEndLoc(); - Token = getLexer().getTok().getString(); + Token = std::string(getLexer().getTok().getString()); Parser.Lex(); if (getLexer().getTok().getLoc() != Loc) return MatchOperand_ParseFail; @@ -7032,6 +7190,8 @@ unsigned AMDGPUAsmParser::validateTargetOperandClass(MCParsedAsmOperand &Op, return Operand.isInterpAttr() ? Match_Success : Match_InvalidOperand; case MCK_AttrChan: return Operand.isAttrChan() ? Match_Success : Match_InvalidOperand; + case MCK_ImmSMEMOffset: + return Operand.isSMEMOffset() ? Match_Success : Match_InvalidOperand; case MCK_SReg_64: case MCK_SReg_64_XEXEC: // Null is defined as a 32-bit register but |