From 693ce8291cd1ddd62ca0ba50f02f0a4f0d5e0189 Mon Sep 17 00:00:00 2001 From: Jim Grosbach Date: Wed, 30 Nov 2011 01:09:44 +0000 Subject: [PATCH] ARM parsing aliases for VLD1 single register all lanes. llvm-svn: 145464 --- lib/Target/ARM/ARMInstrInfo.td | 3 + lib/Target/ARM/ARMInstrNEON.td | 18 ++- lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 117 +++++++++++++++++- lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp | 7 ++ lib/Target/ARM/InstPrinter/ARMInstPrinter.h | 2 + utils/TableGen/EDEmitter.cpp | 1 + 6 files changed, 142 insertions(+), 6 deletions(-) diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td index be039246a0e..f0077e5b10c 100644 --- a/lib/Target/ARM/ARMInstrInfo.td +++ b/lib/Target/ARM/ARMInstrInfo.td @@ -812,6 +812,9 @@ def addrmode6dup : Operand, let PrintMethod = "printAddrMode6Operand"; let MIOperandInfo = (ops GPR:$addr, i32imm); let EncoderMethod = "getAddrMode6DupAddressOpValue"; + // FIXME: This is close, but not quite right. The alignment specifier is + // different. + let ParserMatchClass = AddrMode6AsmOperand; } // addrmodepc := pc + reg diff --git a/lib/Target/ARM/ARMInstrNEON.td b/lib/Target/ARM/ARMInstrNEON.td index ce2ea30779b..0a1afa454b5 100644 --- a/lib/Target/ARM/ARMInstrNEON.td +++ b/lib/Target/ARM/ARMInstrNEON.td @@ -120,6 +120,16 @@ def VecListTwoQ : RegisterOperand { let ParserMatchClass = VecListTwoQAsmOperand; } +// Register list of one D register, with "all lanes" subscripting. +def VecListOneDAllLanesAsmOperand : AsmOperandClass { + let Name = "VecListOneDAllLanes"; + let ParserMethod = "parseVectorList"; + let RenderMethod = "addVecListOperands"; +} +def VecListOneDAllLanes : RegisterOperand { + let ParserMatchClass = VecListOneDAllLanesAsmOperand; +} + //===----------------------------------------------------------------------===// // NEON-specific DAG Nodes. //===----------------------------------------------------------------------===// @@ -1003,9 +1013,11 @@ def VLD4LNq32Pseudo_UPD : VLDQQQQLNWBPseudo; // VLD1DUP : Vector Load (single element to all lanes) class VLD1DUP op7_4, string Dt, ValueType Ty, PatFrag LoadOp> - : NLdSt<1, 0b10, 0b1100, op7_4, (outs DPR:$Vd), (ins addrmode6dup:$Rn), - IIC_VLD1dup, "vld1", Dt, "\\{$Vd[]\\}, $Rn", "", - [(set DPR:$Vd, (Ty (NEONvdup (i32 (LoadOp addrmode6dup:$Rn)))))]> { + : NLdSt<1, 0b10, 0b1100, op7_4, (outs VecListOneDAllLanes:$Vd), + (ins addrmode6dup:$Rn), + IIC_VLD1dup, "vld1", Dt, "$Vd, $Rn", "", + [(set VecListOneDAllLanes:$Vd, + (Ty (NEONvdup (i32 (LoadOp addrmode6dup:$Rn)))))]> { let Rm = 0b1111; let Inst{4} = Rn{4}; let DecoderMethod = "DecodeVLD1DupInstruction"; diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index b2e2f7a5b59..a96b37d53ac 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -39,6 +39,8 @@ namespace { class ARMOperand; +enum VectorLaneTy { NoLanes, AllLanes }; + class ARMAsmParser : public MCTargetAsmParser { MCSubtargetInfo &STI; MCAsmParser &Parser; @@ -161,6 +163,7 @@ class ARMAsmParser : public MCTargetAsmParser { OperandMatchResultTy parseAM3Offset(SmallVectorImpl&); OperandMatchResultTy parseFPImm(SmallVectorImpl&); OperandMatchResultTy parseVectorList(SmallVectorImpl&); + OperandMatchResultTy parseVectorLane(VectorLaneTy &LaneKind); // Asm Match Converter Methods bool cvtT2LdrdPre(MCInst &Inst, unsigned Opcode, @@ -271,6 +274,7 @@ class ARMOperand : public MCParsedAsmOperand { k_DPRRegisterList, k_SPRRegisterList, k_VectorList, + k_VectorListAllLanes, k_ShiftedRegister, k_ShiftedImmediate, k_ShifterImmediate, @@ -409,6 +413,7 @@ public: Registers = o.Registers; break; case k_VectorList: + case k_VectorListAllLanes: VectorList = o.VectorList; break; case k_CoprocNum: @@ -967,6 +972,11 @@ public: return VectorList.Count == 2 && false; } + bool isVecListOneDAllLanes() const { + if (Kind != k_VectorListAllLanes) return false; + return VectorList.Count == 1; + } + bool isVectorIndex8() const { if (Kind != k_VectorIndex) return false; return VectorIndex.Val < 8; @@ -1761,6 +1771,16 @@ public: return Op; } + static ARMOperand *CreateVectorListAllLanes(unsigned RegNum, unsigned Count, + SMLoc S, SMLoc E) { + ARMOperand *Op = new ARMOperand(k_VectorListAllLanes); + Op->VectorList.RegNum = RegNum; + Op->VectorList.Count = Count; + Op->StartLoc = S; + Op->EndLoc = E; + return Op; + } + static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E, MCContext &Ctx) { ARMOperand *Op = new ARMOperand(k_VectorIndex); @@ -1954,6 +1974,10 @@ void ARMOperand::print(raw_ostream &OS) const { OS << ""; break; + case k_VectorListAllLanes: + OS << ""; + break; case k_Token: OS << "'" << getToken() << "'"; break; @@ -2453,9 +2477,29 @@ parseRegisterList(SmallVectorImpl &Operands) { return false; } +// Helper function to parse the lane index for vector lists. +ARMAsmParser::OperandMatchResultTy ARMAsmParser:: +parseVectorLane(VectorLaneTy &LaneKind) { + if (Parser.getTok().is(AsmToken::LBrac)) { + Parser.Lex(); // Eat the '['. + if (Parser.getTok().is(AsmToken::RBrac)) { + // "Dn[]" is the 'all lanes' syntax. + LaneKind = AllLanes; + Parser.Lex(); // Eat the ']'. + return MatchOperand_Success; + } + // FIXME: Other lane kinds as we add them. + Error(Parser.getTok().getLoc(), "FIXME: Unexpected lane kind."); + return MatchOperand_ParseFail; + } + LaneKind = NoLanes; + return MatchOperand_Success; +} + // parse a vector register list ARMAsmParser::OperandMatchResultTy ARMAsmParser:: parseVectorList(SmallVectorImpl &Operands) { + VectorLaneTy LaneKind; SMLoc S = Parser.getTok().getLoc(); // As an extension (to match gas), support a plain D register or Q register // (without encosing curly braces) as a single or double entry list, @@ -2466,12 +2510,40 @@ parseVectorList(SmallVectorImpl &Operands) { return MatchOperand_NoMatch; SMLoc E = Parser.getTok().getLoc(); if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) { - Operands.push_back(ARMOperand::CreateVectorList(Reg, 1, S, E)); + OperandMatchResultTy Res = parseVectorLane(LaneKind); + if (Res != MatchOperand_Success) + return Res; + switch (LaneKind) { + default: + assert(0 && "unexpected lane kind!"); + case NoLanes: + E = Parser.getTok().getLoc(); + Operands.push_back(ARMOperand::CreateVectorList(Reg, 1, S, E)); + break; + case AllLanes: + E = Parser.getTok().getLoc(); + Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 1, S, E)); + break; + } return MatchOperand_Success; } if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) { Reg = getDRegFromQReg(Reg); - Operands.push_back(ARMOperand::CreateVectorList(Reg, 2, S, E)); + OperandMatchResultTy Res = parseVectorLane(LaneKind); + if (Res != MatchOperand_Success) + return Res; + switch (LaneKind) { + default: + assert(0 && "unexpected lane kind!"); + case NoLanes: + E = Parser.getTok().getLoc(); + Operands.push_back(ARMOperand::CreateVectorList(Reg, 2, S, E)); + break; + case AllLanes: + E = Parser.getTok().getLoc(); + Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 2, S, E)); + break; + } return MatchOperand_Success; } Error(S, "vector register expected"); @@ -2498,6 +2570,8 @@ parseVectorList(SmallVectorImpl &Operands) { ++Reg; ++Count; } + if (parseVectorLane(LaneKind) != MatchOperand_Success) + return MatchOperand_ParseFail; while (Parser.getTok().is(AsmToken::Comma) || Parser.getTok().is(AsmToken::Minus)) { @@ -2526,6 +2600,15 @@ parseVectorList(SmallVectorImpl &Operands) { Error(EndLoc, "bad range in register list"); return MatchOperand_ParseFail; } + // Parse the lane specifier if present. + VectorLaneTy NextLaneKind; + if (parseVectorLane(NextLaneKind) != MatchOperand_Success) + return MatchOperand_ParseFail; + if (NextLaneKind != LaneKind) { + Error(EndLoc, "mismatched lane index in register list"); + return MatchOperand_ParseFail; + } + EndLoc = Parser.getTok().getLoc(); // Add all the registers in the range to the register list. Count += EndReg - Reg; @@ -2554,6 +2637,15 @@ parseVectorList(SmallVectorImpl &Operands) { } ++Reg; Count += 2; + // Parse the lane specifier if present. + VectorLaneTy NextLaneKind; + SMLoc EndLoc = Parser.getTok().getLoc(); + if (parseVectorLane(NextLaneKind) != MatchOperand_Success) + return MatchOperand_ParseFail; + if (NextLaneKind != LaneKind) { + Error(EndLoc, "mismatched lane index in register list"); + return MatchOperand_ParseFail; + } continue; } // Normal D register. Just check that it's contiguous and keep going. @@ -2562,6 +2654,15 @@ parseVectorList(SmallVectorImpl &Operands) { return MatchOperand_ParseFail; } ++Count; + // Parse the lane specifier if present. + VectorLaneTy NextLaneKind; + SMLoc EndLoc = Parser.getTok().getLoc(); + if (parseVectorLane(NextLaneKind) != MatchOperand_Success) + return MatchOperand_ParseFail; + if (NextLaneKind != LaneKind) { + Error(EndLoc, "mismatched lane index in register list"); + return MatchOperand_ParseFail; + } } SMLoc E = Parser.getTok().getLoc(); @@ -2571,7 +2672,17 @@ parseVectorList(SmallVectorImpl &Operands) { } Parser.Lex(); // Eat '}' token. - Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count, S, E)); + switch (LaneKind) { + default: + assert(0 && "unexpected lane kind in register list."); + case NoLanes: + Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count, S, E)); + break; + case AllLanes: + Operands.push_back(ARMOperand::CreateVectorListAllLanes(FirstReg, Count, + S, E)); + break; + } return MatchOperand_Success; } diff --git a/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp b/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp index 6c6c02146fa..ed2594e2aef 100644 --- a/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp +++ b/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp @@ -1029,3 +1029,10 @@ void ARMInstPrinter::printVectorListFour(const MCInst *MI, unsigned OpNum, << getRegisterName(MI->getOperand(OpNum).getReg() + 2) << ", " << getRegisterName(MI->getOperand(OpNum).getReg() + 3) << "}"; } + +void ARMInstPrinter::printVectorListOneAllLanes(const MCInst *MI, + unsigned OpNum, + raw_ostream &O) { + O << "{" << getRegisterName(MI->getOperand(OpNum).getReg()) << "[]}"; +} + diff --git a/lib/Target/ARM/InstPrinter/ARMInstPrinter.h b/lib/Target/ARM/InstPrinter/ARMInstPrinter.h index 3f38f1a0ee2..e25fc7c199f 100644 --- a/lib/Target/ARM/InstPrinter/ARMInstPrinter.h +++ b/lib/Target/ARM/InstPrinter/ARMInstPrinter.h @@ -133,6 +133,8 @@ public: void printVectorListTwo(const MCInst *MI, unsigned OpNum, raw_ostream &O); void printVectorListThree(const MCInst *MI, unsigned OpNum, raw_ostream &O); void printVectorListFour(const MCInst *MI, unsigned OpNum, raw_ostream &O); + void printVectorListOneAllLanes(const MCInst *MI, unsigned OpNum, + raw_ostream &O); }; } // end namespace llvm diff --git a/utils/TableGen/EDEmitter.cpp b/utils/TableGen/EDEmitter.cpp index 1953dadbdce..0a7e2513338 100644 --- a/utils/TableGen/EDEmitter.cpp +++ b/utils/TableGen/EDEmitter.cpp @@ -576,6 +576,7 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type, REG("VecListThreeD"); REG("VecListFourD"); REG("VecListTwoQ"); + REG("VecListOneDAllLanes"); IMM("i32imm"); IMM("i32imm_hilo16");