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
Alex Susu via llvm-dev
2016-Dec-24 22:44 UTC
[llvm-dev] TableGen - Help to implement a form of gather/scatter operations for Mips MSA
Hello. I managed to fix the bug reported earlier here. An important reason it failed is that vectoraddr took 5 arguments instead of just 1 (meaning the C++ helper method selectVectorAddr() took 5 reference parameters which are used as return values), and I was not setting these arguments to proper values before returning from the function. (Note also, that, although, in this email I don't talk about masked_scatter, we need to give in the constructor of TargetLowering to avoid errors: setOperationAction(ISD::MSCATTER, aType, Legal); ). Now, the correct TableGen spec for gather is: /* Because of the SDNPMemOperand attribute of masked_gather it seems we need to make the index operator a memory operand. It also seems we need to make it a scalar operand by using iPTR and use a C++ method that returns a vector type. */ // Gather mem operands def ScatterGatherMemOperand : Operand<iPTR> { let PrintMethod = "printScatterGatherMemOperand"; let MIOperandInfo = (ops MSA128D); } /* 1 means selectVectorAddr() takes 1 extra argument, in this case reference int Index which we set with N->getIndex(). Otherwise, the 3rd parameter of masked_gather would receive the base pointer IIRC. */ def vectoraddr : ComplexPattern<iPTR, 1, "selectVectorAddr", [], [SDNPWantParent]>; // Inspired from [REPO]/llvm/lib/Target/X86/X86InstrAVX512.td class LD_INDIRECT_DESC_BASE< RegisterOperand ROWD, RegisterOperand ROWSP = ROWD, InstrItinClass itin = NoItinerary> { dag OutOperandList = (outs ROWD:$wd, BoolMaskOpnd:$wdm); dag InOperandList = (ins ROWSP:$wsp, // passthru register BoolMaskOpnd:$wsm, // mask register ScatterGatherMemOperand:$wsi // index register ); string AsmString = "$wd = LS[$wsi]; // READ (gather)"; list<dag> Pattern = [(set ROWD:$wd, BoolMaskOpnd:$wdm, (masked_gather ROWSP:$wsp, BoolMaskOpnd:$wsm, vectoraddr:$wsi) )]; InstrItinClass Itinerary = itin; string DecoderMethod = "DecodeMSA128Mem"; } class LD_INDIRECT_D_DESC : LD_INDIRECT_DESC_BASE<MSA128DOpnd>; class LD_INDIRECT_D_ENC : MSA_3R_FMT<0b101001110>; def LD_INDIRECT_D: LD_INDIRECT_D_ENC, LD_INDIRECT_D_DESC; Note that at selection time, the ConnexDAGToDAGISel::selectVectorAddr() method is called. This method is responsible for taking both vector address (by calling getIndex()) and base-pointer (by calling getBasePtr()) parameters of the machine-independent SDNode and assembling them in one iPTR parameter, as required by the machine instruction ISD::MGATHER. Note that the parameters differ quite a bit between the machine-independent masked_gather and the machine instruction ISD::MGATHER, whose parameters are specified by the SDTMaskedGather TableGen record. Note that we need to pass a vector of pointers obtained with the LLVM IR instruction getelementptr to the gather instr - see http://llvm.org/docs/LangRef.html#llvm-masked-gather-intrinsics for list of arguments, etc. An example of LLVM IR program that llc is able to compile is: %myOnes = add <128 x i16> zeroinitializer, <i16 1,...> %B = inttoptr i16 51 to i16* %VectorGep = getelementptr i16, i16* %B, <128 x i16> %myOnes %gatherResMyOnes = call <128 x i16> @llvm.masked.gather.v128i16(<128 x i16*> %VectorGep, i32 4, <128 x i1> <i1 true,...> ... Wish you Merry Xmas! Alex On 12/15/2016 6:09 PM, Alex Susu wrote:> 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
Alex Susu via llvm-dev
2017-May-25 01:08 UTC
[llvm-dev] TableGen - Help to implement a form of gather/scatter operations for Mips MSA
Hello. I come back to this older thread about specifying (automatic or manual) instruction selection for gather/scatter operations. I have in my ISA a gather (and scatter) instruction that doesn't have mask and passthru. I would like to avoid using them, but LLVM's machine instruction masked_gather takes all these parameters - see https://llvm.org/svn/llvm-project/llvm/trunk/include/llvm/Target/TargetSelectionDAG.td, around "def masked_gather" (and also the email from this thread from date 12/15/2016 and the LLVM IR instruction equivalent http://llvm.org/docs/LangRef.html#llvm-masked-gather-intrinsics). This forces the instruction-selection to generate unnecessary instructions (and lated allocate unnecessary registers) for the passthru operand (the mask seems to be discarded by my back end by default). I am therefore planning to discard the previous solution with TableGen description (see below) and perform manual/custom Instruction selection to avoid selecting the passthru (maybe also the mask) operand. Can you recommend a (better) way to do this in TableGen? I tried to avoid the selection of the passthru operand in my TableGen description below, but I always got an error. Thank you very much, Alex On 12/25/2016 12:44 AM, Alex Susu wrote:> Hello. > I managed to fix the bug reported earlier here. > An important reason it failed is that vectoraddr took 5 arguments instead of just 1 > (meaning the C++ helper method selectVectorAddr() took 5 reference parameters which are > used as return values), and I was not setting these arguments to proper values before > returning from the function. (Note also, that, although, in this email I don't talk about > masked_scatter, we need to give in the constructor of TargetLowering to avoid errors: > setOperationAction(ISD::MSCATTER, aType, Legal); ). > > Now, the correct TableGen spec for gather is: > /* Because of the SDNPMemOperand attribute of masked_gather it seems > we need to make the index operator a memory operand. > It also seems we need to make it a scalar operand by using iPTR and use a C++ > method that returns a vector type. */ > // Gather mem operands > def ScatterGatherMemOperand : Operand<iPTR> { > let PrintMethod = "printScatterGatherMemOperand"; > let MIOperandInfo = (ops MSA128D); > } > > /* 1 means selectVectorAddr() takes 1 extra argument, in this case reference > int Index which we set with N->getIndex(). Otherwise, the 3rd parameter of > masked_gather would receive the base pointer IIRC. */ > def vectoraddr : ComplexPattern<iPTR, 1, "selectVectorAddr", [], [SDNPWantParent]>; > > // Inspired from [REPO]/llvm/lib/Target/X86/X86InstrAVX512.td > class LD_INDIRECT_DESC_BASE< > RegisterOperand ROWD, > RegisterOperand ROWSP = ROWD, > InstrItinClass itin = NoItinerary> { > dag OutOperandList = (outs ROWD:$wd, BoolMaskOpnd:$wdm); > dag InOperandList = (ins ROWSP:$wsp, // passthru register > BoolMaskOpnd:$wsm, // mask register > ScatterGatherMemOperand:$wsi // index register > ); > string AsmString = "$wd = LS[$wsi]; // READ (gather)"; > list<dag> Pattern = [(set ROWD:$wd, BoolMaskOpnd:$wdm, > (masked_gather > ROWSP:$wsp, BoolMaskOpnd:$wsm, vectoraddr:$wsi) > )]; > InstrItinClass Itinerary = itin; > string DecoderMethod = "DecodeMSA128Mem"; > } > class LD_INDIRECT_D_DESC : LD_INDIRECT_DESC_BASE<MSA128DOpnd>; > class LD_INDIRECT_D_ENC : MSA_3R_FMT<0b101001110>; > def LD_INDIRECT_D: LD_INDIRECT_D_ENC, LD_INDIRECT_D_DESC; > > > Note that at selection time, the ConnexDAGToDAGISel::selectVectorAddr() method is > called. This method is responsible for taking both vector address (by calling getIndex()) > and base-pointer (by calling getBasePtr()) parameters of the machine-independent SDNode > and assembling them in one iPTR parameter, as required by the machine instruction > ISD::MGATHER. Note that the parameters differ quite a bit between the machine-independent > masked_gather and the machine instruction ISD::MGATHER, whose parameters are specified by > the SDTMaskedGather TableGen record. > > Note that we need to pass a vector of pointers obtained with the LLVM IR instruction > getelementptr to the gather instr - see > http://llvm.org/docs/LangRef.html#llvm-masked-gather-intrinsics for list of arguments, etc. > An example of LLVM IR program that llc is able to compile is: > %myOnes = add <128 x i16> zeroinitializer, <i16 1,...> > %B = inttoptr i16 51 to i16* > %VectorGep = getelementptr i16, i16* %B, <128 x i16> %myOnes > %gatherResMyOnes = call <128 x i16> @llvm.masked.gather.v128i16(<128 x i16*> > %VectorGep, i32 4, <128 x i1> <i1 true,...> > ... > > Wish you Merry Xmas! > Alex > > > > On 12/15/2016 6:09 PM, Alex Susu wrote: >> 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