Phil Tomson via llvm-dev
2016-May-04 00:20 UTC
[llvm-dev] Conditional tablegen expressions with math ops?
In our generated asm code we've got a constraint such that two registers in a ternary op have to be in different "banks", best illustrated with an example: add r1,r2,r1 # r1 <- r2 + r1 The problem here is that the first operand (the receiver of the value) is in the same "bank" as the 3rd operand (r1 again). This will cause an extra cycle to be burned. As it turns out the first and second operands can be in the same bank, so the issue is with the first and third operand being in the same bank. This example is easily "fixed" (the performance is optimized) by swapping the 2nd and 3rd operands: add r1, r1, r2 # r1 <- r1 + r2 There are four banks and the formula to figure out which bank a register is in is just: r%4 Which brings me to tablegen: We've got this in our specialized ArchInstrInfo.td: // r1 = r2 op r3 // class ArithOp_RR< bits<7> op, string instr_asm, SDNode opNode, OperandInfo info, InstrItinClass itin > : FR3< op, (outs info.regClass:$r1), (ins info.regClass:$r2, info.regClass:$r3), instr_asm # "\t\t$r1, $r2, $r3, " # info.sizeStr, [(set info.regClass:$r1, (opNode info.regClass:$r2, info.regClass:$r3))], itin > { let isFloat = info.isFloat; let opsize = info.sizeCode; } Is there a way to do something like: // r1 = r2 op r3 // class ArithOp_RR< bits<7> op, string instr_asm, SDNode opNode, OperandInfo info, InstrItinClass itin > : FR3< op, (outs info.regClass:$r1), (ins info.regClass:$r2, info.regClass:$r3), if( $r1%4 == $r3%4 ) { instr_asm # "\t\t$r1, $r3, $r2, " # info.sizeStr, [(set info.regClass:$r1, (opNode info.regClass:$r3, info.regClass:$r2))], } else { instr_asm # "\t\t$r1, $r2, $r3, " # info.sizeStr, [(set info.regClass:$r1, (opNode info.regClass:$r2, info.regClass:$r3))], } itin > { let isFloat = info.isFloat; let opsize = info.sizeCode; } Is that even remotely possible? If not, are there other ways to achieve this sort of thing? Would I be better off doing it in the ArchASMPrinter.cpp (I would think this could be problematic)? Or is there somewhere "further up" which would be more appropriate? Phil -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20160503/fd1b1280/attachment.html>
Matthias Braun via llvm-dev
2016-May-04 01:32 UTC
[llvm-dev] Conditional tablegen expressions with math ops?
As there are no physical registers allocated at instruction selection time. This sounds something you should rather do in a custom target pass running after register allocation. Or you could indeed fix it up at ASMPrinter time (though a custom pass would be more typical I think). - Matthias> On May 3, 2016, at 5:20 PM, Phil Tomson via llvm-dev <llvm-dev at lists.llvm.org> wrote: > > In our generated asm code we've got a constraint such that two registers in a ternary op have to be in different "banks", best illustrated with an example: > > add r1,r2,r1 # r1 <- r2 + r1 > > The problem here is that the first operand (the receiver of the value) is in the same "bank" as the 3rd operand (r1 again). This will cause an extra cycle to be burned. As it turns out the first and second operands can be in the same bank, so the issue is with the first and third operand being in the same bank. > > This example is easily "fixed" (the performance is optimized) by swapping the 2nd and 3rd operands: > > add r1, r1, r2 # r1 <- r1 + r2 > > > There are four banks and the formula to figure out which bank a register is in is just: r%4 > > Which brings me to tablegen: > > We've got this in our specialized ArchInstrInfo.td: > > // r1 = r2 op r3 > // > class ArithOp_RR< bits<7> op, > string instr_asm, > SDNode opNode, > OperandInfo info, > InstrItinClass itin > > : FR3< op, > (outs info.regClass:$r1), > (ins info.regClass:$r2, info.regClass:$r3), > instr_asm # "\t\t$r1, $r2, $r3, " # info.sizeStr, > [(set info.regClass:$r1, (opNode info.regClass:$r2, info.regClass:$r3))], > itin > { > let isFloat = info.isFloat; > let opsize = info.sizeCode; > } > > Is there a way to do something like: > > > // r1 = r2 op r3 > // > class ArithOp_RR< bits<7> op, > string instr_asm, > SDNode opNode, > OperandInfo info, > InstrItinClass itin > > : FR3< op, > (outs info.regClass:$r1), > (ins info.regClass:$r2, info.regClass:$r3), > if( $r1%4 == $r3%4 ) { > instr_asm # "\t\t$r1, $r3, $r2, " # info.sizeStr, > [(set info.regClass:$r1, (opNode info.regClass:$r3, info.regClass:$r2))], > } else { > instr_asm # "\t\t$r1, $r2, $r3, " # info.sizeStr, > [(set info.regClass:$r1, (opNode info.regClass:$r2, info.regClass:$r3))], > } > itin > { > let isFloat = info.isFloat; > let opsize = info.sizeCode; > } > > > Is that even remotely possible? If not, are there other ways to achieve this sort of thing? Would I be better off doing it in the ArchASMPrinter.cpp (I would think this could be problematic)? Or is there somewhere "further up" which would be more appropriate? > > Phil > _______________________________________________ > LLVM Developers mailing list > llvm-dev at lists.llvm.org > http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
Marcello Maggioni via llvm-dev
2016-May-04 01:39 UTC
[llvm-dev] Conditional tablegen expressions with math ops?
You can also give hints to the register allocator to not allocate the registers in a way that would create bank conflicts. I suggest looking for getRegAllocationHits() in the targets ***RegisterInfo.cpp file for examples. Marcello> On 3 May 2016, at 18:32, Matthias Braun via llvm-dev <llvm-dev at lists.llvm.org> wrote: > > As there are no physical registers allocated at instruction selection time. This sounds something you should rather do in a custom target pass running after register allocation. Or you could indeed fix it up at ASMPrinter time (though a custom pass would be more typical I think). > > - Matthias > >> On May 3, 2016, at 5:20 PM, Phil Tomson via llvm-dev <llvm-dev at lists.llvm.org> wrote: >> >> In our generated asm code we've got a constraint such that two registers in a ternary op have to be in different "banks", best illustrated with an example: >> >> add r1,r2,r1 # r1 <- r2 + r1 >> >> The problem here is that the first operand (the receiver of the value) is in the same "bank" as the 3rd operand (r1 again). This will cause an extra cycle to be burned. As it turns out the first and second operands can be in the same bank, so the issue is with the first and third operand being in the same bank. >> >> This example is easily "fixed" (the performance is optimized) by swapping the 2nd and 3rd operands: >> >> add r1, r1, r2 # r1 <- r1 + r2 >> >> >> There are four banks and the formula to figure out which bank a register is in is just: r%4 >> >> Which brings me to tablegen: >> >> We've got this in our specialized ArchInstrInfo.td: >> >> // r1 = r2 op r3 >> // >> class ArithOp_RR< bits<7> op, >> string instr_asm, >> SDNode opNode, >> OperandInfo info, >> InstrItinClass itin > >> : FR3< op, >> (outs info.regClass:$r1), >> (ins info.regClass:$r2, info.regClass:$r3), >> instr_asm # "\t\t$r1, $r2, $r3, " # info.sizeStr, >> [(set info.regClass:$r1, (opNode info.regClass:$r2, info.regClass:$r3))], >> itin > { >> let isFloat = info.isFloat; >> let opsize = info.sizeCode; >> } >> >> Is there a way to do something like: >> >> >> // r1 = r2 op r3 >> // >> class ArithOp_RR< bits<7> op, >> string instr_asm, >> SDNode opNode, >> OperandInfo info, >> InstrItinClass itin > >> : FR3< op, >> (outs info.regClass:$r1), >> (ins info.regClass:$r2, info.regClass:$r3), >> if( $r1%4 == $r3%4 ) { >> instr_asm # "\t\t$r1, $r3, $r2, " # info.sizeStr, >> [(set info.regClass:$r1, (opNode info.regClass:$r3, info.regClass:$r2))], >> } else { >> instr_asm # "\t\t$r1, $r2, $r3, " # info.sizeStr, >> [(set info.regClass:$r1, (opNode info.regClass:$r2, info.regClass:$r3))], >> } >> itin > { >> let isFloat = info.isFloat; >> let opsize = info.sizeCode; >> } >> >> >> Is that even remotely possible? If not, are there other ways to achieve this sort of thing? Would I be better off doing it in the ArchASMPrinter.cpp (I would think this could be problematic)? Or is there somewhere "further up" which would be more appropriate? >> >> Phil >> _______________________________________________ >> LLVM Developers mailing list >> llvm-dev at lists.llvm.org >> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev > > _______________________________________________ > LLVM Developers mailing list > llvm-dev at lists.llvm.org > http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
Phil Tomson via llvm-dev
2016-May-05 18:15 UTC
[llvm-dev] Conditional tablegen expressions with math ops?
On Tue, May 3, 2016 at 6:32 PM, Matthias Braun <mbraun at apple.com> wrote:> As there are no physical registers allocated at instruction selection > time. This sounds something you should rather do in a custom target pass > running after register allocation.Would such a pass be added in addMachineLateOptimization()?> Or you could indeed fix it up at ASMPrinter time (though a custom pass > would be more typical I think). > > - Matthias > > > On May 3, 2016, at 5:20 PM, Phil Tomson via llvm-dev < > llvm-dev at lists.llvm.org> wrote: > > > > In our generated asm code we've got a constraint such that two registers > in a ternary op have to be in different "banks", best illustrated with an > example: > > > > add r1,r2,r1 # r1 <- r2 + r1 > > > > The problem here is that the first operand (the receiver of the value) > is in the same "bank" as the 3rd operand (r1 again). This will cause an > extra cycle to be burned. As it turns out the first and second operands can > be in the same bank, so the issue is with the first and third operand being > in the same bank. > > > > This example is easily "fixed" (the performance is optimized) by > swapping the 2nd and 3rd operands: > > > > add r1, r1, r2 # r1 <- r1 + r2 > > > > > > There are four banks and the formula to figure out which bank a register > is in is just: r%4 > > > > Which brings me to tablegen: > > > > We've got this in our specialized ArchInstrInfo.td: > > > > // r1 = r2 op r3 > > // > > class ArithOp_RR< bits<7> op, > > string instr_asm, > > SDNode opNode, > > OperandInfo info, > > InstrItinClass itin > > > : FR3< op, > > (outs info.regClass:$r1), > > (ins info.regClass:$r2, info.regClass:$r3), > > instr_asm # "\t\t$r1, $r2, $r3, " # info.sizeStr, > > [(set info.regClass:$r1, (opNode info.regClass:$r2, > info.regClass:$r3))], > > itin > { > > let isFloat = info.isFloat; > > let opsize = info.sizeCode; > > } > > > > Is there a way to do something like: > > > > > > // r1 = r2 op r3 > > // > > class ArithOp_RR< bits<7> op, > > string instr_asm, > > SDNode opNode, > > OperandInfo info, > > InstrItinClass itin > > > : FR3< op, > > (outs info.regClass:$r1), > > (ins info.regClass:$r2, info.regClass:$r3), > > if( $r1%4 == $r3%4 ) { > > instr_asm # "\t\t$r1, $r3, $r2, " # info.sizeStr, > > [(set info.regClass:$r1, (opNode info.regClass:$r3, > info.regClass:$r2))], > > } else { > > instr_asm # "\t\t$r1, $r2, $r3, " # info.sizeStr, > > [(set info.regClass:$r1, (opNode info.regClass:$r2, > info.regClass:$r3))], > > } > > itin > { > > let isFloat = info.isFloat; > > let opsize = info.sizeCode; > > } > > > > > > Is that even remotely possible? If not, are there other ways to achieve > this sort of thing? Would I be better off doing it in the > ArchASMPrinter.cpp (I would think this could be problematic)? Or is there > somewhere "further up" which would be more appropriate? > > > > Phil > > _______________________________________________ > > 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/20160505/873e017c/attachment.html>
Matt Arsenault via llvm-dev
2016-May-05 20:36 UTC
[llvm-dev] Conditional tablegen expressions with math ops?
On 05/03/2016 05:20 PM, Phil Tomson via llvm-dev wrote:> This example is easily "fixed" (the performance is optimized) by > swapping the 2nd and 3rd operands: > > add r1, r1, r2 # r1 <- r1 + r2 > > > There are four banks and the formula to figure out which bank a > register is in is just: r%4How are your instruction operands defined? Do you have a separate register class for each bank, and then a superset class for the operands in the instruction? With a post-isel hook or pass you could try constraining the register class of the virtual register operands, which may or may not result in a copy in the end. -Matt