[llvm-dev] TableGen - Help to implement a form of gather/scatter operations for Mips MSA

Alex Susu via llvm-dev llvm-dev at lists.llvm.org
Wed May 24 18:08:04 PDT 2017


   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


More information about the llvm-dev mailing list