RISCVMakeCompressible.cpp 15 KB

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