1*0b57cec5SDimitry Andric //===- ARCExpandPseudosPass - ARC expand pseudo loads -----------*- C++ -*-===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric // 9*0b57cec5SDimitry Andric // This pass expands stores with large offsets into an appropriate sequence. 10*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 11*0b57cec5SDimitry Andric 12*0b57cec5SDimitry Andric #include "ARC.h" 13*0b57cec5SDimitry Andric #include "ARCInstrInfo.h" 14*0b57cec5SDimitry Andric #include "ARCRegisterInfo.h" 15*0b57cec5SDimitry Andric #include "ARCSubtarget.h" 16*0b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h" 17*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h" 18*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h" 19*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h" 20*0b57cec5SDimitry Andric 21*0b57cec5SDimitry Andric using namespace llvm; 22*0b57cec5SDimitry Andric 23*0b57cec5SDimitry Andric #define DEBUG_TYPE "arc-expand-pseudos" 24*0b57cec5SDimitry Andric 25*0b57cec5SDimitry Andric namespace { 26*0b57cec5SDimitry Andric 27*0b57cec5SDimitry Andric class ARCExpandPseudos : public MachineFunctionPass { 28*0b57cec5SDimitry Andric public: 29*0b57cec5SDimitry Andric static char ID; 30*0b57cec5SDimitry Andric ARCExpandPseudos() : MachineFunctionPass(ID) {} 31*0b57cec5SDimitry Andric 32*0b57cec5SDimitry Andric bool runOnMachineFunction(MachineFunction &Fn) override; 33*0b57cec5SDimitry Andric 34*0b57cec5SDimitry Andric StringRef getPassName() const override { return "ARC Expand Pseudos"; } 35*0b57cec5SDimitry Andric 36*0b57cec5SDimitry Andric private: 37*0b57cec5SDimitry Andric void ExpandStore(MachineFunction &, MachineBasicBlock::iterator); 38*0b57cec5SDimitry Andric 39*0b57cec5SDimitry Andric const ARCInstrInfo *TII; 40*0b57cec5SDimitry Andric }; 41*0b57cec5SDimitry Andric 42*0b57cec5SDimitry Andric char ARCExpandPseudos::ID = 0; 43*0b57cec5SDimitry Andric 44*0b57cec5SDimitry Andric } // end anonymous namespace 45*0b57cec5SDimitry Andric 46*0b57cec5SDimitry Andric static unsigned getMappedOp(unsigned PseudoOp) { 47*0b57cec5SDimitry Andric switch (PseudoOp) { 48*0b57cec5SDimitry Andric case ARC::ST_FAR: 49*0b57cec5SDimitry Andric return ARC::ST_rs9; 50*0b57cec5SDimitry Andric case ARC::STH_FAR: 51*0b57cec5SDimitry Andric return ARC::STH_rs9; 52*0b57cec5SDimitry Andric case ARC::STB_FAR: 53*0b57cec5SDimitry Andric return ARC::STB_rs9; 54*0b57cec5SDimitry Andric default: 55*0b57cec5SDimitry Andric llvm_unreachable("Unhandled pseudo op."); 56*0b57cec5SDimitry Andric } 57*0b57cec5SDimitry Andric } 58*0b57cec5SDimitry Andric 59*0b57cec5SDimitry Andric void ARCExpandPseudos::ExpandStore(MachineFunction &MF, 60*0b57cec5SDimitry Andric MachineBasicBlock::iterator SII) { 61*0b57cec5SDimitry Andric MachineInstr &SI = *SII; 62*0b57cec5SDimitry Andric unsigned AddrReg = MF.getRegInfo().createVirtualRegister(&ARC::GPR32RegClass); 63*0b57cec5SDimitry Andric unsigned AddOpc = 64*0b57cec5SDimitry Andric isUInt<6>(SI.getOperand(2).getImm()) ? ARC::ADD_rru6 : ARC::ADD_rrlimm; 65*0b57cec5SDimitry Andric BuildMI(*SI.getParent(), SI, SI.getDebugLoc(), TII->get(AddOpc), AddrReg) 66*0b57cec5SDimitry Andric .addReg(SI.getOperand(1).getReg()) 67*0b57cec5SDimitry Andric .addImm(SI.getOperand(2).getImm()); 68*0b57cec5SDimitry Andric BuildMI(*SI.getParent(), SI, SI.getDebugLoc(), 69*0b57cec5SDimitry Andric TII->get(getMappedOp(SI.getOpcode()))) 70*0b57cec5SDimitry Andric .addReg(SI.getOperand(0).getReg()) 71*0b57cec5SDimitry Andric .addReg(AddrReg) 72*0b57cec5SDimitry Andric .addImm(0); 73*0b57cec5SDimitry Andric SI.eraseFromParent(); 74*0b57cec5SDimitry Andric } 75*0b57cec5SDimitry Andric 76*0b57cec5SDimitry Andric bool ARCExpandPseudos::runOnMachineFunction(MachineFunction &MF) { 77*0b57cec5SDimitry Andric const ARCSubtarget *STI = &MF.getSubtarget<ARCSubtarget>(); 78*0b57cec5SDimitry Andric TII = STI->getInstrInfo(); 79*0b57cec5SDimitry Andric bool ExpandedStore = false; 80*0b57cec5SDimitry Andric for (auto &MBB : MF) { 81*0b57cec5SDimitry Andric MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end(); 82*0b57cec5SDimitry Andric while (MBBI != E) { 83*0b57cec5SDimitry Andric MachineBasicBlock::iterator NMBBI = std::next(MBBI); 84*0b57cec5SDimitry Andric switch (MBBI->getOpcode()) { 85*0b57cec5SDimitry Andric case ARC::ST_FAR: 86*0b57cec5SDimitry Andric case ARC::STH_FAR: 87*0b57cec5SDimitry Andric case ARC::STB_FAR: 88*0b57cec5SDimitry Andric ExpandStore(MF, MBBI); 89*0b57cec5SDimitry Andric ExpandedStore = true; 90*0b57cec5SDimitry Andric break; 91*0b57cec5SDimitry Andric default: 92*0b57cec5SDimitry Andric break; 93*0b57cec5SDimitry Andric } 94*0b57cec5SDimitry Andric MBBI = NMBBI; 95*0b57cec5SDimitry Andric } 96*0b57cec5SDimitry Andric } 97*0b57cec5SDimitry Andric return ExpandedStore; 98*0b57cec5SDimitry Andric } 99*0b57cec5SDimitry Andric 100*0b57cec5SDimitry Andric FunctionPass *llvm::createARCExpandPseudosPass() { 101*0b57cec5SDimitry Andric return new ARCExpandPseudos(); 102*0b57cec5SDimitry Andric } 103