Index: llvm/trunk/lib/Target/AArch64/AArch64RegisterInfo.td =================================================================== --- llvm/trunk/lib/Target/AArch64/AArch64RegisterInfo.td +++ llvm/trunk/lib/Target/AArch64/AArch64RegisterInfo.td @@ -776,7 +776,7 @@ let ParserMethod = "tryParseSVEPredicateVector"; } -def PPRAsmOpAny : PPRAsmOperand<"PredicateAny", "PPR", -1>; +def PPRAsmOpAny : PPRAsmOperand<"PredicateAny", "PPR", 0>; def PPRAsmOp8 : PPRAsmOperand<"PredicateB", "PPR", 8>; def PPRAsmOp16 : PPRAsmOperand<"PredicateH", "PPR", 16>; def PPRAsmOp32 : PPRAsmOperand<"PredicateS", "PPR", 32>; @@ -788,7 +788,7 @@ def PPR32 : PPRRegOp<"s", PPRAsmOp32, PPR>; def PPR64 : PPRRegOp<"d", PPRAsmOp64, PPR>; -def PPRAsmOp3bAny : PPRAsmOperand<"Predicate3bAny", "PPR_3b", -1>; +def PPRAsmOp3bAny : PPRAsmOperand<"Predicate3bAny", "PPR_3b", 0>; def PPRAsmOp3b8 : PPRAsmOperand<"Predicate3bB", "PPR_3b", 8>; def PPRAsmOp3b16 : PPRAsmOperand<"Predicate3bH", "PPR_3b", 16>; def PPRAsmOp3b32 : PPRAsmOperand<"Predicate3bS", "PPR_3b", 32>; @@ -818,10 +818,10 @@ # Width # ", AArch64::ZPRRegClassID>"; let RenderMethod = "addRegOperands"; let ParserMethod = "tryParseSVEDataVector<" - # !if(!eq(Width, -1), "false", "true") # ">"; + # !if(!eq(Width, 0), "false", "true") # ">"; } -def ZPRAsmOpAny : ZPRAsmOperand<"VectorAny", -1>; +def ZPRAsmOpAny : ZPRAsmOperand<"VectorAny", 0>; def ZPRAsmOp8 : ZPRAsmOperand<"VectorB", 8>; def ZPRAsmOp16 : ZPRAsmOperand<"VectorH", 16>; def ZPRAsmOp32 : ZPRAsmOperand<"VectorS", 32>; 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 @@ -86,7 +86,6 @@ bool parseCondCode(OperandVector &Operands, bool invertCondCode); unsigned matchRegisterNameAlias(StringRef Name, RegKind Kind); int tryParseRegister(); - int tryMatchVectorRegister(StringRef &Kind, bool expected); bool parseRegister(OperandVector &Operands); bool parseSymbolicImmVal(const MCExpr *&ImmVal); bool parseVectorList(OperandVector &Operands); @@ -121,8 +120,8 @@ /// } - OperandMatchResultTy tryParseSVERegister(int &Reg, StringRef &Kind, - RegKind MatchKind); + OperandMatchResultTy tryParseVectorRegister(int &Reg, StringRef &Kind, + RegKind MatchKind); OperandMatchResultTy tryParseOptionalShiftExtend(OperandVector &Operands); OperandMatchResultTy tryParseBarrierOperand(OperandVector &Operands); OperandMatchResultTy tryParseMRSSystemRegister(OperandVector &Operands); @@ -822,7 +821,7 @@ template bool isSVEVectorRegOfWidth() const { return isSVEVectorReg() && - (ElementWidth == -1 || Reg.ElementWidth == ElementWidth); + (ElementWidth == 0 || Reg.ElementWidth == ElementWidth); } bool isGPR32as64() const { @@ -1573,8 +1572,11 @@ } static std::unique_ptr - CreateReg(unsigned RegNum, RegKind Kind, unsigned ElementWidth, - SMLoc S, SMLoc E, MCContext &Ctx) { + CreateVectorReg(unsigned RegNum, RegKind Kind, unsigned ElementWidth, + SMLoc S, SMLoc E, MCContext &Ctx) { + assert((Kind == RegKind::NeonVector || Kind == RegKind::SVEDataVector || + Kind == RegKind::SVEPredicateVector) && + "Invalid vector kind"); auto Op = make_unique(k_Register, Ctx); Op->Reg.RegNum = RegNum; Op->Reg.ElementWidth = ElementWidth; @@ -1586,12 +1588,30 @@ static std::unique_ptr CreateVectorList(unsigned RegNum, unsigned Count, unsigned NumElements, - char ElementKind, SMLoc S, SMLoc E, MCContext &Ctx) { + unsigned ElementWidth, SMLoc S, SMLoc E, MCContext &Ctx) { auto Op = make_unique(k_VectorList, Ctx); Op->VectorList.RegNum = RegNum; Op->VectorList.Count = Count; Op->VectorList.NumElements = NumElements; - Op->VectorList.ElementKind = ElementKind; + switch (ElementWidth) { + case 0: + Op->VectorList.ElementKind = 0; + break; + case 8: + Op->VectorList.ElementKind = 'b'; + break; + case 16: + Op->VectorList.ElementKind = 'h'; + break; + case 32: + Op->VectorList.ElementKind = 's'; + break; + case 64: + Op->VectorList.ElementKind = 'd'; + break; + default: + llvm_unreachable("Unsupported elementwidth"); + } Op->StartLoc = S; Op->EndLoc = E; return Op; @@ -1839,29 +1859,65 @@ .Default(0); } -static bool isValidVectorKind(StringRef Name) { - return StringSwitch(Name.lower()) - .Case(".8b", true) - .Case(".16b", true) - .Case(".4h", true) - .Case(".8h", true) - .Case(".2s", true) - .Case(".4s", true) - .Case(".1d", true) - .Case(".2d", true) - .Case(".1q", true) - // Accept the width neutral ones, too, for verbose syntax. If those - // aren't used in the right places, the token operand won't match so - // all will work out. - .Case(".b", true) - .Case(".h", true) - .Case(".s", true) - .Case(".d", true) - // Needed for fp16 scalar pairwise reductions - .Case(".2h", true) - // another special case for the ARMv8.2a dot product operand - .Case(".4b", true) - .Default(false); +/// Returns an optional pair of (#elements, element-width) if Suffix +/// is a valid vector kind. Where the number of elements in a vector +/// or the vector width is implicit or explicitly unknown (but still a +/// valid suffix kind), 0 is used. +static Optional> parseVectorKind(StringRef Suffix, + RegKind VectorKind) { + std::pair Res = {-1, -1}; + + switch (VectorKind) { + case RegKind::NeonVector: + Res = + StringSwitch>(Suffix.lower()) + .Case("", {0, 0}) + .Case(".1d", {1, 64}) + .Case(".1q", {1, 128}) + // '.2h' needed for fp16 scalar pairwise reductions + .Case(".2h", {2, 16}) + .Case(".2s", {2, 32}) + .Case(".2d", {2, 64}) + // '.4b' is another special case for the ARMv8.2a dot product + // operand + .Case(".4b", {4, 8}) + .Case(".4h", {4, 16}) + .Case(".4s", {4, 32}) + .Case(".8b", {8, 8}) + .Case(".8h", {8, 16}) + .Case(".16b", {16, 8}) + // Accept the width neutral ones, too, for verbose syntax. If those + // aren't used in the right places, the token operand won't match so + // all will work out. + .Case(".b", {0, 8}) + .Case(".h", {0, 16}) + .Case(".s", {0, 32}) + .Case(".d", {0, 64}) + .Default({-1, -1}); + break; + case RegKind::SVEPredicateVector: + case RegKind::SVEDataVector: + Res = StringSwitch>(Suffix.lower()) + .Case("", {0, 0}) + .Case(".b", {0, 8}) + .Case(".h", {0, 16}) + .Case(".s", {0, 32}) + .Case(".d", {0, 64}) + .Case(".q", {0, 128}) + .Default({-1, -1}); + break; + default: + llvm_unreachable("Unsupported RegKind"); + } + + if (Res == std::make_pair(-1, -1)) + return Optional>(); + + return Optional>(Res); +} + +static bool isValidVectorKind(StringRef Suffix, RegKind VectorKind) { + return parseVectorKind(Suffix, VectorKind).hasValue(); } static unsigned matchSVEDataVectorRegName(StringRef Name) { @@ -1922,34 +1978,6 @@ .Default(0); } -static bool isValidSVEKind(StringRef Name) { - return StringSwitch(Name.lower()) - .Case(".b", true) - .Case(".h", true) - .Case(".s", true) - .Case(".d", true) - .Case(".q", true) - .Default(false); -} - -static void parseValidVectorKind(StringRef Name, unsigned &NumElements, - char &ElementKind) { - assert(isValidVectorKind(Name)); - - ElementKind = Name.lower()[Name.size() - 1]; - NumElements = 0; - - if (Name.size() == 2) - return; - - // Parse the lane count - Name = Name.drop_front(); - while (isdigit(Name.front())) { - NumElements = 10 * NumElements + (Name.front() - '0'); - Name = Name.drop_front(); - } -} - bool AArch64AsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) { StartLoc = getLoc(); @@ -2018,39 +2046,6 @@ return RegNum; } -/// tryMatchVectorRegister - Try to parse a vector register name with optional -/// kind specifier. If it is a register specifier, eat the token and return it. -int AArch64AsmParser::tryMatchVectorRegister(StringRef &Kind, bool expected) { - MCAsmParser &Parser = getParser(); - if (Parser.getTok().isNot(AsmToken::Identifier)) { - TokError("vector register expected"); - return -1; - } - - StringRef Name = Parser.getTok().getString(); - // If there is a kind specifier, it's separated from the register name by - // a '.'. - size_t Start = 0, Next = Name.find('.'); - StringRef Head = Name.slice(Start, Next); - unsigned RegNum = matchRegisterNameAlias(Head, RegKind::NeonVector); - - if (RegNum) { - if (Next != StringRef::npos) { - Kind = Name.slice(Next, StringRef::npos); - if (!isValidVectorKind(Kind)) { - TokError("invalid vector kind qualifier"); - return -1; - } - } - Parser.Lex(); // Eat the register token. - return RegNum; - } - - if (expected) - TokError("vector register expected"); - return -1; -} - /// tryParseSysCROperand - Try to parse a system instruction CR operand name. OperandMatchResultTy AArch64AsmParser::tryParseSysCROperand(OperandVector &Operands) { @@ -2660,12 +2655,20 @@ SMLoc S = getLoc(); // Check for a vector register specifier first. StringRef Kind; - int64_t Reg = tryMatchVectorRegister(Kind, false); - if (Reg == -1) + int Reg = -1; + OperandMatchResultTy Res = + tryParseVectorRegister(Reg, Kind, RegKind::NeonVector); + if (Res != MatchOperand_Success) + return true; + + const auto &KindRes = parseVectorKind(Kind, RegKind::NeonVector); + if (!KindRes) return true; + + unsigned ElementWidth = KindRes->second; Operands.push_back( - AArch64Operand::CreateReg(Reg, RegKind::NeonVector, S, getLoc(), - getContext())); + AArch64Operand::CreateVectorReg(Reg, RegKind::NeonVector, ElementWidth, + S, getLoc(), getContext())); // If there was an explicit qualifier, that goes on as a literal text // operand. @@ -2697,12 +2700,12 @@ return false; } -// tryParseSVEDataVectorRegister - Try to parse a SVE vector register name with +// tryParseVectorRegister - Try to parse a vector register name with // optional kind specifier. If it is a register specifier, eat the token // and return it. OperandMatchResultTy -AArch64AsmParser::tryParseSVERegister(int &Reg, StringRef &Kind, - RegKind MatchKind) { +AArch64AsmParser::tryParseVectorRegister(int &Reg, StringRef &Kind, + RegKind MatchKind) { MCAsmParser &Parser = getParser(); const AsmToken &Tok = Parser.getTok(); @@ -2719,8 +2722,8 @@ if (RegNum) { if (Next != StringRef::npos) { Kind = Name.slice(Next, StringRef::npos); - if (!isValidSVEKind(Kind)) { - TokError("invalid sve vector kind qualifier"); + if (!isValidVectorKind(Kind, MatchKind)) { + TokError("invalid vector kind qualifier"); return MatchOperand_ParseFail; } } @@ -2740,25 +2743,18 @@ const SMLoc S = getLoc(); StringRef Kind; int RegNum = -1; - auto Res = tryParseSVERegister(RegNum, Kind, RegKind::SVEPredicateVector); + auto Res = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector); if (Res != MatchOperand_Success) return Res; - unsigned ElementWidth = StringSwitch(Kind.lower()) - .Case("", -1) - .Case(".b", 8) - .Case(".h", 16) - .Case(".s", 32) - .Case(".d", 64) - .Case(".q", 128) - .Default(0); - - if (!ElementWidth) + const auto &KindRes = parseVectorKind(Kind, RegKind::SVEPredicateVector); + if (!KindRes) return MatchOperand_NoMatch; - Operands.push_back( - AArch64Operand::CreateReg(RegNum, RegKind::SVEPredicateVector, - ElementWidth, S, getLoc(), getContext())); + unsigned ElementWidth = KindRes->second; + Operands.push_back(AArch64Operand::CreateVectorReg( + RegNum, RegKind::SVEPredicateVector, ElementWidth, S, + getLoc(), getContext())); // Not all predicates are followed by a '/m' or '/z'. MCAsmParser &Parser = getParser(); @@ -2884,21 +2880,38 @@ bool AArch64AsmParser::parseVectorList(OperandVector &Operands) { MCAsmParser &Parser = getParser(); assert(Parser.getTok().is(AsmToken::LCurly) && "Token is not a Left Bracket"); + + // Wrapper around parse function + auto ParseVector = [this](int &Reg, StringRef &Kind, SMLoc Loc) { + if (tryParseVectorRegister(Reg, Kind, RegKind::NeonVector) == + MatchOperand_Success) { + if (parseVectorKind(Kind, RegKind::NeonVector)) + return true; + llvm_unreachable("Expected a valid vector kind"); + } + + Error(Loc, "vector register expected"); + return false; + }; + SMLoc S = getLoc(); Parser.Lex(); // Eat left bracket token. StringRef Kind; - int64_t FirstReg = tryMatchVectorRegister(Kind, true); - if (FirstReg == -1) - return true; + int FirstReg = -1; + if (!ParseVector(FirstReg, Kind, getLoc())) + return true; + int64_t PrevReg = FirstReg; unsigned Count = 1; if (parseOptionalToken(AsmToken::Minus)) { SMLoc Loc = getLoc(); StringRef NextKind; - int64_t Reg = tryMatchVectorRegister(NextKind, true); - if (Reg == -1) + + int Reg; + if (!ParseVector(Reg, NextKind, getLoc())) return true; + // Any Kind suffices must match on all regs in the list. if (Kind != NextKind) return Error(Loc, "mismatched register size suffix"); @@ -2915,8 +2928,8 @@ while (parseOptionalToken(AsmToken::Comma)) { SMLoc Loc = getLoc(); StringRef NextKind; - int64_t Reg = tryMatchVectorRegister(NextKind, true); - if (Reg == -1) + int Reg; + if (!ParseVector(Reg, NextKind, getLoc())) return true; // Any Kind suffices must match on all regs in the list. if (Kind != NextKind) @@ -2939,12 +2952,14 @@ return Error(S, "invalid number of vectors"); unsigned NumElements = 0; - char ElementKind = 0; - if (!Kind.empty()) - parseValidVectorKind(Kind, NumElements, ElementKind); + unsigned ElementWidth = 0; + if (!Kind.empty()) { + if (const auto &VK = parseVectorKind(Kind, RegKind::NeonVector)) + std::tie(NumElements, ElementWidth) = *VK; + } Operands.push_back(AArch64Operand::CreateVectorList( - FirstReg, Count, NumElements, ElementKind, S, getLoc(), getContext())); + FirstReg, Count, NumElements, ElementWidth, S, getLoc(), getContext())); // If there is an index specifier following the list, parse that too. SMLoc SIdx = getLoc(); @@ -4454,8 +4469,13 @@ if (RegNum == -1) { StringRef Kind; RegisterKind = RegKind::NeonVector; - RegNum = tryMatchVectorRegister(Kind, false); - if (!Kind.empty()) + OperandMatchResultTy Res = + tryParseVectorRegister(RegNum, Kind, RegKind::NeonVector); + + if (Res == MatchOperand_ParseFail) + return true; + + if (Res == MatchOperand_Success && !Kind.empty()) return Error(SRegLoc, "vector register without type specifier expected"); } @@ -4463,7 +4483,7 @@ StringRef Kind; RegisterKind = RegKind::SVEDataVector; OperandMatchResultTy Res = - tryParseSVERegister(RegNum, Kind, RegKind::SVEDataVector); + tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector); if (Res == MatchOperand_ParseFail) return true; @@ -4477,7 +4497,7 @@ StringRef Kind; RegisterKind = RegKind::SVEPredicateVector; OperandMatchResultTy Res = - tryParseSVERegister(RegNum, Kind, RegKind::SVEPredicateVector); + tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector); if (Res == MatchOperand_ParseFail) return true; @@ -4722,7 +4742,7 @@ StringRef Kind; OperandMatchResultTy Res = - tryParseSVERegister(RegNum, Kind, RegKind::SVEDataVector); + tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector); if (Res != MatchOperand_Success) return Res; @@ -4730,20 +4750,14 @@ if (ParseSuffix && Kind.empty()) return MatchOperand_NoMatch; - unsigned ElementWidth = StringSwitch(Kind.lower()) - .Case("", -1) - .Case(".b", 8) - .Case(".h", 16) - .Case(".s", 32) - .Case(".d", 64) - .Case(".q", 128) - .Default(0); - if (!ElementWidth) + const auto &KindRes = parseVectorKind(Kind, RegKind::SVEDataVector); + if (!KindRes) return MatchOperand_NoMatch; - Operands.push_back( - AArch64Operand::CreateReg(RegNum, RegKind::SVEDataVector, ElementWidth, - S, S, getContext())); + unsigned ElementWidth = KindRes->second; + Operands.push_back(AArch64Operand::CreateVectorReg( + RegNum, RegKind::SVEDataVector, ElementWidth, S, S, + getContext())); return MatchOperand_Success; } Index: llvm/trunk/test/MC/AArch64/SVE/add-diagnostics.s =================================================================== --- llvm/trunk/test/MC/AArch64/SVE/add-diagnostics.s +++ llvm/trunk/test/MC/AArch64/SVE/add-diagnostics.s @@ -8,7 +8,7 @@ // Invalid element kind. add z20.h, z2.h, z31.x -// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid sve vector kind qualifier +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid vector kind qualifier // CHECK-NEXT: add z20.h, z2.h, z31.x // CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: Index: llvm/trunk/test/MC/AArch64/SVE/sub-diagnostics.s =================================================================== --- llvm/trunk/test/MC/AArch64/SVE/sub-diagnostics.s +++ llvm/trunk/test/MC/AArch64/SVE/sub-diagnostics.s @@ -8,7 +8,7 @@ // Invalid element kind. sub z4.h, z27.h, z31.x -// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid sve vector kind qualifier +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid vector kind qualifier // CHECK-NEXT: sub z4.h, z27.h, z31.x // CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: Index: llvm/trunk/test/MC/AArch64/SVE/zip1-diagnostics.s =================================================================== --- llvm/trunk/test/MC/AArch64/SVE/zip1-diagnostics.s +++ llvm/trunk/test/MC/AArch64/SVE/zip1-diagnostics.s @@ -2,7 +2,7 @@ // Invalid element kind. zip1 z10.h, z22.h, z31.x -// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid sve vector kind qualifier +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid vector kind qualifier // CHECK-NEXT: zip1 z10.h, z22.h, z31.x // CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: Index: llvm/trunk/test/MC/AArch64/SVE/zip2-diagnostics.s =================================================================== --- llvm/trunk/test/MC/AArch64/SVE/zip2-diagnostics.s +++ llvm/trunk/test/MC/AArch64/SVE/zip2-diagnostics.s @@ -2,7 +2,7 @@ // Invalid element kind. zip2 z6.h, z23.h, z31.x -// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid sve vector kind qualifier +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid vector kind qualifier // CHECK-NEXT: zip2 z6.h, z23.h, z31.x // CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: