xref: /openbsd-src/gnu/llvm/llvm/lib/CodeGen/GlobalISel/Legalizer.cpp (revision d415bd752c734aee168c4ee86ff32e8cc249eb16)
109467b48Spatrick //===-- llvm/CodeGen/GlobalISel/Legalizer.cpp -----------------------------===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick //
909467b48Spatrick /// \file This file implements the LegalizerHelper class to legalize individual
1009467b48Spatrick /// instructions and the LegalizePass wrapper pass for the primary
1109467b48Spatrick /// legalization.
1209467b48Spatrick //
1309467b48Spatrick //===----------------------------------------------------------------------===//
1409467b48Spatrick 
1509467b48Spatrick #include "llvm/CodeGen/GlobalISel/Legalizer.h"
1609467b48Spatrick #include "llvm/ADT/PostOrderIterator.h"
17*d415bd75Srobert #include "llvm/Analysis/OptimizationRemarkEmitter.h"
1809467b48Spatrick #include "llvm/CodeGen/GlobalISel/CSEInfo.h"
1909467b48Spatrick #include "llvm/CodeGen/GlobalISel/CSEMIRBuilder.h"
2009467b48Spatrick #include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h"
2109467b48Spatrick #include "llvm/CodeGen/GlobalISel/GISelWorkList.h"
2209467b48Spatrick #include "llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h"
2309467b48Spatrick #include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
24097a140dSpatrick #include "llvm/CodeGen/GlobalISel/LostDebugLocObserver.h"
2509467b48Spatrick #include "llvm/CodeGen/GlobalISel/Utils.h"
2609467b48Spatrick #include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h"
2709467b48Spatrick #include "llvm/CodeGen/TargetPassConfig.h"
2809467b48Spatrick #include "llvm/CodeGen/TargetSubtargetInfo.h"
2909467b48Spatrick #include "llvm/InitializePasses.h"
3009467b48Spatrick #include "llvm/Support/Debug.h"
31097a140dSpatrick #include "llvm/Support/Error.h"
3209467b48Spatrick 
3309467b48Spatrick #define DEBUG_TYPE "legalizer"
3409467b48Spatrick 
3509467b48Spatrick using namespace llvm;
3609467b48Spatrick 
3709467b48Spatrick static cl::opt<bool>
3809467b48Spatrick     EnableCSEInLegalizer("enable-cse-in-legalizer",
3909467b48Spatrick                          cl::desc("Should enable CSE in Legalizer"),
4009467b48Spatrick                          cl::Optional, cl::init(false));
4109467b48Spatrick 
4273471bf0Spatrick // This is a temporary hack, should be removed soon.
4373471bf0Spatrick static cl::opt<bool> AllowGInsertAsArtifact(
4473471bf0Spatrick     "allow-ginsert-as-artifact",
4573471bf0Spatrick     cl::desc("Allow G_INSERT to be considered an artifact. Hack around AMDGPU "
4673471bf0Spatrick              "test infinite loops."),
4773471bf0Spatrick     cl::Optional, cl::init(true));
4873471bf0Spatrick 
49097a140dSpatrick enum class DebugLocVerifyLevel {
50097a140dSpatrick   None,
51097a140dSpatrick   Legalizations,
52097a140dSpatrick   LegalizationsAndArtifactCombiners,
53097a140dSpatrick };
54097a140dSpatrick #ifndef NDEBUG
55097a140dSpatrick static cl::opt<DebugLocVerifyLevel> VerifyDebugLocs(
56097a140dSpatrick     "verify-legalizer-debug-locs",
57097a140dSpatrick     cl::desc("Verify that debug locations are handled"),
58097a140dSpatrick     cl::values(
59097a140dSpatrick         clEnumValN(DebugLocVerifyLevel::None, "none", "No verification"),
60097a140dSpatrick         clEnumValN(DebugLocVerifyLevel::Legalizations, "legalizations",
61097a140dSpatrick                    "Verify legalizations"),
62097a140dSpatrick         clEnumValN(DebugLocVerifyLevel::LegalizationsAndArtifactCombiners,
63097a140dSpatrick                    "legalizations+artifactcombiners",
64097a140dSpatrick                    "Verify legalizations and artifact combines")),
65097a140dSpatrick     cl::init(DebugLocVerifyLevel::Legalizations));
66097a140dSpatrick #else
67097a140dSpatrick // Always disable it for release builds by preventing the observer from being
68097a140dSpatrick // installed.
69097a140dSpatrick static const DebugLocVerifyLevel VerifyDebugLocs = DebugLocVerifyLevel::None;
70097a140dSpatrick #endif
71097a140dSpatrick 
7209467b48Spatrick char Legalizer::ID = 0;
7309467b48Spatrick INITIALIZE_PASS_BEGIN(Legalizer, DEBUG_TYPE,
7409467b48Spatrick                       "Legalize the Machine IR a function's Machine IR", false,
7509467b48Spatrick                       false)
INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)7609467b48Spatrick INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
7709467b48Spatrick INITIALIZE_PASS_DEPENDENCY(GISelCSEAnalysisWrapperPass)
7809467b48Spatrick INITIALIZE_PASS_END(Legalizer, DEBUG_TYPE,
7909467b48Spatrick                     "Legalize the Machine IR a function's Machine IR", false,
8009467b48Spatrick                     false)
8109467b48Spatrick 
8209467b48Spatrick Legalizer::Legalizer() : MachineFunctionPass(ID) { }
8309467b48Spatrick 
getAnalysisUsage(AnalysisUsage & AU) const8409467b48Spatrick void Legalizer::getAnalysisUsage(AnalysisUsage &AU) const {
8509467b48Spatrick   AU.addRequired<TargetPassConfig>();
8609467b48Spatrick   AU.addRequired<GISelCSEAnalysisWrapperPass>();
8709467b48Spatrick   AU.addPreserved<GISelCSEAnalysisWrapperPass>();
8809467b48Spatrick   getSelectionDAGFallbackAnalysisUsage(AU);
8909467b48Spatrick   MachineFunctionPass::getAnalysisUsage(AU);
9009467b48Spatrick }
9109467b48Spatrick 
init(MachineFunction & MF)9209467b48Spatrick void Legalizer::init(MachineFunction &MF) {
9309467b48Spatrick }
9409467b48Spatrick 
isArtifact(const MachineInstr & MI)9509467b48Spatrick static bool isArtifact(const MachineInstr &MI) {
9609467b48Spatrick   switch (MI.getOpcode()) {
9709467b48Spatrick   default:
9809467b48Spatrick     return false;
9909467b48Spatrick   case TargetOpcode::G_TRUNC:
10009467b48Spatrick   case TargetOpcode::G_ZEXT:
10109467b48Spatrick   case TargetOpcode::G_ANYEXT:
10209467b48Spatrick   case TargetOpcode::G_SEXT:
10309467b48Spatrick   case TargetOpcode::G_MERGE_VALUES:
10409467b48Spatrick   case TargetOpcode::G_UNMERGE_VALUES:
10509467b48Spatrick   case TargetOpcode::G_CONCAT_VECTORS:
10609467b48Spatrick   case TargetOpcode::G_BUILD_VECTOR:
10709467b48Spatrick   case TargetOpcode::G_EXTRACT:
10809467b48Spatrick     return true;
10973471bf0Spatrick   case TargetOpcode::G_INSERT:
11073471bf0Spatrick     return AllowGInsertAsArtifact;
11109467b48Spatrick   }
11209467b48Spatrick }
11309467b48Spatrick using InstListTy = GISelWorkList<256>;
11409467b48Spatrick using ArtifactListTy = GISelWorkList<128>;
11509467b48Spatrick 
11609467b48Spatrick namespace {
11709467b48Spatrick class LegalizerWorkListManager : public GISelChangeObserver {
11809467b48Spatrick   InstListTy &InstList;
11909467b48Spatrick   ArtifactListTy &ArtifactList;
12009467b48Spatrick #ifndef NDEBUG
12109467b48Spatrick   SmallVector<MachineInstr *, 4> NewMIs;
12209467b48Spatrick #endif
12309467b48Spatrick 
12409467b48Spatrick public:
LegalizerWorkListManager(InstListTy & Insts,ArtifactListTy & Arts)12509467b48Spatrick   LegalizerWorkListManager(InstListTy &Insts, ArtifactListTy &Arts)
12609467b48Spatrick       : InstList(Insts), ArtifactList(Arts) {}
12709467b48Spatrick 
createdOrChangedInstr(MachineInstr & MI)12809467b48Spatrick   void createdOrChangedInstr(MachineInstr &MI) {
12909467b48Spatrick     // Only legalize pre-isel generic instructions.
13009467b48Spatrick     // Legalization process could generate Target specific pseudo
13109467b48Spatrick     // instructions with generic types. Don't record them
13209467b48Spatrick     if (isPreISelGenericOpcode(MI.getOpcode())) {
13309467b48Spatrick       if (isArtifact(MI))
13409467b48Spatrick         ArtifactList.insert(&MI);
13509467b48Spatrick       else
13609467b48Spatrick         InstList.insert(&MI);
13709467b48Spatrick     }
13809467b48Spatrick   }
13909467b48Spatrick 
createdInstr(MachineInstr & MI)14009467b48Spatrick   void createdInstr(MachineInstr &MI) override {
14109467b48Spatrick     LLVM_DEBUG(NewMIs.push_back(&MI));
14209467b48Spatrick     createdOrChangedInstr(MI);
14309467b48Spatrick   }
14409467b48Spatrick 
printNewInstrs()14509467b48Spatrick   void printNewInstrs() {
14609467b48Spatrick     LLVM_DEBUG({
14709467b48Spatrick       for (const auto *MI : NewMIs)
14809467b48Spatrick         dbgs() << ".. .. New MI: " << *MI;
14909467b48Spatrick       NewMIs.clear();
15009467b48Spatrick     });
15109467b48Spatrick   }
15209467b48Spatrick 
erasingInstr(MachineInstr & MI)15309467b48Spatrick   void erasingInstr(MachineInstr &MI) override {
15409467b48Spatrick     LLVM_DEBUG(dbgs() << ".. .. Erasing: " << MI);
15509467b48Spatrick     InstList.remove(&MI);
15609467b48Spatrick     ArtifactList.remove(&MI);
15709467b48Spatrick   }
15809467b48Spatrick 
changingInstr(MachineInstr & MI)15909467b48Spatrick   void changingInstr(MachineInstr &MI) override {
16009467b48Spatrick     LLVM_DEBUG(dbgs() << ".. .. Changing MI: " << MI);
16109467b48Spatrick   }
16209467b48Spatrick 
changedInstr(MachineInstr & MI)16309467b48Spatrick   void changedInstr(MachineInstr &MI) override {
16409467b48Spatrick     // When insts change, we want to revisit them to legalize them again.
16509467b48Spatrick     // We'll consider them the same as created.
16609467b48Spatrick     LLVM_DEBUG(dbgs() << ".. .. Changed MI: " << MI);
16709467b48Spatrick     createdOrChangedInstr(MI);
16809467b48Spatrick   }
16909467b48Spatrick };
17009467b48Spatrick } // namespace
17109467b48Spatrick 
17209467b48Spatrick Legalizer::MFResult
legalizeMachineFunction(MachineFunction & MF,const LegalizerInfo & LI,ArrayRef<GISelChangeObserver * > AuxObservers,LostDebugLocObserver & LocObserver,MachineIRBuilder & MIRBuilder)17309467b48Spatrick Legalizer::legalizeMachineFunction(MachineFunction &MF, const LegalizerInfo &LI,
17409467b48Spatrick                                    ArrayRef<GISelChangeObserver *> AuxObservers,
175097a140dSpatrick                                    LostDebugLocObserver &LocObserver,
17609467b48Spatrick                                    MachineIRBuilder &MIRBuilder) {
177097a140dSpatrick   MIRBuilder.setMF(MF);
17809467b48Spatrick   MachineRegisterInfo &MRI = MF.getRegInfo();
17909467b48Spatrick 
18009467b48Spatrick   // Populate worklists.
18109467b48Spatrick   InstListTy InstList;
18209467b48Spatrick   ArtifactListTy ArtifactList;
18309467b48Spatrick   ReversePostOrderTraversal<MachineFunction *> RPOT(&MF);
18409467b48Spatrick   // Perform legalization bottom up so we can DCE as we legalize.
18509467b48Spatrick   // Traverse BB in RPOT and within each basic block, add insts top down,
18609467b48Spatrick   // so when we pop_back_val in the legalization process, we traverse bottom-up.
18709467b48Spatrick   for (auto *MBB : RPOT) {
18809467b48Spatrick     if (MBB->empty())
18909467b48Spatrick       continue;
19009467b48Spatrick     for (MachineInstr &MI : *MBB) {
19109467b48Spatrick       // Only legalize pre-isel generic instructions: others don't have types
19209467b48Spatrick       // and are assumed to be legal.
19309467b48Spatrick       if (!isPreISelGenericOpcode(MI.getOpcode()))
19409467b48Spatrick         continue;
19509467b48Spatrick       if (isArtifact(MI))
19609467b48Spatrick         ArtifactList.deferred_insert(&MI);
19709467b48Spatrick       else
19809467b48Spatrick         InstList.deferred_insert(&MI);
19909467b48Spatrick     }
20009467b48Spatrick   }
20109467b48Spatrick   ArtifactList.finalize();
20209467b48Spatrick   InstList.finalize();
20309467b48Spatrick 
20409467b48Spatrick   // This observer keeps the worklists updated.
20509467b48Spatrick   LegalizerWorkListManager WorkListObserver(InstList, ArtifactList);
20609467b48Spatrick   // We want both WorkListObserver as well as all the auxiliary observers (e.g.
20709467b48Spatrick   // CSEInfo) to observe all changes. Use the wrapper observer.
20809467b48Spatrick   GISelObserverWrapper WrapperObserver(&WorkListObserver);
20909467b48Spatrick   for (GISelChangeObserver *Observer : AuxObservers)
21009467b48Spatrick     WrapperObserver.addObserver(Observer);
21109467b48Spatrick 
21209467b48Spatrick   // Now install the observer as the delegate to MF.
21309467b48Spatrick   // This will keep all the observers notified about new insertions/deletions.
214097a140dSpatrick   RAIIMFObsDelInstaller Installer(MF, WrapperObserver);
21509467b48Spatrick   LegalizerHelper Helper(MF, LI, WrapperObserver, MIRBuilder);
21609467b48Spatrick   LegalizationArtifactCombiner ArtCombiner(MIRBuilder, MRI, LI);
21709467b48Spatrick   bool Changed = false;
21809467b48Spatrick   SmallVector<MachineInstr *, 128> RetryList;
21909467b48Spatrick   do {
22009467b48Spatrick     LLVM_DEBUG(dbgs() << "=== New Iteration ===\n");
22109467b48Spatrick     assert(RetryList.empty() && "Expected no instructions in RetryList");
22209467b48Spatrick     unsigned NumArtifacts = ArtifactList.size();
22309467b48Spatrick     while (!InstList.empty()) {
22409467b48Spatrick       MachineInstr &MI = *InstList.pop_back_val();
22509467b48Spatrick       assert(isPreISelGenericOpcode(MI.getOpcode()) &&
22609467b48Spatrick              "Expecting generic opcode");
22709467b48Spatrick       if (isTriviallyDead(MI, MRI)) {
228*d415bd75Srobert         salvageDebugInfo(MRI, MI);
229*d415bd75Srobert         eraseInstr(MI, MRI, &LocObserver);
23009467b48Spatrick         continue;
23109467b48Spatrick       }
23209467b48Spatrick 
23309467b48Spatrick       // Do the legalization for this instruction.
23473471bf0Spatrick       auto Res = Helper.legalizeInstrStep(MI, LocObserver);
23509467b48Spatrick       // Error out if we couldn't legalize this instruction. We may want to
23609467b48Spatrick       // fall back to DAG ISel instead in the future.
23709467b48Spatrick       if (Res == LegalizerHelper::UnableToLegalize) {
23809467b48Spatrick         // Move illegal artifacts to RetryList instead of aborting because
23909467b48Spatrick         // legalizing InstList may generate artifacts that allow
24009467b48Spatrick         // ArtifactCombiner to combine away them.
24109467b48Spatrick         if (isArtifact(MI)) {
24209467b48Spatrick           LLVM_DEBUG(dbgs() << ".. Not legalized, moving to artifacts retry\n");
24309467b48Spatrick           assert(NumArtifacts == 0 &&
24409467b48Spatrick                  "Artifacts are only expected in instruction list starting the "
24509467b48Spatrick                  "second iteration, but each iteration starting second must "
24609467b48Spatrick                  "start with an empty artifacts list");
24709467b48Spatrick           (void)NumArtifacts;
24809467b48Spatrick           RetryList.push_back(&MI);
24909467b48Spatrick           continue;
25009467b48Spatrick         }
25109467b48Spatrick         Helper.MIRBuilder.stopObservingChanges();
25209467b48Spatrick         return {Changed, &MI};
25309467b48Spatrick       }
25409467b48Spatrick       WorkListObserver.printNewInstrs();
255097a140dSpatrick       LocObserver.checkpoint();
25609467b48Spatrick       Changed |= Res == LegalizerHelper::Legalized;
25709467b48Spatrick     }
25809467b48Spatrick     // Try to combine the instructions in RetryList again if there
25909467b48Spatrick     // are new artifacts. If not, stop legalizing.
26009467b48Spatrick     if (!RetryList.empty()) {
26109467b48Spatrick       if (!ArtifactList.empty()) {
26209467b48Spatrick         while (!RetryList.empty())
26309467b48Spatrick           ArtifactList.insert(RetryList.pop_back_val());
26409467b48Spatrick       } else {
26509467b48Spatrick         LLVM_DEBUG(dbgs() << "No new artifacts created, not retrying!\n");
26609467b48Spatrick         Helper.MIRBuilder.stopObservingChanges();
26709467b48Spatrick         return {Changed, RetryList.front()};
26809467b48Spatrick       }
26909467b48Spatrick     }
270097a140dSpatrick     LocObserver.checkpoint();
27109467b48Spatrick     while (!ArtifactList.empty()) {
27209467b48Spatrick       MachineInstr &MI = *ArtifactList.pop_back_val();
27309467b48Spatrick       assert(isPreISelGenericOpcode(MI.getOpcode()) &&
27409467b48Spatrick              "Expecting generic opcode");
27509467b48Spatrick       if (isTriviallyDead(MI, MRI)) {
276*d415bd75Srobert         salvageDebugInfo(MRI, MI);
277*d415bd75Srobert         eraseInstr(MI, MRI, &LocObserver);
27809467b48Spatrick         continue;
27909467b48Spatrick       }
28009467b48Spatrick       SmallVector<MachineInstr *, 4> DeadInstructions;
28109467b48Spatrick       LLVM_DEBUG(dbgs() << "Trying to combine: " << MI);
28209467b48Spatrick       if (ArtCombiner.tryCombineInstruction(MI, DeadInstructions,
28309467b48Spatrick                                             WrapperObserver)) {
28409467b48Spatrick         WorkListObserver.printNewInstrs();
285*d415bd75Srobert         eraseInstrs(DeadInstructions, MRI, &LocObserver);
286097a140dSpatrick         LocObserver.checkpoint(
287097a140dSpatrick             VerifyDebugLocs ==
288097a140dSpatrick             DebugLocVerifyLevel::LegalizationsAndArtifactCombiners);
28909467b48Spatrick         Changed = true;
29009467b48Spatrick         continue;
29109467b48Spatrick       }
29209467b48Spatrick       // If this was not an artifact (that could be combined away), this might
29309467b48Spatrick       // need special handling. Add it to InstList, so when it's processed
29409467b48Spatrick       // there, it has to be legal or specially handled.
29509467b48Spatrick       else {
29609467b48Spatrick         LLVM_DEBUG(dbgs() << ".. Not combined, moving to instructions list\n");
29709467b48Spatrick         InstList.insert(&MI);
29809467b48Spatrick       }
29909467b48Spatrick     }
30009467b48Spatrick   } while (!InstList.empty());
30109467b48Spatrick 
30209467b48Spatrick   return {Changed, /*FailedOn*/ nullptr};
30309467b48Spatrick }
30409467b48Spatrick 
runOnMachineFunction(MachineFunction & MF)30509467b48Spatrick bool Legalizer::runOnMachineFunction(MachineFunction &MF) {
30609467b48Spatrick   // If the ISel pipeline failed, do not bother running that pass.
30709467b48Spatrick   if (MF.getProperties().hasProperty(
30809467b48Spatrick           MachineFunctionProperties::Property::FailedISel))
30909467b48Spatrick     return false;
31009467b48Spatrick   LLVM_DEBUG(dbgs() << "Legalize Machine IR for: " << MF.getName() << '\n');
31109467b48Spatrick   init(MF);
31209467b48Spatrick   const TargetPassConfig &TPC = getAnalysis<TargetPassConfig>();
31309467b48Spatrick   GISelCSEAnalysisWrapper &Wrapper =
31409467b48Spatrick       getAnalysis<GISelCSEAnalysisWrapperPass>().getCSEWrapper();
31509467b48Spatrick   MachineOptimizationRemarkEmitter MORE(MF, /*MBFI=*/nullptr);
31609467b48Spatrick 
31709467b48Spatrick   const size_t NumBlocks = MF.size();
31809467b48Spatrick 
31909467b48Spatrick   std::unique_ptr<MachineIRBuilder> MIRBuilder;
32009467b48Spatrick   GISelCSEInfo *CSEInfo = nullptr;
32109467b48Spatrick   bool EnableCSE = EnableCSEInLegalizer.getNumOccurrences()
32209467b48Spatrick                        ? EnableCSEInLegalizer
32309467b48Spatrick                        : TPC.isGISelCSEEnabled();
32409467b48Spatrick   if (EnableCSE) {
32509467b48Spatrick     MIRBuilder = std::make_unique<CSEMIRBuilder>();
32609467b48Spatrick     CSEInfo = &Wrapper.get(TPC.getCSEConfig());
32709467b48Spatrick     MIRBuilder->setCSEInfo(CSEInfo);
32809467b48Spatrick   } else
32909467b48Spatrick     MIRBuilder = std::make_unique<MachineIRBuilder>();
33009467b48Spatrick 
33109467b48Spatrick   SmallVector<GISelChangeObserver *, 1> AuxObservers;
33209467b48Spatrick   if (EnableCSE && CSEInfo) {
33309467b48Spatrick     // We want CSEInfo in addition to WorkListObserver to observe all changes.
33409467b48Spatrick     AuxObservers.push_back(CSEInfo);
33509467b48Spatrick   }
336097a140dSpatrick   assert(!CSEInfo || !errorToBool(CSEInfo->verify()));
337097a140dSpatrick   LostDebugLocObserver LocObserver(DEBUG_TYPE);
338097a140dSpatrick   if (VerifyDebugLocs > DebugLocVerifyLevel::None)
339097a140dSpatrick     AuxObservers.push_back(&LocObserver);
34009467b48Spatrick 
34109467b48Spatrick   const LegalizerInfo &LI = *MF.getSubtarget().getLegalizerInfo();
342097a140dSpatrick   MFResult Result =
343097a140dSpatrick       legalizeMachineFunction(MF, LI, AuxObservers, LocObserver, *MIRBuilder);
34409467b48Spatrick 
34509467b48Spatrick   if (Result.FailedOn) {
34609467b48Spatrick     reportGISelFailure(MF, TPC, MORE, "gisel-legalize",
34709467b48Spatrick                        "unable to legalize instruction", *Result.FailedOn);
34809467b48Spatrick     return false;
34909467b48Spatrick   }
35009467b48Spatrick   // For now don't support if new blocks are inserted - we would need to fix the
35109467b48Spatrick   // outer loop for that.
35209467b48Spatrick   if (MF.size() != NumBlocks) {
35309467b48Spatrick     MachineOptimizationRemarkMissed R("gisel-legalize", "GISelFailure",
35409467b48Spatrick                                       MF.getFunction().getSubprogram(),
35509467b48Spatrick                                       /*MBB=*/nullptr);
35609467b48Spatrick     R << "inserting blocks is not supported yet";
35709467b48Spatrick     reportGISelFailure(MF, TPC, MORE, R);
35809467b48Spatrick     return false;
35909467b48Spatrick   }
360097a140dSpatrick 
361097a140dSpatrick   if (LocObserver.getNumLostDebugLocs()) {
362097a140dSpatrick     MachineOptimizationRemarkMissed R("gisel-legalize", "LostDebugLoc",
363097a140dSpatrick                                       MF.getFunction().getSubprogram(),
364097a140dSpatrick                                       /*MBB=*/&*MF.begin());
365097a140dSpatrick     R << "lost "
366097a140dSpatrick       << ore::NV("NumLostDebugLocs", LocObserver.getNumLostDebugLocs())
367097a140dSpatrick       << " debug locations during pass";
368097a140dSpatrick     reportGISelWarning(MF, TPC, MORE, R);
369097a140dSpatrick     // Example remark:
370097a140dSpatrick     // --- !Missed
371097a140dSpatrick     // Pass:            gisel-legalize
372097a140dSpatrick     // Name:            GISelFailure
373097a140dSpatrick     // DebugLoc:        { File: '.../legalize-urem.mir', Line: 1, Column: 0 }
374097a140dSpatrick     // Function:        test_urem_s32
375097a140dSpatrick     // Args:
376097a140dSpatrick     //   - String:          'lost '
377097a140dSpatrick     //   - NumLostDebugLocs: '1'
378097a140dSpatrick     //   - String:          ' debug locations during pass'
379097a140dSpatrick     // ...
380097a140dSpatrick   }
381097a140dSpatrick 
382097a140dSpatrick   // If for some reason CSE was not enabled, make sure that we invalidate the
383097a140dSpatrick   // CSEInfo object (as we currently declare that the analysis is preserved).
384097a140dSpatrick   // The next time get on the wrapper is called, it will force it to recompute
385097a140dSpatrick   // the analysis.
386097a140dSpatrick   if (!EnableCSE)
387097a140dSpatrick     Wrapper.setComputed(false);
38809467b48Spatrick   return Result.Changed;
38909467b48Spatrick }
390