diff options
author | Sander de Smalen <sander.desmalen@arm.com> | 2018-04-25 09:26:47 +0000 |
---|---|---|
committer | Sander de Smalen <sander.desmalen@arm.com> | 2018-04-25 09:26:47 +0000 |
commit | 4dbfefddbb0e7ac5f1a70d46fe4eff37dc8ec0f2 (patch) | |
tree | a6b50f9c2aa1c82ffa2da83e5474c244bea2b86d | |
parent | 925ebe7327797f3e0a1226ab457d96e48a127441 (diff) |
[AArch64][SVE] Asm: Add AsmOperand classes for SVE gather/scatter addressing modes.
This patch adds parsing support for 'vector + shift/extend' and
corresponding asm operand classes, needed for implementing SVE's
gather/scatter addressing modes.
The added combinations of vector (ZPR) and Shift/Extend are:
Unscaled:
ZPR64ExtLSL8: signed 64-bit offsets (z0.d)
ZPR32ExtUXTW8: unsigned 32-bit offsets (z0.s, uxtw)
ZPR32ExtSXTW8: signed 32-bit offsets (z0.s, sxtw)
Unpacked and unscaled:
ZPR64ExtUXTW8: unsigned 32-bit offsets (z0.d, uxtw)
ZPR64ExtSXTW8: signed 32-bit offsets (z0.d, sxtw)
Unpacked and scaled:
ZPR64ExtUXTW<scale>: unsigned 32-bit offsets (z0.d, uxtw #<shift>)
ZPR64ExtSXTW<scale>: signed 32-bit offsets (z0.d, sxtw #<shift>)
Scaled:
ZPR32ExtUXTW<scale>: unsigned 32-bit offsets (z0.s, uxtw #<shift>)
ZPR32ExtSXTW<scale>: signed 32-bit offsets (z0.s, sxtw #<shift>)
ZPR64ExtLSL<scale>: unsigned 64-bit offsets (z0.d, lsl #<shift>)
ZPR64ExtLSL<scale>: signed 64-bit offsets (z0.d, lsl #<shift>)
Patch [1/3] in series to add support for SVE's gather load instructions
that use scalar+vector addressing modes:
- Patch [1/3]: https://reviews.llvm.org/D45951
- Patch [2/3]: https://reviews.llvm.org/D46023
- Patch [3/3]: https://reviews.llvm.org/D45958
Reviewers: fhahn, rengolin, samparker, SjoerdMeijer, t.p.northover, echristo, evandro, javed.absar
Reviewed By: fhahn
Differential Revision: https://reviews.llvm.org/D45951
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@330805 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Target/AArch64/AArch64RegisterInfo.td | 62 | ||||
-rw-r--r-- | lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp | 88 | ||||
-rw-r--r-- | lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp | 6 | ||||
-rw-r--r-- | lib/Target/AArch64/InstPrinter/AArch64InstPrinter.h | 2 |
4 files changed, 150 insertions, 8 deletions
diff --git a/lib/Target/AArch64/AArch64RegisterInfo.td b/lib/Target/AArch64/AArch64RegisterInfo.td index 80637a8e8ca..0a69a2142fa 100644 --- a/lib/Target/AArch64/AArch64RegisterInfo.td +++ b/lib/Target/AArch64/AArch64RegisterInfo.td @@ -821,7 +821,7 @@ class ZPRAsmOperand <string name, int Width>: AsmOperandClass { let PredicateMethod = "isSVEVectorRegOfWidth<" # Width # ", AArch64::ZPRRegClassID>"; let RenderMethod = "addRegOperands"; - let ParserMethod = "tryParseSVEDataVector<" + let ParserMethod = "tryParseSVEDataVector<false, " # !if(!eq(Width, 0), "false", "true") # ">"; } @@ -934,6 +934,64 @@ def ZZZZ_d : RegisterOperand<ZPR4, "printTypedVectorList<0,'d'>"> { let ParserMatchClass = ZPRVectorList<64, 4>; } +class ZPRExtendAsmOperand<string ShiftExtend, int RegWidth, int Scale> + : 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<true, true>"; +} + +class ZPRExtendRegisterOperand<bit SignExtend, bit IsLSL, string Repr, + int RegWidth, int Scale> : RegisterOperand<ZPR> { + let ParserMatchClass = + !cast<AsmOperandClass>("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 <string AsmOperandName, int Scale, string RegClass> : AsmOperandClass { let Name = AsmOperandName # Scale; let PredicateMethod = "isGPR64WithShiftExtend<AArch64::"#RegClass#"RegClassID, " # Scale # ">"; @@ -944,7 +1002,7 @@ class GPR64ShiftExtendAsmOperand <string AsmOperandName, int Scale, string RegCl class GPR64ExtendRegisterOperand<string Name, int Scale, RegisterClass RegClass> : RegisterOperand<RegClass>{ let ParserMatchClass = !cast<AsmOperandClass>(Name); - let PrintMethod = "printRegWithShiftExtend<false, " # Scale # ", 'x'>"; + let PrintMethod = "printRegWithShiftExtend<false, " # Scale # ", 'x', 0>"; } foreach Scale = [8, 16, 32, 64] in { diff --git a/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp index cee7a7d4887..6af1207b580 100644 --- a/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp +++ b/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp @@ -140,7 +140,7 @@ private: OperandMatchResultTy tryParseGPRSeqPair(OperandVector &Operands); template <bool ParseShiftExtend> OperandMatchResultTy tryParseGPROperand(OperandVector &Operands); - template <bool ParseSuffix> + template <bool ParseShiftExtend, bool ParseSuffix> OperandMatchResultTy tryParseSVEDataVector(OperandVector &Operands); OperandMatchResultTy tryParseSVEPredicateVector(OperandVector &Operands); template <RegKind VectorKind> @@ -857,6 +857,14 @@ public: (ElementWidth == 0 || Reg.ElementWidth == ElementWidth); } + template <int ElementWidth, unsigned Class, + AArch64_AM::ShiftExtendType ShiftExtendTy, int ShiftWidth> + bool isSVEVectorRegWithShiftExtend() const { + return Kind == k_Register && isSVEVectorRegOfWidth<ElementWidth, Class>() && + 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 @@ bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode, 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 @@ bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, 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 @@ AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) { return MatchOperand_Success; } -template <bool ParseSuffix> +template <bool ParseShiftExtend, bool ParseSuffix> OperandMatchResultTy AArch64AsmParser::tryParseSVEDataVector(OperandVector &Operands) { const SMLoc S = getLoc(); @@ -4919,9 +4979,29 @@ AArch64AsmParser::tryParseSVEDataVector(OperandVector &Operands) { 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<std::unique_ptr<MCParsedAsmOperand>, 1> ExtOpnd; + Res = tryParseOptionalShiftExtend(ExtOpnd); + if (Res != MatchOperand_Success) + return Res; + + auto Ext = static_cast<AArch64Operand *>(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; } diff --git a/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp b/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp index 9a742f42ec9..e743e5f42ea 100644 --- a/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp +++ b/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp @@ -991,12 +991,16 @@ void AArch64InstPrinter::printMemExtend(const MCInst *MI, unsigned OpNum, printMemExtendImpl(SignExtend, DoShift, Width, SrcRegKind, O); } -template <bool SignExtend, int ExtWidth, char SrcRegKind> +template <bool SignExtend, int ExtWidth, char SrcRegKind, char Suffix> 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') { diff --git a/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.h b/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.h index d889ffd507c..63a9ef82c6a 100644 --- a/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.h +++ b/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.h @@ -90,7 +90,7 @@ protected: const MCSubtargetInfo &STI, raw_ostream &O) { printMemExtend(MI, OpNum, O, SrcRegKind, Width); } - template <bool SignedExtend, int ExtWidth, char SrcRegKind> + template <bool SignedExtend, int ExtWidth, char SrcRegKind, char Suffix> void printRegWithShiftExtend(const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI, raw_ostream &O); void printCondCode(const MCInst *MI, unsigned OpNum, |