CSEInfo.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447
  1. //===- CSEInfo.cpp ------------------------------===//
  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. //
  10. //===----------------------------------------------------------------------===//
  11. #include "llvm/CodeGen/GlobalISel/CSEInfo.h"
  12. #include "llvm/CodeGen/MachineRegisterInfo.h"
  13. #include "llvm/InitializePasses.h"
  14. #include "llvm/Support/Error.h"
  15. #define DEBUG_TYPE "cseinfo"
  16. using namespace llvm;
  17. char llvm::GISelCSEAnalysisWrapperPass::ID = 0;
  18. GISelCSEAnalysisWrapperPass::GISelCSEAnalysisWrapperPass()
  19. : MachineFunctionPass(ID) {
  20. initializeGISelCSEAnalysisWrapperPassPass(*PassRegistry::getPassRegistry());
  21. }
  22. INITIALIZE_PASS_BEGIN(GISelCSEAnalysisWrapperPass, DEBUG_TYPE,
  23. "Analysis containing CSE Info", false, true)
  24. INITIALIZE_PASS_END(GISelCSEAnalysisWrapperPass, DEBUG_TYPE,
  25. "Analysis containing CSE Info", false, true)
  26. /// -------- UniqueMachineInstr -------------//
  27. void UniqueMachineInstr::Profile(FoldingSetNodeID &ID) {
  28. GISelInstProfileBuilder(ID, MI->getMF()->getRegInfo()).addNodeID(MI);
  29. }
  30. /// -----------------------------------------
  31. /// --------- CSEConfigFull ---------- ///
  32. bool CSEConfigFull::shouldCSEOpc(unsigned Opc) {
  33. switch (Opc) {
  34. default:
  35. break;
  36. case TargetOpcode::G_ADD:
  37. case TargetOpcode::G_AND:
  38. case TargetOpcode::G_ASHR:
  39. case TargetOpcode::G_LSHR:
  40. case TargetOpcode::G_MUL:
  41. case TargetOpcode::G_OR:
  42. case TargetOpcode::G_SHL:
  43. case TargetOpcode::G_SUB:
  44. case TargetOpcode::G_XOR:
  45. case TargetOpcode::G_UDIV:
  46. case TargetOpcode::G_SDIV:
  47. case TargetOpcode::G_UREM:
  48. case TargetOpcode::G_SREM:
  49. case TargetOpcode::G_CONSTANT:
  50. case TargetOpcode::G_FCONSTANT:
  51. case TargetOpcode::G_IMPLICIT_DEF:
  52. case TargetOpcode::G_ZEXT:
  53. case TargetOpcode::G_SEXT:
  54. case TargetOpcode::G_ANYEXT:
  55. case TargetOpcode::G_UNMERGE_VALUES:
  56. case TargetOpcode::G_TRUNC:
  57. case TargetOpcode::G_PTR_ADD:
  58. case TargetOpcode::G_EXTRACT:
  59. case TargetOpcode::G_SELECT:
  60. case TargetOpcode::G_BUILD_VECTOR:
  61. case TargetOpcode::G_BUILD_VECTOR_TRUNC:
  62. case TargetOpcode::G_SEXT_INREG:
  63. return true;
  64. }
  65. return false;
  66. }
  67. bool CSEConfigConstantOnly::shouldCSEOpc(unsigned Opc) {
  68. return Opc == TargetOpcode::G_CONSTANT || Opc == TargetOpcode::G_FCONSTANT ||
  69. Opc == TargetOpcode::G_IMPLICIT_DEF;
  70. }
  71. std::unique_ptr<CSEConfigBase>
  72. llvm::getStandardCSEConfigForOpt(CodeGenOpt::Level Level) {
  73. std::unique_ptr<CSEConfigBase> Config;
  74. if (Level == CodeGenOpt::None)
  75. Config = std::make_unique<CSEConfigConstantOnly>();
  76. else
  77. Config = std::make_unique<CSEConfigFull>();
  78. return Config;
  79. }
  80. /// -----------------------------------------
  81. /// -------- GISelCSEInfo -------------//
  82. void GISelCSEInfo::setMF(MachineFunction &MF) {
  83. this->MF = &MF;
  84. this->MRI = &MF.getRegInfo();
  85. }
  86. GISelCSEInfo::~GISelCSEInfo() = default;
  87. bool GISelCSEInfo::isUniqueMachineInstValid(
  88. const UniqueMachineInstr &UMI) const {
  89. // Should we check here and assert that the instruction has been fully
  90. // constructed?
  91. // FIXME: Any other checks required to be done here? Remove this method if
  92. // none.
  93. return true;
  94. }
  95. void GISelCSEInfo::invalidateUniqueMachineInstr(UniqueMachineInstr *UMI) {
  96. bool Removed = CSEMap.RemoveNode(UMI);
  97. (void)Removed;
  98. assert(Removed && "Invalidation called on invalid UMI");
  99. // FIXME: Should UMI be deallocated/destroyed?
  100. }
  101. UniqueMachineInstr *GISelCSEInfo::getNodeIfExists(FoldingSetNodeID &ID,
  102. MachineBasicBlock *MBB,
  103. void *&InsertPos) {
  104. auto *Node = CSEMap.FindNodeOrInsertPos(ID, InsertPos);
  105. if (Node) {
  106. if (!isUniqueMachineInstValid(*Node)) {
  107. invalidateUniqueMachineInstr(Node);
  108. return nullptr;
  109. }
  110. if (Node->MI->getParent() != MBB)
  111. return nullptr;
  112. }
  113. return Node;
  114. }
  115. void GISelCSEInfo::insertNode(UniqueMachineInstr *UMI, void *InsertPos) {
  116. handleRecordedInsts();
  117. assert(UMI);
  118. UniqueMachineInstr *MaybeNewNode = UMI;
  119. if (InsertPos)
  120. CSEMap.InsertNode(UMI, InsertPos);
  121. else
  122. MaybeNewNode = CSEMap.GetOrInsertNode(UMI);
  123. if (MaybeNewNode != UMI) {
  124. // A similar node exists in the folding set. Let's ignore this one.
  125. return;
  126. }
  127. assert(InstrMapping.count(UMI->MI) == 0 &&
  128. "This instruction should not be in the map");
  129. InstrMapping[UMI->MI] = MaybeNewNode;
  130. }
  131. UniqueMachineInstr *GISelCSEInfo::getUniqueInstrForMI(const MachineInstr *MI) {
  132. assert(shouldCSE(MI->getOpcode()) && "Trying to CSE an unsupported Node");
  133. auto *Node = new (UniqueInstrAllocator) UniqueMachineInstr(MI);
  134. return Node;
  135. }
  136. void GISelCSEInfo::insertInstr(MachineInstr *MI, void *InsertPos) {
  137. assert(MI);
  138. // If it exists in temporary insts, remove it.
  139. TemporaryInsts.remove(MI);
  140. auto *Node = getUniqueInstrForMI(MI);
  141. insertNode(Node, InsertPos);
  142. }
  143. MachineInstr *GISelCSEInfo::getMachineInstrIfExists(FoldingSetNodeID &ID,
  144. MachineBasicBlock *MBB,
  145. void *&InsertPos) {
  146. handleRecordedInsts();
  147. if (auto *Inst = getNodeIfExists(ID, MBB, InsertPos)) {
  148. LLVM_DEBUG(dbgs() << "CSEInfo::Found Instr " << *Inst->MI;);
  149. return const_cast<MachineInstr *>(Inst->MI);
  150. }
  151. return nullptr;
  152. }
  153. void GISelCSEInfo::countOpcodeHit(unsigned Opc) {
  154. #ifndef NDEBUG
  155. if (OpcodeHitTable.count(Opc))
  156. OpcodeHitTable[Opc] += 1;
  157. else
  158. OpcodeHitTable[Opc] = 1;
  159. #endif
  160. // Else do nothing.
  161. }
  162. void GISelCSEInfo::recordNewInstruction(MachineInstr *MI) {
  163. if (shouldCSE(MI->getOpcode())) {
  164. TemporaryInsts.insert(MI);
  165. LLVM_DEBUG(dbgs() << "CSEInfo::Recording new MI " << *MI);
  166. }
  167. }
  168. void GISelCSEInfo::handleRecordedInst(MachineInstr *MI) {
  169. assert(shouldCSE(MI->getOpcode()) && "Invalid instruction for CSE");
  170. auto *UMI = InstrMapping.lookup(MI);
  171. LLVM_DEBUG(dbgs() << "CSEInfo::Handling recorded MI " << *MI);
  172. if (UMI) {
  173. // Invalidate this MI.
  174. invalidateUniqueMachineInstr(UMI);
  175. InstrMapping.erase(MI);
  176. }
  177. /// Now insert the new instruction.
  178. if (UMI) {
  179. /// We'll reuse the same UniqueMachineInstr to avoid the new
  180. /// allocation.
  181. *UMI = UniqueMachineInstr(MI);
  182. insertNode(UMI, nullptr);
  183. } else {
  184. /// This is a new instruction. Allocate a new UniqueMachineInstr and
  185. /// Insert.
  186. insertInstr(MI);
  187. }
  188. }
  189. void GISelCSEInfo::handleRemoveInst(MachineInstr *MI) {
  190. if (auto *UMI = InstrMapping.lookup(MI)) {
  191. invalidateUniqueMachineInstr(UMI);
  192. InstrMapping.erase(MI);
  193. }
  194. TemporaryInsts.remove(MI);
  195. }
  196. void GISelCSEInfo::handleRecordedInsts() {
  197. while (!TemporaryInsts.empty()) {
  198. auto *MI = TemporaryInsts.pop_back_val();
  199. handleRecordedInst(MI);
  200. }
  201. }
  202. bool GISelCSEInfo::shouldCSE(unsigned Opc) const {
  203. assert(CSEOpt.get() && "CSEConfig not set");
  204. return CSEOpt->shouldCSEOpc(Opc);
  205. }
  206. void GISelCSEInfo::erasingInstr(MachineInstr &MI) { handleRemoveInst(&MI); }
  207. void GISelCSEInfo::createdInstr(MachineInstr &MI) { recordNewInstruction(&MI); }
  208. void GISelCSEInfo::changingInstr(MachineInstr &MI) {
  209. // For now, perform erase, followed by insert.
  210. erasingInstr(MI);
  211. createdInstr(MI);
  212. }
  213. void GISelCSEInfo::changedInstr(MachineInstr &MI) { changingInstr(MI); }
  214. void GISelCSEInfo::analyze(MachineFunction &MF) {
  215. setMF(MF);
  216. for (auto &MBB : MF) {
  217. if (MBB.empty())
  218. continue;
  219. for (MachineInstr &MI : MBB) {
  220. if (!shouldCSE(MI.getOpcode()))
  221. continue;
  222. LLVM_DEBUG(dbgs() << "CSEInfo::Add MI: " << MI);
  223. insertInstr(&MI);
  224. }
  225. }
  226. }
  227. void GISelCSEInfo::releaseMemory() {
  228. print();
  229. CSEMap.clear();
  230. InstrMapping.clear();
  231. UniqueInstrAllocator.Reset();
  232. TemporaryInsts.clear();
  233. CSEOpt.reset();
  234. MRI = nullptr;
  235. MF = nullptr;
  236. #ifndef NDEBUG
  237. OpcodeHitTable.clear();
  238. #endif
  239. }
  240. #ifndef NDEBUG
  241. static const char *stringify(const MachineInstr *MI, std::string &S) {
  242. raw_string_ostream OS(S);
  243. OS << *MI;
  244. return OS.str().c_str();
  245. }
  246. #endif
  247. Error GISelCSEInfo::verify() {
  248. #ifndef NDEBUG
  249. std::string S1, S2;
  250. handleRecordedInsts();
  251. // For each instruction in map from MI -> UMI,
  252. // Profile(MI) and make sure UMI is found for that profile.
  253. for (auto &It : InstrMapping) {
  254. FoldingSetNodeID TmpID;
  255. GISelInstProfileBuilder(TmpID, *MRI).addNodeID(It.first);
  256. void *InsertPos;
  257. UniqueMachineInstr *FoundNode =
  258. CSEMap.FindNodeOrInsertPos(TmpID, InsertPos);
  259. if (FoundNode != It.second)
  260. return createStringError(std::errc::not_supported,
  261. "CSEMap mismatch, InstrMapping has MIs without "
  262. "corresponding Nodes in CSEMap:\n%s",
  263. stringify(It.second->MI, S1));
  264. }
  265. // For every node in the CSEMap, make sure that the InstrMapping
  266. // points to it.
  267. for (const UniqueMachineInstr &UMI : CSEMap) {
  268. if (!InstrMapping.count(UMI.MI))
  269. return createStringError(std::errc::not_supported,
  270. "Node in CSE without InstrMapping:\n%s",
  271. stringify(UMI.MI, S1));
  272. if (InstrMapping[UMI.MI] != &UMI)
  273. return createStringError(std::make_error_code(std::errc::not_supported),
  274. "Mismatch in CSE mapping:\n%s\n%s",
  275. stringify(InstrMapping[UMI.MI]->MI, S1),
  276. stringify(UMI.MI, S2));
  277. }
  278. #endif
  279. return Error::success();
  280. }
  281. void GISelCSEInfo::print() {
  282. LLVM_DEBUG(for (auto &It
  283. : OpcodeHitTable) {
  284. dbgs() << "CSEInfo::CSE Hit for Opc " << It.first << " : " << It.second
  285. << "\n";
  286. };);
  287. }
  288. /// -----------------------------------------
  289. // ---- Profiling methods for FoldingSetNode --- //
  290. const GISelInstProfileBuilder &
  291. GISelInstProfileBuilder::addNodeID(const MachineInstr *MI) const {
  292. addNodeIDMBB(MI->getParent());
  293. addNodeIDOpcode(MI->getOpcode());
  294. for (const auto &Op : MI->operands())
  295. addNodeIDMachineOperand(Op);
  296. addNodeIDFlag(MI->getFlags());
  297. return *this;
  298. }
  299. const GISelInstProfileBuilder &
  300. GISelInstProfileBuilder::addNodeIDOpcode(unsigned Opc) const {
  301. ID.AddInteger(Opc);
  302. return *this;
  303. }
  304. const GISelInstProfileBuilder &
  305. GISelInstProfileBuilder::addNodeIDRegType(const LLT Ty) const {
  306. uint64_t Val = Ty.getUniqueRAWLLTData();
  307. ID.AddInteger(Val);
  308. return *this;
  309. }
  310. const GISelInstProfileBuilder &
  311. GISelInstProfileBuilder::addNodeIDRegType(const TargetRegisterClass *RC) const {
  312. ID.AddPointer(RC);
  313. return *this;
  314. }
  315. const GISelInstProfileBuilder &
  316. GISelInstProfileBuilder::addNodeIDRegType(const RegisterBank *RB) const {
  317. ID.AddPointer(RB);
  318. return *this;
  319. }
  320. const GISelInstProfileBuilder &
  321. GISelInstProfileBuilder::addNodeIDImmediate(int64_t Imm) const {
  322. ID.AddInteger(Imm);
  323. return *this;
  324. }
  325. const GISelInstProfileBuilder &
  326. GISelInstProfileBuilder::addNodeIDRegNum(Register Reg) const {
  327. ID.AddInteger(Reg);
  328. return *this;
  329. }
  330. const GISelInstProfileBuilder &
  331. GISelInstProfileBuilder::addNodeIDRegType(const Register Reg) const {
  332. addNodeIDMachineOperand(MachineOperand::CreateReg(Reg, false));
  333. return *this;
  334. }
  335. const GISelInstProfileBuilder &
  336. GISelInstProfileBuilder::addNodeIDMBB(const MachineBasicBlock *MBB) const {
  337. ID.AddPointer(MBB);
  338. return *this;
  339. }
  340. const GISelInstProfileBuilder &
  341. GISelInstProfileBuilder::addNodeIDFlag(unsigned Flag) const {
  342. if (Flag)
  343. ID.AddInteger(Flag);
  344. return *this;
  345. }
  346. const GISelInstProfileBuilder &
  347. GISelInstProfileBuilder::addNodeIDReg(Register Reg) const {
  348. LLT Ty = MRI.getType(Reg);
  349. if (Ty.isValid())
  350. addNodeIDRegType(Ty);
  351. if (const RegClassOrRegBank &RCOrRB = MRI.getRegClassOrRegBank(Reg)) {
  352. if (const auto *RB = RCOrRB.dyn_cast<const RegisterBank *>())
  353. addNodeIDRegType(RB);
  354. else if (const auto *RC = RCOrRB.dyn_cast<const TargetRegisterClass *>())
  355. addNodeIDRegType(RC);
  356. }
  357. return *this;
  358. }
  359. const GISelInstProfileBuilder &GISelInstProfileBuilder::addNodeIDMachineOperand(
  360. const MachineOperand &MO) const {
  361. if (MO.isReg()) {
  362. Register Reg = MO.getReg();
  363. if (!MO.isDef())
  364. addNodeIDRegNum(Reg);
  365. // Profile the register properties.
  366. addNodeIDReg(Reg);
  367. assert(!MO.isImplicit() && "Unhandled case");
  368. } else if (MO.isImm())
  369. ID.AddInteger(MO.getImm());
  370. else if (MO.isCImm())
  371. ID.AddPointer(MO.getCImm());
  372. else if (MO.isFPImm())
  373. ID.AddPointer(MO.getFPImm());
  374. else if (MO.isPredicate())
  375. ID.AddInteger(MO.getPredicate());
  376. else
  377. llvm_unreachable("Unhandled operand type");
  378. // Handle other types
  379. return *this;
  380. }
  381. GISelCSEInfo &
  382. GISelCSEAnalysisWrapper::get(std::unique_ptr<CSEConfigBase> CSEOpt,
  383. bool Recompute) {
  384. if (!AlreadyComputed || Recompute) {
  385. Info.releaseMemory();
  386. Info.setCSEConfig(std::move(CSEOpt));
  387. Info.analyze(*MF);
  388. AlreadyComputed = true;
  389. }
  390. return Info;
  391. }
  392. void GISelCSEAnalysisWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
  393. AU.setPreservesAll();
  394. MachineFunctionPass::getAnalysisUsage(AU);
  395. }
  396. bool GISelCSEAnalysisWrapperPass::runOnMachineFunction(MachineFunction &MF) {
  397. releaseMemory();
  398. Wrapper.setMF(MF);
  399. return false;
  400. }