1*81ad6265SDimitry Andric //===-- RISCVMakeCompressible.cpp - Make more instructions compressible ---===// 2*81ad6265SDimitry Andric // 3*81ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*81ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*81ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*81ad6265SDimitry Andric // 7*81ad6265SDimitry Andric //===----------------------------------------------------------------------===// 8*81ad6265SDimitry Andric // 9*81ad6265SDimitry Andric // This pass searches for instructions that are prevented from being compressed 10*81ad6265SDimitry Andric // by one of the following: 11*81ad6265SDimitry Andric // 12*81ad6265SDimitry Andric // 1. The use of a single uncompressed register. 13*81ad6265SDimitry Andric // 2. A base register + offset where the offset is too large to be compressed 14*81ad6265SDimitry Andric // and the base register may or may not be compressed. 15*81ad6265SDimitry Andric // 16*81ad6265SDimitry Andric // 17*81ad6265SDimitry Andric // For case 1, if a compressed register is available, then the uncompressed 18*81ad6265SDimitry Andric // register is copied to the compressed register and its uses are replaced. 19*81ad6265SDimitry Andric // 20*81ad6265SDimitry Andric // For example, storing zero uses the uncompressible zero register: 21*81ad6265SDimitry Andric // sw zero, 0(a0) # if zero 22*81ad6265SDimitry Andric // sw zero, 8(a0) # if zero 23*81ad6265SDimitry Andric // sw zero, 4(a0) # if zero 24*81ad6265SDimitry Andric // sw zero, 24(a0) # if zero 25*81ad6265SDimitry Andric // 26*81ad6265SDimitry Andric // If a compressed register (e.g. a1) is available, the above can be transformed 27*81ad6265SDimitry Andric // to the following to improve code size: 28*81ad6265SDimitry Andric // li a1, 0 29*81ad6265SDimitry Andric // c.sw a1, 0(a0) 30*81ad6265SDimitry Andric // c.sw a1, 8(a0) 31*81ad6265SDimitry Andric // c.sw a1, 4(a0) 32*81ad6265SDimitry Andric // c.sw a1, 24(a0) 33*81ad6265SDimitry Andric // 34*81ad6265SDimitry Andric // 35*81ad6265SDimitry Andric // For case 2, if a compressed register is available, then the original base 36*81ad6265SDimitry Andric // is copied and adjusted such that: 37*81ad6265SDimitry Andric // 38*81ad6265SDimitry Andric // new_base_register = base_register + adjustment 39*81ad6265SDimitry Andric // base_register + large_offset = new_base_register + small_offset 40*81ad6265SDimitry Andric // 41*81ad6265SDimitry Andric // For example, the following offsets are too large for c.sw: 42*81ad6265SDimitry Andric // lui a2, 983065 43*81ad6265SDimitry Andric // sw a1, -236(a2) 44*81ad6265SDimitry Andric // sw a1, -240(a2) 45*81ad6265SDimitry Andric // sw a1, -244(a2) 46*81ad6265SDimitry Andric // sw a1, -248(a2) 47*81ad6265SDimitry Andric // sw a1, -252(a2) 48*81ad6265SDimitry Andric // sw a0, -256(a2) 49*81ad6265SDimitry Andric // 50*81ad6265SDimitry Andric // If a compressed register is available (e.g. a3), a new base could be created 51*81ad6265SDimitry Andric // such that the addresses can accessed with a compressible offset, thus 52*81ad6265SDimitry Andric // improving code size: 53*81ad6265SDimitry Andric // lui a2, 983065 54*81ad6265SDimitry Andric // addi a3, a2, -256 55*81ad6265SDimitry Andric // c.sw a1, 20(a3) 56*81ad6265SDimitry Andric // c.sw a1, 16(a3) 57*81ad6265SDimitry Andric // c.sw a1, 12(a3) 58*81ad6265SDimitry Andric // c.sw a1, 8(a3) 59*81ad6265SDimitry Andric // c.sw a1, 4(a3) 60*81ad6265SDimitry Andric // c.sw a0, 0(a3) 61*81ad6265SDimitry Andric // 62*81ad6265SDimitry Andric // 63*81ad6265SDimitry Andric // This optimization is only applied if there are enough uses of the copied 64*81ad6265SDimitry Andric // register for code size to be reduced. 65*81ad6265SDimitry Andric // 66*81ad6265SDimitry Andric //===----------------------------------------------------------------------===// 67*81ad6265SDimitry Andric 68*81ad6265SDimitry Andric #include "RISCV.h" 69*81ad6265SDimitry Andric #include "RISCVSubtarget.h" 70*81ad6265SDimitry Andric #include "llvm/CodeGen/Passes.h" 71*81ad6265SDimitry Andric #include "llvm/CodeGen/RegisterScavenging.h" 72*81ad6265SDimitry Andric #include "llvm/MC/TargetRegistry.h" 73*81ad6265SDimitry Andric #include "llvm/Support/Debug.h" 74*81ad6265SDimitry Andric 75*81ad6265SDimitry Andric using namespace llvm; 76*81ad6265SDimitry Andric 77*81ad6265SDimitry Andric #define DEBUG_TYPE "riscv-make-compressible" 78*81ad6265SDimitry Andric #define RISCV_COMPRESS_INSTRS_NAME "RISCV Make Compressible" 79*81ad6265SDimitry Andric 80*81ad6265SDimitry Andric namespace { 81*81ad6265SDimitry Andric 82*81ad6265SDimitry Andric struct RISCVMakeCompressibleOpt : public MachineFunctionPass { 83*81ad6265SDimitry Andric static char ID; 84*81ad6265SDimitry Andric 85*81ad6265SDimitry Andric bool runOnMachineFunction(MachineFunction &Fn) override; 86*81ad6265SDimitry Andric 87*81ad6265SDimitry Andric RISCVMakeCompressibleOpt() : MachineFunctionPass(ID) { 88*81ad6265SDimitry Andric initializeRISCVMakeCompressibleOptPass(*PassRegistry::getPassRegistry()); 89*81ad6265SDimitry Andric } 90*81ad6265SDimitry Andric 91*81ad6265SDimitry Andric StringRef getPassName() const override { return RISCV_COMPRESS_INSTRS_NAME; } 92*81ad6265SDimitry Andric }; 93*81ad6265SDimitry Andric } // namespace 94*81ad6265SDimitry Andric 95*81ad6265SDimitry Andric char RISCVMakeCompressibleOpt::ID = 0; 96*81ad6265SDimitry Andric INITIALIZE_PASS(RISCVMakeCompressibleOpt, "riscv-make-compressible", 97*81ad6265SDimitry Andric RISCV_COMPRESS_INSTRS_NAME, false, false) 98*81ad6265SDimitry Andric 99*81ad6265SDimitry Andric // Return log2(widthInBytes) of load/store done by Opcode. 100*81ad6265SDimitry Andric static unsigned log2LdstWidth(unsigned Opcode) { 101*81ad6265SDimitry Andric switch (Opcode) { 102*81ad6265SDimitry Andric default: 103*81ad6265SDimitry Andric llvm_unreachable("Unexpected opcode"); 104*81ad6265SDimitry Andric case RISCV::LW: 105*81ad6265SDimitry Andric case RISCV::SW: 106*81ad6265SDimitry Andric case RISCV::FLW: 107*81ad6265SDimitry Andric case RISCV::FSW: 108*81ad6265SDimitry Andric return 2; 109*81ad6265SDimitry Andric case RISCV::LD: 110*81ad6265SDimitry Andric case RISCV::SD: 111*81ad6265SDimitry Andric case RISCV::FLD: 112*81ad6265SDimitry Andric case RISCV::FSD: 113*81ad6265SDimitry Andric return 3; 114*81ad6265SDimitry Andric } 115*81ad6265SDimitry Andric } 116*81ad6265SDimitry Andric 117*81ad6265SDimitry Andric // Return a mask for the offset bits of a non-stack-pointer based compressed 118*81ad6265SDimitry Andric // load/store. 119*81ad6265SDimitry Andric static uint8_t compressedLDSTOffsetMask(unsigned Opcode) { 120*81ad6265SDimitry Andric return 0x1f << log2LdstWidth(Opcode); 121*81ad6265SDimitry Andric } 122*81ad6265SDimitry Andric 123*81ad6265SDimitry Andric // Return true if Offset fits within a compressed stack-pointer based 124*81ad6265SDimitry Andric // load/store. 125*81ad6265SDimitry Andric static bool compressibleSPOffset(int64_t Offset, unsigned Opcode) { 126*81ad6265SDimitry Andric return log2LdstWidth(Opcode) == 2 ? isShiftedUInt<6, 2>(Offset) 127*81ad6265SDimitry Andric : isShiftedUInt<6, 3>(Offset); 128*81ad6265SDimitry Andric } 129*81ad6265SDimitry Andric 130*81ad6265SDimitry Andric // Given an offset for a load/store, return the adjustment required to the base 131*81ad6265SDimitry Andric // register such that the address can be accessed with a compressible offset. 132*81ad6265SDimitry Andric // This will return 0 if the offset is already compressible. 133*81ad6265SDimitry Andric static int64_t getBaseAdjustForCompression(int64_t Offset, unsigned Opcode) { 134*81ad6265SDimitry Andric // Return the excess bits that do not fit in a compressible offset. 135*81ad6265SDimitry Andric return Offset & ~compressedLDSTOffsetMask(Opcode); 136*81ad6265SDimitry Andric } 137*81ad6265SDimitry Andric 138*81ad6265SDimitry Andric // Return true if Reg is in a compressed register class. 139*81ad6265SDimitry Andric static bool isCompressedReg(Register Reg) { 140*81ad6265SDimitry Andric return RISCV::GPRCRegClass.contains(Reg) || 141*81ad6265SDimitry Andric RISCV::FPR32CRegClass.contains(Reg) || 142*81ad6265SDimitry Andric RISCV::FPR64CRegClass.contains(Reg); 143*81ad6265SDimitry Andric } 144*81ad6265SDimitry Andric 145*81ad6265SDimitry Andric // Return true if MI is a load for which there exists a compressed version. 146*81ad6265SDimitry Andric static bool isCompressibleLoad(const MachineInstr &MI) { 147*81ad6265SDimitry Andric const RISCVSubtarget &STI = MI.getMF()->getSubtarget<RISCVSubtarget>(); 148*81ad6265SDimitry Andric const unsigned Opcode = MI.getOpcode(); 149*81ad6265SDimitry Andric 150*81ad6265SDimitry Andric return Opcode == RISCV::LW || (!STI.is64Bit() && Opcode == RISCV::FLW) || 151*81ad6265SDimitry Andric Opcode == RISCV::LD || Opcode == RISCV::FLD; 152*81ad6265SDimitry Andric } 153*81ad6265SDimitry Andric 154*81ad6265SDimitry Andric // Return true if MI is a store for which there exists a compressed version. 155*81ad6265SDimitry Andric static bool isCompressibleStore(const MachineInstr &MI) { 156*81ad6265SDimitry Andric const RISCVSubtarget &STI = MI.getMF()->getSubtarget<RISCVSubtarget>(); 157*81ad6265SDimitry Andric const unsigned Opcode = MI.getOpcode(); 158*81ad6265SDimitry Andric 159*81ad6265SDimitry Andric return Opcode == RISCV::SW || (!STI.is64Bit() && Opcode == RISCV::FSW) || 160*81ad6265SDimitry Andric Opcode == RISCV::SD || Opcode == RISCV::FSD; 161*81ad6265SDimitry Andric } 162*81ad6265SDimitry Andric 163*81ad6265SDimitry Andric // Find a single register and/or large offset which, if compressible, would 164*81ad6265SDimitry Andric // allow the given instruction to be compressed. 165*81ad6265SDimitry Andric // 166*81ad6265SDimitry Andric // Possible return values: 167*81ad6265SDimitry Andric // 168*81ad6265SDimitry Andric // {Reg, 0} - Uncompressed Reg needs replacing with a compressed 169*81ad6265SDimitry Andric // register. 170*81ad6265SDimitry Andric // {Reg, N} - Reg needs replacing with a compressed register and 171*81ad6265SDimitry Andric // N needs adding to the new register. (Reg may be 172*81ad6265SDimitry Andric // compressed or uncompressed). 173*81ad6265SDimitry Andric // {RISCV::NoRegister, 0} - No suitable optimization found for this 174*81ad6265SDimitry Andric // instruction. 175*81ad6265SDimitry Andric static RegImmPair getRegImmPairPreventingCompression(const MachineInstr &MI) { 176*81ad6265SDimitry Andric const unsigned Opcode = MI.getOpcode(); 177*81ad6265SDimitry Andric 178*81ad6265SDimitry Andric if (isCompressibleLoad(MI) || isCompressibleStore(MI)) { 179*81ad6265SDimitry Andric const MachineOperand &MOImm = MI.getOperand(2); 180*81ad6265SDimitry Andric if (!MOImm.isImm()) 181*81ad6265SDimitry Andric return RegImmPair(RISCV::NoRegister, 0); 182*81ad6265SDimitry Andric 183*81ad6265SDimitry Andric int64_t Offset = MOImm.getImm(); 184*81ad6265SDimitry Andric int64_t NewBaseAdjust = getBaseAdjustForCompression(Offset, Opcode); 185*81ad6265SDimitry Andric Register Base = MI.getOperand(1).getReg(); 186*81ad6265SDimitry Andric 187*81ad6265SDimitry Andric // Memory accesses via the stack pointer do not have a requirement for 188*81ad6265SDimitry Andric // either of the registers to be compressible and can take a larger offset. 189*81ad6265SDimitry Andric if (RISCV::SPRegClass.contains(Base)) { 190*81ad6265SDimitry Andric if (!compressibleSPOffset(Offset, Opcode) && NewBaseAdjust) 191*81ad6265SDimitry Andric return RegImmPair(Base, NewBaseAdjust); 192*81ad6265SDimitry Andric } else { 193*81ad6265SDimitry Andric Register SrcDest = MI.getOperand(0).getReg(); 194*81ad6265SDimitry Andric bool SrcDestCompressed = isCompressedReg(SrcDest); 195*81ad6265SDimitry Andric bool BaseCompressed = isCompressedReg(Base); 196*81ad6265SDimitry Andric 197*81ad6265SDimitry Andric // If only Base and/or offset prevent compression, then return Base and 198*81ad6265SDimitry Andric // any adjustment required to make the offset compressible. 199*81ad6265SDimitry Andric if ((!BaseCompressed || NewBaseAdjust) && SrcDestCompressed) 200*81ad6265SDimitry Andric return RegImmPair(Base, NewBaseAdjust); 201*81ad6265SDimitry Andric 202*81ad6265SDimitry Andric // For loads, we can only change the base register since dest is defined 203*81ad6265SDimitry Andric // rather than used. 204*81ad6265SDimitry Andric // 205*81ad6265SDimitry Andric // For stores, we can change SrcDest (and Base if SrcDest == Base) but 206*81ad6265SDimitry Andric // cannot resolve an uncompressible offset in this case. 207*81ad6265SDimitry Andric if (isCompressibleStore(MI)) { 208*81ad6265SDimitry Andric if (!SrcDestCompressed && (BaseCompressed || SrcDest == Base) && 209*81ad6265SDimitry Andric !NewBaseAdjust) 210*81ad6265SDimitry Andric return RegImmPair(SrcDest, NewBaseAdjust); 211*81ad6265SDimitry Andric } 212*81ad6265SDimitry Andric } 213*81ad6265SDimitry Andric } 214*81ad6265SDimitry Andric return RegImmPair(RISCV::NoRegister, 0); 215*81ad6265SDimitry Andric } 216*81ad6265SDimitry Andric 217*81ad6265SDimitry Andric // Check all uses after FirstMI of the given register, keeping a vector of 218*81ad6265SDimitry Andric // instructions that would be compressible if the given register (and offset if 219*81ad6265SDimitry Andric // applicable) were compressible. 220*81ad6265SDimitry Andric // 221*81ad6265SDimitry Andric // If there are enough uses for this optimization to improve code size and a 222*81ad6265SDimitry Andric // compressed register is available, return that compressed register. 223*81ad6265SDimitry Andric static Register analyzeCompressibleUses(MachineInstr &FirstMI, 224*81ad6265SDimitry Andric RegImmPair RegImm, 225*81ad6265SDimitry Andric SmallVectorImpl<MachineInstr *> &MIs) { 226*81ad6265SDimitry Andric MachineBasicBlock &MBB = *FirstMI.getParent(); 227*81ad6265SDimitry Andric const TargetRegisterInfo *TRI = 228*81ad6265SDimitry Andric MBB.getParent()->getSubtarget().getRegisterInfo(); 229*81ad6265SDimitry Andric 230*81ad6265SDimitry Andric RegScavenger RS; 231*81ad6265SDimitry Andric RS.enterBasicBlock(MBB); 232*81ad6265SDimitry Andric 233*81ad6265SDimitry Andric for (MachineBasicBlock::instr_iterator I = FirstMI.getIterator(), 234*81ad6265SDimitry Andric E = MBB.instr_end(); 235*81ad6265SDimitry Andric I != E; ++I) { 236*81ad6265SDimitry Andric MachineInstr &MI = *I; 237*81ad6265SDimitry Andric 238*81ad6265SDimitry Andric // Determine if this is an instruction which would benefit from using the 239*81ad6265SDimitry Andric // new register. 240*81ad6265SDimitry Andric RegImmPair CandidateRegImm = getRegImmPairPreventingCompression(MI); 241*81ad6265SDimitry Andric if (CandidateRegImm.Reg == RegImm.Reg && 242*81ad6265SDimitry Andric CandidateRegImm.Imm == RegImm.Imm) { 243*81ad6265SDimitry Andric // Advance tracking since the value in the new register must be live for 244*81ad6265SDimitry Andric // this instruction too. 245*81ad6265SDimitry Andric RS.forward(I); 246*81ad6265SDimitry Andric 247*81ad6265SDimitry Andric MIs.push_back(&MI); 248*81ad6265SDimitry Andric } 249*81ad6265SDimitry Andric 250*81ad6265SDimitry Andric // If RegImm.Reg is modified by this instruction, then we cannot optimize 251*81ad6265SDimitry Andric // past this instruction. If the register is already compressed, then it may 252*81ad6265SDimitry Andric // possible to optimize a large offset in the current instruction - this 253*81ad6265SDimitry Andric // will have been detected by the preceeding call to 254*81ad6265SDimitry Andric // getRegImmPairPreventingCompression. 255*81ad6265SDimitry Andric if (MI.modifiesRegister(RegImm.Reg, TRI)) 256*81ad6265SDimitry Andric break; 257*81ad6265SDimitry Andric } 258*81ad6265SDimitry Andric 259*81ad6265SDimitry Andric // Adjusting the base costs one new uncompressed addi and therefore three uses 260*81ad6265SDimitry Andric // are required for a code size reduction. If no base adjustment is required, 261*81ad6265SDimitry Andric // then copying the register costs one new c.mv (or c.li Rd, 0 for "copying" 262*81ad6265SDimitry Andric // the zero register) and therefore two uses are required for a code size 263*81ad6265SDimitry Andric // reduction. 264*81ad6265SDimitry Andric if (MIs.size() < 2 || (RegImm.Imm != 0 && MIs.size() < 3)) 265*81ad6265SDimitry Andric return RISCV::NoRegister; 266*81ad6265SDimitry Andric 267*81ad6265SDimitry Andric // Find a compressible register which will be available from the first 268*81ad6265SDimitry Andric // instruction we care about to the last. 269*81ad6265SDimitry Andric const TargetRegisterClass *RCToScavenge; 270*81ad6265SDimitry Andric 271*81ad6265SDimitry Andric // Work out the compressed register class from which to scavenge. 272*81ad6265SDimitry Andric if (RISCV::GPRRegClass.contains(RegImm.Reg)) 273*81ad6265SDimitry Andric RCToScavenge = &RISCV::GPRCRegClass; 274*81ad6265SDimitry Andric else if (RISCV::FPR32RegClass.contains(RegImm.Reg)) 275*81ad6265SDimitry Andric RCToScavenge = &RISCV::FPR32CRegClass; 276*81ad6265SDimitry Andric else if (RISCV::FPR64RegClass.contains(RegImm.Reg)) 277*81ad6265SDimitry Andric RCToScavenge = &RISCV::FPR64CRegClass; 278*81ad6265SDimitry Andric else 279*81ad6265SDimitry Andric return RISCV::NoRegister; 280*81ad6265SDimitry Andric 281*81ad6265SDimitry Andric return RS.scavengeRegisterBackwards(*RCToScavenge, FirstMI.getIterator(), 282*81ad6265SDimitry Andric /*RestoreAfter=*/false, /*SPAdj=*/0, 283*81ad6265SDimitry Andric /*AllowSpill=*/false); 284*81ad6265SDimitry Andric } 285*81ad6265SDimitry Andric 286*81ad6265SDimitry Andric // Update uses of the old register in the given instruction to the new register. 287*81ad6265SDimitry Andric static void updateOperands(MachineInstr &MI, RegImmPair OldRegImm, 288*81ad6265SDimitry Andric Register NewReg) { 289*81ad6265SDimitry Andric unsigned Opcode = MI.getOpcode(); 290*81ad6265SDimitry Andric 291*81ad6265SDimitry Andric // If this pass is extended to support more instructions, the check for 292*81ad6265SDimitry Andric // definedness may need to be strengthened. 293*81ad6265SDimitry Andric assert((isCompressibleLoad(MI) || isCompressibleStore(MI)) && 294*81ad6265SDimitry Andric "Unsupported instruction for this optimization."); 295*81ad6265SDimitry Andric 296*81ad6265SDimitry Andric // Update registers 297*81ad6265SDimitry Andric for (MachineOperand &MO : MI.operands()) 298*81ad6265SDimitry Andric if (MO.isReg() && MO.getReg() == OldRegImm.Reg) { 299*81ad6265SDimitry Andric // Do not update operands that define the old register. 300*81ad6265SDimitry Andric // 301*81ad6265SDimitry Andric // The new register was scavenged for the range of instructions that are 302*81ad6265SDimitry Andric // being updated, therefore it should not be defined within this range 303*81ad6265SDimitry Andric // except possibly in the final instruction. 304*81ad6265SDimitry Andric if (MO.isDef()) { 305*81ad6265SDimitry Andric assert(isCompressibleLoad(MI)); 306*81ad6265SDimitry Andric continue; 307*81ad6265SDimitry Andric } 308*81ad6265SDimitry Andric // Update reg 309*81ad6265SDimitry Andric MO.setReg(NewReg); 310*81ad6265SDimitry Andric } 311*81ad6265SDimitry Andric 312*81ad6265SDimitry Andric // Update offset 313*81ad6265SDimitry Andric MachineOperand &MOImm = MI.getOperand(2); 314*81ad6265SDimitry Andric int64_t NewOffset = MOImm.getImm() & compressedLDSTOffsetMask(Opcode); 315*81ad6265SDimitry Andric MOImm.setImm(NewOffset); 316*81ad6265SDimitry Andric } 317*81ad6265SDimitry Andric 318*81ad6265SDimitry Andric bool RISCVMakeCompressibleOpt::runOnMachineFunction(MachineFunction &Fn) { 319*81ad6265SDimitry Andric // This is a size optimization. 320*81ad6265SDimitry Andric if (skipFunction(Fn.getFunction()) || !Fn.getFunction().hasMinSize()) 321*81ad6265SDimitry Andric return false; 322*81ad6265SDimitry Andric 323*81ad6265SDimitry Andric const RISCVSubtarget &STI = Fn.getSubtarget<RISCVSubtarget>(); 324*81ad6265SDimitry Andric const RISCVInstrInfo &TII = *STI.getInstrInfo(); 325*81ad6265SDimitry Andric 326*81ad6265SDimitry Andric // This optimization only makes sense if compressed instructions are emitted. 327*81ad6265SDimitry Andric if (!STI.hasStdExtC()) 328*81ad6265SDimitry Andric return false; 329*81ad6265SDimitry Andric 330*81ad6265SDimitry Andric for (MachineBasicBlock &MBB : Fn) { 331*81ad6265SDimitry Andric LLVM_DEBUG(dbgs() << "MBB: " << MBB.getName() << "\n"); 332*81ad6265SDimitry Andric for (MachineInstr &MI : MBB) { 333*81ad6265SDimitry Andric // Determine if this instruction would otherwise be compressed if not for 334*81ad6265SDimitry Andric // an uncompressible register or offset. 335*81ad6265SDimitry Andric RegImmPair RegImm = getRegImmPairPreventingCompression(MI); 336*81ad6265SDimitry Andric if (!RegImm.Reg && RegImm.Imm == 0) 337*81ad6265SDimitry Andric continue; 338*81ad6265SDimitry Andric 339*81ad6265SDimitry Andric // Determine if there is a set of instructions for which replacing this 340*81ad6265SDimitry Andric // register with a compressed register (and compressible offset if 341*81ad6265SDimitry Andric // applicable) is possible and will allow compression. 342*81ad6265SDimitry Andric SmallVector<MachineInstr *, 8> MIs; 343*81ad6265SDimitry Andric Register NewReg = analyzeCompressibleUses(MI, RegImm, MIs); 344*81ad6265SDimitry Andric if (!NewReg) 345*81ad6265SDimitry Andric continue; 346*81ad6265SDimitry Andric 347*81ad6265SDimitry Andric // Create the appropriate copy and/or offset. 348*81ad6265SDimitry Andric if (RISCV::GPRRegClass.contains(RegImm.Reg)) { 349*81ad6265SDimitry Andric assert(isInt<12>(RegImm.Imm)); 350*81ad6265SDimitry Andric BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(RISCV::ADDI), NewReg) 351*81ad6265SDimitry Andric .addReg(RegImm.Reg) 352*81ad6265SDimitry Andric .addImm(RegImm.Imm); 353*81ad6265SDimitry Andric } else { 354*81ad6265SDimitry Andric // If we are looking at replacing an FPR register we don't expect to 355*81ad6265SDimitry Andric // have any offset. The only compressible FP instructions with an offset 356*81ad6265SDimitry Andric // are loads and stores, for which the offset applies to the GPR operand 357*81ad6265SDimitry Andric // not the FPR operand. 358*81ad6265SDimitry Andric assert(RegImm.Imm == 0); 359*81ad6265SDimitry Andric unsigned Opcode = RISCV::FPR32RegClass.contains(RegImm.Reg) 360*81ad6265SDimitry Andric ? RISCV::FSGNJ_S 361*81ad6265SDimitry Andric : RISCV::FSGNJ_D; 362*81ad6265SDimitry Andric BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(Opcode), NewReg) 363*81ad6265SDimitry Andric .addReg(RegImm.Reg) 364*81ad6265SDimitry Andric .addReg(RegImm.Reg); 365*81ad6265SDimitry Andric } 366*81ad6265SDimitry Andric 367*81ad6265SDimitry Andric // Update the set of instructions to use the compressed register and 368*81ad6265SDimitry Andric // compressible offset instead. These instructions should now be 369*81ad6265SDimitry Andric // compressible. 370*81ad6265SDimitry Andric // TODO: Update all uses if RegImm.Imm == 0? Not just those that are 371*81ad6265SDimitry Andric // expected to become compressible. 372*81ad6265SDimitry Andric for (MachineInstr *UpdateMI : MIs) 373*81ad6265SDimitry Andric updateOperands(*UpdateMI, RegImm, NewReg); 374*81ad6265SDimitry Andric } 375*81ad6265SDimitry Andric } 376*81ad6265SDimitry Andric return true; 377*81ad6265SDimitry Andric } 378*81ad6265SDimitry Andric 379*81ad6265SDimitry Andric /// Returns an instance of the Make Compressible Optimization pass. 380*81ad6265SDimitry Andric FunctionPass *llvm::createRISCVMakeCompressibleOptPass() { 381*81ad6265SDimitry Andric return new RISCVMakeCompressibleOpt(); 382*81ad6265SDimitry Andric } 383