Legalizer.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  1. //===-- llvm/CodeGen/GlobalISel/Legalizer.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. /// \file This file implements the LegalizerHelper class to legalize individual
  10. /// instructions and the LegalizePass wrapper pass for the primary
  11. /// legalization.
  12. //
  13. //===----------------------------------------------------------------------===//
  14. #include "llvm/CodeGen/GlobalISel/Legalizer.h"
  15. #include "llvm/ADT/PostOrderIterator.h"
  16. #include "llvm/ADT/SetVector.h"
  17. #include "llvm/CodeGen/GlobalISel/CSEInfo.h"
  18. #include "llvm/CodeGen/GlobalISel/CSEMIRBuilder.h"
  19. #include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h"
  20. #include "llvm/CodeGen/GlobalISel/GISelWorkList.h"
  21. #include "llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h"
  22. #include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
  23. #include "llvm/CodeGen/GlobalISel/LostDebugLocObserver.h"
  24. #include "llvm/CodeGen/GlobalISel/Utils.h"
  25. #include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h"
  26. #include "llvm/CodeGen/MachineRegisterInfo.h"
  27. #include "llvm/CodeGen/TargetPassConfig.h"
  28. #include "llvm/CodeGen/TargetSubtargetInfo.h"
  29. #include "llvm/InitializePasses.h"
  30. #include "llvm/Support/Debug.h"
  31. #include "llvm/Support/Error.h"
  32. #include "llvm/Target/TargetMachine.h"
  33. #include <iterator>
  34. #define DEBUG_TYPE "legalizer"
  35. using namespace llvm;
  36. static cl::opt<bool>
  37. EnableCSEInLegalizer("enable-cse-in-legalizer",
  38. cl::desc("Should enable CSE in Legalizer"),
  39. cl::Optional, cl::init(false));
  40. // This is a temporary hack, should be removed soon.
  41. static cl::opt<bool> AllowGInsertAsArtifact(
  42. "allow-ginsert-as-artifact",
  43. cl::desc("Allow G_INSERT to be considered an artifact. Hack around AMDGPU "
  44. "test infinite loops."),
  45. cl::Optional, cl::init(true));
  46. enum class DebugLocVerifyLevel {
  47. None,
  48. Legalizations,
  49. LegalizationsAndArtifactCombiners,
  50. };
  51. #ifndef NDEBUG
  52. static cl::opt<DebugLocVerifyLevel> VerifyDebugLocs(
  53. "verify-legalizer-debug-locs",
  54. cl::desc("Verify that debug locations are handled"),
  55. cl::values(
  56. clEnumValN(DebugLocVerifyLevel::None, "none", "No verification"),
  57. clEnumValN(DebugLocVerifyLevel::Legalizations, "legalizations",
  58. "Verify legalizations"),
  59. clEnumValN(DebugLocVerifyLevel::LegalizationsAndArtifactCombiners,
  60. "legalizations+artifactcombiners",
  61. "Verify legalizations and artifact combines")),
  62. cl::init(DebugLocVerifyLevel::Legalizations));
  63. #else
  64. // Always disable it for release builds by preventing the observer from being
  65. // installed.
  66. static const DebugLocVerifyLevel VerifyDebugLocs = DebugLocVerifyLevel::None;
  67. #endif
  68. char Legalizer::ID = 0;
  69. INITIALIZE_PASS_BEGIN(Legalizer, DEBUG_TYPE,
  70. "Legalize the Machine IR a function's Machine IR", false,
  71. false)
  72. INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
  73. INITIALIZE_PASS_DEPENDENCY(GISelCSEAnalysisWrapperPass)
  74. INITIALIZE_PASS_END(Legalizer, DEBUG_TYPE,
  75. "Legalize the Machine IR a function's Machine IR", false,
  76. false)
  77. Legalizer::Legalizer() : MachineFunctionPass(ID) { }
  78. void Legalizer::getAnalysisUsage(AnalysisUsage &AU) const {
  79. AU.addRequired<TargetPassConfig>();
  80. AU.addRequired<GISelCSEAnalysisWrapperPass>();
  81. AU.addPreserved<GISelCSEAnalysisWrapperPass>();
  82. getSelectionDAGFallbackAnalysisUsage(AU);
  83. MachineFunctionPass::getAnalysisUsage(AU);
  84. }
  85. void Legalizer::init(MachineFunction &MF) {
  86. }
  87. static bool isArtifact(const MachineInstr &MI) {
  88. switch (MI.getOpcode()) {
  89. default:
  90. return false;
  91. case TargetOpcode::G_TRUNC:
  92. case TargetOpcode::G_ZEXT:
  93. case TargetOpcode::G_ANYEXT:
  94. case TargetOpcode::G_SEXT:
  95. case TargetOpcode::G_MERGE_VALUES:
  96. case TargetOpcode::G_UNMERGE_VALUES:
  97. case TargetOpcode::G_CONCAT_VECTORS:
  98. case TargetOpcode::G_BUILD_VECTOR:
  99. case TargetOpcode::G_EXTRACT:
  100. return true;
  101. case TargetOpcode::G_INSERT:
  102. return AllowGInsertAsArtifact;
  103. }
  104. }
  105. using InstListTy = GISelWorkList<256>;
  106. using ArtifactListTy = GISelWorkList<128>;
  107. namespace {
  108. class LegalizerWorkListManager : public GISelChangeObserver {
  109. InstListTy &InstList;
  110. ArtifactListTy &ArtifactList;
  111. #ifndef NDEBUG
  112. SmallVector<MachineInstr *, 4> NewMIs;
  113. #endif
  114. public:
  115. LegalizerWorkListManager(InstListTy &Insts, ArtifactListTy &Arts)
  116. : InstList(Insts), ArtifactList(Arts) {}
  117. void createdOrChangedInstr(MachineInstr &MI) {
  118. // Only legalize pre-isel generic instructions.
  119. // Legalization process could generate Target specific pseudo
  120. // instructions with generic types. Don't record them
  121. if (isPreISelGenericOpcode(MI.getOpcode())) {
  122. if (isArtifact(MI))
  123. ArtifactList.insert(&MI);
  124. else
  125. InstList.insert(&MI);
  126. }
  127. }
  128. void createdInstr(MachineInstr &MI) override {
  129. LLVM_DEBUG(NewMIs.push_back(&MI));
  130. createdOrChangedInstr(MI);
  131. }
  132. void printNewInstrs() {
  133. LLVM_DEBUG({
  134. for (const auto *MI : NewMIs)
  135. dbgs() << ".. .. New MI: " << *MI;
  136. NewMIs.clear();
  137. });
  138. }
  139. void erasingInstr(MachineInstr &MI) override {
  140. LLVM_DEBUG(dbgs() << ".. .. Erasing: " << MI);
  141. InstList.remove(&MI);
  142. ArtifactList.remove(&MI);
  143. }
  144. void changingInstr(MachineInstr &MI) override {
  145. LLVM_DEBUG(dbgs() << ".. .. Changing MI: " << MI);
  146. }
  147. void changedInstr(MachineInstr &MI) override {
  148. // When insts change, we want to revisit them to legalize them again.
  149. // We'll consider them the same as created.
  150. LLVM_DEBUG(dbgs() << ".. .. Changed MI: " << MI);
  151. createdOrChangedInstr(MI);
  152. }
  153. };
  154. } // namespace
  155. Legalizer::MFResult
  156. Legalizer::legalizeMachineFunction(MachineFunction &MF, const LegalizerInfo &LI,
  157. ArrayRef<GISelChangeObserver *> AuxObservers,
  158. LostDebugLocObserver &LocObserver,
  159. MachineIRBuilder &MIRBuilder) {
  160. MIRBuilder.setMF(MF);
  161. MachineRegisterInfo &MRI = MF.getRegInfo();
  162. // Populate worklists.
  163. InstListTy InstList;
  164. ArtifactListTy ArtifactList;
  165. ReversePostOrderTraversal<MachineFunction *> RPOT(&MF);
  166. // Perform legalization bottom up so we can DCE as we legalize.
  167. // Traverse BB in RPOT and within each basic block, add insts top down,
  168. // so when we pop_back_val in the legalization process, we traverse bottom-up.
  169. for (auto *MBB : RPOT) {
  170. if (MBB->empty())
  171. continue;
  172. for (MachineInstr &MI : *MBB) {
  173. // Only legalize pre-isel generic instructions: others don't have types
  174. // and are assumed to be legal.
  175. if (!isPreISelGenericOpcode(MI.getOpcode()))
  176. continue;
  177. if (isArtifact(MI))
  178. ArtifactList.deferred_insert(&MI);
  179. else
  180. InstList.deferred_insert(&MI);
  181. }
  182. }
  183. ArtifactList.finalize();
  184. InstList.finalize();
  185. // This observer keeps the worklists updated.
  186. LegalizerWorkListManager WorkListObserver(InstList, ArtifactList);
  187. // We want both WorkListObserver as well as all the auxiliary observers (e.g.
  188. // CSEInfo) to observe all changes. Use the wrapper observer.
  189. GISelObserverWrapper WrapperObserver(&WorkListObserver);
  190. for (GISelChangeObserver *Observer : AuxObservers)
  191. WrapperObserver.addObserver(Observer);
  192. // Now install the observer as the delegate to MF.
  193. // This will keep all the observers notified about new insertions/deletions.
  194. RAIIMFObsDelInstaller Installer(MF, WrapperObserver);
  195. LegalizerHelper Helper(MF, LI, WrapperObserver, MIRBuilder);
  196. LegalizationArtifactCombiner ArtCombiner(MIRBuilder, MRI, LI);
  197. bool Changed = false;
  198. SmallVector<MachineInstr *, 128> RetryList;
  199. do {
  200. LLVM_DEBUG(dbgs() << "=== New Iteration ===\n");
  201. assert(RetryList.empty() && "Expected no instructions in RetryList");
  202. unsigned NumArtifacts = ArtifactList.size();
  203. while (!InstList.empty()) {
  204. MachineInstr &MI = *InstList.pop_back_val();
  205. assert(isPreISelGenericOpcode(MI.getOpcode()) &&
  206. "Expecting generic opcode");
  207. if (isTriviallyDead(MI, MRI)) {
  208. eraseInstr(MI, MRI, &LocObserver);
  209. continue;
  210. }
  211. // Do the legalization for this instruction.
  212. auto Res = Helper.legalizeInstrStep(MI, LocObserver);
  213. // Error out if we couldn't legalize this instruction. We may want to
  214. // fall back to DAG ISel instead in the future.
  215. if (Res == LegalizerHelper::UnableToLegalize) {
  216. // Move illegal artifacts to RetryList instead of aborting because
  217. // legalizing InstList may generate artifacts that allow
  218. // ArtifactCombiner to combine away them.
  219. if (isArtifact(MI)) {
  220. LLVM_DEBUG(dbgs() << ".. Not legalized, moving to artifacts retry\n");
  221. assert(NumArtifacts == 0 &&
  222. "Artifacts are only expected in instruction list starting the "
  223. "second iteration, but each iteration starting second must "
  224. "start with an empty artifacts list");
  225. (void)NumArtifacts;
  226. RetryList.push_back(&MI);
  227. continue;
  228. }
  229. Helper.MIRBuilder.stopObservingChanges();
  230. return {Changed, &MI};
  231. }
  232. WorkListObserver.printNewInstrs();
  233. LocObserver.checkpoint();
  234. Changed |= Res == LegalizerHelper::Legalized;
  235. }
  236. // Try to combine the instructions in RetryList again if there
  237. // are new artifacts. If not, stop legalizing.
  238. if (!RetryList.empty()) {
  239. if (!ArtifactList.empty()) {
  240. while (!RetryList.empty())
  241. ArtifactList.insert(RetryList.pop_back_val());
  242. } else {
  243. LLVM_DEBUG(dbgs() << "No new artifacts created, not retrying!\n");
  244. Helper.MIRBuilder.stopObservingChanges();
  245. return {Changed, RetryList.front()};
  246. }
  247. }
  248. LocObserver.checkpoint();
  249. while (!ArtifactList.empty()) {
  250. MachineInstr &MI = *ArtifactList.pop_back_val();
  251. assert(isPreISelGenericOpcode(MI.getOpcode()) &&
  252. "Expecting generic opcode");
  253. if (isTriviallyDead(MI, MRI)) {
  254. eraseInstr(MI, MRI, &LocObserver);
  255. continue;
  256. }
  257. SmallVector<MachineInstr *, 4> DeadInstructions;
  258. LLVM_DEBUG(dbgs() << "Trying to combine: " << MI);
  259. if (ArtCombiner.tryCombineInstruction(MI, DeadInstructions,
  260. WrapperObserver)) {
  261. WorkListObserver.printNewInstrs();
  262. eraseInstrs(DeadInstructions, MRI, &LocObserver);
  263. LocObserver.checkpoint(
  264. VerifyDebugLocs ==
  265. DebugLocVerifyLevel::LegalizationsAndArtifactCombiners);
  266. Changed = true;
  267. continue;
  268. }
  269. // If this was not an artifact (that could be combined away), this might
  270. // need special handling. Add it to InstList, so when it's processed
  271. // there, it has to be legal or specially handled.
  272. else {
  273. LLVM_DEBUG(dbgs() << ".. Not combined, moving to instructions list\n");
  274. InstList.insert(&MI);
  275. }
  276. }
  277. } while (!InstList.empty());
  278. return {Changed, /*FailedOn*/ nullptr};
  279. }
  280. bool Legalizer::runOnMachineFunction(MachineFunction &MF) {
  281. // If the ISel pipeline failed, do not bother running that pass.
  282. if (MF.getProperties().hasProperty(
  283. MachineFunctionProperties::Property::FailedISel))
  284. return false;
  285. LLVM_DEBUG(dbgs() << "Legalize Machine IR for: " << MF.getName() << '\n');
  286. init(MF);
  287. const TargetPassConfig &TPC = getAnalysis<TargetPassConfig>();
  288. GISelCSEAnalysisWrapper &Wrapper =
  289. getAnalysis<GISelCSEAnalysisWrapperPass>().getCSEWrapper();
  290. MachineOptimizationRemarkEmitter MORE(MF, /*MBFI=*/nullptr);
  291. const size_t NumBlocks = MF.size();
  292. std::unique_ptr<MachineIRBuilder> MIRBuilder;
  293. GISelCSEInfo *CSEInfo = nullptr;
  294. bool EnableCSE = EnableCSEInLegalizer.getNumOccurrences()
  295. ? EnableCSEInLegalizer
  296. : TPC.isGISelCSEEnabled();
  297. if (EnableCSE) {
  298. MIRBuilder = std::make_unique<CSEMIRBuilder>();
  299. CSEInfo = &Wrapper.get(TPC.getCSEConfig());
  300. MIRBuilder->setCSEInfo(CSEInfo);
  301. } else
  302. MIRBuilder = std::make_unique<MachineIRBuilder>();
  303. SmallVector<GISelChangeObserver *, 1> AuxObservers;
  304. if (EnableCSE && CSEInfo) {
  305. // We want CSEInfo in addition to WorkListObserver to observe all changes.
  306. AuxObservers.push_back(CSEInfo);
  307. }
  308. assert(!CSEInfo || !errorToBool(CSEInfo->verify()));
  309. LostDebugLocObserver LocObserver(DEBUG_TYPE);
  310. if (VerifyDebugLocs > DebugLocVerifyLevel::None)
  311. AuxObservers.push_back(&LocObserver);
  312. const LegalizerInfo &LI = *MF.getSubtarget().getLegalizerInfo();
  313. MFResult Result =
  314. legalizeMachineFunction(MF, LI, AuxObservers, LocObserver, *MIRBuilder);
  315. if (Result.FailedOn) {
  316. reportGISelFailure(MF, TPC, MORE, "gisel-legalize",
  317. "unable to legalize instruction", *Result.FailedOn);
  318. return false;
  319. }
  320. // For now don't support if new blocks are inserted - we would need to fix the
  321. // outer loop for that.
  322. if (MF.size() != NumBlocks) {
  323. MachineOptimizationRemarkMissed R("gisel-legalize", "GISelFailure",
  324. MF.getFunction().getSubprogram(),
  325. /*MBB=*/nullptr);
  326. R << "inserting blocks is not supported yet";
  327. reportGISelFailure(MF, TPC, MORE, R);
  328. return false;
  329. }
  330. if (LocObserver.getNumLostDebugLocs()) {
  331. MachineOptimizationRemarkMissed R("gisel-legalize", "LostDebugLoc",
  332. MF.getFunction().getSubprogram(),
  333. /*MBB=*/&*MF.begin());
  334. R << "lost "
  335. << ore::NV("NumLostDebugLocs", LocObserver.getNumLostDebugLocs())
  336. << " debug locations during pass";
  337. reportGISelWarning(MF, TPC, MORE, R);
  338. // Example remark:
  339. // --- !Missed
  340. // Pass: gisel-legalize
  341. // Name: GISelFailure
  342. // DebugLoc: { File: '.../legalize-urem.mir', Line: 1, Column: 0 }
  343. // Function: test_urem_s32
  344. // Args:
  345. // - String: 'lost '
  346. // - NumLostDebugLocs: '1'
  347. // - String: ' debug locations during pass'
  348. // ...
  349. }
  350. // If for some reason CSE was not enabled, make sure that we invalidate the
  351. // CSEInfo object (as we currently declare that the analysis is preserved).
  352. // The next time get on the wrapper is called, it will force it to recompute
  353. // the analysis.
  354. if (!EnableCSE)
  355. Wrapper.setComputed(false);
  356. return Result.Changed;
  357. }