<html><head></head><body><div class="ydp9cb078a2yahoo-style-wrap" style="font-family:Helvetica Neue, Helvetica, Arial, sans-serif;font-size:13px;"><div></div>
<div dir="ltr" data-setdir="false">Hello,</div><div dir="ltr" data-setdir="false"><br></div><div dir="ltr" data-setdir="false">Thanks, this is very interesting! I've also found some comparable code in the ARC backend (ARCBranchFinalize.cpp). To summarize for other people who may face the same problem in the future:</div><div dir="ltr" data-setdir="false"><br></div><div dir="ltr" data-setdir="false">- On X86, there is an imm32 version of all the jump instructions. It is assumed to be okay, as a function will never be larger than 4 GB.<br></div><div dir="ltr" data-setdir="false">- On ARM, it seems that the branches are "large enough", as pointed out by Peter. Jumps to symbols more than 16 MB away from the current IP are considered rare enough to be okay to be solved with "trampolines" inserted by the linker (I've seen code in LLD doing that).</div><div dir="ltr" data-setdir="false">- ARC and MIPS have much more problematic jump instructions, as the farthest they can jump is only a few kilobytes away at most. Jumps that are too far for these instructions are therefore common, and these backends both implement a MachineFunctionPass that solves the problem using as few instructions as possible.</div><div dir="ltr" data-setdir="false"><br></div><div dir="ltr" data-setdir="false">The solutions used by ARC and MIPS look quite comparable:</div><div dir="ltr" data-setdir="false"><br></div><div dir="ltr" data-setdir="false">- ARC: Every function is "measured". If the size of a function is larger than the jump range, then all the jumps in the function that have a limited range are replaced with instructions that can jump farther (in the code, BRcc instructions are replaced with CMP + Bcc)</div><div dir="ltr" data-setdir="false">- MIPS: A bit smarter, but also much more complex: the distance of each jump is quite precisely measured, taking into account things like basic block alignment. Instructions that are found to jump too far are replaced, on a per-instruction basis, with instructions that jump farther.</div><div dir="ltr" data-setdir="false"><br></div><div dir="ltr" data-setdir="false">In my case, I'm temporarily solving my problem using a solution that is both super short (in code, about 20 lines in total) but also extremely inelegant:</div><div dir="ltr" data-setdir="false"><br></div><div dir="ltr" data-setdir="false">- I kept all my small JCC imm9 instructions until AsmBackend sees them</div><div dir="ltr" data-setdir="false">- I added a new instruction to TargetInstrInfo.td : IPREL+JCC. This single instruction, producing a single MCInst, is encoded using twice the number of bits as a normal instruction. It basically encodes a pair of instructions, one that adds an imm18 constant to IP, and one that jumps to an address put in a register (how I solve register allocation in this case is outside the scope of this email).</div><div dir="ltr" data-setdir="false">- My AsmBackend simply relaxes JCC instructions that jump our of range with IPREL+JCC.</div><div dir="ltr" data-setdir="false"><br></div><div dir="ltr" data-setdir="false">Looking at ARC, MIPS, and now my backend, I'm starting to wonder if an configurable "small jumps to larger jumps" MachineFunctionPass should not be added in the target-independent part of LLVM. ARC, for instance, would greatly benefit from having a version of the MIPS code implemented for it, as would my backend. I'll look into making that pass myself, but it seems quite complicated and I will probably be able to do it only in a few months. This project is therefore still open for someone else to do.<br></div><div dir="ltr" data-setdir="false"><br></div><div dir="ltr" data-setdir="false">Best regards, and thanks for all the suggestions!</div><div dir="ltr" data-setdir="false">Denis<br></div><div><br></div>
</div><div id="yahoo_quoted_4146418842" class="yahoo_quoted">
<div style="font-family:'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;color:#26282a;">
<div>
Le mercredi 1 juillet 2020 à 16:46:47 UTC+2, Hal Finkel <hfinkel@anl.gov> a écrit :
</div>
<div><br></div>
<div><br></div>
<div><div dir="ltr">Hi, Denis,<br clear="none"><br clear="none">You might also take a look at llvm/lib/Target/PowerPC/PPCBranchSelector.cpp<br clear="none"><br clear="none">It does things like change:<br clear="none"><br clear="none"> // short branch:<br clear="none"> // bCC MBB<br clear="none"><br clear="none">into:<br clear="none"><br clear="none"> // long branch:<br clear="none"> // b!CC $PC+8<br clear="none"> // b MBB<br clear="none"><br clear="none"> -Hal<br clear="none"><div class="yqt8464168537" id="yqtfd72499"><br clear="none">On 7/1/20 3:47 AM, Denis Steckelmacher via llvm-dev wrote:<br clear="none">> Hello,<br clear="none">><br clear="none">> I'm working on an LLVM backend for an experimental microprocessor. <br clear="none">> Work is going on nicely, and I've until now found the answer to all my <br clear="none">> questions directly in the LLVM source code, or in the documentation.<br clear="none">><br clear="none">> However, I'm having problems with the AsmBackend class and the <br clear="none">> handling of fixups.<br clear="none">><br clear="none">> The processor I'm working with has a single conditional branch <br clear="none">> instruction, JCC, that takes an IP-relative 9-bit immediate offset as <br clear="none">> operand. A second version of the instruction takes a register as <br clear="none">> operand and can therefore jump to any 32-bit address.<br clear="none">><br clear="none">> In AsmBackend, there are methods for relaxing instructions, that I <br clear="none">> wanted to use to replace "JCC imm9" instructions with a sequence of <br clear="none">> instructions that jumps further. However, I have two questions:<br clear="none">><br clear="none">> - relaxInstruction does not seem to be able to replace one instruction <br clear="none">> with a sequence of instructions<br clear="none">> - I've looked at many other LLVM backends (AVR, ARC, ARM, MIPS and <br clear="none">> RISC-V), and none of them really seem to do interesting things in <br clear="none">> relaxInstruction. ARM for instance relaxes Thumb instructions to <br clear="none">> normal instructions, and RISC-V relaxes compressed instructions to <br clear="none">> normal ones too. But in both cases, even the normal instructions have <br clear="none">> limited range, for which there is an assertion, but no "solution" for <br clear="none">> when a branch exceeds the range of the instruction.<br clear="none">><br clear="none">> It therefore seems that the problem of "conditional branches that jump <br clear="none">> too far" is solved elsewhere, but I could not find that location. I <br clear="none">> looked at LLD, and I've seen that RISC-V has some code there (related <br clear="none">> to the PLT) that produces sequences of instructions, but not the other <br clear="none">> targets.<br clear="none">><br clear="none">> So, what would be the best way to change "JCC imm9" instructions to <br clear="none">> something else when a branch has to jump further than 256 instructions <br clear="none">> before or after the current one?<br clear="none">><br clear="none">> Best regards,<br clear="none">> Denis Steckelmacher<br clear="none">> _______________________________________________<br clear="none">> LLVM Developers mailing list<br clear="none">> <a shape="rect" ymailto="mailto:llvm-dev@lists.llvm.org" href="mailto:llvm-dev@lists.llvm.org">llvm-dev@lists.llvm.org</a><br clear="none">> <a shape="rect" href="https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev</a></div><br clear="none"><br clear="none">-- <br clear="none">Hal Finkel<br clear="none">Lead, Compiler Technology and Programming Languages<br clear="none">Leadership Computing Facility<br clear="none">Argonne National Laboratory<div class="yqt8464168537" id="yqtfd32655"><br clear="none"><br clear="none"></div></div></div>
</div>
</div></body></html>