Index: llvm/trunk/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp =================================================================== --- llvm/trunk/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp +++ llvm/trunk/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp @@ -64,6 +64,43 @@ typedef std::unique_ptr Ptr; + struct Modifiers { + bool Abs; + bool Neg; + bool Sext; + + bool hasFPModifiers() const { return Abs || Neg; } + bool hasIntModifiers() const { return Sext; } + bool hasModifiers() const { return hasFPModifiers() || hasIntModifiers(); } + + int64_t getFPModifiersOperand() const { + int64_t Operand = 0; + Operand |= Abs ? SISrcMods::ABS : 0; + Operand |= Neg ? SISrcMods::NEG : 0; + return Operand; + } + + int64_t getIntModifiersOperand() const { + int64_t Operand = 0; + Operand |= Sext ? SISrcMods::SEXT : 0; + return Operand; + } + + int64_t getModifiersOperand() const { + assert(!(hasFPModifiers() && hasIntModifiers()) + && "fp and int modifiers should not be used simultaneously"); + if (hasFPModifiers()) { + return getFPModifiersOperand(); + } else if (hasIntModifiers()) { + return getIntModifiersOperand(); + } else { + return 0; + } + } + + friend raw_ostream &operator <<(raw_ostream &OS, AMDGPUOperand::Modifiers Mods); + }; + enum ImmTy { ImmTyNone, ImmTyGDS, @@ -104,12 +141,12 @@ bool IsFPImm; ImmTy Type; int64_t Val; - int Modifiers; + Modifiers Mods; }; struct RegOp { unsigned RegNo; - int Modifiers; + Modifiers Mods; const MCRegisterInfo *TRI; const MCSubtargetInfo *STI; bool IsForcedVOP3; @@ -122,65 +159,6 @@ const MCExpr *Expr; }; - void addImmOperands(MCInst &Inst, unsigned N, bool ApplyModifiers = true) const { - if (Imm.Type == ImmTyNone && ApplyModifiers && Imm.Modifiers != 0) { - // Apply modifiers to immediate value - int64_t Val = Imm.Val; - bool Negate = Imm.Modifiers & 0x1; - bool Abs = Imm.Modifiers & 0x2; - if (Imm.IsFPImm) { - APFloat F(BitsToFloat(Val)); - if (Abs) { - F.clearSign(); - } - if (Negate) { - F.changeSign(); - } - Val = F.bitcastToAPInt().getZExtValue(); - } else { - Val = Abs ? std::abs(Val) : Val; - Val = Negate ? -Val : Val; - } - Inst.addOperand(MCOperand::createImm(Val)); - } else { - Inst.addOperand(MCOperand::createImm(getImm())); - } - } - - StringRef getToken() const { - return StringRef(Tok.Data, Tok.Length); - } - - void addRegOperands(MCInst &Inst, unsigned N) const { - Inst.addOperand(MCOperand::createReg(AMDGPU::getMCReg(getReg(), *Reg.STI))); - } - - void addRegOrImmOperands(MCInst &Inst, unsigned N) const { - if (isRegKind()) - addRegOperands(Inst, N); - else - addImmOperands(Inst, N); - } - - void addRegOrImmWithInputModsOperands(MCInst &Inst, unsigned N) const { - if (isRegKind()) { - Inst.addOperand(MCOperand::createImm(Reg.Modifiers)); - addRegOperands(Inst, N); - } else { - Inst.addOperand(MCOperand::createImm(Imm.Modifiers)); - addImmOperands(Inst, N, false); - } - } - - void addSoppBrTargetOperands(MCInst &Inst, unsigned N) const { - if (isImm()) - addImmOperands(Inst, N); - else { - assert(isExpr()); - Inst.addOperand(MCOperand::createExpr(Expr)); - } - } - bool isToken() const override { return Kind == Token; } @@ -190,9 +168,10 @@ } bool isInlinableImm() const { - if (!isImm() || Imm.Type != AMDGPUOperand::ImmTyNone /* Only plain - immediates are inlinable (e.g. "clamp" attribute is not) */ ) + if (!isImmTy(ImmTyNone)) { + // Only plain immediates are inlinable (e.g. "clamp" attribute is not) return false; + } // TODO: We should avoid using host float here. It would be better to // check the float bit values which is what a few other places do. // We've had bot failures before due to weird NaN support on mips hosts. @@ -203,56 +182,33 @@ F == 2.0 || F == -2.0 || F == 4.0 || F == -4.0); } - int64_t getImm() const { - return Imm.Val; - } - - enum ImmTy getImmTy() const { - assert(isImm()); - return Imm.Type; - } - bool isRegKind() const { return Kind == Register; } bool isReg() const override { - return Kind == Register && Reg.Modifiers == 0; + return isRegKind() && !Reg.Mods.hasModifiers(); } bool isRegOrImmWithInputMods() const { - return Kind == Register || isInlinableImm(); + return isRegKind() || isInlinableImm(); } bool isImmTy(ImmTy ImmT) const { return isImm() && Imm.Type == ImmT; } - - bool isClampSI() const { - return isImmTy(ImmTyClampSI); - } - - bool isOModSI() const { - return isImmTy(ImmTyOModSI); - } - + bool isImmModifier() const { - return Kind == Immediate && Imm.Type != ImmTyNone; + return isImm() && Imm.Type != ImmTyNone; } - - bool isDMask() const { - return isImmTy(ImmTyDMask); - } - + + bool isClampSI() const { return isImmTy(ImmTyClampSI); } + bool isOModSI() const { return isImmTy(ImmTyOModSI); } + bool isDMask() const { return isImmTy(ImmTyDMask); } bool isUNorm() const { return isImmTy(ImmTyUNorm); } bool isDA() const { return isImmTy(ImmTyDA); } bool isR128() const { return isImmTy(ImmTyUNorm); } bool isLWE() const { return isImmTy(ImmTyLWE); } - - bool isMod() const { - return isClampSI() || isOModSI(); - } - bool isOffen() const { return isImmTy(ImmTyOffen); } bool isIdxen() const { return isImmTy(ImmTyIdxen); } bool isAddr64() const { return isImmTy(ImmTyAddr64); } @@ -263,50 +219,16 @@ bool isGLC() const { return isImmTy(ImmTyGLC); } bool isSLC() const { return isImmTy(ImmTySLC); } bool isTFE() const { return isImmTy(ImmTyTFE); } - - bool isBankMask() const { - return isImmTy(ImmTyDppBankMask); - } - - bool isRowMask() const { - return isImmTy(ImmTyDppRowMask); - } - - bool isBoundCtrl() const { - return isImmTy(ImmTyDppBoundCtrl); - } - - bool isSDWADstSel() const { - return isImmTy(ImmTySdwaDstSel); - } - - bool isSDWASrc0Sel() const { - return isImmTy(ImmTySdwaSrc0Sel); - } - - bool isSDWASrc1Sel() const { - return isImmTy(ImmTySdwaSrc1Sel); - } - - bool isSDWADstUnused() const { - return isImmTy(ImmTySdwaDstUnused); - } - - void setModifiers(unsigned Mods) { - assert(isReg() || (isImm() && Imm.Modifiers == 0)); - if (isReg()) - Reg.Modifiers = Mods; - else - Imm.Modifiers = Mods; - } - - bool hasModifiers() const { - assert(isRegKind() || isImm()); - return isRegKind() ? Reg.Modifiers != 0 : Imm.Modifiers != 0; - } - - unsigned getReg() const override { - return Reg.RegNo; + bool isBankMask() const { return isImmTy(ImmTyDppBankMask); } + bool isRowMask() const { return isImmTy(ImmTyDppRowMask); } + bool isBoundCtrl() const { return isImmTy(ImmTyDppBoundCtrl); } + bool isSDWADstSel() const { return isImmTy(ImmTySdwaDstSel); } + bool isSDWASrc0Sel() const { return isImmTy(ImmTySdwaSrc0Sel); } + bool isSDWASrc1Sel() const { return isImmTy(ImmTySdwaSrc1Sel); } + bool isSDWADstUnused() const { return isImmTy(ImmTySdwaDstUnused); } + + bool isMod() const { + return isClampSI() || isOModSI(); } bool isRegOrImm() const { @@ -368,6 +290,32 @@ return isExpr() || isImm(); } + bool isSWaitCnt() const; + bool isHwreg() const; + bool isSendMsg() const; + bool isMubufOffset() const; + bool isSMRDOffset() const; + bool isSMRDLiteralOffset() const; + bool isDPPCtrl() const; + + StringRef getToken() const { + return StringRef(Tok.Data, Tok.Length); + } + + int64_t getImm() const { + assert(isImm()); + return Imm.Val; + } + + enum ImmTy getImmTy() const { + assert(isImm()); + return Imm.Type; + } + + unsigned getReg() const override { + return Reg.RegNo; + } + SMLoc getStartLoc() const override { return StartLoc; } @@ -376,6 +324,91 @@ return EndLoc; } + Modifiers getModifiers() const { + assert(isRegKind() || isImmTy(ImmTyNone)); + return isRegKind() ? Reg.Mods : Imm.Mods; + } + + void setModifiers(Modifiers Mods) { + assert(isRegKind() || isImmTy(ImmTyNone)); + if (isRegKind()) + Reg.Mods = Mods; + else + Imm.Mods = Mods; + } + + bool hasModifiers() const { + return getModifiers().hasModifiers(); + } + + bool hasFPModifiers() const { + return getModifiers().hasFPModifiers(); + } + + bool hasIntModifiers() const { + return getModifiers().hasIntModifiers(); + } + + void addImmOperands(MCInst &Inst, unsigned N, bool ApplyModifiers = true) const { + if (isImmTy(ImmTyNone) && ApplyModifiers && Imm.Mods.hasFPModifiers()) { + // Apply modifiers to immediate value + int64_t Val = Imm.Val; + bool Negate = Imm.Mods.Neg; // Only negate can get here + if (Imm.IsFPImm) { + APFloat F(BitsToFloat(Val)); + if (Negate) { + F.changeSign(); + } + Val = F.bitcastToAPInt().getZExtValue(); + } else { + Val = Negate ? -Val : Val; + } + Inst.addOperand(MCOperand::createImm(Val)); + } else { + Inst.addOperand(MCOperand::createImm(getImm())); + } + } + + void addRegOperands(MCInst &Inst, unsigned N) const { + Inst.addOperand(MCOperand::createReg(AMDGPU::getMCReg(getReg(), *Reg.STI))); + } + + void addRegOrImmOperands(MCInst &Inst, unsigned N) const { + if (isRegKind()) + addRegOperands(Inst, N); + else + addImmOperands(Inst, N); + } + + void addRegOrImmWithInputModsOperands(MCInst &Inst, unsigned N) const { + Modifiers Mods = getModifiers(); + Inst.addOperand(MCOperand::createImm(Mods.getModifiersOperand())); + if (isRegKind()) { + addRegOperands(Inst, N); + } else { + addImmOperands(Inst, N, false); + } + } + + void addRegOrImmWithFPInputModsOperands(MCInst &Inst, unsigned N) const { + assert(!hasIntModifiers()); + addRegOrImmWithInputModsOperands(Inst, N); + } + + void addRegOrImmWithIntInputModsOperands(MCInst &Inst, unsigned N) const { + assert(!hasFPModifiers()); + addRegOrImmWithInputModsOperands(Inst, N); + } + + void addSoppBrTargetOperands(MCInst &Inst, unsigned N) const { + if (isImm()) + addImmOperands(Inst, N); + else { + assert(isExpr()); + Inst.addOperand(MCOperand::createExpr(Expr)); + } + } + void printImmTy(raw_ostream& OS, ImmTy Type) const { switch (Type) { case ImmTyNone: OS << "None"; break; @@ -412,14 +445,14 @@ void print(raw_ostream &OS) const override { switch (Kind) { case Register: - OS << "'; + OS << "'; break; case Immediate: OS << '<' << getImm(); if (getImmTy() != ImmTyNone) { OS << " type: "; printImmTy(OS, getImmTy()); } - OS << " mods: " << Imm.Modifiers << '>'; + OS << " mods: " << Imm.Mods << '>'; break; case Token: OS << '\'' << getToken() << '\''; @@ -437,7 +470,7 @@ Op->Imm.Val = Val; Op->Imm.IsFPImm = IsFPImm; Op->Imm.Type = Type; - Op->Imm.Modifiers = 0; + Op->Imm.Mods = {false, false, false}; Op->StartLoc = Loc; Op->EndLoc = Loc; return Op; @@ -462,7 +495,7 @@ Op->Reg.RegNo = RegNo; Op->Reg.TRI = TRI; Op->Reg.STI = STI; - Op->Reg.Modifiers = 0; + Op->Reg.Mods = {false, false, false}; Op->Reg.IsForcedVOP3 = ForceVOP3; Op->StartLoc = S; Op->EndLoc = E; @@ -476,16 +509,13 @@ Op->EndLoc = S; return Op; } - - bool isSWaitCnt() const; - bool isHwreg() const; - bool isSendMsg() const; - bool isMubufOffset() const; - bool isSMRDOffset() const; - bool isSMRDLiteralOffset() const; - bool isDPPCtrl() const; }; +raw_ostream &operator <<(raw_ostream &OS, AMDGPUOperand::Modifiers Mods) { + OS << "abs:" << Mods.Abs << " neg: " << Mods.Neg << " sext:" << Mods.Sext; + return OS; +} + class AMDGPUAsmParser : public MCTargetAsmParser { const MCInstrInfo &MII; MCAsmParser &Parser; @@ -598,7 +628,8 @@ OperandMatchResultTy parseImm(OperandVector &Operands); OperandMatchResultTy parseRegOrImm(OperandVector &Operands); - OperandMatchResultTy parseRegOrImmWithInputMods(OperandVector &Operands); + OperandMatchResultTy parseRegOrImmWithFPInputMods(OperandVector &Operands); + OperandMatchResultTy parseRegOrImmWithIntInputMods(OperandVector &Operands); void cvtDSOffset01(MCInst &Inst, const OperandVector &Operands); void cvtDS(MCInst &Inst, const OperandVector &Operands); @@ -665,12 +696,9 @@ AMDGPUOperand::Ptr defaultSDWASrc0Sel() const; AMDGPUOperand::Ptr defaultSDWASrc1Sel() const; AMDGPUOperand::Ptr defaultSDWADstUnused() const; - void cvtSdwaVop1_mod(MCInst &Inst, const OperandVector &Operands); - void cvtSdwaVop1_nomod(MCInst &Inst, const OperandVector &Operands); - void cvtSdwaVop2_mod(MCInst &Inst, const OperandVector &Operands); - void cvtSdwaVop2_nomod(MCInst &Inst, const OperandVector &Operands); - void cvtSDWA(MCInst &Inst, const OperandVector &Operands, bool HasMods, - bool IsVOP1); + void cvtSdwaVOP1(MCInst &Inst, const OperandVector &Operands); + void cvtSdwaVOP2(MCInst &Inst, const OperandVector &Operands); + void cvtSDWA(MCInst &Inst, const OperandVector &Operands, bool IsVOP1); }; struct OptionalOperand { @@ -969,7 +997,7 @@ } AMDGPUAsmParser::OperandMatchResultTy -AMDGPUAsmParser::parseRegOrImmWithInputMods(OperandVector &Operands) { +AMDGPUAsmParser::parseRegOrImmWithFPInputMods(OperandVector &Operands) { // XXX: During parsing we can't determine if minus sign means // negate-modifier or negative immediate value. // By default we suppose it is modifier. @@ -1004,9 +1032,9 @@ return Res; } - unsigned Modifiers = 0; + AMDGPUOperand::Modifiers Mods = {false, false, false}; if (Negate) { - Modifiers |= 0x1; + Mods.Neg = true; } if (Abs) { if (getLexer().getKind() != AsmToken::Pipe) { @@ -1014,7 +1042,7 @@ return MatchOperand_ParseFail; } Parser.Lex(); - Modifiers |= 0x2; + Mods.Abs = true; } if (Abs2) { if (getLexer().isNot(AsmToken::RParen)) { @@ -1022,16 +1050,56 @@ return MatchOperand_ParseFail; } Parser.Lex(); - Modifiers |= 0x2; + Mods.Abs = true; } - if (Modifiers) { + if (Mods.hasFPModifiers()) { AMDGPUOperand &Op = static_cast(*Operands.back()); - Op.setModifiers(Modifiers); + Op.setModifiers(Mods); } return MatchOperand_Success; } +AMDGPUAsmParser::OperandMatchResultTy +AMDGPUAsmParser::parseRegOrImmWithIntInputMods(OperandVector &Operands) { + bool Sext = false; + + if (getLexer().getKind() == AsmToken::Identifier && Parser.getTok().getString() == "sext") { + Parser.Lex(); + Sext = true; + if (getLexer().isNot(AsmToken::LParen)) { + Error(Parser.getTok().getLoc(), "expected left paren after sext"); + return MatchOperand_ParseFail; + } + Parser.Lex(); + } + + auto Res = parseRegOrImm(Operands); + if (Res != MatchOperand_Success) { + return Res; + } + + AMDGPUOperand &Op = static_cast(*Operands.back()); + if (Op.isImm() && Op.Imm.IsFPImm) { + Error(Parser.getTok().getLoc(), "floating point operands not allowed with sext() modifier"); + return MatchOperand_ParseFail; + } + + AMDGPUOperand::Modifiers Mods = {false, false, false}; + if (Sext) { + if (getLexer().isNot(AsmToken::RParen)) { + Error(Parser.getTok().getLoc(), "expected closing parentheses"); + return MatchOperand_ParseFail; + } + Parser.Lex(); + Mods.Sext = true; + } + + if (Mods.hasIntModifiers()) { + Op.setModifiers(Mods); + } + return MatchOperand_Success; +} unsigned AMDGPUAsmParser::checkTargetMatchPredicate(MCInst &Inst) { @@ -2338,7 +2406,8 @@ for (unsigned E = Operands.size(); I != E; ++I) { AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]); if (Op.isRegOrImmWithInputMods()) { - Op.addRegOrImmWithInputModsOperands(Inst, 2); + // only fp modifiers allowed in VOP3 + Op.addRegOrImmWithFPInputModsOperands(Inst, 2); } else if (Op.isImm()) { OptionalIdx[Op.getImmTy()] = I; } else { @@ -2511,8 +2580,8 @@ AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]); // Add the register arguments if (Op.isRegOrImmWithInputMods()) { - // We convert only instructions with modifiers - Op.addRegOrImmWithInputModsOperands(Inst, 2); + // Only float modifiers supported in DPP + Op.addRegOrImmWithFPInputModsOperands(Inst, 2); } else if (Op.isDPPCtrl()) { Op.addImmOperands(Inst, 1); } else if (Op.isImm()) { @@ -2612,24 +2681,16 @@ return AMDGPUOperand::CreateImm(0, SMLoc(), AMDGPUOperand::ImmTySdwaDstUnused); } -void AMDGPUAsmParser::cvtSdwaVop1_mod(MCInst &Inst, const OperandVector &Operands) { - cvtSDWA(Inst, Operands, true, true); +void AMDGPUAsmParser::cvtSdwaVOP1(MCInst &Inst, const OperandVector &Operands) { + cvtSDWA(Inst, Operands, true); } -void AMDGPUAsmParser::cvtSdwaVop1_nomod(MCInst &Inst, const OperandVector &Operands) { - cvtSDWA(Inst, Operands, false, true); -} - -void AMDGPUAsmParser::cvtSdwaVop2_mod(MCInst &Inst, const OperandVector &Operands) { - cvtSDWA(Inst, Operands, true, false); -} - -void AMDGPUAsmParser::cvtSdwaVop2_nomod(MCInst &Inst, const OperandVector &Operands) { - cvtSDWA(Inst, Operands, false, false); +void AMDGPUAsmParser::cvtSdwaVOP2(MCInst &Inst, const OperandVector &Operands) { + cvtSDWA(Inst, Operands, false); } void AMDGPUAsmParser::cvtSDWA(MCInst &Inst, const OperandVector &Operands, - bool HasMods, bool IsVOP1) { + bool IsVOP1) { OptionalImmIndexMap OptionalIdx; unsigned I = 1; @@ -2641,10 +2702,8 @@ for (unsigned E = Operands.size(); I != E; ++I) { AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]); // Add the register arguments - if (!HasMods && Op.isReg()) { - Op.addRegOperands(Inst, 1); - } else if (HasMods && Op.isRegOrImmWithInputMods()) { - Op.addRegOrImmWithInputModsOperands(Inst, 2); + if (Op.isRegOrImmWithInputMods()) { + Op.addRegOrImmWithInputModsOperands(Inst, 2); } else if (Op.isImm()) { // Handle optional arguments OptionalIdx[Op.getImmTy()] = I; @@ -2653,9 +2712,8 @@ } } - if (HasMods) { - addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI, 0); - } + addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI, 0); + if (Inst.getOpcode() == AMDGPU::V_NOP_sdwa) { // V_NOP_sdwa has no optional sdwa arguments return; Index: llvm/trunk/lib/Target/AMDGPU/InstPrinter/AMDGPUInstPrinter.h =================================================================== --- llvm/trunk/lib/Target/AMDGPU/InstPrinter/AMDGPUInstPrinter.h +++ llvm/trunk/lib/Target/AMDGPU/InstPrinter/AMDGPUInstPrinter.h @@ -64,7 +64,8 @@ void printImmediate32(uint32_t I, raw_ostream &O); void printImmediate64(uint64_t I, raw_ostream &O); void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O); - void printOperandAndMods(const MCInst *MI, unsigned OpNo, raw_ostream &O); + void printOperandAndFPInputMods(const MCInst *MI, unsigned OpNo, raw_ostream &O); + void printOperandAndIntInputMods(const MCInst *MI, unsigned OpNo, raw_ostream &O); void printDPPCtrl(const MCInst *MI, unsigned OpNo, raw_ostream &O); void printRowMask(const MCInst *MI, unsigned OpNo, raw_ostream &O); void printBankMask(const MCInst *MI, unsigned OpNo, raw_ostream &O); Index: llvm/trunk/lib/Target/AMDGPU/InstPrinter/AMDGPUInstPrinter.cpp =================================================================== --- llvm/trunk/lib/Target/AMDGPU/InstPrinter/AMDGPUInstPrinter.cpp +++ llvm/trunk/lib/Target/AMDGPU/InstPrinter/AMDGPUInstPrinter.cpp @@ -423,8 +423,9 @@ } } -void AMDGPUInstPrinter::printOperandAndMods(const MCInst *MI, unsigned OpNo, - raw_ostream &O) { +void AMDGPUInstPrinter::printOperandAndFPInputMods(const MCInst *MI, + unsigned OpNo, + raw_ostream &O) { unsigned InputModifiers = MI->getOperand(OpNo).getImm(); if (InputModifiers & SISrcMods::NEG) O << '-'; @@ -435,6 +436,17 @@ O << '|'; } +void AMDGPUInstPrinter::printOperandAndIntInputMods(const MCInst *MI, + unsigned OpNo, + raw_ostream &O) { + unsigned InputModifiers = MI->getOperand(OpNo).getImm(); + if (InputModifiers & SISrcMods::SEXT) + O << "sext("; + printOperand(MI, OpNo + 1, O); + if (InputModifiers & SISrcMods::SEXT) + O << ')'; +} + void AMDGPUInstPrinter::printDPPCtrl(const MCInst *MI, unsigned OpNo, raw_ostream &O) { Index: llvm/trunk/lib/Target/AMDGPU/SIDefines.h =================================================================== --- llvm/trunk/lib/Target/AMDGPU/SIDefines.h +++ llvm/trunk/lib/Target/AMDGPU/SIDefines.h @@ -79,10 +79,13 @@ }; } +// Input operand modifiers bit-masks +// NEG and SEXT share same bit-mask because they can't be set simultaneously. namespace SISrcMods { enum { - NEG = 1 << 0, - ABS = 1 << 1 + NEG = 1 << 0, // Floating-point negate modifier + ABS = 1 << 1, // Floating-point absolute modifier + SEXT = 1 << 0 // Integer sign-extend modifier }; } Index: llvm/trunk/lib/Target/AMDGPU/SIInstrInfo.td =================================================================== --- llvm/trunk/lib/Target/AMDGPU/SIInstrInfo.td +++ llvm/trunk/lib/Target/AMDGPU/SIInstrInfo.td @@ -560,6 +560,28 @@ def VOPDstS64 : VOPDstOperand ; +def FPInputModsMatchClass : AsmOperandClass { + let Name = "RegOrImmWithFPInputMods"; + let ParserMethod = "parseRegOrImmWithFPInputMods"; + let PredicateMethod = "isRegOrImmWithInputMods"; +} + +def FPInputMods : Operand { + let PrintMethod = "printOperandAndFPInputMods"; + let ParserMatchClass = FPInputModsMatchClass; +} + +def IntInputModsMatchClass : AsmOperandClass { + let Name = "RegOrImmWithIntInputMods"; + let ParserMethod = "parseRegOrImmWithIntInputMods"; + let PredicateMethod = "isRegOrImmWithInputMods"; +} + +def IntInputMods: Operand { + let PrintMethod = "printOperandAndIntInputMods"; + let ParserMatchClass = IntInputModsMatchClass; +} + //===----------------------------------------------------------------------===// // Complex patterns //===----------------------------------------------------------------------===// @@ -1093,21 +1115,6 @@ // Vector ALU classes //===----------------------------------------------------------------------===// -// This must always be right before the operand being input modified. -def InputMods : OperandWithDefaultOps { - let PrintMethod = "printOperandAndMods"; -} - -def InputModsMatchClass : AsmOperandClass { - let Name = "RegOrImmWithInputMods"; - let ParserMethod = "parseRegOrImmWithInputMods"; -} - -def InputModsNoDefault : Operand { - let PrintMethod = "printOperandAndMods"; - let ParserMatchClass = InputModsMatchClass; -} - class getNumSrcArgs { int ret = !if (!eq(Src0.Value, untyped.Value), 0, @@ -1179,7 +1186,7 @@ !if (!eq(NumSrcArgs, 1), !if (!eq(HasModifiers, 1), // VOP1 with modifiers - (ins InputModsNoDefault:$src0_modifiers, Src0RC:$src0, + (ins FPInputMods:$src0_modifiers, Src0RC:$src0, clampmod:$clamp, omod:$omod) /* else */, // VOP1 without modifiers @@ -1188,8 +1195,8 @@ !if (!eq(NumSrcArgs, 2), !if (!eq(HasModifiers, 1), // VOP 2 with modifiers - (ins InputModsNoDefault:$src0_modifiers, Src0RC:$src0, - InputModsNoDefault:$src1_modifiers, Src1RC:$src1, + (ins FPInputMods:$src0_modifiers, Src0RC:$src0, + FPInputMods:$src1_modifiers, Src1RC:$src1, clampmod:$clamp, omod:$omod) /* else */, // VOP2 without modifiers @@ -1198,9 +1205,9 @@ /* NumSrcArgs == 3 */, !if (!eq(HasModifiers, 1), // VOP3 with modifiers - (ins InputModsNoDefault:$src0_modifiers, Src0RC:$src0, - InputModsNoDefault:$src1_modifiers, Src1RC:$src1, - InputModsNoDefault:$src2_modifiers, Src2RC:$src2, + (ins FPInputMods:$src0_modifiers, Src0RC:$src0, + FPInputMods:$src1_modifiers, Src1RC:$src1, + FPInputMods:$src2_modifiers, Src2RC:$src2, clampmod:$clamp, omod:$omod) /* else */, // VOP3 without modifiers @@ -1218,7 +1225,7 @@ !if (!eq(NumSrcArgs, 1), !if (!eq(HasModifiers, 1), // VOP1_DPP with modifiers - (ins InputModsNoDefault:$src0_modifiers, Src0RC:$src0, + (ins FPInputMods:$src0_modifiers, Src0RC:$src0, dpp_ctrl:$dpp_ctrl, row_mask:$row_mask, bank_mask:$bank_mask, bound_ctrl:$bound_ctrl) /* else */, @@ -1229,10 +1236,10 @@ /* NumSrcArgs == 2 */, !if (!eq(HasModifiers, 1), // VOP2_DPP with modifiers - (ins InputModsNoDefault:$src0_modifiers, Src0RC:$src0, - InputModsNoDefault:$src1_modifiers, Src1RC:$src1, - dpp_ctrl:$dpp_ctrl, row_mask:$row_mask, - bank_mask:$bank_mask, bound_ctrl:$bound_ctrl) + (ins FPInputMods:$src0_modifiers, Src0RC:$src0, + FPInputMods:$src1_modifiers, Src1RC:$src1, + dpp_ctrl:$dpp_ctrl, row_mask:$row_mask, + bank_mask:$bank_mask, bound_ctrl:$bound_ctrl) /* else */, // VOP2_DPP without modifiers (ins Src0RC:$src0, Src1RC:$src1, dpp_ctrl:$dpp_ctrl, @@ -1242,34 +1249,35 @@ } class getInsSDWA { + bit HasFloatModifiers> { dag ret = !if (!eq(NumSrcArgs, 0), // VOP1 without input operands (V_NOP) (ins), !if (!eq(NumSrcArgs, 1), - !if (!eq(HasModifiers, 1), - // VOP1_SDWA with modifiers - (ins InputModsNoDefault:$src0_fmodifiers, Src0RC:$src0, + !if (HasFloatModifiers, + // VOP1_SDWA with float modifiers + (ins FPInputMods:$src0_fmodifiers, Src0RC:$src0, clampmod:$clamp, dst_sel:$dst_sel, dst_unused:$dst_unused, src0_sel:$src0_sel) /* else */, - // VOP1_SDWA without modifiers - // FIXME: sext() modifier is not supported yet - (ins Src0RC:$src0, dst_sel:$dst_sel, dst_unused:$dst_unused, + // VOP1_SDWA with sext modifier + (ins IntInputMods:$src0_imodifiers, Src0RC:$src0, + clampmod:$clamp, dst_sel:$dst_sel, dst_unused:$dst_unused, src0_sel:$src0_sel) /* endif */) /* NumSrcArgs == 2 */, - !if (!eq(HasModifiers, 1), - // VOP2_SDWA with modifiers - (ins InputModsNoDefault:$src0_fmodifiers, Src0RC:$src0, - InputModsNoDefault:$src1_fmodifiers, Src1RC:$src1, + !if (HasFloatModifiers, + // VOP2_SDWA with float modifiers + (ins FPInputMods:$src0_fmodifiers, Src0RC:$src0, + FPInputMods:$src1_fmodifiers, Src1RC:$src1, clampmod:$clamp, dst_sel:$dst_sel, dst_unused:$dst_unused, src0_sel:$src0_sel, src1_sel:$src1_sel) /* else */, - // VOP2_DPP without modifiers - (ins Src0RC:$src0, Src1RC:$src1, - dst_sel:$dst_sel, dst_unused:$dst_unused, + // VOP2_DPP with sext modifier + (ins IntInputMods:$src0_imodifiers, Src0RC:$src0, + IntInputMods:$src1_imodifiers, Src1RC:$src1, + clampmod:$clamp, dst_sel:$dst_sel, dst_unused:$dst_unused, src0_sel:$src0_sel, src1_sel:$src1_sel) /* endif */))); } @@ -1328,19 +1336,22 @@ string ret = dst#args#" $dpp_ctrl$row_mask$bank_mask$bound_ctrl"; } -class getAsmSDWA { - string dst = !if(HasDst, +class getAsmSDWA { + string dst = !if(HasDst, !if(!eq(DstVT.Size, 1), - "$sdst", + "$sdst", // use $sdst for VOPC "$vdst"), - ""); // use $sdst for VOPC - string src0 = !if(!eq(NumSrcArgs, 1), "$src0_fmodifiers", "$src0_fmodifiers,"); - string src1 = !if(!eq(NumSrcArgs, 1), "", - !if(!eq(NumSrcArgs, 2), " $src1_fmodifiers", - " $src1_fmodifiers,")); - string args = !if(!eq(HasModifiers, 0), - getAsm32<0, NumSrcArgs, DstVT>.ret, - ", "#src0#src1#"$clamp"); + ""); + string src0 = !if(HasFloatModifiers, "$src0_fmodifiers", "$src0_imodifiers"); + string src1 = !if(HasFloatModifiers, "$src1_fmodifiers", "$src1_imodifiers"); + string args = !if(!eq(NumSrcArgs, 0), + "", + !if(!eq(NumSrcArgs, 1), + ", "#src0#"$clamp", + ", "#src0#", "#src1#"$clamp" + ) + ); string sdwa = !if(!eq(NumSrcArgs, 0), "", !if(!eq(NumSrcArgs, 1), @@ -1518,7 +1529,7 @@ } class VOPC_Class_Profile : VOPC_Profile { - let Ins64 = (ins InputModsNoDefault:$src0_modifiers, Src0RC64:$src0, Src1RC64:$src1); + let Ins64 = (ins FPInputMods:$src0_modifiers, Src0RC64:$src0, Src1RC64:$src1); let Asm64 = "$sdst, $src0_modifiers, $src1"; } @@ -1549,13 +1560,13 @@ let Ins32 = (ins Src0RC32:$src0, Src1RC32:$src1, VGPR_32:$src2); let Ins64 = getIns64, 3, HasModifiers>.ret; - let InsDPP = (ins InputModsNoDefault:$src0_modifiers, Src0RC32:$src0, - InputModsNoDefault:$src1_modifiers, Src1RC32:$src1, + let InsDPP = (ins FPInputMods:$src0_modifiers, Src0RC32:$src0, + FPInputMods:$src1_modifiers, Src1RC32:$src1, VGPR_32:$src2, // stub argument dpp_ctrl:$dpp_ctrl, row_mask:$row_mask, bank_mask:$bank_mask, bound_ctrl:$bound_ctrl); - let InsSDWA = (ins InputModsNoDefault:$src0_fmodifiers, Src0RC32:$src0, - InputModsNoDefault:$src1_fmodifiers, Src1RC32:$src1, + let InsSDWA = (ins FPInputMods:$src0_fmodifiers, Src0RC32:$src0, + FPInputMods:$src1_fmodifiers, Src1RC32:$src1, VGPR_32:$src2, // stub argument clampmod:$clamp, dst_sel:$dst_sel, dst_unused:$dst_unused, src0_sel:$src0_sel, src1_sel:$src1_sel); @@ -1682,25 +1693,31 @@ class SDWADisableFields { bits<8> src0 = !if(!eq(p.NumSrcArgs, 0), 0, ?); bits<3> src0_sel = !if(!eq(p.NumSrcArgs, 0), 6, ?); - bits<2> src0_fmodifiers = !if(p.HasModifiers, ?, 0); - bits<1> src0_imodifiers = 0; // FIXME: always 0 untill sext modifier is supported + bits<2> src0_fmodifiers = !if(!eq(p.NumSrcArgs, 0), + 0, + !if(p.HasModifiers, ?, 0)); + bits<1> src0_imodifiers = !if(!eq(p.NumSrcArgs, 0), + 0, + !if(p.HasModifiers, 0, ?)); bits<3> src1_sel = !if(!eq(p.NumSrcArgs, 0), 6, !if(!eq(p.NumSrcArgs, 1), 6, ?)); bits<2> src1_fmodifiers = !if(!eq(p.NumSrcArgs, 0), 0, !if(!eq(p.NumSrcArgs, 1), 0, !if(p.HasModifiers, ?, 0))); - bits<1> src1_imodifiers = 0; + bits<1> src1_imodifiers = !if(!eq(p.NumSrcArgs, 0), 0, + !if(!eq(p.NumSrcArgs, 1), 0, + !if(p.HasModifiers, 0, ?))); bits<3> dst_sel = !if(p.HasDst, ?, 6); bits<2> dst_unused = !if(p.HasDst, ?, 2); - bits<1> clamp = !if(p.HasModifiers, ?, 0); + bits<1> clamp = !if(!eq(p.NumSrcArgs, 0), 0, ?); } class VOP1_SDWA : VOP1_SDWAe , VOP_SDWA , SDWADisableFields

{ - let AsmMatchConverter = !if(!eq(p.HasModifiers,1), "cvtSdwaVop1_mod", "cvtSdwaVop1_nomod"); + let AsmMatchConverter = "cvtSdwaVOP1"; let AssemblerPredicates = !if(p.HasExt, [isVI], [DisableInst]); let DecoderNamespace = "SDWA"; let DisableDecoder = DisableVIDecoder; @@ -1774,7 +1791,7 @@ VOP2_SDWAe , VOP_SDWA , SDWADisableFields

{ - let AsmMatchConverter = !if(!eq(p.HasModifiers,1), "cvtSdwaVop2_mod", "cvtSdwaVop2_nomod"); + let AsmMatchConverter = "cvtSdwaVOP2"; let AssemblerPredicates = !if(p.HasExt, [isVI], [DisableInst]); let DecoderNamespace = "SDWA"; let DisableDecoder = DisableVIDecoder; @@ -2397,9 +2414,9 @@ SDPatternOperator node = null_frag> : VOP3_Helper < op, opName, (outs P.DstRC.RegClass:$vdst), - (ins InputModsNoDefault:$src0_modifiers, P.Src0RC64:$src0, - InputModsNoDefault:$src1_modifiers, P.Src1RC64:$src1, - InputModsNoDefault:$src2_modifiers, P.Src2RC64:$src2, + (ins FPInputMods:$src0_modifiers, P.Src0RC64:$src0, + FPInputMods:$src1_modifiers, P.Src1RC64:$src1, + FPInputMods:$src2_modifiers, P.Src2RC64:$src2, clampmod:$clamp, omod:$omod), "$vdst, $src0_modifiers, $src1_modifiers, $src2_modifiers"#"$clamp"#"$omod", Index: llvm/trunk/test/MC/AMDGPU/vop_sdwa.s =================================================================== --- llvm/trunk/test/MC/AMDGPU/vop_sdwa.s +++ llvm/trunk/test/MC/AMDGPU/vop_sdwa.s @@ -45,8 +45,8 @@ //---------------------------------------------------------------------------// // NOSICI: error: -// VI: v_cvt_u32_f32_sdwa v0, v0 dst_sel:DWORD dst_unused:UNUSED_PRESERVE src0_sel:DWORD ; encoding: [0xf9,0x0e,0x00,0x7e,0x00,0x16,0x06,0x06] -v_cvt_u32_f32 v0, v0 dst_sel:DWORD +// VI: v_cvt_u32_f32_sdwa v0, v0 clamp dst_sel:DWORD dst_unused:UNUSED_PRESERVE src0_sel:DWORD ; encoding: [0xf9,0x0e,0x00,0x7e,0x00,0x36,0x06,0x06] +v_cvt_u32_f32 v0, v0 clamp dst_sel:DWORD // NOSICI: error: // VI: v_fract_f32_sdwa v0, v0 clamp dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:DWORD ; encoding: [0xf9,0x36,0x00,0x7e,0x00,0x26,0x06,0x06] @@ -57,8 +57,8 @@ v_sin_f32 v0, v0 dst_unused:UNUSED_PAD src0_sel:WORD_1 // NOSICI: error: -// VI: v_mov_b32_sdwa v1, v0 dst_sel:DWORD dst_unused:UNUSED_PRESERVE src0_sel:WORD_1 ; encoding: [0xf9,0x02,0x02,0x7e,0x00,0x16,0x05,0x06] -v_mov_b32 v1, v0 src0_sel:WORD_1 +// VI: v_mov_b32_sdwa v1, v0 clamp dst_sel:DWORD dst_unused:UNUSED_PRESERVE src0_sel:WORD_1 ; encoding: [0xf9,0x02,0x02,0x7e,0x00,0x36,0x05,0x06] +v_mov_b32 v1, v0 clamp src0_sel:WORD_1 // NOSICI: error: // VI: v_trunc_f32_sdwa v1, v0 clamp dst_sel:DWORD dst_unused:UNUSED_PRESERVE src0_sel:WORD_1 ; encoding: [0xf9,0x38,0x02,0x7e,0x00,0x36,0x05,0x06] @@ -81,8 +81,8 @@ v_and_b32 v0, v0, v0 dst_unused:UNUSED_PAD src1_sel:BYTE_2 // NOSICI: error: -// VI: v_mul_i32_i24_sdwa v1, v2, v3 dst_sel:DWORD dst_unused:UNUSED_PRESERVE src0_sel:DWORD src1_sel:DWORD ; encoding: [0xf9,0x06,0x02,0x0c,0x02,0x16,0x06,0x06] -v_mul_i32_i24_sdwa v1, v2, v3 +// VI: v_mul_i32_i24_sdwa v1, v2, v3 clamp dst_sel:DWORD dst_unused:UNUSED_PRESERVE src0_sel:DWORD src1_sel:DWORD ; encoding: [0xf9,0x06,0x02,0x0c,0x02,0x36,0x06,0x06] +v_mul_i32_i24_sdwa v1, v2, v3 clamp //===----------------------------------------------------------------------===// // Check modifiers @@ -104,6 +104,14 @@ // VI: v_min_f32_sdwa v0, |v0|, -v0 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1 src1_sel:BYTE_2 ; encoding: [0xf9,0x00,0x00,0x14,0x00,0x06,0x25,0x12] v_min_f32 v0, abs(v0), -v0 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1 src1_sel:BYTE_2 +// NOSICI: error: +// VI: v_mov_b32_sdwa v1, sext(v0) dst_sel:DWORD dst_unused:UNUSED_PRESERVE src0_sel:DWORD ; encoding: [0xf9,0x02,0x02,0x7e,0x00,0x16,0x0e,0x06] +v_mov_b32_sdwa v1, sext(v0) + +// NOSICI: error: +// VI: v_and_b32_sdwa v0, sext(v0), sext(v0) dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:DWORD src1_sel:BYTE_2 ; encoding: [0xf9,0x00,0x00,0x26,0x00,0x06,0x0e,0x0a] +v_and_b32 v0, sext(v0), sext(v0) dst_unused:UNUSED_PAD src1_sel:BYTE_2 + //===----------------------------------------------------------------------===// // Check VOP1 opcodes //===----------------------------------------------------------------------===//