//===----- RISCVMergeBaseOffset.cpp - Optimise address calculations ------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // Merge the offset of address calculation into the offset field // of instructions in a global address lowering sequence. // //===----------------------------------------------------------------------===// #include "RISCV.h" #include "RISCVTargetMachine.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/Passes.h" #include "llvm/MC/TargetRegistry.h" #include "llvm/Support/Debug.h" #include "llvm/Target/TargetOptions.h" #include <optional> usingnamespacellvm; #define DEBUG_TYPE … #define RISCV_MERGE_BASE_OFFSET_NAME … namespace { class RISCVMergeBaseOffsetOpt : public MachineFunctionPass { … }; } // end anonymous namespace char RISCVMergeBaseOffsetOpt::ID = …; INITIALIZE_PASS(…) // Detect either of the patterns: // // 1. (medlow pattern): // lui vreg1, %hi(s) // addi vreg2, vreg1, %lo(s) // // 2. (medany pattern): // .Lpcrel_hi1: // auipc vreg1, %pcrel_hi(s) // addi vreg2, vreg1, %pcrel_lo(.Lpcrel_hi1) // // The pattern is only accepted if: // 1) The first instruction has only one use, which is the ADDI. // 2) The address operands have the appropriate type, reflecting the // lowering of a global address or constant pool using medlow or medany. // 3) The offset value in the Global Address or Constant Pool is 0. bool RISCVMergeBaseOffsetOpt::detectFoldable(MachineInstr &Hi, MachineInstr *&Lo) { … } // Update the offset in Hi and Lo instructions. // Delete the tail instruction and update all the uses to use the // output from Lo. void RISCVMergeBaseOffsetOpt::foldOffset(MachineInstr &Hi, MachineInstr &Lo, MachineInstr &Tail, int64_t Offset) { … } // Detect patterns for large offsets that are passed into an ADD instruction. // If the pattern is found, updates the offset in Hi and Lo instructions // and deletes TailAdd and the instructions that produced the offset. // // Base address lowering is of the form: // Hi: lui vreg1, %hi(s) // Lo: addi vreg2, vreg1, %lo(s) // / \ // / \ // / \ // / The large offset can be of two forms: \ // 1) Offset that has non zero bits in lower 2) Offset that has non zero // 12 bits and upper 20 bits bits in upper 20 bits only // OffseLUI: lui vreg3, 4 // OffsetTail: addi voff, vreg3, 188 OffsetTail: lui voff, 128 // \ / // \ / // \ / // \ / // TailAdd: add vreg4, vreg2, voff bool RISCVMergeBaseOffsetOpt::foldLargeOffset(MachineInstr &Hi, MachineInstr &Lo, MachineInstr &TailAdd, Register GAReg) { … } // Detect patterns for offsets that are passed into a SHXADD instruction. // The offset has 1, 2, or 3 trailing zeros and fits in simm13, simm14, simm15. // The constant is created with addi voff, x0, C, and shXadd is used to // fill insert the trailing zeros and do the addition. // If the pattern is found, updates the offset in Hi and Lo instructions // and deletes TailShXAdd and the instructions that produced the offset. // // Hi: lui vreg1, %hi(s) // Lo: addi vreg2, vreg1, %lo(s) // OffsetTail: addi voff, x0, C // TailAdd: shXadd vreg4, voff, vreg2 bool RISCVMergeBaseOffsetOpt::foldShiftedOffset(MachineInstr &Hi, MachineInstr &Lo, MachineInstr &TailShXAdd, Register GAReg) { … } bool RISCVMergeBaseOffsetOpt::detectAndFoldOffset(MachineInstr &Hi, MachineInstr &Lo) { … } bool RISCVMergeBaseOffsetOpt::foldIntoMemoryOps(MachineInstr &Hi, MachineInstr &Lo) { … } bool RISCVMergeBaseOffsetOpt::runOnMachineFunction(MachineFunction &Fn) { … } /// Returns an instance of the Merge Base Offset Optimization pass. FunctionPass *llvm::createRISCVMergeBaseOffsetOptPass() { … }