Alex Susu via llvm-dev
2016-Dec-11 03:31 UTC
[llvm-dev] TableGen - Help to implement a form of gather/scatter operations for Mips MSA
Hello. Will, thanks a lot for pointing me to the MaskedGatherSDNode and mgatherv4i32. I have to say that the definition of the "multiclass avx512_gather" from lib/Target/X86/X86InstrAVX512.td is difficult to follow and I prefer not to use it. I currently have some serious problems with TableGen - it gives an assertion failure: "llvm/utils/TableGen/CodeGenDAGPatterns.cpp:2153: llvm::TreePatternNode* llvm::TreePattern::ParseTreePattern(llvm::Init*, llvm::StringRef): Assertion `New->getNumTypes() == 1 && "FIXME: Unhandled"' failed." Can somebody help me with the code below responsible for this error? // From llvm/lib/Target/X86/X86InstrFragmentsSIMD.td def mgatherv128i16 : PatFrag<(ops node:$src1, node:$src2, node:$src3), (masked_gather node:$src1, node:$src2, node:$src3) , [{ if (MaskedGatherSDNode *mgNode = dyn_cast<MaskedGatherSDNode>(N)) return (mgNode->getIndex().getValueType() == MVT::v128i16 || mgNode->getBasePtr().getValueType() == MVT::v128i16); return false; }]>; foreach RegId = 0-31 in def Mask#RegId : MipsReg<0, "Mask"#RegId>, DwarfRegNum<[!add(RegId, 10)]>; def VK128: RegisterClass<"Connex", [v128i1], 32, (sequence "Mask%u", 0, 31)>; def VK128Opnd : RegisterOperand<VK128> { let ParserMatchClass = MSA128AsmOperand; } class LD_INDIRECT_DESC_BASE2<string instr_asm, ValueType TyNode, RegisterOperand ROWD, RegisterOperand ROWSI = ROWD, RegisterOperand ROWSP = ROWD, // passthru register InstrItinClass itin = NoItinerary> { dag OutOperandList = (outs ROWD:$wd); dag InOperandList = (ins ROWSP:$wsp, VK128Opnd:$wsm, ROWSI:$wsptr, ROWSI:$wsi); string AsmString = "$wd = LS[R($wsi )];"; list<dag> Pattern = [(set ROWD:$wd, (TyNode (masked_gather ROWSP:$wsp, VK128Opnd :$wsm, ROWSI:$wsptr, ROWSI:$wsi)))]; InstrItinClass Itinerary = itin; string DecoderMethod = "DecodeMSA128Mem"; } class LD_INDIRECT_D_DESC2 : LD_INDIRECT_DESC_BASE2<"read", v128i16, MSA128DOpnd>; class LD_INDIRECT_D_ENC2 : MSA_2R_FMT<0b101001110>; def LD_INDIRECT_D2: LD_INDIRECT_D_ENC2, LD_INDIRECT_D_DESC2; /* // From http://llvm.org/docs/doxygen/html/SelectionDAGNodes_8h_source.html: 02115 // In the both nodes address is Op1, mask is Op2: 02116 // MaskedGatherSDNode (Chain, src0, mask, base, index), src0 is a passthru value 02117 // MaskedScatterSDNode (Chain, value, mask, base, index) 02118 // Mask is a vector of i1 elements 02119 const SDValue &getBasePtr() const { return getOperand(3); } 02120 const SDValue &getIndex() const { return getOperand(4); } 02121 const SDValue &getMask() const { return getOperand(2); } 02122 const SDValue &getValue() const { return getOperand(1); } // Alex: this is pass-thru */ Thank you very much, Alex On 12/9/2016 4:18 PM, Will Lovett wrote:> Hi Alex, > > I don’t know too much about recent MIPS, but have recently been doing something similar > for the new ARM SVE architecture, so hopefully this will get you closer to what you need: > > If you’re looking where I think you are (lib/Target/X86/X86InstrAVX512.td), ‘GatherNode’ > is a template argument, not a definition. > It allows a PatFrag be passed into the avx512_gather multiclass definition. > > Working backwards from here, the actual PatFrags passed into this are things like > ‘mgatherv4i32’. These are patterns that match a MaskedGatherSDNode for a particular data > type. > > MaskedGatherSDNode is the generic SD node that represents a predicated gather, which in > turn was generated from Intrinsic::masked_gather in the IR > (in SelectionDAGBuilder::visitMaskedGather) > > If your MIPS instruction has a predicate, you will need to create MIPS tablegen that > matches MaskedGatherSDNode. If not, I guess you’ll need to create a new intrinsic that > represents an unpredicted gather, and add appropriate uses of it during IR creation (such > as in LoopVectorize, where masked gathers are created today) > > Hope that helps, > > Will Lovett > > > On 9 December 2016 at 01:52:48, Alex Susu via llvm-dev (llvm-dev at lists.llvm.org > <mailto:llvm-dev at lists.llvm.org>) wrote: > >> Hello. >> I read on page 4 of http://www.cs.fsu.edu/~whalley/cda5155/chap4.pdf that gather and >> scatter operations exist for Mips, named LVI and SVI, respectively. >> >> Did anyone think of implementing in the LLVM Mips back end (part of the MSA vector >> instructions) gather and scatter operations? >> If so, can you share with me the TableGen spec? (I tried to start from LD_DESC_BASE, >> but it doesn't seem to be trivial. Also, LLVM seems to have implemented scatter/gather >> instructions only for the x86 processor - there, they defined new SDNodes called >> GatherNode and ScatterNode.) >> >> Thank you, >> Alex >> _______________________________________________ >> LLVM Developers mailing list >> llvm-dev at lists.llvm.org >> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
Alex Susu via llvm-dev
2016-Dec-12 02:18 UTC
[llvm-dev] TableGen - Help to implement a form of gather/scatter operations for Mips MSA
Hello. I wanted to inform that I fixed the bug from the previous email. The main reason for the bug was that I thought that the SDNode masked_gather is returning only 1 value, but it returns 2 (hence, I guess, the earlier reported, difficult to follow, error: "Assertion `New->getNumTypes() == 1"). masked_gather returns 2 values because: // SDTypeProfile - This profile describes the type requirements of a Selection // DAG node. class SDTypeProfile<int numresults, int numoperands, list<SDTypeConstraint> constraints> { int NumResults = numresults; int NumOperands = numoperands; list<SDTypeConstraint> Constraints = constraints; } // So: 2 results, 3 operands. // Params are: passthru, mask, index; results are: vector of i1, ptr!! // Params are 0, 1, 2 and results are 3, 4. // Opnds 0 and 1 have vector type, with same number of elements. // Opnds 0 and 2 have identical types. // Opnds 1 and 3 have identical types. // --> Opnd 3 (result 0?) is i1 vector // Opnd 4 (result 1?) has pointer type. // Opnd 1 is vector type with element type of i1. def SDTMaskedGather: SDTypeProfile<2, 3, [ // masked gather SDTCisVec<0>, SDTCisVec<1>, SDTCisSameAs<0, 2>, SDTCisSameAs<1, 3>, SDTCisPtrTy<4>, SDTCVecEltisVT<1, i1>, SDTCisSameNumEltsAs<0, 1> ]>; def masked_gather : SDNode<"ISD::MGATHER", SDTMaskedGather, [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>; Also, we need to make the operand $wsi a memory operand (otherwise we get the difficult error: <<In LD_INDIRECT_D2: Type inference contradiction found, 'v128i16' needs to be scalar>>), like in the following complete specification: // Inspired heavily from lib/Target/X86/X86InstrInfo.td class X86MemOperand<string printMethod> : Operand<iPTR> { let PrintMethod = printMethod; let MIOperandInfo = (ops i8imm, i32imm); let OperandType = "OPERAND_MEMORY"; } // Gather mem operands class X86VMemOperand<RegisterClass RC, string printMethod> : X86MemOperand<printMethod> { let MIOperandInfo = (ops i8imm, RC, i32imm); } def vx256xmem : X86VMemOperand<MSA128D, "printi256mem">; def vectoraddr : ComplexPattern<iPTR, 5, "selectVectorAddr", [],[SDNPWantParent]>; class LD_INDIRECT_DESC_BASE2<string instr_asm, RegisterOperand ROWD, RegisterOperand ROWSP = ROWD, InstrItinClass itin = NoItinerary> { dag OutOperandList = (outs ROWD:$wd, VK128Opnd:$wdm); dag InOperandList = (ins ROWSP:$wsp, VK128Opnd:$wsm, vx256xmem:$wsi); string AsmString = !strconcat("$wd = LS[$wsi]; // iread (or Mips MSA's LD) strinstr_asm = ", instr_asm); list<dag> Pattern = [(set ROWD:$wd, VK128Opnd:$wdm, (masked_gather ROWSP:$wsp, VK128Opnd:$wsm, vectoraddr:$wsi))]; InstrItinClass Itinerary = itin; string DecoderMethod = "DecodeMSA128Mem"; } class LD_INDIRECT_D_DESC2 : LD_INDIRECT_DESC_BASE2<"read", MSA128DOpnd>; class LD_INDIRECT_D_ENC2 : MSA_3R_FMT<0b101001110>; def LD_INDIRECT_D2: LD_INDIRECT_D_ENC2, LD_INDIRECT_D_DESC2; Unfortunately, now I have another problem: llc fails when trying to select my masked_gather node. More exactly, it first tries to split it and then gives an error: Split node operand: t13: v128i16,ch = masked_gather<LD256[<unknown>]> t0, t23, t40, TargetConstant:i64<0>, t24 Widen node result 0: t46: v64i16 = extract_subvector t23, Constant:i64<64> Widen node result 0: t48: v64i16,ch = masked_gather<LD128[<unknown>](align=256)> t0, t46, t44, TargetConstant:i64<0>, t26 Split node result: t121: v128i64 = BUILD_VECTOR Constant:i64<0>, Constant:i64<0>, Constant:i64<0>, Constant:i64<0>, Constant:i64<0>, Constant:i64<0>, Constant:i64<0>, Constant:i64<0>, Constant:i64<0>, Constant:i64<0>, Constant:i64<0>, Constant:i64<0>, Constant:i... Split node result: t123: v64i64 = BUILD_VECTOR undef:i64, undef:i64, undef:i64, undef:i64, undef:i64, undef:i64, undef:i64, undef:i64, undef:i64, undef:i64, undef:i64, undef:i64, undef:i64, undef:i64, undef:i64, undef:i64, undef:i64, undef:i64, undef:i64, undef:... Split node result: t124: v32i64 = BUILD_VECTOR undef:i64, undef:i64, undef:i64, undef:i64, undef:i64, undef:i64, undef:i64, undef:i64, undef:i64, undef:i64, undef:i64, undef:i64, undef:i64, undef:i64, undef:i64, undef:i64, undef:i64, undef:i64, undef:i64, undef:... Split node result: t125: v16i64 = BUILD_VECTOR undef:i64, undef:i64, undef:i64, undef:i64, undef:i64, undef:i64, undef:i64, undef:i64, undef:i64, undef:i64, undef:i64, undef:i64, undef:i64, undef:i64, undef:i64, undef:i64... Split node result: t126: v8i64 = BUILD_VECTOR undef:i64, undef:i64, undef:i64, undef:i64, undef:i64, undef:i64, undef:i64, undef:i64... Split node result: t127: v4i64 = BUILD_VECTOR undef:i64, undef:i64, undef:i64, undef:i64... Split node result: t128: v2i64 = BUILD_VECTOR undef:i64, undef:i64 Split node operand: t122: v128i16,ch = masked_gather<LD128[<unknown>](align=256)> t0, t130, t193, TargetConstant:i64<0>, t121 llc: /home/asusu/LLVM/llvm38Nov2016/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp:6804: llvm::MemSDNode::MemSDNode(unsigned int, unsigned int, const llvm::DebugLoc&, llvm::SDVTList, llvm::EVT, llvm::MachineMemOperand*): Assertion `memvt.getStoreSize() <= MMO->getSize() && "Size mismatch!"' failed. Does anybody know why this happens? I'd like to mention that I also gave in [Target]ISelLowering.cpp a call to setOperationAction(ISD::MGATHER, aType, Legal), which should have fixed this problem, but it doesn't. Best regards, Alex On 12/11/2016 5:31 AM, Alex Susu wrote:> Hello. > Will, thanks a lot for pointing me to the MaskedGatherSDNode and mgatherv4i32. I have > to say that the definition of the "multiclass avx512_gather" from > lib/Target/X86/X86InstrAVX512.td is difficult to follow and I prefer not to use it. > > I currently have some serious problems with TableGen - it gives an assertion failure: > "llvm/utils/TableGen/CodeGenDAGPatterns.cpp:2153: llvm::TreePatternNode* > llvm::TreePattern::ParseTreePattern(llvm::Init*, llvm::StringRef): Assertion > `New->getNumTypes() == 1 && "FIXME: Unhandled"' failed." > > Can somebody help me with the code below responsible for this error? > > // From llvm/lib/Target/X86/X86InstrFragmentsSIMD.td > def mgatherv128i16 : PatFrag<(ops node:$src1, node:$src2, node:$src3), > (masked_gather node:$src1, node:$src2, node:$src3) , [{ > if (MaskedGatherSDNode *mgNode = dyn_cast<MaskedGatherSDNode>(N)) > return (mgNode->getIndex().getValueType() == MVT::v128i16 || > mgNode->getBasePtr().getValueType() == MVT::v128i16); > return false; > }]>; > > foreach RegId = 0-31 in > def Mask#RegId : MipsReg<0, "Mask"#RegId>, DwarfRegNum<[!add(RegId, 10)]>; > def VK128: RegisterClass<"Connex", [v128i1], 32, (sequence "Mask%u", 0, 31)>; > def VK128Opnd : RegisterOperand<VK128> { > let ParserMatchClass = MSA128AsmOperand; > } > > class LD_INDIRECT_DESC_BASE2<string instr_asm, > ValueType TyNode, > RegisterOperand ROWD, > RegisterOperand ROWSI = ROWD, > RegisterOperand ROWSP = ROWD, // passthru register > InstrItinClass itin = NoItinerary> { > dag OutOperandList = (outs ROWD:$wd); > dag InOperandList = (ins ROWSP:$wsp, VK128Opnd:$wsm, ROWSI:$wsptr, ROWSI:$wsi); > string AsmString = "$wd = LS[R($wsi )];"; > list<dag> Pattern = [(set ROWD:$wd, (TyNode (masked_gather ROWSP:$wsp, VK128Opnd > :$wsm, ROWSI:$wsptr, ROWSI:$wsi)))]; > InstrItinClass Itinerary = itin; > string DecoderMethod = "DecodeMSA128Mem"; > } > class LD_INDIRECT_D_DESC2 : LD_INDIRECT_DESC_BASE2<"read", v128i16, MSA128DOpnd>; > class LD_INDIRECT_D_ENC2 : MSA_2R_FMT<0b101001110>; > def LD_INDIRECT_D2: LD_INDIRECT_D_ENC2, LD_INDIRECT_D_DESC2; > > /* > // From http://llvm.org/docs/doxygen/html/SelectionDAGNodes_8h_source.html: > 02115 // In the both nodes address is Op1, mask is Op2: > 02116 // MaskedGatherSDNode (Chain, src0, mask, base, index), src0 is a > passthru value > 02117 // MaskedScatterSDNode (Chain, value, mask, base, index) > 02118 // Mask is a vector of i1 elements > 02119 const SDValue &getBasePtr() const { return getOperand(3); } > 02120 const SDValue &getIndex() const { return getOperand(4); } > 02121 const SDValue &getMask() const { return getOperand(2); } > 02122 const SDValue &getValue() const { return getOperand(1); } // Alex: this > is pass-thru > > */ > > > Thank you very much, > Alex > > On 12/9/2016 4:18 PM, Will Lovett wrote: >> Hi Alex, >> >> I don’t know too much about recent MIPS, but have recently been doing something similar >> for the new ARM SVE architecture, so hopefully this will get you closer to what you need: >> >> If you’re looking where I think you are (lib/Target/X86/X86InstrAVX512.td), ‘GatherNode’ >> is a template argument, not a definition. >> It allows a PatFrag be passed into the avx512_gather multiclass definition. >> >> Working backwards from here, the actual PatFrags passed into this are things like >> ‘mgatherv4i32’. These are patterns that match a MaskedGatherSDNode for a particular data >> type. >> >> MaskedGatherSDNode is the generic SD node that represents a predicated gather, which in >> turn was generated from Intrinsic::masked_gather in the IR >> (in SelectionDAGBuilder::visitMaskedGather) >> >> If your MIPS instruction has a predicate, you will need to create MIPS tablegen that >> matches MaskedGatherSDNode. If not, I guess you’ll need to create a new intrinsic that >> represents an unpredicted gather, and add appropriate uses of it during IR creation (such >> as in LoopVectorize, where masked gathers are created today) >> >> Hope that helps, >> >> Will Lovett >> >> >> On 9 December 2016 at 01:52:48, Alex Susu via llvm-dev (llvm-dev at lists.llvm.org >> <mailto:llvm-dev at lists.llvm.org>) wrote: >> >>> Hello. >>> I read on page 4 of http://www.cs.fsu.edu/~whalley/cda5155/chap4.pdf that gather and >>> scatter operations exist for Mips, named LVI and SVI, respectively. >>> >>> Did anyone think of implementing in the LLVM Mips back end (part of the MSA vector >>> instructions) gather and scatter operations? >>> If so, can you share with me the TableGen spec? (I tried to start from LD_DESC_BASE, >>> but it doesn't seem to be trivial. Also, LLVM seems to have implemented scatter/gather >>> instructions only for the x86 processor - there, they defined new SDNodes called >>> GatherNode and ScatterNode.) >>> >>> Thank you, >>> Alex >>> _______________________________________________ >>> LLVM Developers mailing list >>> llvm-dev at lists.llvm.org >>> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
Alex Susu via llvm-dev
2016-Dec-15 16:09 UTC
[llvm-dev] TableGen - Help to implement a form of gather/scatter operations for Mips MSA
Hello. I fixed the bug reported in the previous post on this thread (<<llvm::MemSDNode::MemSDNode(unsigned int, unsigned int, const llvm::DebugLoc&, llvm::SDVTList, llvm::EVT, llvm::MachineMemOperand*): Assertion `memvt.getStoreSize() < MMO->getSize() && "Size mismatch!"' failed.>>) The problem with this strange error reported comes from the fact I actually did NOT have defined type v128i64 in files: [repo]/llvm/include/llvm/IR/Intrinsics.td [repo]/llvm/include/llvm/CodeGen/MachineValueType.h [repo]/llvm/lib/IR/ValueTypes.cpp [repo]/llvm/include/llvm/CodeGen/ValueTypes.td The reason I need this type, v128i64, is that pointers have size 64 bits - my ConnexTargetMachine::computeDataLayout() returns normally string "e-m:e-p:64:32-i32:32:32-i64:64-n32:32-S128", since my back end basically extends with vector instructions the LLVM BPF back end. So, at instruction selection it lowers the <128 x i16> value to <128 x i64>, since pointers have 64 bits, which we can see from the debug info of llc: t25: v128i16 = BUILD_VECTOR Constant:i64<31>, Constant:i64<31>, Constant:i64<31>, Constant:i64<31>, Constant:i64<31>, Constant:i64<31>, Constant:i64<31>, Constant:i64<31>, Constant:i64<31>, Constant:i64<31>, Constant:i64<31>, ... Combining: t10: v128i64 = zero_extend t25 ... into: t26: v128i64 = BUILD_VECTOR Constant:i64<31>, Constant:i64<31>, Constant:i64<31>, Constant:i64<31> Once I have defined type v128i64 in the above mentioned 4 files (2 .td, 1 .h, 1 .cpp), I no longer get this strange error. However, now I start getting Segfault at selection for masked_gather, the reason being that I don't have vector registers of 64-bits: ISEL: Starting pattern match on root node: t14: v128i16,ch = masked_gather<LD256[<unknown>]> t0, t22, t29, TargetConstant:i64<0>, t33 Initial Opcode index to 1692 #0 0x00007f08faa9e700 llvm::sys::PrintStackTrace(llvm::raw_ostream&) /llvm/lib/Support/Unix/Signals.inc:402:0 #1 0x00007f08faa9ea9a PrintStackTraceSignalHandler(void*) /llvm/lib/Support/Unix/Signals.inc:470:0 #2 0x00007f08faa9cb55 llvm::sys::RunSignalHandlers() /llvm/lib/Support/Signals.cpp:44:0 #3 0x00007f08faa9df4b SignalHandler(int) /llvm/lib/Support/Unix/Signals.inc:256:0 #4 0x00007f08f994e4a0 (/lib/x86_64-linux-gnu/libc.so.6+0x354a0) #5 0x00007f08fae80078 llvm::SDUse::addToList(llvm::SDUse**) /llvm/include/llvm/CodeGen/SelectionDAGNodes.h:299:0 #6 0x00007f08fae80b2b llvm::SDNode::addUse(llvm::SDUse&) /llvm/include/llvm/CodeGen/SelectionDAGNodes.h:801:0 #7 0x00007f08fae80f6c llvm::SDUse::setInitial(llvm::SDValue const&) /llvm/include/llvm/CodeGen/SelectionDAGNodes.h:920:0 #8 0x00007f08fb024851 llvm::SelectionDAG::createOperands(llvm::SDNode*, llvm::ArrayRef<llvm::SDValue>) /llvm/include/llvm/CodeGen/SelectionDAG.h:300:0 #9 0x00007f08fb0186b8 llvm::SelectionDAG::MorphNodeTo(llvm::SDNode*, unsigned int, llvm::SDVTList, llvm::ArrayRef<llvm::SDValue>) /llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp:6092:0 #10 0x00007f08fb04a3e9 llvm::SelectionDAGISel::MorphNode(llvm::SDNode*, unsigned int, llvm::SDVTList, llvm::ArrayRef<llvm::SDValue>, unsigned int) /llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:2474:0 #11 0x00007f08fb05106b llvm::SelectionDAGISel::SelectCodeCommon(llvm::SDNode*, unsigned char const*, unsigned int) /llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:3441:0 #12 0x00007f0901714eb0 (anonymous namespace)::ConnexDAGToDAGISel::SelectCode(llvm::SDNode*) /llvm/lib/Target/Connex/ConnexGenDAGISel.inc:1075:0 ... I really need the pointer values of masked_gather to be stored in a 16-bit element vector register, which is standard in my back end, since I don't want to create 64-bits vector registers just for scatter/gather pointer value vectors, since my processor does not have physical 64-bist registers. To achieve this I made ConnexTargetMachine::computeDataLayout() return string "e-m:e-p:16:16-i32:32:32-i64:64-n32:32-S128". I also gave at the end of ConnexTargetLowering::ConnexTargetLowering() the following: ValueTypeActions.setTypeAction(MVT::i16, TypeLegal); to avoid errors like: Promote integer operand: t16: ch = store<ST256[inttoptr (i16 250 to <128 x i16>*)]> t13:1, t13, Constant:i16<250>, undef:i16 But even now it gives errors like: ISEL: Starting pattern match on root node: t16: ch = store<ST256[inttoptr (i16 250 to <128 x i16>*)]> t13:1, t13, Constant:i16<250>, undef:i16 Initial Opcode index to 157 Skipped scope entry (due to false predicate) at index 162, continuing at 236 Match failed at index 246 Continuing at 263 LLVM ERROR: Cannot select: t16: ch = store<ST256[inttoptr (i16 250 to <128 x i16>*)]> t13:1, t13, Constant:i16<250>, undef:i16 because all my scalar memory operands are i64 or i64imm in the .td specification files. So I guess I need to change all scalar memory operands to i16 or i16imm in the .td specification files. Please let me know if you see a possibility to fix this problem I guess I should do something like: - // Inspired from ARMISelLowering.cpp: for (unsigned im = (unsigned)ISD::PRE_INC; im != (unsigned)ISD::LAST_INDEXED_MODE; ++im) { setIndexedLoadAction(im, MVT::i64, Legal); setIndexedLoadAction(im, MVT::i16, Promote); setIndexedStoreAction(im, MVT::i64, Legal); setIndexedStoreAction(im, MVT::i16, Promote); } - do custom instruction selection for masked_gather and masked_scatter . Best regards, Alex On 12/12/2016 4:18 AM, Alex Susu wrote:> Hello. > I wanted to inform that I fixed the bug from the previous email. > The main reason for the bug was that I thought that the SDNode masked_gather is > returning only 1 value, but it returns 2 (hence, I guess, the earlier reported, difficult > to follow, error: "Assertion `New->getNumTypes() == 1"). > > masked_gather returns 2 values because: > // SDTypeProfile - This profile describes the type requirements of a Selection > // DAG node. > class SDTypeProfile<int numresults, int numoperands, > list<SDTypeConstraint> constraints> { > int NumResults = numresults; > int NumOperands = numoperands; > list<SDTypeConstraint> Constraints = constraints; > } > > // So: 2 results, 3 operands. > // Params are: passthru, mask, index; results are: vector of i1, ptr!! > // Params are 0, 1, 2 and results are 3, 4. > // Opnds 0 and 1 have vector type, with same number of elements. > // Opnds 0 and 2 have identical types. > // Opnds 1 and 3 have identical types. > // --> Opnd 3 (result 0?) is i1 vector > // Opnd 4 (result 1?) has pointer type. > // Opnd 1 is vector type with element type of i1. > def SDTMaskedGather: SDTypeProfile<2, 3, [ // masked gather > SDTCisVec<0>, SDTCisVec<1>, SDTCisSameAs<0, 2>, SDTCisSameAs<1, 3>, > SDTCisPtrTy<4>, SDTCVecEltisVT<1, i1>, SDTCisSameNumEltsAs<0, 1> > ]>; > > def masked_gather : SDNode<"ISD::MGATHER", SDTMaskedGather, > [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>; > > > Also, we need to make the operand $wsi a memory operand (otherwise we get the > difficult error: <<In LD_INDIRECT_D2: Type inference contradiction found, 'v128i16' needs > to be scalar>>), like in the following complete specification: > // Inspired heavily from lib/Target/X86/X86InstrInfo.td > class X86MemOperand<string printMethod> : Operand<iPTR> { > let PrintMethod = printMethod; > let MIOperandInfo = (ops i8imm, i32imm); > let OperandType = "OPERAND_MEMORY"; > } > // Gather mem operands > class X86VMemOperand<RegisterClass RC, string printMethod> > : X86MemOperand<printMethod> { > let MIOperandInfo = (ops i8imm, RC, i32imm); > } > def vx256xmem : X86VMemOperand<MSA128D, "printi256mem">; > > def vectoraddr : ComplexPattern<iPTR, 5, "selectVectorAddr", [],[SDNPWantParent]>; > > class LD_INDIRECT_DESC_BASE2<string instr_asm, > RegisterOperand ROWD, > RegisterOperand ROWSP = ROWD, > InstrItinClass itin = NoItinerary> { > dag OutOperandList = (outs ROWD:$wd, VK128Opnd:$wdm); > dag InOperandList = (ins ROWSP:$wsp, VK128Opnd:$wsm, vx256xmem:$wsi); > string AsmString = !strconcat("$wd = LS[$wsi]; // iread (or Mips MSA's LD) > strinstr_asm = ", > instr_asm); > list<dag> Pattern = [(set ROWD:$wd, VK128Opnd:$wdm, > (masked_gather > ROWSP:$wsp, VK128Opnd:$wsm, vectoraddr:$wsi))]; > > InstrItinClass Itinerary = itin; > string DecoderMethod = "DecodeMSA128Mem"; > } > class LD_INDIRECT_D_DESC2 : LD_INDIRECT_DESC_BASE2<"read", MSA128DOpnd>; > class LD_INDIRECT_D_ENC2 : MSA_3R_FMT<0b101001110>; > def LD_INDIRECT_D2: LD_INDIRECT_D_ENC2, LD_INDIRECT_D_DESC2; > > > > Unfortunately, now I have another problem: llc fails when trying to select my > masked_gather node. More exactly, it first tries to split it and then gives an error: > Split node operand: t13: v128i16,ch = masked_gather<LD256[<unknown>]> t0, t23, t40, > TargetConstant:i64<0>, t24 > Widen node result 0: t46: v64i16 = extract_subvector t23, Constant:i64<64> > Widen node result 0: t48: v64i16,ch = masked_gather<LD128[<unknown>](align=256)> t0, > t46, t44, TargetConstant:i64<0>, t26 > Split node result: t121: v128i64 = BUILD_VECTOR Constant:i64<0>, Constant:i64<0>, > Constant:i64<0>, Constant:i64<0>, Constant:i64<0>, Constant:i64<0>, Constant:i64<0>, > Constant:i64<0>, Constant:i64<0>, Constant:i64<0>, Constant:i64<0>, Constant:i64<0>, > Constant:i... > Split node result: t123: v64i64 = BUILD_VECTOR undef:i64, undef:i64, undef:i64, > undef:i64, undef:i64, undef:i64, undef:i64, undef:i64, undef:i64, undef:i64, undef:i64, > undef:i64, undef:i64, undef:i64, undef:i64, undef:i64, undef:i64, undef:i64, undef:i64, > undef:... > Split node result: t124: v32i64 = BUILD_VECTOR undef:i64, undef:i64, undef:i64, > undef:i64, undef:i64, undef:i64, undef:i64, undef:i64, undef:i64, undef:i64, undef:i64, > undef:i64, undef:i64, undef:i64, undef:i64, undef:i64, undef:i64, undef:i64, undef:i64, > undef:... > Split node result: t125: v16i64 = BUILD_VECTOR undef:i64, undef:i64, undef:i64, > undef:i64, undef:i64, undef:i64, undef:i64, undef:i64, undef:i64, undef:i64, undef:i64, > undef:i64, undef:i64, undef:i64, undef:i64, undef:i64... > Split node result: t126: v8i64 = BUILD_VECTOR undef:i64, undef:i64, undef:i64, > undef:i64, undef:i64, undef:i64, undef:i64, undef:i64... > Split node result: t127: v4i64 = BUILD_VECTOR undef:i64, undef:i64, undef:i64, > undef:i64... > Split node result: t128: v2i64 = BUILD_VECTOR undef:i64, undef:i64 > > Split node operand: t122: v128i16,ch = masked_gather<LD128[<unknown>](align=256)> t0, > t130, t193, TargetConstant:i64<0>, t121 > > llc: > /llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp:6804: > llvm::MemSDNode::MemSDNode(unsigned int, unsigned int, const llvm::DebugLoc&, > llvm::SDVTList, llvm::EVT, llvm::MachineMemOperand*): Assertion `memvt.getStoreSize() <> MMO->getSize() && "Size mismatch!"' failed. > > Does anybody know why this happens? I'd like to mention that I also gave in > [Target]ISelLowering.cpp a call to setOperationAction(ISD::MGATHER, aType, Legal), which > should have fixed this problem, but it doesn't. > > Best regards, > Alex > > > > On 12/11/2016 5:31 AM, Alex Susu wrote: >> Hello. >> Will, thanks a lot for pointing me to the MaskedGatherSDNode and mgatherv4i32. I have >> to say that the definition of the "multiclass avx512_gather" from >> lib/Target/X86/X86InstrAVX512.td is difficult to follow and I prefer not to use it. >> >> I currently have some serious problems with TableGen - it gives an assertion failure: >> "llvm/utils/TableGen/CodeGenDAGPatterns.cpp:2153: llvm::TreePatternNode* >> llvm::TreePattern::ParseTreePattern(llvm::Init*, llvm::StringRef): Assertion >> `New->getNumTypes() == 1 && "FIXME: Unhandled"' failed." >> >> Can somebody help me with the code below responsible for this error? >> >> // From llvm/lib/Target/X86/X86InstrFragmentsSIMD.td >> def mgatherv128i16 : PatFrag<(ops node:$src1, node:$src2, node:$src3), >> (masked_gather node:$src1, node:$src2, node:$src3) , [{ >> if (MaskedGatherSDNode *mgNode = dyn_cast<MaskedGatherSDNode>(N)) >> return (mgNode->getIndex().getValueType() == MVT::v128i16 || >> mgNode->getBasePtr().getValueType() == MVT::v128i16); >> return false; >> }]>; >> >> foreach RegId = 0-31 in >> def Mask#RegId : MipsReg<0, "Mask"#RegId>, DwarfRegNum<[!add(RegId, 10)]>; >> def VK128: RegisterClass<"Connex", [v128i1], 32, (sequence "Mask%u", 0, 31)>; >> def VK128Opnd : RegisterOperand<VK128> { >> let ParserMatchClass = MSA128AsmOperand; >> } >> >> class LD_INDIRECT_DESC_BASE2<string instr_asm, >> ValueType TyNode, >> RegisterOperand ROWD, >> RegisterOperand ROWSI = ROWD, >> RegisterOperand ROWSP = ROWD, // passthru register >> InstrItinClass itin = NoItinerary> { >> dag OutOperandList = (outs ROWD:$wd); >> dag InOperandList = (ins ROWSP:$wsp, VK128Opnd:$wsm, ROWSI:$wsptr, ROWSI:$wsi); >> string AsmString = "$wd = LS[R($wsi )];"; >> list<dag> Pattern = [(set ROWD:$wd, (TyNode (masked_gather ROWSP:$wsp, VK128Opnd >> :$wsm, ROWSI:$wsptr, ROWSI:$wsi)))]; >> InstrItinClass Itinerary = itin; >> string DecoderMethod = "DecodeMSA128Mem"; >> } >> class LD_INDIRECT_D_DESC2 : LD_INDIRECT_DESC_BASE2<"read", v128i16, MSA128DOpnd>; >> class LD_INDIRECT_D_ENC2 : MSA_2R_FMT<0b101001110>; >> def LD_INDIRECT_D2: LD_INDIRECT_D_ENC2, LD_INDIRECT_D_DESC2; >> >> /* >> // From http://llvm.org/docs/doxygen/html/SelectionDAGNodes_8h_source.html: >> 02115 // In the both nodes address is Op1, mask is Op2: >> 02116 // MaskedGatherSDNode (Chain, src0, mask, base, index), src0 is a >> passthru value >> 02117 // MaskedScatterSDNode (Chain, value, mask, base, index) >> 02118 // Mask is a vector of i1 elements >> 02119 const SDValue &getBasePtr() const { return getOperand(3); } >> 02120 const SDValue &getIndex() const { return getOperand(4); } >> 02121 const SDValue &getMask() const { return getOperand(2); } >> 02122 const SDValue &getValue() const { return getOperand(1); } // Alex: this >> is pass-thru >> >> */ >> >> >> Thank you very much, >> Alex >> >> On 12/9/2016 4:18 PM, Will Lovett wrote: >>> Hi Alex, >>> >>> I don’t know too much about recent MIPS, but have recently been doing something similar >>> for the new ARM SVE architecture, so hopefully this will get you closer to what you need: >>> >>> If you’re looking where I think you are (lib/Target/X86/X86InstrAVX512.td), ‘GatherNode’ >>> is a template argument, not a definition. >>> It allows a PatFrag be passed into the avx512_gather multiclass definition. >>> >>> Working backwards from here, the actual PatFrags passed into this are things like >>> ‘mgatherv4i32’. These are patterns that match a MaskedGatherSDNode for a particular data >>> type. >>> >>> MaskedGatherSDNode is the generic SD node that represents a predicated gather, which in >>> turn was generated from Intrinsic::masked_gather in the IR >>> (in SelectionDAGBuilder::visitMaskedGather) >>> >>> If your MIPS instruction has a predicate, you will need to create MIPS tablegen that >>> matches MaskedGatherSDNode. If not, I guess you’ll need to create a new intrinsic that >>> represents an unpredicted gather, and add appropriate uses of it during IR creation (such >>> as in LoopVectorize, where masked gathers are created today) >>> >>> Hope that helps, >>> >>> Will Lovett >>> >>> >>> On 9 December 2016 at 01:52:48, Alex Susu via llvm-dev (llvm-dev at lists.llvm.org >>> <mailto:llvm-dev at lists.llvm.org>) wrote: >>> >>>> Hello. >>>> I read on page 4 of http://www.cs.fsu.edu/~whalley/cda5155/chap4.pdf that gather and >>>> scatter operations exist for Mips, named LVI and SVI, respectively. >>>> >>>> Did anyone think of implementing in the LLVM Mips back end (part of the MSA vector >>>> instructions) gather and scatter operations? >>>> If so, can you share with me the TableGen spec? (I tried to start from LD_DESC_BASE, >>>> but it doesn't seem to be trivial. Also, LLVM seems to have implemented scatter/gather >>>> instructions only for the x86 processor - there, they defined new SDNodes called >>>> GatherNode and ScatterNode.) >>>> >>>> Thank you, >>>> Alex >>>> _______________________________________________ >>>> LLVM Developers mailing list >>>> llvm-dev at lists.llvm.org >>>> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
Seemingly Similar Threads
- TableGen - Help to implement a form of gather/scatter operations for Mips MSA
- TableGen - Help to implement a form of gather/scatter operations for Mips MSA
- TableGen - Help to implement a form of gather/scatter operations for Mips MSA
- TableGen - Help to implement a form of gather/scatter operations for Mips MSA
- Instruction selection confusion at register - chooses vector register instead of scalar one