aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSander de Smalen <sander.desmalen@arm.com>2018-04-25 09:26:47 +0000
committerSander de Smalen <sander.desmalen@arm.com>2018-04-25 09:26:47 +0000
commit4dbfefddbb0e7ac5f1a70d46fe4eff37dc8ec0f2 (patch)
treea6b50f9c2aa1c82ffa2da83e5474c244bea2b86d
parent925ebe7327797f3e0a1226ab457d96e48a127441 (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.td62
-rw-r--r--lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp88
-rw-r--r--lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp6
-rw-r--r--lib/Target/AArch64/InstPrinter/AArch64InstPrinter.h2
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,