CSEInfo.cpp 13 KB

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