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