xref: /freebsd/contrib/llvm-project/llvm/lib/CodeGen/GlobalISel/Legalizer.cpp (revision 480093f4440d54b30b3025afeac24b48f2ba7a2e)
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"
170b57cec5SDimitry Andric #include "llvm/ADT/SetVector.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"
210b57cec5SDimitry Andric #include "llvm/CodeGen/GlobalISel/GISelWorkList.h"
220b57cec5SDimitry Andric #include "llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h"
230b57cec5SDimitry Andric #include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
240b57cec5SDimitry Andric #include "llvm/CodeGen/GlobalISel/Utils.h"
250b57cec5SDimitry Andric #include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h"
260b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
270b57cec5SDimitry Andric #include "llvm/CodeGen/TargetPassConfig.h"
280b57cec5SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h"
29*480093f4SDimitry Andric #include "llvm/InitializePasses.h"
300b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
310b57cec5SDimitry Andric #include "llvm/Target/TargetMachine.h"
320b57cec5SDimitry Andric 
330b57cec5SDimitry Andric #include <iterator>
340b57cec5SDimitry Andric 
350b57cec5SDimitry Andric #define DEBUG_TYPE "legalizer"
360b57cec5SDimitry Andric 
370b57cec5SDimitry Andric using namespace llvm;
380b57cec5SDimitry Andric 
390b57cec5SDimitry Andric static cl::opt<bool>
400b57cec5SDimitry Andric     EnableCSEInLegalizer("enable-cse-in-legalizer",
410b57cec5SDimitry Andric                          cl::desc("Should enable CSE in Legalizer"),
420b57cec5SDimitry Andric                          cl::Optional, cl::init(false));
430b57cec5SDimitry Andric 
440b57cec5SDimitry Andric char Legalizer::ID = 0;
450b57cec5SDimitry Andric INITIALIZE_PASS_BEGIN(Legalizer, DEBUG_TYPE,
460b57cec5SDimitry Andric                       "Legalize the Machine IR a function's Machine IR", false,
470b57cec5SDimitry Andric                       false)
480b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
490b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(GISelCSEAnalysisWrapperPass)
500b57cec5SDimitry Andric INITIALIZE_PASS_END(Legalizer, DEBUG_TYPE,
510b57cec5SDimitry Andric                     "Legalize the Machine IR a function's Machine IR", false,
520b57cec5SDimitry Andric                     false)
530b57cec5SDimitry Andric 
540b57cec5SDimitry Andric Legalizer::Legalizer() : MachineFunctionPass(ID) { }
550b57cec5SDimitry Andric 
560b57cec5SDimitry Andric void Legalizer::getAnalysisUsage(AnalysisUsage &AU) const {
570b57cec5SDimitry Andric   AU.addRequired<TargetPassConfig>();
580b57cec5SDimitry Andric   AU.addRequired<GISelCSEAnalysisWrapperPass>();
590b57cec5SDimitry Andric   AU.addPreserved<GISelCSEAnalysisWrapperPass>();
600b57cec5SDimitry Andric   getSelectionDAGFallbackAnalysisUsage(AU);
610b57cec5SDimitry Andric   MachineFunctionPass::getAnalysisUsage(AU);
620b57cec5SDimitry Andric }
630b57cec5SDimitry Andric 
640b57cec5SDimitry Andric void Legalizer::init(MachineFunction &MF) {
650b57cec5SDimitry Andric }
660b57cec5SDimitry Andric 
670b57cec5SDimitry Andric static bool isArtifact(const MachineInstr &MI) {
680b57cec5SDimitry Andric   switch (MI.getOpcode()) {
690b57cec5SDimitry Andric   default:
700b57cec5SDimitry Andric     return false;
710b57cec5SDimitry Andric   case TargetOpcode::G_TRUNC:
720b57cec5SDimitry Andric   case TargetOpcode::G_ZEXT:
730b57cec5SDimitry Andric   case TargetOpcode::G_ANYEXT:
740b57cec5SDimitry Andric   case TargetOpcode::G_SEXT:
750b57cec5SDimitry Andric   case TargetOpcode::G_MERGE_VALUES:
760b57cec5SDimitry Andric   case TargetOpcode::G_UNMERGE_VALUES:
770b57cec5SDimitry Andric   case TargetOpcode::G_CONCAT_VECTORS:
780b57cec5SDimitry Andric   case TargetOpcode::G_BUILD_VECTOR:
790b57cec5SDimitry Andric   case TargetOpcode::G_EXTRACT:
800b57cec5SDimitry Andric     return true;
810b57cec5SDimitry Andric   }
820b57cec5SDimitry Andric }
830b57cec5SDimitry Andric using InstListTy = GISelWorkList<256>;
840b57cec5SDimitry Andric using ArtifactListTy = GISelWorkList<128>;
850b57cec5SDimitry Andric 
860b57cec5SDimitry Andric namespace {
870b57cec5SDimitry Andric class LegalizerWorkListManager : public GISelChangeObserver {
880b57cec5SDimitry Andric   InstListTy &InstList;
890b57cec5SDimitry Andric   ArtifactListTy &ArtifactList;
900b57cec5SDimitry Andric #ifndef NDEBUG
910b57cec5SDimitry Andric   SmallVector<MachineInstr *, 4> NewMIs;
920b57cec5SDimitry Andric #endif
930b57cec5SDimitry Andric 
940b57cec5SDimitry Andric public:
950b57cec5SDimitry Andric   LegalizerWorkListManager(InstListTy &Insts, ArtifactListTy &Arts)
960b57cec5SDimitry Andric       : InstList(Insts), ArtifactList(Arts) {}
970b57cec5SDimitry Andric 
980b57cec5SDimitry Andric   void createdOrChangedInstr(MachineInstr &MI) {
990b57cec5SDimitry Andric     // Only legalize pre-isel generic instructions.
1000b57cec5SDimitry Andric     // Legalization process could generate Target specific pseudo
1010b57cec5SDimitry Andric     // instructions with generic types. Don't record them
1020b57cec5SDimitry Andric     if (isPreISelGenericOpcode(MI.getOpcode())) {
1030b57cec5SDimitry Andric       if (isArtifact(MI))
1040b57cec5SDimitry Andric         ArtifactList.insert(&MI);
1050b57cec5SDimitry Andric       else
1060b57cec5SDimitry Andric         InstList.insert(&MI);
1070b57cec5SDimitry Andric     }
1080b57cec5SDimitry Andric   }
1090b57cec5SDimitry Andric 
1100b57cec5SDimitry Andric   void createdInstr(MachineInstr &MI) override {
1110b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << ".. .. New MI: " << MI);
1120b57cec5SDimitry Andric     LLVM_DEBUG(NewMIs.push_back(&MI));
1130b57cec5SDimitry Andric     createdOrChangedInstr(MI);
1140b57cec5SDimitry Andric   }
1150b57cec5SDimitry Andric 
1160b57cec5SDimitry Andric   void printNewInstrs() {
1170b57cec5SDimitry Andric     LLVM_DEBUG({
1180b57cec5SDimitry Andric       for (const auto *MI : NewMIs)
1190b57cec5SDimitry Andric         dbgs() << ".. .. New MI: " << *MI;
1200b57cec5SDimitry Andric       NewMIs.clear();
1210b57cec5SDimitry Andric     });
1220b57cec5SDimitry Andric   }
1230b57cec5SDimitry Andric 
1240b57cec5SDimitry Andric   void erasingInstr(MachineInstr &MI) override {
1250b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << ".. .. Erasing: " << MI);
1260b57cec5SDimitry Andric     InstList.remove(&MI);
1270b57cec5SDimitry Andric     ArtifactList.remove(&MI);
1280b57cec5SDimitry Andric   }
1290b57cec5SDimitry Andric 
1300b57cec5SDimitry Andric   void changingInstr(MachineInstr &MI) override {
1310b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << ".. .. Changing MI: " << MI);
1320b57cec5SDimitry Andric   }
1330b57cec5SDimitry Andric 
1340b57cec5SDimitry Andric   void changedInstr(MachineInstr &MI) override {
1350b57cec5SDimitry Andric     // When insts change, we want to revisit them to legalize them again.
1360b57cec5SDimitry Andric     // We'll consider them the same as created.
1370b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << ".. .. Changed MI: " << MI);
1380b57cec5SDimitry Andric     createdOrChangedInstr(MI);
1390b57cec5SDimitry Andric   }
1400b57cec5SDimitry Andric };
1410b57cec5SDimitry Andric } // namespace
1420b57cec5SDimitry Andric 
143*480093f4SDimitry Andric Legalizer::MFResult
144*480093f4SDimitry Andric Legalizer::legalizeMachineFunction(MachineFunction &MF, const LegalizerInfo &LI,
145*480093f4SDimitry Andric                                    ArrayRef<GISelChangeObserver *> AuxObservers,
146*480093f4SDimitry Andric                                    MachineIRBuilder &MIRBuilder) {
1470b57cec5SDimitry Andric   MachineRegisterInfo &MRI = MF.getRegInfo();
1480b57cec5SDimitry Andric 
149*480093f4SDimitry Andric   // Populate worklists.
1500b57cec5SDimitry Andric   InstListTy InstList;
1510b57cec5SDimitry Andric   ArtifactListTy ArtifactList;
1520b57cec5SDimitry Andric   ReversePostOrderTraversal<MachineFunction *> RPOT(&MF);
1530b57cec5SDimitry Andric   // Perform legalization bottom up so we can DCE as we legalize.
1540b57cec5SDimitry Andric   // Traverse BB in RPOT and within each basic block, add insts top down,
1550b57cec5SDimitry Andric   // so when we pop_back_val in the legalization process, we traverse bottom-up.
1560b57cec5SDimitry Andric   for (auto *MBB : RPOT) {
1570b57cec5SDimitry Andric     if (MBB->empty())
1580b57cec5SDimitry Andric       continue;
1590b57cec5SDimitry Andric     for (MachineInstr &MI : *MBB) {
1600b57cec5SDimitry Andric       // Only legalize pre-isel generic instructions: others don't have types
1610b57cec5SDimitry Andric       // and are assumed to be legal.
1620b57cec5SDimitry Andric       if (!isPreISelGenericOpcode(MI.getOpcode()))
1630b57cec5SDimitry Andric         continue;
1640b57cec5SDimitry Andric       if (isArtifact(MI))
1650b57cec5SDimitry Andric         ArtifactList.deferred_insert(&MI);
1660b57cec5SDimitry Andric       else
1670b57cec5SDimitry Andric         InstList.deferred_insert(&MI);
1680b57cec5SDimitry Andric     }
1690b57cec5SDimitry Andric   }
1700b57cec5SDimitry Andric   ArtifactList.finalize();
1710b57cec5SDimitry Andric   InstList.finalize();
1720b57cec5SDimitry Andric 
173*480093f4SDimitry Andric   // This observer keeps the worklists updated.
1740b57cec5SDimitry Andric   LegalizerWorkListManager WorkListObserver(InstList, ArtifactList);
175*480093f4SDimitry Andric   // We want both WorkListObserver as well as all the auxiliary observers (e.g.
176*480093f4SDimitry Andric   // CSEInfo) to observe all changes. Use the wrapper observer.
1770b57cec5SDimitry Andric   GISelObserverWrapper WrapperObserver(&WorkListObserver);
178*480093f4SDimitry Andric   for (GISelChangeObserver *Observer : AuxObservers)
179*480093f4SDimitry Andric     WrapperObserver.addObserver(Observer);
180*480093f4SDimitry Andric 
1810b57cec5SDimitry Andric   // Now install the observer as the delegate to MF.
1820b57cec5SDimitry Andric   // This will keep all the observers notified about new insertions/deletions.
1830b57cec5SDimitry Andric   RAIIDelegateInstaller DelInstall(MF, &WrapperObserver);
184*480093f4SDimitry Andric   LegalizerHelper Helper(MF, LI, WrapperObserver, MIRBuilder);
185*480093f4SDimitry Andric   LegalizationArtifactCombiner ArtCombiner(MIRBuilder, MRI, LI);
1860b57cec5SDimitry Andric   auto RemoveDeadInstFromLists = [&WrapperObserver](MachineInstr *DeadMI) {
1870b57cec5SDimitry Andric     WrapperObserver.erasingInstr(*DeadMI);
1880b57cec5SDimitry Andric   };
1890b57cec5SDimitry Andric   bool Changed = false;
1908bcb0991SDimitry Andric   SmallVector<MachineInstr *, 128> RetryList;
1910b57cec5SDimitry Andric   do {
192*480093f4SDimitry Andric     LLVM_DEBUG(dbgs() << "=== New Iteration ===\n");
1938bcb0991SDimitry Andric     assert(RetryList.empty() && "Expected no instructions in RetryList");
1948bcb0991SDimitry Andric     unsigned NumArtifacts = ArtifactList.size();
1950b57cec5SDimitry Andric     while (!InstList.empty()) {
1960b57cec5SDimitry Andric       MachineInstr &MI = *InstList.pop_back_val();
197*480093f4SDimitry Andric       assert(isPreISelGenericOpcode(MI.getOpcode()) &&
198*480093f4SDimitry Andric              "Expecting generic opcode");
1990b57cec5SDimitry Andric       if (isTriviallyDead(MI, MRI)) {
2000b57cec5SDimitry Andric         LLVM_DEBUG(dbgs() << MI << "Is dead; erasing.\n");
2010b57cec5SDimitry Andric         MI.eraseFromParentAndMarkDBGValuesForRemoval();
2020b57cec5SDimitry Andric         continue;
2030b57cec5SDimitry Andric       }
2040b57cec5SDimitry Andric 
2050b57cec5SDimitry Andric       // Do the legalization for this instruction.
2060b57cec5SDimitry Andric       auto Res = Helper.legalizeInstrStep(MI);
2070b57cec5SDimitry Andric       // Error out if we couldn't legalize this instruction. We may want to
2080b57cec5SDimitry Andric       // fall back to DAG ISel instead in the future.
2090b57cec5SDimitry Andric       if (Res == LegalizerHelper::UnableToLegalize) {
2108bcb0991SDimitry Andric         // Move illegal artifacts to RetryList instead of aborting because
2118bcb0991SDimitry Andric         // legalizing InstList may generate artifacts that allow
2128bcb0991SDimitry Andric         // ArtifactCombiner to combine away them.
2138bcb0991SDimitry Andric         if (isArtifact(MI)) {
214*480093f4SDimitry Andric           LLVM_DEBUG(dbgs() << ".. Not legalized, moving to artifacts retry\n");
215*480093f4SDimitry Andric           assert(NumArtifacts == 0 &&
216*480093f4SDimitry Andric                  "Artifacts are only expected in instruction list starting the "
217*480093f4SDimitry Andric                  "second iteration, but each iteration starting second must "
218*480093f4SDimitry Andric                  "start with an empty artifacts list");
219*480093f4SDimitry Andric           (void)NumArtifacts;
2208bcb0991SDimitry Andric           RetryList.push_back(&MI);
2218bcb0991SDimitry Andric           continue;
2228bcb0991SDimitry Andric         }
223*480093f4SDimitry Andric         Helper.MIRBuilder.stopObservingChanges();
224*480093f4SDimitry Andric         return {Changed, &MI};
2250b57cec5SDimitry Andric       }
2260b57cec5SDimitry Andric       WorkListObserver.printNewInstrs();
2270b57cec5SDimitry Andric       Changed |= Res == LegalizerHelper::Legalized;
2280b57cec5SDimitry Andric     }
2298bcb0991SDimitry Andric     // Try to combine the instructions in RetryList again if there
2308bcb0991SDimitry Andric     // are new artifacts. If not, stop legalizing.
2318bcb0991SDimitry Andric     if (!RetryList.empty()) {
232*480093f4SDimitry Andric       if (!ArtifactList.empty()) {
2338bcb0991SDimitry Andric         while (!RetryList.empty())
2348bcb0991SDimitry Andric           ArtifactList.insert(RetryList.pop_back_val());
2358bcb0991SDimitry Andric       } else {
236*480093f4SDimitry Andric         LLVM_DEBUG(dbgs() << "No new artifacts created, not retrying!\n");
237*480093f4SDimitry Andric         Helper.MIRBuilder.stopObservingChanges();
238*480093f4SDimitry Andric         return {Changed, RetryList.front()};
2398bcb0991SDimitry Andric       }
2408bcb0991SDimitry Andric     }
2410b57cec5SDimitry Andric     while (!ArtifactList.empty()) {
2420b57cec5SDimitry Andric       MachineInstr &MI = *ArtifactList.pop_back_val();
243*480093f4SDimitry Andric       assert(isPreISelGenericOpcode(MI.getOpcode()) &&
244*480093f4SDimitry Andric              "Expecting generic opcode");
2450b57cec5SDimitry Andric       if (isTriviallyDead(MI, MRI)) {
2460b57cec5SDimitry Andric         LLVM_DEBUG(dbgs() << MI << "Is dead\n");
2470b57cec5SDimitry Andric         RemoveDeadInstFromLists(&MI);
2480b57cec5SDimitry Andric         MI.eraseFromParentAndMarkDBGValuesForRemoval();
2490b57cec5SDimitry Andric         continue;
2500b57cec5SDimitry Andric       }
2510b57cec5SDimitry Andric       SmallVector<MachineInstr *, 4> DeadInstructions;
252*480093f4SDimitry Andric       LLVM_DEBUG(dbgs() << "Trying to combine: " << MI);
2530b57cec5SDimitry Andric       if (ArtCombiner.tryCombineInstruction(MI, DeadInstructions,
2540b57cec5SDimitry Andric                                             WrapperObserver)) {
2550b57cec5SDimitry Andric         WorkListObserver.printNewInstrs();
2560b57cec5SDimitry Andric         for (auto *DeadMI : DeadInstructions) {
2570b57cec5SDimitry Andric           LLVM_DEBUG(dbgs() << *DeadMI << "Is dead\n");
2580b57cec5SDimitry Andric           RemoveDeadInstFromLists(DeadMI);
2590b57cec5SDimitry Andric           DeadMI->eraseFromParentAndMarkDBGValuesForRemoval();
2600b57cec5SDimitry Andric         }
2610b57cec5SDimitry Andric         Changed = true;
2620b57cec5SDimitry Andric         continue;
2630b57cec5SDimitry Andric       }
2640b57cec5SDimitry Andric       // If this was not an artifact (that could be combined away), this might
2650b57cec5SDimitry Andric       // need special handling. Add it to InstList, so when it's processed
2660b57cec5SDimitry Andric       // there, it has to be legal or specially handled.
267*480093f4SDimitry Andric       else {
268*480093f4SDimitry Andric         LLVM_DEBUG(dbgs() << ".. Not combined, moving to instructions list\n");
2690b57cec5SDimitry Andric         InstList.insert(&MI);
2700b57cec5SDimitry Andric       }
271*480093f4SDimitry Andric     }
2720b57cec5SDimitry Andric   } while (!InstList.empty());
2730b57cec5SDimitry Andric 
274*480093f4SDimitry Andric   return {Changed, /*FailedOn*/ nullptr};
275*480093f4SDimitry Andric }
276*480093f4SDimitry Andric 
277*480093f4SDimitry Andric bool Legalizer::runOnMachineFunction(MachineFunction &MF) {
278*480093f4SDimitry Andric   // If the ISel pipeline failed, do not bother running that pass.
279*480093f4SDimitry Andric   if (MF.getProperties().hasProperty(
280*480093f4SDimitry Andric           MachineFunctionProperties::Property::FailedISel))
281*480093f4SDimitry Andric     return false;
282*480093f4SDimitry Andric   LLVM_DEBUG(dbgs() << "Legalize Machine IR for: " << MF.getName() << '\n');
283*480093f4SDimitry Andric   init(MF);
284*480093f4SDimitry Andric   const TargetPassConfig &TPC = getAnalysis<TargetPassConfig>();
285*480093f4SDimitry Andric   GISelCSEAnalysisWrapper &Wrapper =
286*480093f4SDimitry Andric       getAnalysis<GISelCSEAnalysisWrapperPass>().getCSEWrapper();
287*480093f4SDimitry Andric   MachineOptimizationRemarkEmitter MORE(MF, /*MBFI=*/nullptr);
288*480093f4SDimitry Andric 
289*480093f4SDimitry Andric   const size_t NumBlocks = MF.size();
290*480093f4SDimitry Andric 
291*480093f4SDimitry Andric   std::unique_ptr<MachineIRBuilder> MIRBuilder;
292*480093f4SDimitry Andric   GISelCSEInfo *CSEInfo = nullptr;
293*480093f4SDimitry Andric   bool EnableCSE = EnableCSEInLegalizer.getNumOccurrences()
294*480093f4SDimitry Andric                        ? EnableCSEInLegalizer
295*480093f4SDimitry Andric                        : TPC.isGISelCSEEnabled();
296*480093f4SDimitry Andric   if (EnableCSE) {
297*480093f4SDimitry Andric     MIRBuilder = std::make_unique<CSEMIRBuilder>();
298*480093f4SDimitry Andric     CSEInfo = &Wrapper.get(TPC.getCSEConfig());
299*480093f4SDimitry Andric     MIRBuilder->setCSEInfo(CSEInfo);
300*480093f4SDimitry Andric   } else
301*480093f4SDimitry Andric     MIRBuilder = std::make_unique<MachineIRBuilder>();
302*480093f4SDimitry Andric 
303*480093f4SDimitry Andric   SmallVector<GISelChangeObserver *, 1> AuxObservers;
304*480093f4SDimitry Andric   if (EnableCSE && CSEInfo) {
305*480093f4SDimitry Andric     // We want CSEInfo in addition to WorkListObserver to observe all changes.
306*480093f4SDimitry Andric     AuxObservers.push_back(CSEInfo);
307*480093f4SDimitry Andric   }
308*480093f4SDimitry Andric 
309*480093f4SDimitry Andric   const LegalizerInfo &LI = *MF.getSubtarget().getLegalizerInfo();
310*480093f4SDimitry Andric   MFResult Result = legalizeMachineFunction(MF, LI, AuxObservers, *MIRBuilder);
311*480093f4SDimitry Andric 
312*480093f4SDimitry Andric   if (Result.FailedOn) {
313*480093f4SDimitry Andric     reportGISelFailure(MF, TPC, MORE, "gisel-legalize",
314*480093f4SDimitry Andric                        "unable to legalize instruction", *Result.FailedOn);
315*480093f4SDimitry Andric     return false;
316*480093f4SDimitry Andric   }
3170b57cec5SDimitry Andric   // For now don't support if new blocks are inserted - we would need to fix the
3180b57cec5SDimitry Andric   // outer loop for that.
3190b57cec5SDimitry Andric   if (MF.size() != NumBlocks) {
3200b57cec5SDimitry Andric     MachineOptimizationRemarkMissed R("gisel-legalize", "GISelFailure",
3210b57cec5SDimitry Andric                                       MF.getFunction().getSubprogram(),
3220b57cec5SDimitry Andric                                       /*MBB=*/nullptr);
3230b57cec5SDimitry Andric     R << "inserting blocks is not supported yet";
3240b57cec5SDimitry Andric     reportGISelFailure(MF, TPC, MORE, R);
3250b57cec5SDimitry Andric     return false;
3260b57cec5SDimitry Andric   }
327*480093f4SDimitry Andric   return Result.Changed;
3280b57cec5SDimitry Andric }
329