10b57cec5SDimitry Andric //=== HexagonSplitConst32AndConst64.cpp - split CONST32/Const64 into HI/LO ===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // When the compiler is invoked with no small data, for instance, with the -G0
100b57cec5SDimitry Andric // command line option, then all CONST* opcodes should be broken down into
110b57cec5SDimitry Andric // appropriate LO and HI instructions. This splitting is done by this pass.
120b57cec5SDimitry Andric // The only reason this is not done in the DAG lowering itself is that there
130b57cec5SDimitry Andric // is no simple way of getting the register allocator to allot the same hard
140b57cec5SDimitry Andric // register to the result of LO and HI instructions. This pass is always
150b57cec5SDimitry Andric // scheduled after register allocation.
160b57cec5SDimitry Andric //
170b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
180b57cec5SDimitry Andric 
190b57cec5SDimitry Andric #include "HexagonSubtarget.h"
200b57cec5SDimitry Andric #include "HexagonTargetMachine.h"
210b57cec5SDimitry Andric #include "HexagonTargetObjectFile.h"
220b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
230b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
240b57cec5SDimitry Andric #include "llvm/CodeGen/Passes.h"
250b57cec5SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h"
260b57cec5SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h"
270b57cec5SDimitry Andric 
280b57cec5SDimitry Andric using namespace llvm;
290b57cec5SDimitry Andric 
300b57cec5SDimitry Andric #define DEBUG_TYPE "xfer"
310b57cec5SDimitry Andric 
320b57cec5SDimitry Andric namespace llvm {
330b57cec5SDimitry Andric   FunctionPass *createHexagonSplitConst32AndConst64();
340b57cec5SDimitry Andric   void initializeHexagonSplitConst32AndConst64Pass(PassRegistry&);
350b57cec5SDimitry Andric }
360b57cec5SDimitry Andric 
370b57cec5SDimitry Andric namespace {
380b57cec5SDimitry Andric   class HexagonSplitConst32AndConst64 : public MachineFunctionPass {
390b57cec5SDimitry Andric   public:
400b57cec5SDimitry Andric     static char ID;
HexagonSplitConst32AndConst64()410b57cec5SDimitry Andric     HexagonSplitConst32AndConst64() : MachineFunctionPass(ID) {
420b57cec5SDimitry Andric       PassRegistry &R = *PassRegistry::getPassRegistry();
430b57cec5SDimitry Andric       initializeHexagonSplitConst32AndConst64Pass(R);
440b57cec5SDimitry Andric     }
getPassName() const450b57cec5SDimitry Andric     StringRef getPassName() const override {
460b57cec5SDimitry Andric       return "Hexagon Split Const32s and Const64s";
470b57cec5SDimitry Andric     }
480b57cec5SDimitry Andric     bool runOnMachineFunction(MachineFunction &Fn) override;
getRequiredProperties() const490b57cec5SDimitry Andric     MachineFunctionProperties getRequiredProperties() const override {
500b57cec5SDimitry Andric       return MachineFunctionProperties().set(
510b57cec5SDimitry Andric           MachineFunctionProperties::Property::NoVRegs);
520b57cec5SDimitry Andric     }
530b57cec5SDimitry Andric   };
540b57cec5SDimitry Andric }
550b57cec5SDimitry Andric 
560b57cec5SDimitry Andric char HexagonSplitConst32AndConst64::ID = 0;
570b57cec5SDimitry Andric 
580b57cec5SDimitry Andric INITIALIZE_PASS(HexagonSplitConst32AndConst64, "split-const-for-sdata",
590b57cec5SDimitry Andric       "Hexagon Split Const32s and Const64s", false, false)
600b57cec5SDimitry Andric 
runOnMachineFunction(MachineFunction & Fn)610b57cec5SDimitry Andric bool HexagonSplitConst32AndConst64::runOnMachineFunction(MachineFunction &Fn) {
620b57cec5SDimitry Andric   auto &HST = Fn.getSubtarget<HexagonSubtarget>();
630b57cec5SDimitry Andric   auto &HTM = static_cast<const HexagonTargetMachine&>(Fn.getTarget());
640b57cec5SDimitry Andric   auto &TLOF = *HTM.getObjFileLowering();
650b57cec5SDimitry Andric   if (HST.useSmallData() && TLOF.isSmallDataEnabled(HTM))
660b57cec5SDimitry Andric     return false;
670b57cec5SDimitry Andric 
680b57cec5SDimitry Andric   const TargetInstrInfo *TII = HST.getInstrInfo();
690b57cec5SDimitry Andric   const TargetRegisterInfo *TRI = HST.getRegisterInfo();
700b57cec5SDimitry Andric 
710b57cec5SDimitry Andric   // Loop over all of the basic blocks
720b57cec5SDimitry Andric   for (MachineBasicBlock &B : Fn) {
73349cc55cSDimitry Andric     for (MachineInstr &MI : llvm::make_early_inc_range(B)) {
740b57cec5SDimitry Andric       unsigned Opc = MI.getOpcode();
750b57cec5SDimitry Andric 
760b57cec5SDimitry Andric       if (Opc == Hexagon::CONST32) {
778bcb0991SDimitry Andric         Register DestReg = MI.getOperand(0).getReg();
780b57cec5SDimitry Andric         uint64_t ImmValue = MI.getOperand(1).getImm();
790b57cec5SDimitry Andric         const DebugLoc &DL = MI.getDebugLoc();
800b57cec5SDimitry Andric         BuildMI(B, MI, DL, TII->get(Hexagon::A2_tfrsi), DestReg)
810b57cec5SDimitry Andric             .addImm(ImmValue);
820b57cec5SDimitry Andric         B.erase(&MI);
830b57cec5SDimitry Andric       } else if (Opc == Hexagon::CONST64) {
848bcb0991SDimitry Andric         Register DestReg = MI.getOperand(0).getReg();
850b57cec5SDimitry Andric         int64_t ImmValue = MI.getOperand(1).getImm();
860b57cec5SDimitry Andric         const DebugLoc &DL = MI.getDebugLoc();
878bcb0991SDimitry Andric         Register DestLo = TRI->getSubReg(DestReg, Hexagon::isub_lo);
888bcb0991SDimitry Andric         Register DestHi = TRI->getSubReg(DestReg, Hexagon::isub_hi);
890b57cec5SDimitry Andric 
900b57cec5SDimitry Andric         int32_t LowWord = (ImmValue & 0xFFFFFFFF);
910b57cec5SDimitry Andric         int32_t HighWord = (ImmValue >> 32) & 0xFFFFFFFF;
920b57cec5SDimitry Andric 
930b57cec5SDimitry Andric         BuildMI(B, MI, DL, TII->get(Hexagon::A2_tfrsi), DestLo)
940b57cec5SDimitry Andric             .addImm(LowWord);
950b57cec5SDimitry Andric         BuildMI(B, MI, DL, TII->get(Hexagon::A2_tfrsi), DestHi)
960b57cec5SDimitry Andric             .addImm(HighWord);
970b57cec5SDimitry Andric         B.erase(&MI);
980b57cec5SDimitry Andric       }
990b57cec5SDimitry Andric     }
1000b57cec5SDimitry Andric   }
1010b57cec5SDimitry Andric 
1020b57cec5SDimitry Andric   return true;
1030b57cec5SDimitry Andric }
1040b57cec5SDimitry Andric 
1050b57cec5SDimitry Andric 
1060b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
1070b57cec5SDimitry Andric //                         Public Constructor Functions
1080b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
createHexagonSplitConst32AndConst64()1090b57cec5SDimitry Andric FunctionPass *llvm::createHexagonSplitConst32AndConst64() {
1100b57cec5SDimitry Andric   return new HexagonSplitConst32AndConst64();
1110b57cec5SDimitry Andric }
112