summaryrefslogtreecommitdiff
path: root/bolt/lib/Passes/FixRISCVCallsPass.cpp
AgeCommit message (Collapse)Author
2024-03-31[BOLT][NFC] Clean includes, add license headers (#87200)Amir Ayupov
2024-02-12[BOLT][NFC] Return Error from BinaryFunctionPass::runOnFunctions (#81521)Amir Ayupov
As part of the effort to refactor old error handling code that would directly call exit(1), in this patch we change the interface to `BinaryFunctionPass` to return an Error on `runOnFunctions()`. This gives passes the ability to report a serious problem to the caller (RewriteInstance class), so the caller may decide how to best handle the exceptional situation. Co-authored-by: Rafael Auler <rafaelauler@fb.com> Test Plan: NFC
2023-10-05[BOLT][RISCV] Handle long tail calls (#67098)Job Noorman
Long tail calls use the following instruction sequence on RISC-V: ``` 1: auipc xi, %pcrel_hi(sym) jalr zero, %pcrel_lo(1b)(xi) ``` Since the second instruction in isolation looks like an indirect branch, this confused BOLT and most functions containing a long tail call got marked with "unknown control flow" and didn't get optimized as a consequence. This patch fixes this by detecting long tail call sequence in `analyzeIndirectBranch`. `FixRISCVCallsPass` also had to be updated to expand long tail calls to `PseudoTAIL` instead of `PseudoCALL`. Besides this, this patch also fixes a minor issue with compressed tail calls (`c.jr`) not being detected. Note that I had to change `BinaryFunction::postProcessIndirectBranches` slightly: the documentation of `MCPlusBuilder::analyzeIndirectBranch` mentions that the [`Begin`, `End`) range contains the instructions immediately preceding `Instruction`. However, in `postProcessIndirectBranches`, *all* the instructions in the BB where passed in the range. This made it difficult to find the preceding instruction so I made sure *only* the preceding instructions are passed.
2023-09-21[BOLT][RISCV] Carry-over annotations when fixing calls (#66763)Job Noorman
`FixRISCVCallsPass` changes all different forms of calls to `PseudoCALL` instructions. However, the original call's annotations were lost in the process. This patch fixes this by moving all annotations from the old to the new call. `MCPlusBuilder::moveAnnotations` had to be made public for this.
2023-09-15[BOLT][RISCV] Add support for linker relaxationJob Noorman
Calls on RISC-V are typically compiled to `auipc`/`jalr` pairs to allow a maximum target range (32-bit pc-relative). In order to optimize calls to near targets, linker relaxation may replace those pairs with, for example, single `jal` instructions. To allow BOLT to freely reassign function addresses in relaxed binaries, this patch proposes the following approach: - Expand all relaxed calls back to `auipc`/`jalr`; - Rely on JITLink to relax those back to shorter forms where possible. This is implemented by detecting all possible call instructions and replacing them with `PseudoCALL` (or `PseudoTAIL`) instructions. The RISC-V backend then expands those and adds the necessary relocations for relaxation. Since BOLT generally ignores pseudo instruction, this patch makes `MCPlusBuilder::isPseudo` virtual so that `RISCVMCPlusBuilder` can override it to exclude `PseudoCALL` and `PseudoTAIL`. To ensure JITLink knows about the correct section addresses while relaxing, reassignment of addresses has been moved to a post-allocation pass. Note that this is probably the time it had to be done in the first place since in `notifyResolved` (where it was done before), all symbols are supposed to be resolved already. Depends on D159082 Reviewed By: maksfb Differential Revision: https://reviews.llvm.org/D159089
2023-06-16[BOLT] Add minimal RISC-V 64-bit supportJob Noorman
Just enough features are implemented to process a simple "hello world" executable and produce something that still runs (including libc calls). This was mainly a matter of implementing support for various relocations. Currently, the following are handled: - R_RISCV_JAL - R_RISCV_CALL - R_RISCV_CALL_PLT - R_RISCV_BRANCH - R_RISCV_RVC_BRANCH - R_RISCV_RVC_JUMP - R_RISCV_GOT_HI20 - R_RISCV_PCREL_HI20 - R_RISCV_PCREL_LO12_I - R_RISCV_RELAX - R_RISCV_NONE Executables linked with linker relaxation will probably fail to be processed. BOLT relocates .text to a high address while leaving .plt at its original (low) address. This causes PC-relative PLT calls that were relaxed to a JAL to not fit their offset in an I-immediate anymore. This is something that will be addressed in a later patch. Changes to the BOLT core are relatively minor. Two things were tricky to implement and needed slightly larger changes. I'll explain those below. The R_RISCV_CALL(_PLT) relocation is put on the first instruction of a AUIPC/JALR pair, the second does not get any relocation (unlike other PCREL pairs). This causes issues with the combinations of the way BOLT processes binaries and the RISC-V MC-layer handles relocations: - BOLT reassembles instructions one by one and since the JALR doesn't have a relocation, it simply gets copied without modification; - Even though the MC-layer handles R_RISCV_CALL properly (adjusts both the AUIPC and the JALR), it assumes the immediates of both instructions are 0 (to be able to or-in a new value). This will most likely not be the case for the JALR that got copied over. To handle this difficulty without resorting to RISC-V-specific hacks in the BOLT core, a new binary pass was added that searches for AUIPC/JALR pairs and zeroes-out the immediate of the JALR. A second difficulty was supporting ABS symbols. As far as I can tell, ABS symbols were not handled at all, causing __global_pointer$ to break. RewriteInstance::analyzeRelocation was updated to handle these generically. Tests are provided for all supported relocations. Note that in order to test the correct handling of PLT entries, an ELF file produced by GCC had to be used. While I tried to strip the YAML representation, it's still quite large. Any suggestions on how to improve this would be appreciated. Reviewed By: rafauler Differential Revision: https://reviews.llvm.org/D145687