169fa84a6STim Northover //===-- llvm/CodeGen/GlobalISel/Legalizer.cpp -----------------------------===//
269fa84a6STim Northover //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
669fa84a6STim Northover //
769fa84a6STim Northover //===----------------------------------------------------------------------===//
869fa84a6STim Northover //
969fa84a6STim Northover /// \file This file implements the LegalizerHelper class to legalize individual
1069fa84a6STim Northover /// instructions and the LegalizePass wrapper pass for the primary
1169fa84a6STim Northover /// legalization.
1269fa84a6STim Northover //
1369fa84a6STim Northover //===----------------------------------------------------------------------===//
1469fa84a6STim Northover 
1569fa84a6STim Northover #include "llvm/CodeGen/GlobalISel/Legalizer.h"
16e6201c87SAditya Nandakumar #include "llvm/ADT/PostOrderIterator.h"
17*989f1c72Sserge-sans-paille #include "llvm/Analysis/OptimizationRemarkEmitter.h"
18500e3eadSAditya Nandakumar #include "llvm/CodeGen/GlobalISel/CSEInfo.h"
19500e3eadSAditya Nandakumar #include "llvm/CodeGen/GlobalISel/CSEMIRBuilder.h"
20f75d4f32SAditya Nandakumar #include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h"
21b3bde2eaSDavid Blaikie #include "llvm/CodeGen/GlobalISel/GISelWorkList.h"
22e6201c87SAditya Nandakumar #include "llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h"
2369fa84a6STim Northover #include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
24d9085f65SDaniel Sanders #include "llvm/CodeGen/GlobalISel/LostDebugLocObserver.h"
25ae9dadecSAhmed Bougacha #include "llvm/CodeGen/GlobalISel/Utils.h"
26ae9dadecSAhmed Bougacha #include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h"
2769fa84a6STim Northover #include "llvm/CodeGen/TargetPassConfig.h"
28b3bde2eaSDavid Blaikie #include "llvm/CodeGen/TargetSubtargetInfo.h"
2905da2fe5SReid Kleckner #include "llvm/InitializePasses.h"
3069fa84a6STim Northover #include "llvm/Support/Debug.h"
31b91d9ec0SAditya Nandakumar #include "llvm/Support/Error.h"
325377fb34SDaniel Sanders 
3369fa84a6STim Northover #define DEBUG_TYPE "legalizer"
3469fa84a6STim Northover 
3569fa84a6STim Northover using namespace llvm;
3669fa84a6STim Northover 
37500e3eadSAditya Nandakumar static cl::opt<bool>
38500e3eadSAditya Nandakumar     EnableCSEInLegalizer("enable-cse-in-legalizer",
39500e3eadSAditya Nandakumar                          cl::desc("Should enable CSE in Legalizer"),
40500e3eadSAditya Nandakumar                          cl::Optional, cl::init(false));
41500e3eadSAditya Nandakumar 
4258a2cb51SAmara Emerson // This is a temporary hack, should be removed soon.
4358a2cb51SAmara Emerson static cl::opt<bool> AllowGInsertAsArtifact(
4458a2cb51SAmara Emerson     "allow-ginsert-as-artifact",
4558a2cb51SAmara Emerson     cl::desc("Allow G_INSERT to be considered an artifact. Hack around AMDGPU "
4658a2cb51SAmara Emerson              "test infinite loops."),
4758a2cb51SAmara Emerson     cl::Optional, cl::init(true));
4858a2cb51SAmara Emerson 
49d9085f65SDaniel Sanders enum class DebugLocVerifyLevel {
50d9085f65SDaniel Sanders   None,
51d9085f65SDaniel Sanders   Legalizations,
52d9085f65SDaniel Sanders   LegalizationsAndArtifactCombiners,
53d9085f65SDaniel Sanders };
54d9085f65SDaniel Sanders #ifndef NDEBUG
55d9085f65SDaniel Sanders static cl::opt<DebugLocVerifyLevel> VerifyDebugLocs(
56d9085f65SDaniel Sanders     "verify-legalizer-debug-locs",
57d9085f65SDaniel Sanders     cl::desc("Verify that debug locations are handled"),
587f7f98b1SDaniel Sanders     cl::values(
597f7f98b1SDaniel Sanders         clEnumValN(DebugLocVerifyLevel::None, "none", "No verification"),
607f7f98b1SDaniel Sanders         clEnumValN(DebugLocVerifyLevel::Legalizations, "legalizations",
61d9085f65SDaniel Sanders                    "Verify legalizations"),
627f7f98b1SDaniel Sanders         clEnumValN(DebugLocVerifyLevel::LegalizationsAndArtifactCombiners,
637f7f98b1SDaniel Sanders                    "legalizations+artifactcombiners",
64d9085f65SDaniel Sanders                    "Verify legalizations and artifact combines")),
65d9085f65SDaniel Sanders     cl::init(DebugLocVerifyLevel::Legalizations));
66d9085f65SDaniel Sanders #else
67d9085f65SDaniel Sanders // Always disable it for release builds by preventing the observer from being
68d9085f65SDaniel Sanders // installed.
69d9085f65SDaniel Sanders static const DebugLocVerifyLevel VerifyDebugLocs = DebugLocVerifyLevel::None;
70d9085f65SDaniel Sanders #endif
71d9085f65SDaniel Sanders 
7269fa84a6STim Northover char Legalizer::ID = 0;
7369fa84a6STim Northover INITIALIZE_PASS_BEGIN(Legalizer, DEBUG_TYPE,
7469fa84a6STim Northover                       "Legalize the Machine IR a function's Machine IR", false,
7569fa84a6STim Northover                       false)
INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)7669fa84a6STim Northover INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
77500e3eadSAditya Nandakumar INITIALIZE_PASS_DEPENDENCY(GISelCSEAnalysisWrapperPass)
7869fa84a6STim Northover INITIALIZE_PASS_END(Legalizer, DEBUG_TYPE,
7969fa84a6STim Northover                     "Legalize the Machine IR a function's Machine IR", false,
8069fa84a6STim Northover                     false)
8169fa84a6STim Northover 
821f7f6466STom Stellard Legalizer::Legalizer() : MachineFunctionPass(ID) { }
8369fa84a6STim Northover 
getAnalysisUsage(AnalysisUsage & AU) const8469fa84a6STim Northover void Legalizer::getAnalysisUsage(AnalysisUsage &AU) const {
8569fa84a6STim Northover   AU.addRequired<TargetPassConfig>();
86500e3eadSAditya Nandakumar   AU.addRequired<GISelCSEAnalysisWrapperPass>();
87500e3eadSAditya Nandakumar   AU.addPreserved<GISelCSEAnalysisWrapperPass>();
8890ad6835SMatthias Braun   getSelectionDAGFallbackAnalysisUsage(AU);
8969fa84a6STim Northover   MachineFunctionPass::getAnalysisUsage(AU);
9069fa84a6STim Northover }
9169fa84a6STim Northover 
init(MachineFunction & MF)9269fa84a6STim Northover void Legalizer::init(MachineFunction &MF) {
9369fa84a6STim Northover }
9469fa84a6STim Northover 
isArtifact(const MachineInstr & MI)95e6201c87SAditya Nandakumar static bool isArtifact(const MachineInstr &MI) {
96e6201c87SAditya Nandakumar   switch (MI.getOpcode()) {
97e6201c87SAditya Nandakumar   default:
98e6201c87SAditya Nandakumar     return false;
99e6201c87SAditya Nandakumar   case TargetOpcode::G_TRUNC:
100e6201c87SAditya Nandakumar   case TargetOpcode::G_ZEXT:
101e6201c87SAditya Nandakumar   case TargetOpcode::G_ANYEXT:
102e6201c87SAditya Nandakumar   case TargetOpcode::G_SEXT:
103e6201c87SAditya Nandakumar   case TargetOpcode::G_MERGE_VALUES:
104e6201c87SAditya Nandakumar   case TargetOpcode::G_UNMERGE_VALUES:
1055ec14604SAmara Emerson   case TargetOpcode::G_CONCAT_VECTORS:
1065ec14604SAmara Emerson   case TargetOpcode::G_BUILD_VECTOR:
10724f14993SMatt Arsenault   case TargetOpcode::G_EXTRACT:
108e6201c87SAditya Nandakumar     return true;
10958a2cb51SAmara Emerson   case TargetOpcode::G_INSERT:
11058a2cb51SAmara Emerson     return AllowGInsertAsArtifact;
111e6201c87SAditya Nandakumar   }
112e6201c87SAditya Nandakumar }
113f75d4f32SAditya Nandakumar using InstListTy = GISelWorkList<256>;
114f75d4f32SAditya Nandakumar using ArtifactListTy = GISelWorkList<128>;
115f75d4f32SAditya Nandakumar 
116b17d2136SBenjamin Kramer namespace {
117f75d4f32SAditya Nandakumar class LegalizerWorkListManager : public GISelChangeObserver {
118f75d4f32SAditya Nandakumar   InstListTy &InstList;
119f75d4f32SAditya Nandakumar   ArtifactListTy &ArtifactList;
1208f079844SDaniel Sanders #ifndef NDEBUG
1218f079844SDaniel Sanders   SmallVector<MachineInstr *, 4> NewMIs;
1228f079844SDaniel Sanders #endif
123f75d4f32SAditya Nandakumar 
124f75d4f32SAditya Nandakumar public:
LegalizerWorkListManager(InstListTy & Insts,ArtifactListTy & Arts)125f75d4f32SAditya Nandakumar   LegalizerWorkListManager(InstListTy &Insts, ArtifactListTy &Arts)
126f75d4f32SAditya Nandakumar       : InstList(Insts), ArtifactList(Arts) {}
127f75d4f32SAditya Nandakumar 
createdOrChangedInstr(MachineInstr & MI)1288f079844SDaniel Sanders   void createdOrChangedInstr(MachineInstr &MI) {
129f75d4f32SAditya Nandakumar     // Only legalize pre-isel generic instructions.
130f75d4f32SAditya Nandakumar     // Legalization process could generate Target specific pseudo
131f75d4f32SAditya Nandakumar     // instructions with generic types. Don't record them
132f75d4f32SAditya Nandakumar     if (isPreISelGenericOpcode(MI.getOpcode())) {
133f75d4f32SAditya Nandakumar       if (isArtifact(MI))
134f75d4f32SAditya Nandakumar         ArtifactList.insert(&MI);
135f75d4f32SAditya Nandakumar       else
136f75d4f32SAditya Nandakumar         InstList.insert(&MI);
137f75d4f32SAditya Nandakumar     }
1388f079844SDaniel Sanders   }
1398f079844SDaniel Sanders 
createdInstr(MachineInstr & MI)1408f079844SDaniel Sanders   void createdInstr(MachineInstr &MI) override {
1418f079844SDaniel Sanders     LLVM_DEBUG(NewMIs.push_back(&MI));
1428f079844SDaniel Sanders     createdOrChangedInstr(MI);
1438f079844SDaniel Sanders   }
1448f079844SDaniel Sanders 
printNewInstrs()1458f079844SDaniel Sanders   void printNewInstrs() {
1468f079844SDaniel Sanders     LLVM_DEBUG({
1478f079844SDaniel Sanders       for (const auto *MI : NewMIs)
1488f079844SDaniel Sanders         dbgs() << ".. .. New MI: " << *MI;
1498f079844SDaniel Sanders       NewMIs.clear();
1508f079844SDaniel Sanders     });
151f75d4f32SAditya Nandakumar   }
152f75d4f32SAditya Nandakumar 
erasingInstr(MachineInstr & MI)153500e3eadSAditya Nandakumar   void erasingInstr(MachineInstr &MI) override {
154d001e0e0SDaniel Sanders     LLVM_DEBUG(dbgs() << ".. .. Erasing: " << MI);
155f75d4f32SAditya Nandakumar     InstList.remove(&MI);
156f75d4f32SAditya Nandakumar     ArtifactList.remove(&MI);
157f75d4f32SAditya Nandakumar   }
158f75d4f32SAditya Nandakumar 
changingInstr(MachineInstr & MI)159500e3eadSAditya Nandakumar   void changingInstr(MachineInstr &MI) override {
160d001e0e0SDaniel Sanders     LLVM_DEBUG(dbgs() << ".. .. Changing MI: " << MI);
161d001e0e0SDaniel Sanders   }
162d001e0e0SDaniel Sanders 
changedInstr(MachineInstr & MI)163500e3eadSAditya Nandakumar   void changedInstr(MachineInstr &MI) override {
164f75d4f32SAditya Nandakumar     // When insts change, we want to revisit them to legalize them again.
165f75d4f32SAditya Nandakumar     // We'll consider them the same as created.
166d001e0e0SDaniel Sanders     LLVM_DEBUG(dbgs() << ".. .. Changed MI: " << MI);
1678f079844SDaniel Sanders     createdOrChangedInstr(MI);
168f75d4f32SAditya Nandakumar   }
169f75d4f32SAditya Nandakumar };
170b17d2136SBenjamin Kramer } // namespace
171e6201c87SAditya Nandakumar 
17218bf9670SRoman Tereshin Legalizer::MFResult
legalizeMachineFunction(MachineFunction & MF,const LegalizerInfo & LI,ArrayRef<GISelChangeObserver * > AuxObservers,LostDebugLocObserver & LocObserver,MachineIRBuilder & MIRBuilder)17318bf9670SRoman Tereshin Legalizer::legalizeMachineFunction(MachineFunction &MF, const LegalizerInfo &LI,
17418bf9670SRoman Tereshin                                    ArrayRef<GISelChangeObserver *> AuxObservers,
175d9085f65SDaniel Sanders                                    LostDebugLocObserver &LocObserver,
17618bf9670SRoman Tereshin                                    MachineIRBuilder &MIRBuilder) {
177b94c9e3bSMatt Arsenault   MIRBuilder.setMF(MF);
178e6201c87SAditya Nandakumar   MachineRegisterInfo &MRI = MF.getRegInfo();
17969fa84a6STim Northover 
18018bf9670SRoman Tereshin   // Populate worklists.
181500e3eadSAditya Nandakumar   InstListTy InstList;
182500e3eadSAditya Nandakumar   ArtifactListTy ArtifactList;
183e6201c87SAditya Nandakumar   ReversePostOrderTraversal<MachineFunction *> RPOT(&MF);
184e6201c87SAditya Nandakumar   // Perform legalization bottom up so we can DCE as we legalize.
185e6201c87SAditya Nandakumar   // Traverse BB in RPOT and within each basic block, add insts top down,
186e6201c87SAditya Nandakumar   // so when we pop_back_val in the legalization process, we traverse bottom-up.
187e6201c87SAditya Nandakumar   for (auto *MBB : RPOT) {
188e6201c87SAditya Nandakumar     if (MBB->empty())
189e6201c87SAditya Nandakumar       continue;
190e6201c87SAditya Nandakumar     for (MachineInstr &MI : *MBB) {
19169fa84a6STim Northover       // Only legalize pre-isel generic instructions: others don't have types
19269fa84a6STim Northover       // and are assumed to be legal.
193e6201c87SAditya Nandakumar       if (!isPreISelGenericOpcode(MI.getOpcode()))
19469fa84a6STim Northover         continue;
195e6201c87SAditya Nandakumar       if (isArtifact(MI))
1960e362ec1SAditya Nandakumar         ArtifactList.deferred_insert(&MI);
197e6201c87SAditya Nandakumar       else
1980e362ec1SAditya Nandakumar         InstList.deferred_insert(&MI);
199e6201c87SAditya Nandakumar     }
200e6201c87SAditya Nandakumar   }
2010e362ec1SAditya Nandakumar   ArtifactList.finalize();
2020e362ec1SAditya Nandakumar   InstList.finalize();
2033ba0d94bSAditya Nandakumar 
20418bf9670SRoman Tereshin   // This observer keeps the worklists updated.
205f75d4f32SAditya Nandakumar   LegalizerWorkListManager WorkListObserver(InstList, ArtifactList);
20618bf9670SRoman Tereshin   // We want both WorkListObserver as well as all the auxiliary observers (e.g.
20718bf9670SRoman Tereshin   // CSEInfo) to observe all changes. Use the wrapper observer.
208500e3eadSAditya Nandakumar   GISelObserverWrapper WrapperObserver(&WorkListObserver);
20918bf9670SRoman Tereshin   for (GISelChangeObserver *Observer : AuxObservers)
21018bf9670SRoman Tereshin     WrapperObserver.addObserver(Observer);
21118bf9670SRoman Tereshin 
212500e3eadSAditya Nandakumar   // Now install the observer as the delegate to MF.
213500e3eadSAditya Nandakumar   // This will keep all the observers notified about new insertions/deletions.
214b91d9ec0SAditya Nandakumar   RAIIMFObsDelInstaller Installer(MF, WrapperObserver);
21518bf9670SRoman Tereshin   LegalizerHelper Helper(MF, LI, WrapperObserver, MIRBuilder);
21618bf9670SRoman Tereshin   LegalizationArtifactCombiner ArtCombiner(MIRBuilder, MRI, LI);
2175377fb34SDaniel Sanders   bool Changed = false;
218277631e3SVolkan Keles   SmallVector<MachineInstr *, 128> RetryList;
219eb80a51bSAditya Nandakumar   do {
2208207c815SRoman Tereshin     LLVM_DEBUG(dbgs() << "=== New Iteration ===\n");
221277631e3SVolkan Keles     assert(RetryList.empty() && "Expected no instructions in RetryList");
222277631e3SVolkan Keles     unsigned NumArtifacts = ArtifactList.size();
223e6201c87SAditya Nandakumar     while (!InstList.empty()) {
224e6201c87SAditya Nandakumar       MachineInstr &MI = *InstList.pop_back_val();
22518bf9670SRoman Tereshin       assert(isPreISelGenericOpcode(MI.getOpcode()) &&
22618bf9670SRoman Tereshin              "Expecting generic opcode");
227e6201c87SAditya Nandakumar       if (isTriviallyDead(MI, MRI)) {
228e4c46dddSPetar Avramovic         eraseInstr(MI, MRI, &LocObserver);
229e6201c87SAditya Nandakumar         continue;
230e6201c87SAditya Nandakumar       }
231e6201c87SAditya Nandakumar 
232e6201c87SAditya Nandakumar       // Do the legalization for this instruction.
233324af79dSJessica Paquette       auto Res = Helper.legalizeInstrStep(MI, LocObserver);
234eb80a51bSAditya Nandakumar       // Error out if we couldn't legalize this instruction. We may want to
2355377fb34SDaniel Sanders       // fall back to DAG ISel instead in the future.
23669fa84a6STim Northover       if (Res == LegalizerHelper::UnableToLegalize) {
237277631e3SVolkan Keles         // Move illegal artifacts to RetryList instead of aborting because
238277631e3SVolkan Keles         // legalizing InstList may generate artifacts that allow
239277631e3SVolkan Keles         // ArtifactCombiner to combine away them.
240277631e3SVolkan Keles         if (isArtifact(MI)) {
2418207c815SRoman Tereshin           LLVM_DEBUG(dbgs() << ".. Not legalized, moving to artifacts retry\n");
2428731799fSRoman Tereshin           assert(NumArtifacts == 0 &&
2438731799fSRoman Tereshin                  "Artifacts are only expected in instruction list starting the "
2448731799fSRoman Tereshin                  "second iteration, but each iteration starting second must "
2458731799fSRoman Tereshin                  "start with an empty artifacts list");
2468731799fSRoman Tereshin           (void)NumArtifacts;
247277631e3SVolkan Keles           RetryList.push_back(&MI);
248277631e3SVolkan Keles           continue;
249277631e3SVolkan Keles         }
25018bf9670SRoman Tereshin         Helper.MIRBuilder.stopObservingChanges();
25118bf9670SRoman Tereshin         return {Changed, &MI};
25269fa84a6STim Northover       }
2538f079844SDaniel Sanders       WorkListObserver.printNewInstrs();
254d9085f65SDaniel Sanders       LocObserver.checkpoint();
255eb80a51bSAditya Nandakumar       Changed |= Res == LegalizerHelper::Legalized;
256c6615f56SAditya Nandakumar     }
257277631e3SVolkan Keles     // Try to combine the instructions in RetryList again if there
258277631e3SVolkan Keles     // are new artifacts. If not, stop legalizing.
259277631e3SVolkan Keles     if (!RetryList.empty()) {
2608731799fSRoman Tereshin       if (!ArtifactList.empty()) {
261277631e3SVolkan Keles         while (!RetryList.empty())
262277631e3SVolkan Keles           ArtifactList.insert(RetryList.pop_back_val());
263277631e3SVolkan Keles       } else {
2648207c815SRoman Tereshin         LLVM_DEBUG(dbgs() << "No new artifacts created, not retrying!\n");
26518bf9670SRoman Tereshin         Helper.MIRBuilder.stopObservingChanges();
26618bf9670SRoman Tereshin         return {Changed, RetryList.front()};
267277631e3SVolkan Keles       }
268277631e3SVolkan Keles     }
269d9085f65SDaniel Sanders     LocObserver.checkpoint();
270e6201c87SAditya Nandakumar     while (!ArtifactList.empty()) {
271e6201c87SAditya Nandakumar       MachineInstr &MI = *ArtifactList.pop_back_val();
27218bf9670SRoman Tereshin       assert(isPreISelGenericOpcode(MI.getOpcode()) &&
27318bf9670SRoman Tereshin              "Expecting generic opcode");
274e6201c87SAditya Nandakumar       if (isTriviallyDead(MI, MRI)) {
275e4c46dddSPetar Avramovic         eraseInstr(MI, MRI, &LocObserver);
276e6201c87SAditya Nandakumar         continue;
277e6201c87SAditya Nandakumar       }
278c6615f56SAditya Nandakumar       SmallVector<MachineInstr *, 4> DeadInstructions;
2798207c815SRoman Tereshin       LLVM_DEBUG(dbgs() << "Trying to combine: " << MI);
280381188f1SAmara Emerson       if (ArtCombiner.tryCombineInstruction(MI, DeadInstructions,
281381188f1SAmara Emerson                                             WrapperObserver)) {
2828f079844SDaniel Sanders         WorkListObserver.printNewInstrs();
283e4c46dddSPetar Avramovic         eraseInstrs(DeadInstructions, MRI, &LocObserver);
2845ef64bbfSDaniel Sanders         LocObserver.checkpoint(
2855ef64bbfSDaniel Sanders             VerifyDebugLocs ==
2865ef64bbfSDaniel Sanders             DebugLocVerifyLevel::LegalizationsAndArtifactCombiners);
287e6201c87SAditya Nandakumar         Changed = true;
288e6201c87SAditya Nandakumar         continue;
289c6615f56SAditya Nandakumar       }
290e6201c87SAditya Nandakumar       // If this was not an artifact (that could be combined away), this might
291e6201c87SAditya Nandakumar       // need special handling. Add it to InstList, so when it's processed
292e6201c87SAditya Nandakumar       // there, it has to be legal or specially handled.
2938207c815SRoman Tereshin       else {
2948207c815SRoman Tereshin         LLVM_DEBUG(dbgs() << ".. Not combined, moving to instructions list\n");
295e6201c87SAditya Nandakumar         InstList.insert(&MI);
296e6201c87SAditya Nandakumar       }
2978207c815SRoman Tereshin     }
298e6201c87SAditya Nandakumar   } while (!InstList.empty());
29969fa84a6STim Northover 
30018bf9670SRoman Tereshin   return {Changed, /*FailedOn*/ nullptr};
30118bf9670SRoman Tereshin }
30218bf9670SRoman Tereshin 
runOnMachineFunction(MachineFunction & MF)30318bf9670SRoman Tereshin bool Legalizer::runOnMachineFunction(MachineFunction &MF) {
30418bf9670SRoman Tereshin   // If the ISel pipeline failed, do not bother running that pass.
30518bf9670SRoman Tereshin   if (MF.getProperties().hasProperty(
30618bf9670SRoman Tereshin           MachineFunctionProperties::Property::FailedISel))
30718bf9670SRoman Tereshin     return false;
30818bf9670SRoman Tereshin   LLVM_DEBUG(dbgs() << "Legalize Machine IR for: " << MF.getName() << '\n');
30918bf9670SRoman Tereshin   init(MF);
31018bf9670SRoman Tereshin   const TargetPassConfig &TPC = getAnalysis<TargetPassConfig>();
31118bf9670SRoman Tereshin   GISelCSEAnalysisWrapper &Wrapper =
31218bf9670SRoman Tereshin       getAnalysis<GISelCSEAnalysisWrapperPass>().getCSEWrapper();
31318bf9670SRoman Tereshin   MachineOptimizationRemarkEmitter MORE(MF, /*MBFI=*/nullptr);
31418bf9670SRoman Tereshin 
31518bf9670SRoman Tereshin   const size_t NumBlocks = MF.size();
31618bf9670SRoman Tereshin 
31718bf9670SRoman Tereshin   std::unique_ptr<MachineIRBuilder> MIRBuilder;
31818bf9670SRoman Tereshin   GISelCSEInfo *CSEInfo = nullptr;
31918bf9670SRoman Tereshin   bool EnableCSE = EnableCSEInLegalizer.getNumOccurrences()
32018bf9670SRoman Tereshin                        ? EnableCSEInLegalizer
32118bf9670SRoman Tereshin                        : TPC.isGISelCSEEnabled();
32218bf9670SRoman Tereshin   if (EnableCSE) {
32318bf9670SRoman Tereshin     MIRBuilder = std::make_unique<CSEMIRBuilder>();
32418bf9670SRoman Tereshin     CSEInfo = &Wrapper.get(TPC.getCSEConfig());
32518bf9670SRoman Tereshin     MIRBuilder->setCSEInfo(CSEInfo);
32618bf9670SRoman Tereshin   } else
32718bf9670SRoman Tereshin     MIRBuilder = std::make_unique<MachineIRBuilder>();
32818bf9670SRoman Tereshin 
32918bf9670SRoman Tereshin   SmallVector<GISelChangeObserver *, 1> AuxObservers;
33018bf9670SRoman Tereshin   if (EnableCSE && CSEInfo) {
33118bf9670SRoman Tereshin     // We want CSEInfo in addition to WorkListObserver to observe all changes.
33218bf9670SRoman Tereshin     AuxObservers.push_back(CSEInfo);
33318bf9670SRoman Tereshin   }
334b91d9ec0SAditya Nandakumar   assert(!CSEInfo || !errorToBool(CSEInfo->verify()));
335d9085f65SDaniel Sanders   LostDebugLocObserver LocObserver(DEBUG_TYPE);
336d9085f65SDaniel Sanders   if (VerifyDebugLocs > DebugLocVerifyLevel::None)
337d9085f65SDaniel Sanders     AuxObservers.push_back(&LocObserver);
33818bf9670SRoman Tereshin 
33918bf9670SRoman Tereshin   const LegalizerInfo &LI = *MF.getSubtarget().getLegalizerInfo();
340d9085f65SDaniel Sanders   MFResult Result =
341d9085f65SDaniel Sanders       legalizeMachineFunction(MF, LI, AuxObservers, LocObserver, *MIRBuilder);
34218bf9670SRoman Tereshin 
34318bf9670SRoman Tereshin   if (Result.FailedOn) {
34418bf9670SRoman Tereshin     reportGISelFailure(MF, TPC, MORE, "gisel-legalize",
34518bf9670SRoman Tereshin                        "unable to legalize instruction", *Result.FailedOn);
34618bf9670SRoman Tereshin     return false;
34718bf9670SRoman Tereshin   }
348e6201c87SAditya Nandakumar   // For now don't support if new blocks are inserted - we would need to fix the
349e6201c87SAditya Nandakumar   // outer loop for that.
350e6201c87SAditya Nandakumar   if (MF.size() != NumBlocks) {
351e6201c87SAditya Nandakumar     MachineOptimizationRemarkMissed R("gisel-legalize", "GISelFailure",
352f1caa283SMatthias Braun                                       MF.getFunction().getSubprogram(),
353e6201c87SAditya Nandakumar                                       /*MBB=*/nullptr);
354e6201c87SAditya Nandakumar     R << "inserting blocks is not supported yet";
355e6201c87SAditya Nandakumar     reportGISelFailure(MF, TPC, MORE, R);
356e6201c87SAditya Nandakumar     return false;
35769fa84a6STim Northover   }
358d9085f65SDaniel Sanders 
359d9085f65SDaniel Sanders   if (LocObserver.getNumLostDebugLocs()) {
360d9085f65SDaniel Sanders     MachineOptimizationRemarkMissed R("gisel-legalize", "LostDebugLoc",
361d9085f65SDaniel Sanders                                       MF.getFunction().getSubprogram(),
362d9085f65SDaniel Sanders                                       /*MBB=*/&*MF.begin());
363d9085f65SDaniel Sanders     R << "lost "
364d9085f65SDaniel Sanders       << ore::NV("NumLostDebugLocs", LocObserver.getNumLostDebugLocs())
365d9085f65SDaniel Sanders       << " debug locations during pass";
366d9085f65SDaniel Sanders     reportGISelWarning(MF, TPC, MORE, R);
367d9085f65SDaniel Sanders     // Example remark:
368d9085f65SDaniel Sanders     // --- !Missed
369d9085f65SDaniel Sanders     // Pass:            gisel-legalize
370d9085f65SDaniel Sanders     // Name:            GISelFailure
371d9085f65SDaniel Sanders     // DebugLoc:        { File: '.../legalize-urem.mir', Line: 1, Column: 0 }
372d9085f65SDaniel Sanders     // Function:        test_urem_s32
373d9085f65SDaniel Sanders     // Args:
374d9085f65SDaniel Sanders     //   - String:          'lost '
375d9085f65SDaniel Sanders     //   - NumLostDebugLocs: '1'
376d9085f65SDaniel Sanders     //   - String:          ' debug locations during pass'
377d9085f65SDaniel Sanders     // ...
378d9085f65SDaniel Sanders   }
379d9085f65SDaniel Sanders 
380b91d9ec0SAditya Nandakumar   // If for some reason CSE was not enabled, make sure that we invalidate the
381b91d9ec0SAditya Nandakumar   // CSEInfo object (as we currently declare that the analysis is preserved).
382b91d9ec0SAditya Nandakumar   // The next time get on the wrapper is called, it will force it to recompute
383b91d9ec0SAditya Nandakumar   // the analysis.
384b91d9ec0SAditya Nandakumar   if (!EnableCSE)
385b91d9ec0SAditya Nandakumar     Wrapper.setComputed(false);
38618bf9670SRoman Tereshin   return Result.Changed;
38769fa84a6STim Northover }
388