Xiangyang Guo via llvm-dev
2015-Oct-22 18:50 UTC
[llvm-dev] add intrinsic function support for customized backend
Hi, Gaël, Thanks for your detailed reply. I tried the pattern matching first, however, the intrinsic function is matching with a normal function call. For example, I have the following IR, which contains intrinsic function "foo": ***************************************************************************************** *define i32 @test_func() {* *EntryBlock:* * %0 = call i32 @llvm.foo.i32.i32(i32 2, i32 3)* * ret i32 %0* *}* *declare i32 @llvm.foo.i32.i32(i32, i32)* ******************************************************************************************* In InstroInfo.td, I define a pseudo instruction like this : ****************************************************************************************** *let isPseudo = 1 in {* * def FOO : MyPseudoInst<(outs GRRegs:$dst) , (ins GRRegs:$src1, GRRegs:$src2),* * "foo $dst, $src1, $src2",* * [(set i32:$dst, (int_foo i32:$src1, i32:$src2))]> {* * }* *} * ******************************************************************************************** I want to check the pattern matching first, so I have not implement the part of instruction lowering. Actually, I'm planing to make a source-to-source compiler, so the Pseudo instruction is enough for me. Then I use llc to dump the asm file. However, it gives me ******************************************************************************************* .... * invoke llvm.foo.i32.i32, v0, v1* * return v0* ******************************************************************************************* As you can see, it matchs with function call (the invoke instruction). Do you have any idea how I can fix this? Thanks a lot. Regards, Xiangyang 2015-10-22 11:51 GMT-04:00 Gaël Jobin via llvm-dev <llvm-dev at lists.llvm.org> :> Hi Xiangyang, > > When your intrinsic is passed to the back-end, it will be converted into > DAG nodes automatically (like for a function call). Then the back-end need > to know how to convert it into real instructions or at least how to manage > it through instruction selection pass. An intrinsic cannot exist inside the > backend (it is IR code) but can be converted into pseudo-instruction > instead (at least for the X86 backend). Then, there's many ways to handle > pseudo-instructions inside a backend. > > I will take the X86 backend as an example. > > First, your intrinsics: > > def int_foo : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], > [IntrReadArgMem]>; > > It will be converted into DAG nodes. Then, you can handle it manually > inside the code or using TableGen mechanism. For the latter, you should > define a pseudo-instruction that match your > intrinsic-translated-into-dag-node. The pseudo-instruction definition > should look like this: > > let isPseudo = 1 in { > def FOO : PseudoI<(outs i32mem:$dst), (ins i32mem:$src1, i32mem:$src2, ), > [(set i32mem:$dst, (int_foo i32mem:$src1, i32mem:$src2))]>; > } > > First, you should always set isPeudo to 1 if it is a pseudo-instruction. > Then, if it has some side effect, you should define them. For example, set > Defs = [EFLAGS] if it impacts EFLAGS value. > The tricky part is the pattern matching for dag nodes. I'm not sure it's > correct. I'm used to enable debug pass in Clang to have the resulted dag > node representation of my intrinsics and then create my pseudo-instruction > definition based on it. > > When your intrinsic is correctly translated into pseudo-instruction, you > can use it where you want. If you need to convert it into real > instructions, there's some common place to do it. > > You have the ExpandISelPseudos pass which is called at the beginning of > addMachinePasses. Its operation is relatively simple since it browses the > MachineInstr by looking for pseudo-instructions and then calls > TargetLowering::EmitInstrWithCustomeInserter for each of them. This last > method being abstract, it is implemented by each backend that wants it like > in X86TargetLowering for the x86 backend. Due to its location, this > solution offers the advantage that no optimization has already taken place. > Thus, the added machine code will be optimized in the same way than any > other options of the program. Moreover, you still have the virtual register > abstraction allowing you to be more flexibility in your implementation. > > You also have ExpandPostRA pass. This one commes right after register > allocation and the addition of the prolog-epilog. It calls > TargetInstrInfo::expandPostRAPseudo() giving a chance to the target to > extend the pseudo-instruction encountered. For the backend X86, the > TargetInstrInfo concrete implementation is in X86InstrInfo. As register > allocation and the majority of previous optimizations have already been > done, this solution ensures that the added code will not be altered > afterwards. > > Finally, it the two previous passes are not suitable for a particular > reason, other more generic ways exist. Simply create a new > MachineFunctionPass and call it when you need it. For example from: > - addPreRegAlloc > - addPostRegAlloc > - addPreSched2 > - addPreEmitPass > > I don't have a big LLVM background but thus are my findings when I was > playing with the middle-end/back-end some time ago. > > Regards, > Gaël > > > _______________________________________________ > LLVM Developers mailing list > llvm-dev at lists.llvm.org > http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev > >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20151022/9321a4bf/attachment.html>
Tim Northover via llvm-dev
2015-Oct-22 20:08 UTC
[llvm-dev] add intrinsic function support for customized backend
On 22 October 2015 at 11:50, Xiangyang Guo via llvm-dev <llvm-dev at lists.llvm.org> wrote:> [(set i32:$dst, (int_foo i32:$src1, i32:$src2))]> {What's your definition of int_foo? It should be coming from include/llvm/IR/IntrinsicsXYZ.td. If the expected name and types don't match up with that .td file LLVM tends to just assume you meant a real call. Also, make sure you've included IntrinsicsXYZ.td in Intrinsics.td. Tim.
Xiangyang Guo via llvm-dev
2015-Oct-22 20:14 UTC
[llvm-dev] add intrinsic function support for customized backend
I just put the definition of int_foo in file include/llvm/IR/Intrinsics.td like this "def int_foo : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrReadArgMem]>;", is that a problem? Is a separate file IntrinsicsMyTarget.td necessary in this case? Thanks 2015-10-22 16:08 GMT-04:00 Tim Northover <t.p.northover at gmail.com>:> On 22 October 2015 at 11:50, Xiangyang Guo via llvm-dev > <llvm-dev at lists.llvm.org> wrote: > > [(set i32:$dst, (int_foo i32:$src1, i32:$src2))]> { > > What's your definition of int_foo? It should be coming from > include/llvm/IR/IntrinsicsXYZ.td. If the expected name and types don't > match up with that .td file LLVM tends to just assume you meant a real > call. > > Also, make sure you've included IntrinsicsXYZ.td in Intrinsics.td. > > Tim. >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20151022/7fee43ab/attachment.html>