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