xref: /freebsd/contrib/llvm-project/llvm/lib/CodeGen/GlobalISel/Legalizer.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
10b57cec5SDimitry Andric //===-- llvm/CodeGen/GlobalISel/Legalizer.cpp -----------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric /// \file This file implements the LegalizerHelper class to legalize individual
100b57cec5SDimitry Andric /// instructions and the LegalizePass wrapper pass for the primary
110b57cec5SDimitry Andric /// legalization.
120b57cec5SDimitry Andric //
130b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
140b57cec5SDimitry Andric 
150b57cec5SDimitry Andric #include "llvm/CodeGen/GlobalISel/Legalizer.h"
160b57cec5SDimitry Andric #include "llvm/ADT/PostOrderIterator.h"
1781ad6265SDimitry Andric #include "llvm/Analysis/OptimizationRemarkEmitter.h"
180b57cec5SDimitry Andric #include "llvm/CodeGen/GlobalISel/CSEInfo.h"
190b57cec5SDimitry Andric #include "llvm/CodeGen/GlobalISel/CSEMIRBuilder.h"
200b57cec5SDimitry Andric #include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h"
2106c3fb27SDimitry Andric #include "llvm/CodeGen/GlobalISel/GISelKnownBits.h"
220b57cec5SDimitry Andric #include "llvm/CodeGen/GlobalISel/GISelWorkList.h"
230b57cec5SDimitry Andric #include "llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h"
240b57cec5SDimitry Andric #include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
255ffd83dbSDimitry Andric #include "llvm/CodeGen/GlobalISel/LostDebugLocObserver.h"
260b57cec5SDimitry Andric #include "llvm/CodeGen/GlobalISel/Utils.h"
270b57cec5SDimitry Andric #include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h"
280b57cec5SDimitry Andric #include "llvm/CodeGen/TargetPassConfig.h"
290b57cec5SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h"
30480093f4SDimitry Andric #include "llvm/InitializePasses.h"
310b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
325ffd83dbSDimitry Andric #include "llvm/Support/Error.h"
330b57cec5SDimitry Andric 
340b57cec5SDimitry Andric #define DEBUG_TYPE "legalizer"
350b57cec5SDimitry Andric 
360b57cec5SDimitry Andric using namespace llvm;
370b57cec5SDimitry Andric 
380b57cec5SDimitry Andric static cl::opt<bool>
390b57cec5SDimitry Andric     EnableCSEInLegalizer("enable-cse-in-legalizer",
400b57cec5SDimitry Andric                          cl::desc("Should enable CSE in Legalizer"),
410b57cec5SDimitry Andric                          cl::Optional, cl::init(false));
420b57cec5SDimitry Andric 
43fe6060f1SDimitry Andric // This is a temporary hack, should be removed soon.
44fe6060f1SDimitry Andric static cl::opt<bool> AllowGInsertAsArtifact(
45fe6060f1SDimitry Andric     "allow-ginsert-as-artifact",
46fe6060f1SDimitry Andric     cl::desc("Allow G_INSERT to be considered an artifact. Hack around AMDGPU "
47fe6060f1SDimitry Andric              "test infinite loops."),
48fe6060f1SDimitry Andric     cl::Optional, cl::init(true));
49fe6060f1SDimitry Andric 
505ffd83dbSDimitry Andric enum class DebugLocVerifyLevel {
515ffd83dbSDimitry Andric   None,
525ffd83dbSDimitry Andric   Legalizations,
535ffd83dbSDimitry Andric   LegalizationsAndArtifactCombiners,
545ffd83dbSDimitry Andric };
555ffd83dbSDimitry Andric #ifndef NDEBUG
565ffd83dbSDimitry Andric static cl::opt<DebugLocVerifyLevel> VerifyDebugLocs(
575ffd83dbSDimitry Andric     "verify-legalizer-debug-locs",
585ffd83dbSDimitry Andric     cl::desc("Verify that debug locations are handled"),
595ffd83dbSDimitry Andric     cl::values(
605ffd83dbSDimitry Andric         clEnumValN(DebugLocVerifyLevel::None, "none", "No verification"),
615ffd83dbSDimitry Andric         clEnumValN(DebugLocVerifyLevel::Legalizations, "legalizations",
625ffd83dbSDimitry Andric                    "Verify legalizations"),
635ffd83dbSDimitry Andric         clEnumValN(DebugLocVerifyLevel::LegalizationsAndArtifactCombiners,
645ffd83dbSDimitry Andric                    "legalizations+artifactcombiners",
655ffd83dbSDimitry Andric                    "Verify legalizations and artifact combines")),
665ffd83dbSDimitry Andric     cl::init(DebugLocVerifyLevel::Legalizations));
675ffd83dbSDimitry Andric #else
685ffd83dbSDimitry Andric // Always disable it for release builds by preventing the observer from being
695ffd83dbSDimitry Andric // installed.
705ffd83dbSDimitry Andric static const DebugLocVerifyLevel VerifyDebugLocs = DebugLocVerifyLevel::None;
715ffd83dbSDimitry Andric #endif
725ffd83dbSDimitry Andric 
730b57cec5SDimitry Andric char Legalizer::ID = 0;
740b57cec5SDimitry Andric INITIALIZE_PASS_BEGIN(Legalizer, DEBUG_TYPE,
750b57cec5SDimitry Andric                       "Legalize the Machine IR a function's Machine IR", false,
760b57cec5SDimitry Andric                       false)
770b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
780b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(GISelCSEAnalysisWrapperPass)
7906c3fb27SDimitry Andric INITIALIZE_PASS_DEPENDENCY(GISelKnownBitsAnalysis)
800b57cec5SDimitry Andric INITIALIZE_PASS_END(Legalizer, DEBUG_TYPE,
810b57cec5SDimitry Andric                     "Legalize the Machine IR a function's Machine IR", false,
820b57cec5SDimitry Andric                     false)
830b57cec5SDimitry Andric 
840b57cec5SDimitry Andric Legalizer::Legalizer() : MachineFunctionPass(ID) { }
850b57cec5SDimitry Andric 
860b57cec5SDimitry Andric void Legalizer::getAnalysisUsage(AnalysisUsage &AU) const {
870b57cec5SDimitry Andric   AU.addRequired<TargetPassConfig>();
880b57cec5SDimitry Andric   AU.addRequired<GISelCSEAnalysisWrapperPass>();
890b57cec5SDimitry Andric   AU.addPreserved<GISelCSEAnalysisWrapperPass>();
9006c3fb27SDimitry Andric   AU.addRequired<GISelKnownBitsAnalysis>();
9106c3fb27SDimitry Andric   AU.addPreserved<GISelKnownBitsAnalysis>();
920b57cec5SDimitry Andric   getSelectionDAGFallbackAnalysisUsage(AU);
930b57cec5SDimitry Andric   MachineFunctionPass::getAnalysisUsage(AU);
940b57cec5SDimitry Andric }
950b57cec5SDimitry Andric 
960b57cec5SDimitry Andric void Legalizer::init(MachineFunction &MF) {
970b57cec5SDimitry Andric }
980b57cec5SDimitry Andric 
990b57cec5SDimitry Andric static bool isArtifact(const MachineInstr &MI) {
1000b57cec5SDimitry Andric   switch (MI.getOpcode()) {
1010b57cec5SDimitry Andric   default:
1020b57cec5SDimitry Andric     return false;
1030b57cec5SDimitry Andric   case TargetOpcode::G_TRUNC:
1040b57cec5SDimitry Andric   case TargetOpcode::G_ZEXT:
1050b57cec5SDimitry Andric   case TargetOpcode::G_ANYEXT:
1060b57cec5SDimitry Andric   case TargetOpcode::G_SEXT:
1070b57cec5SDimitry Andric   case TargetOpcode::G_MERGE_VALUES:
1080b57cec5SDimitry Andric   case TargetOpcode::G_UNMERGE_VALUES:
1090b57cec5SDimitry Andric   case TargetOpcode::G_CONCAT_VECTORS:
1100b57cec5SDimitry Andric   case TargetOpcode::G_BUILD_VECTOR:
1110b57cec5SDimitry Andric   case TargetOpcode::G_EXTRACT:
1120b57cec5SDimitry Andric     return true;
113fe6060f1SDimitry Andric   case TargetOpcode::G_INSERT:
114fe6060f1SDimitry Andric     return AllowGInsertAsArtifact;
1150b57cec5SDimitry Andric   }
1160b57cec5SDimitry Andric }
1170b57cec5SDimitry Andric using InstListTy = GISelWorkList<256>;
1180b57cec5SDimitry Andric using ArtifactListTy = GISelWorkList<128>;
1190b57cec5SDimitry Andric 
1200b57cec5SDimitry Andric namespace {
1210b57cec5SDimitry Andric class LegalizerWorkListManager : public GISelChangeObserver {
1220b57cec5SDimitry Andric   InstListTy &InstList;
1230b57cec5SDimitry Andric   ArtifactListTy &ArtifactList;
1240b57cec5SDimitry Andric #ifndef NDEBUG
1250b57cec5SDimitry Andric   SmallVector<MachineInstr *, 4> NewMIs;
1260b57cec5SDimitry Andric #endif
1270b57cec5SDimitry Andric 
1280b57cec5SDimitry Andric public:
1290b57cec5SDimitry Andric   LegalizerWorkListManager(InstListTy &Insts, ArtifactListTy &Arts)
1300b57cec5SDimitry Andric       : InstList(Insts), ArtifactList(Arts) {}
1310b57cec5SDimitry Andric 
1320b57cec5SDimitry Andric   void createdOrChangedInstr(MachineInstr &MI) {
1330b57cec5SDimitry Andric     // Only legalize pre-isel generic instructions.
1340b57cec5SDimitry Andric     // Legalization process could generate Target specific pseudo
1350b57cec5SDimitry Andric     // instructions with generic types. Don't record them
1360b57cec5SDimitry Andric     if (isPreISelGenericOpcode(MI.getOpcode())) {
1370b57cec5SDimitry Andric       if (isArtifact(MI))
1380b57cec5SDimitry Andric         ArtifactList.insert(&MI);
1390b57cec5SDimitry Andric       else
1400b57cec5SDimitry Andric         InstList.insert(&MI);
1410b57cec5SDimitry Andric     }
1420b57cec5SDimitry Andric   }
1430b57cec5SDimitry Andric 
1440b57cec5SDimitry Andric   void createdInstr(MachineInstr &MI) override {
1450b57cec5SDimitry Andric     LLVM_DEBUG(NewMIs.push_back(&MI));
1460b57cec5SDimitry Andric     createdOrChangedInstr(MI);
1470b57cec5SDimitry Andric   }
1480b57cec5SDimitry Andric 
1490b57cec5SDimitry Andric   void printNewInstrs() {
1500b57cec5SDimitry Andric     LLVM_DEBUG({
1510b57cec5SDimitry Andric       for (const auto *MI : NewMIs)
1520b57cec5SDimitry Andric         dbgs() << ".. .. New MI: " << *MI;
1530b57cec5SDimitry Andric       NewMIs.clear();
1540b57cec5SDimitry Andric     });
1550b57cec5SDimitry Andric   }
1560b57cec5SDimitry Andric 
1570b57cec5SDimitry Andric   void erasingInstr(MachineInstr &MI) override {
1580b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << ".. .. Erasing: " << MI);
1590b57cec5SDimitry Andric     InstList.remove(&MI);
1600b57cec5SDimitry Andric     ArtifactList.remove(&MI);
1610b57cec5SDimitry Andric   }
1620b57cec5SDimitry Andric 
1630b57cec5SDimitry Andric   void changingInstr(MachineInstr &MI) override {
1640b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << ".. .. Changing MI: " << MI);
1650b57cec5SDimitry Andric   }
1660b57cec5SDimitry Andric 
1670b57cec5SDimitry Andric   void changedInstr(MachineInstr &MI) override {
1680b57cec5SDimitry Andric     // When insts change, we want to revisit them to legalize them again.
1690b57cec5SDimitry Andric     // We'll consider them the same as created.
1700b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << ".. .. Changed MI: " << MI);
1710b57cec5SDimitry Andric     createdOrChangedInstr(MI);
1720b57cec5SDimitry Andric   }
1730b57cec5SDimitry Andric };
1740b57cec5SDimitry Andric } // namespace
1750b57cec5SDimitry Andric 
176480093f4SDimitry Andric Legalizer::MFResult
177480093f4SDimitry Andric Legalizer::legalizeMachineFunction(MachineFunction &MF, const LegalizerInfo &LI,
178480093f4SDimitry Andric                                    ArrayRef<GISelChangeObserver *> AuxObservers,
1795ffd83dbSDimitry Andric                                    LostDebugLocObserver &LocObserver,
18006c3fb27SDimitry Andric                                    MachineIRBuilder &MIRBuilder,
18106c3fb27SDimitry Andric                                    GISelKnownBits *KB) {
1825ffd83dbSDimitry Andric   MIRBuilder.setMF(MF);
1830b57cec5SDimitry Andric   MachineRegisterInfo &MRI = MF.getRegInfo();
1840b57cec5SDimitry Andric 
185480093f4SDimitry Andric   // Populate worklists.
1860b57cec5SDimitry Andric   InstListTy InstList;
1870b57cec5SDimitry Andric   ArtifactListTy ArtifactList;
1880b57cec5SDimitry Andric   ReversePostOrderTraversal<MachineFunction *> RPOT(&MF);
1890b57cec5SDimitry Andric   // Perform legalization bottom up so we can DCE as we legalize.
1900b57cec5SDimitry Andric   // Traverse BB in RPOT and within each basic block, add insts top down,
1910b57cec5SDimitry Andric   // so when we pop_back_val in the legalization process, we traverse bottom-up.
1920b57cec5SDimitry Andric   for (auto *MBB : RPOT) {
1930b57cec5SDimitry Andric     if (MBB->empty())
1940b57cec5SDimitry Andric       continue;
1950b57cec5SDimitry Andric     for (MachineInstr &MI : *MBB) {
1960b57cec5SDimitry Andric       // Only legalize pre-isel generic instructions: others don't have types
1970b57cec5SDimitry Andric       // and are assumed to be legal.
1980b57cec5SDimitry Andric       if (!isPreISelGenericOpcode(MI.getOpcode()))
1990b57cec5SDimitry Andric         continue;
2000b57cec5SDimitry Andric       if (isArtifact(MI))
2010b57cec5SDimitry Andric         ArtifactList.deferred_insert(&MI);
2020b57cec5SDimitry Andric       else
2030b57cec5SDimitry Andric         InstList.deferred_insert(&MI);
2040b57cec5SDimitry Andric     }
2050b57cec5SDimitry Andric   }
2060b57cec5SDimitry Andric   ArtifactList.finalize();
2070b57cec5SDimitry Andric   InstList.finalize();
2080b57cec5SDimitry Andric 
209480093f4SDimitry Andric   // This observer keeps the worklists updated.
2100b57cec5SDimitry Andric   LegalizerWorkListManager WorkListObserver(InstList, ArtifactList);
211480093f4SDimitry Andric   // We want both WorkListObserver as well as all the auxiliary observers (e.g.
212480093f4SDimitry Andric   // CSEInfo) to observe all changes. Use the wrapper observer.
2130b57cec5SDimitry Andric   GISelObserverWrapper WrapperObserver(&WorkListObserver);
214480093f4SDimitry Andric   for (GISelChangeObserver *Observer : AuxObservers)
215480093f4SDimitry Andric     WrapperObserver.addObserver(Observer);
216480093f4SDimitry Andric 
2170b57cec5SDimitry Andric   // Now install the observer as the delegate to MF.
2180b57cec5SDimitry Andric   // This will keep all the observers notified about new insertions/deletions.
2195ffd83dbSDimitry Andric   RAIIMFObsDelInstaller Installer(MF, WrapperObserver);
22006c3fb27SDimitry Andric   LegalizerHelper Helper(MF, LI, WrapperObserver, MIRBuilder, KB);
221*5f757f3fSDimitry Andric   LegalizationArtifactCombiner ArtCombiner(MIRBuilder, MRI, LI, KB);
2220b57cec5SDimitry Andric   bool Changed = false;
2238bcb0991SDimitry Andric   SmallVector<MachineInstr *, 128> RetryList;
2240b57cec5SDimitry Andric   do {
225480093f4SDimitry Andric     LLVM_DEBUG(dbgs() << "=== New Iteration ===\n");
2268bcb0991SDimitry Andric     assert(RetryList.empty() && "Expected no instructions in RetryList");
2278bcb0991SDimitry Andric     unsigned NumArtifacts = ArtifactList.size();
2280b57cec5SDimitry Andric     while (!InstList.empty()) {
2290b57cec5SDimitry Andric       MachineInstr &MI = *InstList.pop_back_val();
230480093f4SDimitry Andric       assert(isPreISelGenericOpcode(MI.getOpcode()) &&
231480093f4SDimitry Andric              "Expecting generic opcode");
2320b57cec5SDimitry Andric       if (isTriviallyDead(MI, MRI)) {
233bdd1243dSDimitry Andric         salvageDebugInfo(MRI, MI);
234349cc55cSDimitry Andric         eraseInstr(MI, MRI, &LocObserver);
2350b57cec5SDimitry Andric         continue;
2360b57cec5SDimitry Andric       }
2370b57cec5SDimitry Andric 
2380b57cec5SDimitry Andric       // Do the legalization for this instruction.
239fe6060f1SDimitry Andric       auto Res = Helper.legalizeInstrStep(MI, LocObserver);
2400b57cec5SDimitry Andric       // Error out if we couldn't legalize this instruction. We may want to
2410b57cec5SDimitry Andric       // fall back to DAG ISel instead in the future.
2420b57cec5SDimitry Andric       if (Res == LegalizerHelper::UnableToLegalize) {
2438bcb0991SDimitry Andric         // Move illegal artifacts to RetryList instead of aborting because
2448bcb0991SDimitry Andric         // legalizing InstList may generate artifacts that allow
2458bcb0991SDimitry Andric         // ArtifactCombiner to combine away them.
2468bcb0991SDimitry Andric         if (isArtifact(MI)) {
247480093f4SDimitry Andric           LLVM_DEBUG(dbgs() << ".. Not legalized, moving to artifacts retry\n");
248480093f4SDimitry Andric           assert(NumArtifacts == 0 &&
249480093f4SDimitry Andric                  "Artifacts are only expected in instruction list starting the "
250480093f4SDimitry Andric                  "second iteration, but each iteration starting second must "
251480093f4SDimitry Andric                  "start with an empty artifacts list");
252480093f4SDimitry Andric           (void)NumArtifacts;
2538bcb0991SDimitry Andric           RetryList.push_back(&MI);
2548bcb0991SDimitry Andric           continue;
2558bcb0991SDimitry Andric         }
256480093f4SDimitry Andric         Helper.MIRBuilder.stopObservingChanges();
257480093f4SDimitry Andric         return {Changed, &MI};
2580b57cec5SDimitry Andric       }
2590b57cec5SDimitry Andric       WorkListObserver.printNewInstrs();
2605ffd83dbSDimitry Andric       LocObserver.checkpoint();
2610b57cec5SDimitry Andric       Changed |= Res == LegalizerHelper::Legalized;
2620b57cec5SDimitry Andric     }
2638bcb0991SDimitry Andric     // Try to combine the instructions in RetryList again if there
2648bcb0991SDimitry Andric     // are new artifacts. If not, stop legalizing.
2658bcb0991SDimitry Andric     if (!RetryList.empty()) {
266480093f4SDimitry Andric       if (!ArtifactList.empty()) {
2678bcb0991SDimitry Andric         while (!RetryList.empty())
2688bcb0991SDimitry Andric           ArtifactList.insert(RetryList.pop_back_val());
2698bcb0991SDimitry Andric       } else {
270480093f4SDimitry Andric         LLVM_DEBUG(dbgs() << "No new artifacts created, not retrying!\n");
271480093f4SDimitry Andric         Helper.MIRBuilder.stopObservingChanges();
272480093f4SDimitry Andric         return {Changed, RetryList.front()};
2738bcb0991SDimitry Andric       }
2748bcb0991SDimitry Andric     }
2755ffd83dbSDimitry Andric     LocObserver.checkpoint();
2760b57cec5SDimitry Andric     while (!ArtifactList.empty()) {
2770b57cec5SDimitry Andric       MachineInstr &MI = *ArtifactList.pop_back_val();
278480093f4SDimitry Andric       assert(isPreISelGenericOpcode(MI.getOpcode()) &&
279480093f4SDimitry Andric              "Expecting generic opcode");
2800b57cec5SDimitry Andric       if (isTriviallyDead(MI, MRI)) {
281bdd1243dSDimitry Andric         salvageDebugInfo(MRI, MI);
282349cc55cSDimitry Andric         eraseInstr(MI, MRI, &LocObserver);
2830b57cec5SDimitry Andric         continue;
2840b57cec5SDimitry Andric       }
2850b57cec5SDimitry Andric       SmallVector<MachineInstr *, 4> DeadInstructions;
286480093f4SDimitry Andric       LLVM_DEBUG(dbgs() << "Trying to combine: " << MI);
2870b57cec5SDimitry Andric       if (ArtCombiner.tryCombineInstruction(MI, DeadInstructions,
2880b57cec5SDimitry Andric                                             WrapperObserver)) {
2890b57cec5SDimitry Andric         WorkListObserver.printNewInstrs();
290349cc55cSDimitry Andric         eraseInstrs(DeadInstructions, MRI, &LocObserver);
2915ffd83dbSDimitry Andric         LocObserver.checkpoint(
2925ffd83dbSDimitry Andric             VerifyDebugLocs ==
2935ffd83dbSDimitry Andric             DebugLocVerifyLevel::LegalizationsAndArtifactCombiners);
2940b57cec5SDimitry Andric         Changed = true;
2950b57cec5SDimitry Andric         continue;
2960b57cec5SDimitry Andric       }
2970b57cec5SDimitry Andric       // If this was not an artifact (that could be combined away), this might
2980b57cec5SDimitry Andric       // need special handling. Add it to InstList, so when it's processed
2990b57cec5SDimitry Andric       // there, it has to be legal or specially handled.
300480093f4SDimitry Andric       else {
301480093f4SDimitry Andric         LLVM_DEBUG(dbgs() << ".. Not combined, moving to instructions list\n");
3020b57cec5SDimitry Andric         InstList.insert(&MI);
3030b57cec5SDimitry Andric       }
304480093f4SDimitry Andric     }
3050b57cec5SDimitry Andric   } while (!InstList.empty());
3060b57cec5SDimitry Andric 
307480093f4SDimitry Andric   return {Changed, /*FailedOn*/ nullptr};
308480093f4SDimitry Andric }
309480093f4SDimitry Andric 
310480093f4SDimitry Andric bool Legalizer::runOnMachineFunction(MachineFunction &MF) {
311480093f4SDimitry Andric   // If the ISel pipeline failed, do not bother running that pass.
312480093f4SDimitry Andric   if (MF.getProperties().hasProperty(
313480093f4SDimitry Andric           MachineFunctionProperties::Property::FailedISel))
314480093f4SDimitry Andric     return false;
315480093f4SDimitry Andric   LLVM_DEBUG(dbgs() << "Legalize Machine IR for: " << MF.getName() << '\n');
316480093f4SDimitry Andric   init(MF);
317480093f4SDimitry Andric   const TargetPassConfig &TPC = getAnalysis<TargetPassConfig>();
318480093f4SDimitry Andric   GISelCSEAnalysisWrapper &Wrapper =
319480093f4SDimitry Andric       getAnalysis<GISelCSEAnalysisWrapperPass>().getCSEWrapper();
320480093f4SDimitry Andric   MachineOptimizationRemarkEmitter MORE(MF, /*MBFI=*/nullptr);
321480093f4SDimitry Andric 
322480093f4SDimitry Andric   std::unique_ptr<MachineIRBuilder> MIRBuilder;
323480093f4SDimitry Andric   GISelCSEInfo *CSEInfo = nullptr;
324480093f4SDimitry Andric   bool EnableCSE = EnableCSEInLegalizer.getNumOccurrences()
325480093f4SDimitry Andric                        ? EnableCSEInLegalizer
326480093f4SDimitry Andric                        : TPC.isGISelCSEEnabled();
327480093f4SDimitry Andric   if (EnableCSE) {
328480093f4SDimitry Andric     MIRBuilder = std::make_unique<CSEMIRBuilder>();
329480093f4SDimitry Andric     CSEInfo = &Wrapper.get(TPC.getCSEConfig());
330480093f4SDimitry Andric     MIRBuilder->setCSEInfo(CSEInfo);
331480093f4SDimitry Andric   } else
332480093f4SDimitry Andric     MIRBuilder = std::make_unique<MachineIRBuilder>();
333480093f4SDimitry Andric 
334480093f4SDimitry Andric   SmallVector<GISelChangeObserver *, 1> AuxObservers;
335480093f4SDimitry Andric   if (EnableCSE && CSEInfo) {
336480093f4SDimitry Andric     // We want CSEInfo in addition to WorkListObserver to observe all changes.
337480093f4SDimitry Andric     AuxObservers.push_back(CSEInfo);
338480093f4SDimitry Andric   }
3395ffd83dbSDimitry Andric   assert(!CSEInfo || !errorToBool(CSEInfo->verify()));
3405ffd83dbSDimitry Andric   LostDebugLocObserver LocObserver(DEBUG_TYPE);
3415ffd83dbSDimitry Andric   if (VerifyDebugLocs > DebugLocVerifyLevel::None)
3425ffd83dbSDimitry Andric     AuxObservers.push_back(&LocObserver);
343480093f4SDimitry Andric 
34406c3fb27SDimitry Andric   // This allows Known Bits Analysis in the legalizer.
34506c3fb27SDimitry Andric   GISelKnownBits *KB = &getAnalysis<GISelKnownBitsAnalysis>().get(MF);
34606c3fb27SDimitry Andric 
347480093f4SDimitry Andric   const LegalizerInfo &LI = *MF.getSubtarget().getLegalizerInfo();
34806c3fb27SDimitry Andric   MFResult Result = legalizeMachineFunction(MF, LI, AuxObservers, LocObserver,
34906c3fb27SDimitry Andric                                             *MIRBuilder, KB);
350480093f4SDimitry Andric 
351480093f4SDimitry Andric   if (Result.FailedOn) {
352480093f4SDimitry Andric     reportGISelFailure(MF, TPC, MORE, "gisel-legalize",
353480093f4SDimitry Andric                        "unable to legalize instruction", *Result.FailedOn);
354480093f4SDimitry Andric     return false;
355480093f4SDimitry Andric   }
3565ffd83dbSDimitry Andric 
3575ffd83dbSDimitry Andric   if (LocObserver.getNumLostDebugLocs()) {
3585ffd83dbSDimitry Andric     MachineOptimizationRemarkMissed R("gisel-legalize", "LostDebugLoc",
3595ffd83dbSDimitry Andric                                       MF.getFunction().getSubprogram(),
3605ffd83dbSDimitry Andric                                       /*MBB=*/&*MF.begin());
3615ffd83dbSDimitry Andric     R << "lost "
3625ffd83dbSDimitry Andric       << ore::NV("NumLostDebugLocs", LocObserver.getNumLostDebugLocs())
3635ffd83dbSDimitry Andric       << " debug locations during pass";
3645ffd83dbSDimitry Andric     reportGISelWarning(MF, TPC, MORE, R);
3655ffd83dbSDimitry Andric     // Example remark:
3665ffd83dbSDimitry Andric     // --- !Missed
3675ffd83dbSDimitry Andric     // Pass:            gisel-legalize
3685ffd83dbSDimitry Andric     // Name:            GISelFailure
3695ffd83dbSDimitry Andric     // DebugLoc:        { File: '.../legalize-urem.mir', Line: 1, Column: 0 }
3705ffd83dbSDimitry Andric     // Function:        test_urem_s32
3715ffd83dbSDimitry Andric     // Args:
3725ffd83dbSDimitry Andric     //   - String:          'lost '
3735ffd83dbSDimitry Andric     //   - NumLostDebugLocs: '1'
3745ffd83dbSDimitry Andric     //   - String:          ' debug locations during pass'
3755ffd83dbSDimitry Andric     // ...
3765ffd83dbSDimitry Andric   }
3775ffd83dbSDimitry Andric 
3785ffd83dbSDimitry Andric   // If for some reason CSE was not enabled, make sure that we invalidate the
3795ffd83dbSDimitry Andric   // CSEInfo object (as we currently declare that the analysis is preserved).
3805ffd83dbSDimitry Andric   // The next time get on the wrapper is called, it will force it to recompute
3815ffd83dbSDimitry Andric   // the analysis.
3825ffd83dbSDimitry Andric   if (!EnableCSE)
3835ffd83dbSDimitry Andric     Wrapper.setComputed(false);
384480093f4SDimitry Andric   return Result.Changed;
3850b57cec5SDimitry Andric }
386