LoongArchInstrInfo.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488
  1. //=- LoongArchInstrInfo.cpp - LoongArch Instruction Information -*- C++ -*-===//
  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 file contains the LoongArch implementation of the TargetInstrInfo class.
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #include "LoongArchInstrInfo.h"
  13. #include "LoongArch.h"
  14. #include "LoongArchMachineFunctionInfo.h"
  15. #include "LoongArchRegisterInfo.h"
  16. #include "MCTargetDesc/LoongArchMCTargetDesc.h"
  17. #include "MCTargetDesc/LoongArchMatInt.h"
  18. #include "llvm/CodeGen/RegisterScavenging.h"
  19. using namespace llvm;
  20. #define GET_INSTRINFO_CTOR_DTOR
  21. #include "LoongArchGenInstrInfo.inc"
  22. LoongArchInstrInfo::LoongArchInstrInfo(LoongArchSubtarget &STI)
  23. : LoongArchGenInstrInfo(LoongArch::ADJCALLSTACKDOWN,
  24. LoongArch::ADJCALLSTACKUP),
  25. STI(STI) {}
  26. void LoongArchInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
  27. MachineBasicBlock::iterator MBBI,
  28. const DebugLoc &DL, MCRegister DstReg,
  29. MCRegister SrcReg, bool KillSrc) const {
  30. if (LoongArch::GPRRegClass.contains(DstReg, SrcReg)) {
  31. BuildMI(MBB, MBBI, DL, get(LoongArch::OR), DstReg)
  32. .addReg(SrcReg, getKillRegState(KillSrc))
  33. .addReg(LoongArch::R0);
  34. return;
  35. }
  36. // GPR->CFR copy.
  37. if (LoongArch::CFRRegClass.contains(DstReg) &&
  38. LoongArch::GPRRegClass.contains(SrcReg)) {
  39. BuildMI(MBB, MBBI, DL, get(LoongArch::MOVGR2CF), DstReg)
  40. .addReg(SrcReg, getKillRegState(KillSrc));
  41. return;
  42. }
  43. // CFR->GPR copy.
  44. if (LoongArch::GPRRegClass.contains(DstReg) &&
  45. LoongArch::CFRRegClass.contains(SrcReg)) {
  46. BuildMI(MBB, MBBI, DL, get(LoongArch::MOVCF2GR), DstReg)
  47. .addReg(SrcReg, getKillRegState(KillSrc));
  48. return;
  49. }
  50. // FPR->FPR copies.
  51. unsigned Opc;
  52. if (LoongArch::FPR32RegClass.contains(DstReg, SrcReg)) {
  53. Opc = LoongArch::FMOV_S;
  54. } else if (LoongArch::FPR64RegClass.contains(DstReg, SrcReg)) {
  55. Opc = LoongArch::FMOV_D;
  56. } else {
  57. // TODO: support other copies.
  58. llvm_unreachable("Impossible reg-to-reg copy");
  59. }
  60. BuildMI(MBB, MBBI, DL, get(Opc), DstReg)
  61. .addReg(SrcReg, getKillRegState(KillSrc));
  62. }
  63. void LoongArchInstrInfo::storeRegToStackSlot(
  64. MachineBasicBlock &MBB, MachineBasicBlock::iterator I, Register SrcReg,
  65. bool IsKill, int FI, const TargetRegisterClass *RC,
  66. const TargetRegisterInfo *TRI, Register VReg) const {
  67. DebugLoc DL;
  68. if (I != MBB.end())
  69. DL = I->getDebugLoc();
  70. MachineFunction *MF = MBB.getParent();
  71. MachineFrameInfo &MFI = MF->getFrameInfo();
  72. unsigned Opcode;
  73. if (LoongArch::GPRRegClass.hasSubClassEq(RC))
  74. Opcode = TRI->getRegSizeInBits(LoongArch::GPRRegClass) == 32
  75. ? LoongArch::ST_W
  76. : LoongArch::ST_D;
  77. else if (LoongArch::FPR32RegClass.hasSubClassEq(RC))
  78. Opcode = LoongArch::FST_S;
  79. else if (LoongArch::FPR64RegClass.hasSubClassEq(RC))
  80. Opcode = LoongArch::FST_D;
  81. else if (LoongArch::CFRRegClass.hasSubClassEq(RC))
  82. Opcode = LoongArch::PseudoST_CFR;
  83. else
  84. llvm_unreachable("Can't store this register to stack slot");
  85. MachineMemOperand *MMO = MF->getMachineMemOperand(
  86. MachinePointerInfo::getFixedStack(*MF, FI), MachineMemOperand::MOStore,
  87. MFI.getObjectSize(FI), MFI.getObjectAlign(FI));
  88. BuildMI(MBB, I, DL, get(Opcode))
  89. .addReg(SrcReg, getKillRegState(IsKill))
  90. .addFrameIndex(FI)
  91. .addImm(0)
  92. .addMemOperand(MMO);
  93. }
  94. void LoongArchInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
  95. MachineBasicBlock::iterator I,
  96. Register DstReg, int FI,
  97. const TargetRegisterClass *RC,
  98. const TargetRegisterInfo *TRI,
  99. Register VReg) const {
  100. DebugLoc DL;
  101. if (I != MBB.end())
  102. DL = I->getDebugLoc();
  103. MachineFunction *MF = MBB.getParent();
  104. MachineFrameInfo &MFI = MF->getFrameInfo();
  105. unsigned Opcode;
  106. if (LoongArch::GPRRegClass.hasSubClassEq(RC))
  107. Opcode = TRI->getRegSizeInBits(LoongArch::GPRRegClass) == 32
  108. ? LoongArch::LD_W
  109. : LoongArch::LD_D;
  110. else if (LoongArch::FPR32RegClass.hasSubClassEq(RC))
  111. Opcode = LoongArch::FLD_S;
  112. else if (LoongArch::FPR64RegClass.hasSubClassEq(RC))
  113. Opcode = LoongArch::FLD_D;
  114. else if (LoongArch::CFRRegClass.hasSubClassEq(RC))
  115. Opcode = LoongArch::PseudoLD_CFR;
  116. else
  117. llvm_unreachable("Can't load this register from stack slot");
  118. MachineMemOperand *MMO = MF->getMachineMemOperand(
  119. MachinePointerInfo::getFixedStack(*MF, FI), MachineMemOperand::MOLoad,
  120. MFI.getObjectSize(FI), MFI.getObjectAlign(FI));
  121. BuildMI(MBB, I, DL, get(Opcode), DstReg)
  122. .addFrameIndex(FI)
  123. .addImm(0)
  124. .addMemOperand(MMO);
  125. }
  126. void LoongArchInstrInfo::movImm(MachineBasicBlock &MBB,
  127. MachineBasicBlock::iterator MBBI,
  128. const DebugLoc &DL, Register DstReg,
  129. uint64_t Val, MachineInstr::MIFlag Flag) const {
  130. Register SrcReg = LoongArch::R0;
  131. if (!STI.is64Bit() && !isInt<32>(Val))
  132. report_fatal_error("Should only materialize 32-bit constants for LA32");
  133. auto Seq = LoongArchMatInt::generateInstSeq(Val);
  134. assert(!Seq.empty());
  135. for (auto &Inst : Seq) {
  136. switch (Inst.Opc) {
  137. case LoongArch::LU12I_W:
  138. BuildMI(MBB, MBBI, DL, get(Inst.Opc), DstReg)
  139. .addImm(Inst.Imm)
  140. .setMIFlag(Flag);
  141. break;
  142. case LoongArch::ADDI_W:
  143. case LoongArch::ORI:
  144. case LoongArch::LU32I_D: // "rj" is needed due to InstrInfo pattern
  145. case LoongArch::LU52I_D:
  146. BuildMI(MBB, MBBI, DL, get(Inst.Opc), DstReg)
  147. .addReg(SrcReg, RegState::Kill)
  148. .addImm(Inst.Imm)
  149. .setMIFlag(Flag);
  150. break;
  151. default:
  152. assert(false && "Unknown insn emitted by LoongArchMatInt");
  153. }
  154. // Only the first instruction has $zero as its source.
  155. SrcReg = DstReg;
  156. }
  157. }
  158. unsigned LoongArchInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const {
  159. unsigned Opcode = MI.getOpcode();
  160. if (Opcode == TargetOpcode::INLINEASM ||
  161. Opcode == TargetOpcode::INLINEASM_BR) {
  162. const MachineFunction *MF = MI.getParent()->getParent();
  163. const MCAsmInfo *MAI = MF->getTarget().getMCAsmInfo();
  164. return getInlineAsmLength(MI.getOperand(0).getSymbolName(), *MAI);
  165. }
  166. return MI.getDesc().getSize();
  167. }
  168. MachineBasicBlock *
  169. LoongArchInstrInfo::getBranchDestBlock(const MachineInstr &MI) const {
  170. assert(MI.getDesc().isBranch() && "Unexpected opcode!");
  171. // The branch target is always the last operand.
  172. return MI.getOperand(MI.getNumExplicitOperands() - 1).getMBB();
  173. }
  174. static void parseCondBranch(MachineInstr &LastInst, MachineBasicBlock *&Target,
  175. SmallVectorImpl<MachineOperand> &Cond) {
  176. // Block ends with fall-through condbranch.
  177. assert(LastInst.getDesc().isConditionalBranch() &&
  178. "Unknown conditional branch");
  179. int NumOp = LastInst.getNumExplicitOperands();
  180. Target = LastInst.getOperand(NumOp - 1).getMBB();
  181. Cond.push_back(MachineOperand::CreateImm(LastInst.getOpcode()));
  182. for (int i = 0; i < NumOp - 1; i++)
  183. Cond.push_back(LastInst.getOperand(i));
  184. }
  185. bool LoongArchInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
  186. MachineBasicBlock *&TBB,
  187. MachineBasicBlock *&FBB,
  188. SmallVectorImpl<MachineOperand> &Cond,
  189. bool AllowModify) const {
  190. TBB = FBB = nullptr;
  191. Cond.clear();
  192. // If the block has no terminators, it just falls into the block after it.
  193. MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
  194. if (I == MBB.end() || !isUnpredicatedTerminator(*I))
  195. return false;
  196. // Count the number of terminators and find the first unconditional or
  197. // indirect branch.
  198. MachineBasicBlock::iterator FirstUncondOrIndirectBr = MBB.end();
  199. int NumTerminators = 0;
  200. for (auto J = I.getReverse(); J != MBB.rend() && isUnpredicatedTerminator(*J);
  201. J++) {
  202. NumTerminators++;
  203. if (J->getDesc().isUnconditionalBranch() ||
  204. J->getDesc().isIndirectBranch()) {
  205. FirstUncondOrIndirectBr = J.getReverse();
  206. }
  207. }
  208. // If AllowModify is true, we can erase any terminators after
  209. // FirstUncondOrIndirectBR.
  210. if (AllowModify && FirstUncondOrIndirectBr != MBB.end()) {
  211. while (std::next(FirstUncondOrIndirectBr) != MBB.end()) {
  212. std::next(FirstUncondOrIndirectBr)->eraseFromParent();
  213. NumTerminators--;
  214. }
  215. I = FirstUncondOrIndirectBr;
  216. }
  217. // Handle a single unconditional branch.
  218. if (NumTerminators == 1 && I->getDesc().isUnconditionalBranch()) {
  219. TBB = getBranchDestBlock(*I);
  220. return false;
  221. }
  222. // Handle a single conditional branch.
  223. if (NumTerminators == 1 && I->getDesc().isConditionalBranch()) {
  224. parseCondBranch(*I, TBB, Cond);
  225. return false;
  226. }
  227. // Handle a conditional branch followed by an unconditional branch.
  228. if (NumTerminators == 2 && std::prev(I)->getDesc().isConditionalBranch() &&
  229. I->getDesc().isUnconditionalBranch()) {
  230. parseCondBranch(*std::prev(I), TBB, Cond);
  231. FBB = getBranchDestBlock(*I);
  232. return false;
  233. }
  234. // Otherwise, we can't handle this.
  235. return true;
  236. }
  237. bool LoongArchInstrInfo::isBranchOffsetInRange(unsigned BranchOp,
  238. int64_t BrOffset) const {
  239. switch (BranchOp) {
  240. default:
  241. llvm_unreachable("Unknown branch instruction!");
  242. case LoongArch::BEQ:
  243. case LoongArch::BNE:
  244. case LoongArch::BLT:
  245. case LoongArch::BGE:
  246. case LoongArch::BLTU:
  247. case LoongArch::BGEU:
  248. return isInt<18>(BrOffset);
  249. case LoongArch::BEQZ:
  250. case LoongArch::BNEZ:
  251. case LoongArch::BCEQZ:
  252. case LoongArch::BCNEZ:
  253. return isInt<23>(BrOffset);
  254. case LoongArch::B:
  255. case LoongArch::PseudoBR:
  256. return isInt<28>(BrOffset);
  257. }
  258. }
  259. unsigned LoongArchInstrInfo::removeBranch(MachineBasicBlock &MBB,
  260. int *BytesRemoved) const {
  261. if (BytesRemoved)
  262. *BytesRemoved = 0;
  263. MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
  264. if (I == MBB.end())
  265. return 0;
  266. if (!I->getDesc().isBranch())
  267. return 0;
  268. // Remove the branch.
  269. if (BytesRemoved)
  270. *BytesRemoved += getInstSizeInBytes(*I);
  271. I->eraseFromParent();
  272. I = MBB.end();
  273. if (I == MBB.begin())
  274. return 1;
  275. --I;
  276. if (!I->getDesc().isConditionalBranch())
  277. return 1;
  278. // Remove the branch.
  279. if (BytesRemoved)
  280. *BytesRemoved += getInstSizeInBytes(*I);
  281. I->eraseFromParent();
  282. return 2;
  283. }
  284. // Inserts a branch into the end of the specific MachineBasicBlock, returning
  285. // the number of instructions inserted.
  286. unsigned LoongArchInstrInfo::insertBranch(
  287. MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB,
  288. ArrayRef<MachineOperand> Cond, const DebugLoc &DL, int *BytesAdded) const {
  289. if (BytesAdded)
  290. *BytesAdded = 0;
  291. // Shouldn't be a fall through.
  292. assert(TBB && "insertBranch must not be told to insert a fallthrough");
  293. assert(Cond.size() <= 3 && Cond.size() != 1 &&
  294. "LoongArch branch conditions have at most two components!");
  295. // Unconditional branch.
  296. if (Cond.empty()) {
  297. MachineInstr &MI = *BuildMI(&MBB, DL, get(LoongArch::PseudoBR)).addMBB(TBB);
  298. if (BytesAdded)
  299. *BytesAdded += getInstSizeInBytes(MI);
  300. return 1;
  301. }
  302. // Either a one or two-way conditional branch.
  303. MachineInstrBuilder MIB = BuildMI(&MBB, DL, get(Cond[0].getImm()));
  304. for (unsigned i = 1; i < Cond.size(); ++i)
  305. MIB.add(Cond[i]);
  306. MIB.addMBB(TBB);
  307. if (BytesAdded)
  308. *BytesAdded += getInstSizeInBytes(*MIB);
  309. // One-way conditional branch.
  310. if (!FBB)
  311. return 1;
  312. // Two-way conditional branch.
  313. MachineInstr &MI = *BuildMI(&MBB, DL, get(LoongArch::PseudoBR)).addMBB(FBB);
  314. if (BytesAdded)
  315. *BytesAdded += getInstSizeInBytes(MI);
  316. return 2;
  317. }
  318. void LoongArchInstrInfo::insertIndirectBranch(MachineBasicBlock &MBB,
  319. MachineBasicBlock &DestBB,
  320. MachineBasicBlock &RestoreBB,
  321. const DebugLoc &DL,
  322. int64_t BrOffset,
  323. RegScavenger *RS) const {
  324. assert(RS && "RegScavenger required for long branching");
  325. assert(MBB.empty() &&
  326. "new block should be inserted for expanding unconditional branch");
  327. assert(MBB.pred_size() == 1);
  328. MachineFunction *MF = MBB.getParent();
  329. MachineRegisterInfo &MRI = MF->getRegInfo();
  330. const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
  331. LoongArchMachineFunctionInfo *LAFI =
  332. MF->getInfo<LoongArchMachineFunctionInfo>();
  333. if (!isInt<32>(BrOffset))
  334. report_fatal_error(
  335. "Branch offsets outside of the signed 32-bit range not supported");
  336. Register ScratchReg = MRI.createVirtualRegister(&LoongArch::GPRRegClass);
  337. auto II = MBB.end();
  338. MachineInstr &PCALAU12I =
  339. *BuildMI(MBB, II, DL, get(LoongArch::PCALAU12I), ScratchReg)
  340. .addMBB(&DestBB, LoongArchII::MO_PCREL_HI);
  341. MachineInstr &ADDI =
  342. *BuildMI(MBB, II, DL,
  343. get(STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W),
  344. ScratchReg)
  345. .addReg(ScratchReg)
  346. .addMBB(&DestBB, LoongArchII::MO_PCREL_LO);
  347. BuildMI(MBB, II, DL, get(LoongArch::PseudoBRIND))
  348. .addReg(ScratchReg, RegState::Kill)
  349. .addImm(0);
  350. RS->enterBasicBlockEnd(MBB);
  351. Register Scav = RS->scavengeRegisterBackwards(
  352. LoongArch::GPRRegClass, PCALAU12I.getIterator(), /*RestoreAfter=*/false,
  353. /*SPAdj=*/0, /*AllowSpill=*/false);
  354. if (Scav != LoongArch::NoRegister)
  355. RS->setRegUsed(Scav);
  356. else {
  357. // When there is no scavenged register, it needs to specify a register.
  358. // Specify t8 register because it won't be used too often.
  359. Scav = LoongArch::R20;
  360. int FrameIndex = LAFI->getBranchRelaxationSpillFrameIndex();
  361. if (FrameIndex == -1)
  362. report_fatal_error("The function size is incorrectly estimated.");
  363. storeRegToStackSlot(MBB, PCALAU12I, Scav, /*IsKill=*/true, FrameIndex,
  364. &LoongArch::GPRRegClass, TRI, Register());
  365. TRI->eliminateFrameIndex(std::prev(PCALAU12I.getIterator()),
  366. /*SpAdj=*/0, /*FIOperandNum=*/1);
  367. PCALAU12I.getOperand(1).setMBB(&RestoreBB);
  368. ADDI.getOperand(2).setMBB(&RestoreBB);
  369. loadRegFromStackSlot(RestoreBB, RestoreBB.end(), Scav, FrameIndex,
  370. &LoongArch::GPRRegClass, TRI, Register());
  371. TRI->eliminateFrameIndex(RestoreBB.back(),
  372. /*SpAdj=*/0, /*FIOperandNum=*/1);
  373. }
  374. MRI.replaceRegWith(ScratchReg, Scav);
  375. MRI.clearVirtRegs();
  376. }
  377. static unsigned getOppositeBranchOpc(unsigned Opc) {
  378. switch (Opc) {
  379. default:
  380. llvm_unreachable("Unrecognized conditional branch");
  381. case LoongArch::BEQ:
  382. return LoongArch::BNE;
  383. case LoongArch::BNE:
  384. return LoongArch::BEQ;
  385. case LoongArch::BEQZ:
  386. return LoongArch::BNEZ;
  387. case LoongArch::BNEZ:
  388. return LoongArch::BEQZ;
  389. case LoongArch::BCEQZ:
  390. return LoongArch::BCNEZ;
  391. case LoongArch::BCNEZ:
  392. return LoongArch::BCEQZ;
  393. case LoongArch::BLT:
  394. return LoongArch::BGE;
  395. case LoongArch::BGE:
  396. return LoongArch::BLT;
  397. case LoongArch::BLTU:
  398. return LoongArch::BGEU;
  399. case LoongArch::BGEU:
  400. return LoongArch::BLTU;
  401. }
  402. }
  403. bool LoongArchInstrInfo::reverseBranchCondition(
  404. SmallVectorImpl<MachineOperand> &Cond) const {
  405. assert((Cond.size() && Cond.size() <= 3) && "Invalid branch condition!");
  406. Cond[0].setImm(getOppositeBranchOpc(Cond[0].getImm()));
  407. return false;
  408. }
  409. std::pair<unsigned, unsigned>
  410. LoongArchInstrInfo::decomposeMachineOperandsTargetFlags(unsigned TF) const {
  411. return std::make_pair(TF, 0u);
  412. }
  413. ArrayRef<std::pair<unsigned, const char *>>
  414. LoongArchInstrInfo::getSerializableDirectMachineOperandTargetFlags() const {
  415. using namespace LoongArchII;
  416. // TODO: Add more target flags.
  417. static const std::pair<unsigned, const char *> TargetFlags[] = {
  418. {MO_CALL, "loongarch-call"},
  419. {MO_CALL_PLT, "loongarch-call-plt"},
  420. {MO_PCREL_HI, "loongarch-pcrel-hi"},
  421. {MO_PCREL_LO, "loongarch-pcrel-lo"},
  422. {MO_GOT_PC_HI, "loongarch-got-pc-hi"},
  423. {MO_GOT_PC_LO, "loongarch-got-pc-lo"},
  424. {MO_LE_HI, "loongarch-le-hi"},
  425. {MO_LE_LO, "loongarch-le-lo"},
  426. {MO_IE_PC_HI, "loongarch-ie-pc-hi"},
  427. {MO_IE_PC_LO, "loongarch-ie-pc-lo"},
  428. {MO_LD_PC_HI, "loongarch-ld-pc-hi"},
  429. {MO_GD_PC_HI, "loongarch-gd-pc-hi"}};
  430. return ArrayRef(TargetFlags);
  431. }