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