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