Index: llvm/trunk/lib/Target/AArch64/AArch64RegisterInfo.td =================================================================== --- llvm/trunk/lib/Target/AArch64/AArch64RegisterInfo.td +++ llvm/trunk/lib/Target/AArch64/AArch64RegisterInfo.td @@ -821,7 +821,7 @@ let PredicateMethod = "isSVEVectorRegOfWidth<" # Width # ", AArch64::ZPRRegClassID>"; let RenderMethod = "addRegOperands"; - let ParserMethod = "tryParseSVEDataVector<" + let ParserMethod = "tryParseSVEDataVector"; } @@ -934,6 +934,64 @@ let ParserMatchClass = ZPRVectorList<64, 4>; } +class ZPRExtendAsmOperand + : AsmOperandClass { + let Name = "ZPRExtend" # ShiftExtend # RegWidth # Scale; + let PredicateMethod = "isSVEVectorRegWithShiftExtend<" + # RegWidth # ", AArch64::ZPRRegClassID, " + # "AArch64_AM::" # ShiftExtend # ", " + # Scale # ">"; + let DiagnosticType = "InvalidZPR" # RegWidth # ShiftExtend # Scale; + let RenderMethod = "addRegOperands"; + let ParserMethod = "tryParseSVEDataVector"; +} + +class ZPRExtendRegisterOperand : RegisterOperand { + let ParserMatchClass = + !cast("ZPR" # RegWidth # "AsmOpndExt" # Repr # Scale); + let PrintMethod = "printRegWithShiftExtend<" + # !if(SignExtend, "true", "false") # ", " + # Scale # ", " + # !if(IsLSL, "'x'", "'w'") # ", " + # !if(!eq(RegWidth, 32), "'s'", "'d'") # ">"; +} + +foreach RegWidth = [32, 64] in { + // UXTW(8|16|32|64) + def ZPR#RegWidth#AsmOpndExtUXTW8 : ZPRExtendAsmOperand<"UXTW", RegWidth, 8>; + def ZPR#RegWidth#AsmOpndExtUXTW16 : ZPRExtendAsmOperand<"UXTW", RegWidth, 16>; + def ZPR#RegWidth#AsmOpndExtUXTW32 : ZPRExtendAsmOperand<"UXTW", RegWidth, 32>; + def ZPR#RegWidth#AsmOpndExtUXTW64 : ZPRExtendAsmOperand<"UXTW", RegWidth, 64>; + + def ZPR#RegWidth#ExtUXTW8 : ZPRExtendRegisterOperand<0b0, 0b0, "UXTW", RegWidth, 8>; + def ZPR#RegWidth#ExtUXTW16 : ZPRExtendRegisterOperand<0b0, 0b0, "UXTW", RegWidth, 16>; + def ZPR#RegWidth#ExtUXTW32 : ZPRExtendRegisterOperand<0b0, 0b0, "UXTW", RegWidth, 32>; + def ZPR#RegWidth#ExtUXTW64 : ZPRExtendRegisterOperand<0b0, 0b0, "UXTW", RegWidth, 64>; + + // SXTW(8|16|32|64) + def ZPR#RegWidth#AsmOpndExtSXTW8 : ZPRExtendAsmOperand<"SXTW", RegWidth, 8>; + def ZPR#RegWidth#AsmOpndExtSXTW16 : ZPRExtendAsmOperand<"SXTW", RegWidth, 16>; + def ZPR#RegWidth#AsmOpndExtSXTW32 : ZPRExtendAsmOperand<"SXTW", RegWidth, 32>; + def ZPR#RegWidth#AsmOpndExtSXTW64 : ZPRExtendAsmOperand<"SXTW", RegWidth, 64>; + + def ZPR#RegWidth#ExtSXTW8 : ZPRExtendRegisterOperand<0b1, 0b0, "SXTW", RegWidth, 8>; + def ZPR#RegWidth#ExtSXTW16 : ZPRExtendRegisterOperand<0b1, 0b0, "SXTW", RegWidth, 16>; + def ZPR#RegWidth#ExtSXTW32 : ZPRExtendRegisterOperand<0b1, 0b0, "SXTW", RegWidth, 32>; + def ZPR#RegWidth#ExtSXTW64 : ZPRExtendRegisterOperand<0b1, 0b0, "SXTW", RegWidth, 64>; +} + +// LSL(8|16|32|64) +def ZPR64AsmOpndExtLSL8 : ZPRExtendAsmOperand<"LSL", 64, 8>; +def ZPR64AsmOpndExtLSL16 : ZPRExtendAsmOperand<"LSL", 64, 16>; +def ZPR64AsmOpndExtLSL32 : ZPRExtendAsmOperand<"LSL", 64, 32>; +def ZPR64AsmOpndExtLSL64 : ZPRExtendAsmOperand<"LSL", 64, 64>; + +def ZPR64ExtLSL8 : ZPRExtendRegisterOperand<0b0, 0b1, "LSL", 64, 8>; +def ZPR64ExtLSL16 : ZPRExtendRegisterOperand<0b0, 0b1, "LSL", 64, 16>; +def ZPR64ExtLSL32 : ZPRExtendRegisterOperand<0b0, 0b1, "LSL", 64, 32>; +def ZPR64ExtLSL64 : ZPRExtendRegisterOperand<0b0, 0b1, "LSL", 64, 64>; + class GPR64ShiftExtendAsmOperand : AsmOperandClass { let Name = AsmOperandName # Scale; let PredicateMethod = "isGPR64WithShiftExtend"; @@ -944,7 +1002,7 @@ class GPR64ExtendRegisterOperand : RegisterOperand{ let ParserMatchClass = !cast(Name); - let PrintMethod = "printRegWithShiftExtend"; + let PrintMethod = "printRegWithShiftExtend"; } foreach Scale = [8, 16, 32, 64] in { Index: llvm/trunk/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp =================================================================== --- llvm/trunk/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp +++ llvm/trunk/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp @@ -140,7 +140,7 @@ OperandMatchResultTy tryParseGPRSeqPair(OperandVector &Operands); template OperandMatchResultTy tryParseGPROperand(OperandVector &Operands); - template + template OperandMatchResultTy tryParseSVEDataVector(OperandVector &Operands); OperandMatchResultTy tryParseSVEPredicateVector(OperandVector &Operands); template @@ -857,6 +857,14 @@ (ElementWidth == 0 || Reg.ElementWidth == ElementWidth); } + template + bool isSVEVectorRegWithShiftExtend() const { + return Kind == k_Register && isSVEVectorRegOfWidth() && + ShiftExtendTy == getShiftExtendType() && + getShiftExtendAmount() == Log2_32(ShiftWidth / 8); + } + bool isGPR32as64() const { return Kind == k_Register && Reg.Kind == RegKind::Scalar && AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(Reg.RegNum); @@ -3839,6 +3847,38 @@ return Error(Loc, "register must be x0..x30 with required shift 'lsl #2'"); case Match_InvalidGPR64NoXZRshifted64: return Error(Loc, "register must be x0..x30 with required shift 'lsl #3'"); + case Match_InvalidZPR32UXTW8: + case Match_InvalidZPR32SXTW8: + return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw)'"); + case Match_InvalidZPR32UXTW16: + case Match_InvalidZPR32SXTW16: + return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #1'"); + case Match_InvalidZPR32UXTW32: + case Match_InvalidZPR32SXTW32: + return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #2'"); + case Match_InvalidZPR32UXTW64: + case Match_InvalidZPR32SXTW64: + return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #3'"); + case Match_InvalidZPR64UXTW8: + case Match_InvalidZPR64SXTW8: + return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (uxtw|sxtw)'"); + case Match_InvalidZPR64UXTW16: + case Match_InvalidZPR64SXTW16: + return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #1'"); + case Match_InvalidZPR64UXTW32: + case Match_InvalidZPR64SXTW32: + return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #2'"); + case Match_InvalidZPR64UXTW64: + case Match_InvalidZPR64SXTW64: + return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #3'"); + case Match_InvalidZPR64LSL8: + return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d'"); + case Match_InvalidZPR64LSL16: + return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #1'"); + case Match_InvalidZPR64LSL32: + return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #2'"); + case Match_InvalidZPR64LSL64: + return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #3'"); case Match_InvalidSVEPattern: return Error(Loc, "invalid predicate pattern"); case Match_InvalidSVEPredicateAnyReg: @@ -4292,6 +4332,26 @@ case Match_InvalidGPR64NoXZRshifted16: case Match_InvalidGPR64NoXZRshifted32: case Match_InvalidGPR64NoXZRshifted64: + case Match_InvalidZPR32UXTW8: + case Match_InvalidZPR32UXTW16: + case Match_InvalidZPR32UXTW32: + case Match_InvalidZPR32UXTW64: + case Match_InvalidZPR32SXTW8: + case Match_InvalidZPR32SXTW16: + case Match_InvalidZPR32SXTW32: + case Match_InvalidZPR32SXTW64: + case Match_InvalidZPR64UXTW8: + case Match_InvalidZPR64SXTW8: + case Match_InvalidZPR64UXTW16: + case Match_InvalidZPR64SXTW16: + case Match_InvalidZPR64UXTW32: + case Match_InvalidZPR64SXTW32: + case Match_InvalidZPR64UXTW64: + case Match_InvalidZPR64SXTW64: + case Match_InvalidZPR64LSL8: + case Match_InvalidZPR64LSL16: + case Match_InvalidZPR64LSL32: + case Match_InvalidZPR64LSL64: case Match_InvalidSVEPredicateAnyReg: case Match_InvalidSVEPattern: case Match_InvalidSVEPredicateBReg: @@ -4897,7 +4957,7 @@ return MatchOperand_Success; } -template +template OperandMatchResultTy AArch64AsmParser::tryParseSVEDataVector(OperandVector &Operands) { const SMLoc S = getLoc(); @@ -4919,9 +4979,29 @@ return MatchOperand_NoMatch; unsigned ElementWidth = KindRes->second; + + // No shift/extend is the default. + if (!ParseShiftExtend || getParser().getTok().isNot(AsmToken::Comma)) { + Operands.push_back(AArch64Operand::CreateVectorReg( + RegNum, RegKind::SVEDataVector, ElementWidth, S, S, getContext())); + + return MatchOperand_Success; + } + + // Eat the comma + getParser().Lex(); + + // Match the shift + SmallVector, 1> ExtOpnd; + Res = tryParseOptionalShiftExtend(ExtOpnd); + if (Res != MatchOperand_Success) + return Res; + + auto Ext = static_cast(ExtOpnd.back().get()); Operands.push_back(AArch64Operand::CreateVectorReg( - RegNum, RegKind::SVEDataVector, ElementWidth, S, S, - getContext())); + RegNum, RegKind::SVEDataVector, ElementWidth, S, Ext->getEndLoc(), + getContext(), Ext->getShiftExtendType(), Ext->getShiftExtendAmount(), + Ext->hasShiftExtendAmount())); return MatchOperand_Success; } Index: llvm/trunk/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.h =================================================================== --- llvm/trunk/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.h +++ llvm/trunk/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.h @@ -90,7 +90,7 @@ const MCSubtargetInfo &STI, raw_ostream &O) { printMemExtend(MI, OpNum, O, SrcRegKind, Width); } - template + template void printRegWithShiftExtend(const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI, raw_ostream &O); void printCondCode(const MCInst *MI, unsigned OpNum, Index: llvm/trunk/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp =================================================================== --- llvm/trunk/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp +++ llvm/trunk/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp @@ -991,12 +991,16 @@ printMemExtendImpl(SignExtend, DoShift, Width, SrcRegKind, O); } -template +template void AArch64InstPrinter::printRegWithShiftExtend(const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI, raw_ostream &O) { printOperand(MI, OpNum, STI, O); + if (Suffix == 's' || Suffix == 'd') + O << '.' << Suffix; + else + assert(Suffix == 0 && "Unsupported suffix size"); bool DoShift = ExtWidth != 8; if (SignExtend || DoShift || SrcRegKind == 'w') {