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) 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 860b57cec5SDimitry 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 960b57cec5SDimitry Andric void Legalizer::init(MachineFunction &MF) { 970b57cec5SDimitry Andric } 980b57cec5SDimitry Andric 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: 1290b57cec5SDimitry Andric LegalizerWorkListManager(InstListTy &Insts, ArtifactListTy &Arts) 1300b57cec5SDimitry Andric : InstList(Insts), ArtifactList(Arts) {} 1310b57cec5SDimitry Andric 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 1440b57cec5SDimitry Andric void createdInstr(MachineInstr &MI) override { 1450b57cec5SDimitry Andric LLVM_DEBUG(NewMIs.push_back(&MI)); 1460b57cec5SDimitry Andric createdOrChangedInstr(MI); 1470b57cec5SDimitry Andric } 1480b57cec5SDimitry Andric 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 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 1630b57cec5SDimitry Andric void changingInstr(MachineInstr &MI) override { 1640b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << ".. .. Changing MI: " << MI); 1650b57cec5SDimitry Andric } 1660b57cec5SDimitry Andric 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 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 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