1259698Sdim//=== HexagonSplitConst32AndConst64.cpp - split CONST32/Const64 into HI/LO ===// 2259698Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6259698Sdim// 7259698Sdim//===----------------------------------------------------------------------===// 8259698Sdim// 9259698Sdim// When the compiler is invoked with no small data, for instance, with the -G0 10314564Sdim// command line option, then all CONST* opcodes should be broken down into 11259698Sdim// appropriate LO and HI instructions. This splitting is done by this pass. 12259698Sdim// The only reason this is not done in the DAG lowering itself is that there 13259698Sdim// is no simple way of getting the register allocator to allot the same hard 14259698Sdim// register to the result of LO and HI instructions. This pass is always 15259698Sdim// scheduled after register allocation. 16259698Sdim// 17259698Sdim//===----------------------------------------------------------------------===// 18259698Sdim 19276479Sdim#include "HexagonSubtarget.h" 20259698Sdim#include "HexagonTargetMachine.h" 21276479Sdim#include "HexagonTargetObjectFile.h" 22259698Sdim#include "llvm/CodeGen/MachineFunctionPass.h" 23259698Sdim#include "llvm/CodeGen/MachineInstrBuilder.h" 24259698Sdim#include "llvm/CodeGen/Passes.h" 25327952Sdim#include "llvm/CodeGen/TargetInstrInfo.h" 26327952Sdim#include "llvm/CodeGen/TargetRegisterInfo.h" 27259698Sdim 28259698Sdimusing namespace llvm; 29259698Sdim 30276479Sdim#define DEBUG_TYPE "xfer" 31276479Sdim 32288943Sdimnamespace llvm { 33288943Sdim FunctionPass *createHexagonSplitConst32AndConst64(); 34288943Sdim void initializeHexagonSplitConst32AndConst64Pass(PassRegistry&); 35288943Sdim} 36288943Sdim 37259698Sdimnamespace { 38314564Sdim class HexagonSplitConst32AndConst64 : public MachineFunctionPass { 39314564Sdim public: 40259698Sdim static char ID; 41314564Sdim HexagonSplitConst32AndConst64() : MachineFunctionPass(ID) { 42314564Sdim PassRegistry &R = *PassRegistry::getPassRegistry(); 43314564Sdim initializeHexagonSplitConst32AndConst64Pass(R); 44314564Sdim } 45314564Sdim StringRef getPassName() const override { 46259698Sdim return "Hexagon Split Const32s and Const64s"; 47259698Sdim } 48276479Sdim bool runOnMachineFunction(MachineFunction &Fn) override; 49309124Sdim MachineFunctionProperties getRequiredProperties() const override { 50309124Sdim return MachineFunctionProperties().set( 51314564Sdim MachineFunctionProperties::Property::NoVRegs); 52309124Sdim } 53314564Sdim }; 54314564Sdim} 55259698Sdim 56259698Sdimchar HexagonSplitConst32AndConst64::ID = 0; 57259698Sdim 58314564SdimINITIALIZE_PASS(HexagonSplitConst32AndConst64, "split-const-for-sdata", 59314564Sdim "Hexagon Split Const32s and Const64s", false, false) 60259698Sdim 61259698Sdimbool HexagonSplitConst32AndConst64::runOnMachineFunction(MachineFunction &Fn) { 62341825Sdim auto &HST = Fn.getSubtarget<HexagonSubtarget>(); 63341825Sdim auto &HTM = static_cast<const HexagonTargetMachine&>(Fn.getTarget()); 64341825Sdim auto &TLOF = *HTM.getObjFileLowering(); 65344779Sdim if (HST.useSmallData() && TLOF.isSmallDataEnabled(HTM)) 66341825Sdim return false; 67276479Sdim 68341825Sdim const TargetInstrInfo *TII = HST.getInstrInfo(); 69341825Sdim const TargetRegisterInfo *TRI = HST.getRegisterInfo(); 70259698Sdim 71259698Sdim // Loop over all of the basic blocks 72314564Sdim for (MachineBasicBlock &B : Fn) { 73314564Sdim for (auto I = B.begin(), E = B.end(); I != E; ) { 74314564Sdim MachineInstr &MI = *I; 75314564Sdim ++I; 76314564Sdim unsigned Opc = MI.getOpcode(); 77259698Sdim 78314564Sdim if (Opc == Hexagon::CONST32) { 79360784Sdim Register DestReg = MI.getOperand(0).getReg(); 80314564Sdim uint64_t ImmValue = MI.getOperand(1).getImm(); 81314564Sdim const DebugLoc &DL = MI.getDebugLoc(); 82314564Sdim BuildMI(B, MI, DL, TII->get(Hexagon::A2_tfrsi), DestReg) 83309124Sdim .addImm(ImmValue); 84314564Sdim B.erase(&MI); 85314564Sdim } else if (Opc == Hexagon::CONST64) { 86360784Sdim Register DestReg = MI.getOperand(0).getReg(); 87314564Sdim int64_t ImmValue = MI.getOperand(1).getImm(); 88314564Sdim const DebugLoc &DL = MI.getDebugLoc(); 89360784Sdim Register DestLo = TRI->getSubReg(DestReg, Hexagon::isub_lo); 90360784Sdim Register DestHi = TRI->getSubReg(DestReg, Hexagon::isub_hi); 91259698Sdim 92259698Sdim int32_t LowWord = (ImmValue & 0xFFFFFFFF); 93259698Sdim int32_t HighWord = (ImmValue >> 32) & 0xFFFFFFFF; 94259698Sdim 95314564Sdim BuildMI(B, MI, DL, TII->get(Hexagon::A2_tfrsi), DestLo) 96309124Sdim .addImm(LowWord); 97314564Sdim BuildMI(B, MI, DL, TII->get(Hexagon::A2_tfrsi), DestHi) 98309124Sdim .addImm(HighWord); 99314564Sdim B.erase(&MI); 100288943Sdim } 101259698Sdim } 102259698Sdim } 103259698Sdim 104259698Sdim return true; 105259698Sdim} 106259698Sdim 107259698Sdim 108259698Sdim//===----------------------------------------------------------------------===// 109259698Sdim// Public Constructor Functions 110259698Sdim//===----------------------------------------------------------------------===// 111314564SdimFunctionPass *llvm::createHexagonSplitConst32AndConst64() { 112288943Sdim return new HexagonSplitConst32AndConst64(); 113259698Sdim} 114