Xiangyang Guo via llvm-dev
2015-Oct-22 14:52 UTC
[llvm-dev] add intrinsic function support for customized backend
Hi, All, I want to add one intrinsic function for my particular backend. Let's say the intrinsic function is named "foo" which takes two i32 inputs and has one i32 output. First, I add this line "def int_foo : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrReadArgMem]>;" in /include/llvm/IR/Intrinsics.td. Then, in my target/InstrInfo.td, I'm supposed to add one pattern to match this intrinsic function. However, I don't understand how LLVM can tell the difference between this intrinsic function call and other normal function calls. From the IR, I can see both intrinsic functions and other normal functions use 'call'. So my question is how to add intrinsic function support for customized backend? Any hint/suggestion is appreciable. Regards, Xiangyang -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20151022/40a3e934/attachment.html>
Gaël Jobin via llvm-dev
2015-Oct-22 15:51 UTC
[llvm-dev] add intrinsic function support for customized backend
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 -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20151022/35891ede/attachment.html>
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>