[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
Sun Dec 11 18:18:53 PST 2016
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
More information about the llvm-dev
mailing list