Hi guys,
In X86ISelLowering.cpp
I saw”
…
case Intrinsic::x86_rdrand_16:
case Intrinsic::x86_rdrand_32:
….
case Intrinsic::x86_avx512_gather_qpd_512:
case Intrinsic::x86_avx512_gather_qps_512:
…
“
those intrinsics are handled by “LowerINTRINSIC_W_CHAIN”.
How the “INTRINSIC_W_CHAIN” opCode is set instead of “INTRINSIC_WO_CHAIN”?
tks
Kevin
Hello
Chain operand is needed if the intrinsic is reading / writing memory.
Yeah.
I agree that "Chain operand is needed if the intrinsic is reading / writing memory.”,
Just don’t know where and how to set it up.
like intrinsic “int_x86_xtest:
“
def int_x86_xtest : GCCBuiltin<“__builtin_ia32_xtest”>,
Intrinsic<[llvm_i32_ty], , >;
“
"def X86xtest: SDNode<“X86ISD::XTEST”, SDTypeProfile<1, 0, [SDTCisVT<0, i32>]>,
[SDNPHasChain, SDNPSideEffect]>;
“
let Defs = [EFLAGS] in
def XTEST : I<0x01, MRM_D6, (outs), (ins),
“xtest”, [(set EFLAGS, (X86xtest))]>, TB, Requires<[HasTSX]>;
which CALL makes the “Intrinsic::x86_xtest” is caught under “INTRINSIC_W_CHAIN”? feel I missed something, but did not figure out.
tks
kevin
def int_x86_xtest : GCCBuiltin<"__builtin_ia32_xtest">,
Intrinsic<[llvm_i32_ty], , >;
which CALL makes the “Intrinsic::x86_xtest” is caught under
“INTRINSIC_W_CHAIN”? feel I missed something, but did not figure out.
It's this first definition that spawns the INTRINSIC_W_CHAIN. The rest
are x86-specific SDNodes, defined in X86ISelLowering.h and only ever
created from X86ISelLowering.cpp.
I assume (haven't checked) there's some special bit of
X86ISelLowering.cpp that takes an ISD::INTRINSIC_W_CHAIN node
referring to the int_x86_xtest intrinsic and turns it into an
X86ISD::XTEST node.
Specifically, for the W_CHAIN/WO_CHAIN distinction you want to be
looking at the "IntrNoMem" definition and uses in include/[1]. That
should be what determines which path an intrinsic goes down.
Cheers.
Tim.
[1] If you're interested, the code most directly responsible for
choosing between them is in visitTargetIntrinsic in
lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp. It's helped by
TableGen and other components, of course.
Thanks Tim,
Yeah!, you are right!
Also, looks we have to set up a pattern to use the intrinsic node too.
I did something like this:
def int_my_test : Intrinsic
<llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty],
[IntrReadWriteArgMem],
;
and used it directly with the test call “call @my.test( %r0, *%p1).”
It compiles fine. and “int_my_test" intrinsic is caught under INTRINSIC_WO_CHAIN.
Because anyway I have to handle this intrinsic by lowering, I did not think a pattern is necessary.
Just left a there, looks we have to put something there even it is not really needed.
but then the argument is: is it really necessary to put a pattern for it?
For my case, because I need to access memory, I think a chain is necessary. but what type of pattern is meaningful?
for example
intrinsic “ float llvm.my.sincos( float src, *float res)”,
sin result is returned, and cos result is write back to the second pointer argument.
tks
kevin
Never mind.
Looks my bad is: I did not put the “right” type/format in the instruction.
Tim is RIGHT!
tks
kevin