| //===-- llvm/CodeGen/FinalizeISel.cpp ---------------------------*- C++ -*-===// | |
| // | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| // See https://llvm.org/LICENSE.txt for license information. | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| // | |
| //===----------------------------------------------------------------------===// | |
| // | |
| /// This pass expands Pseudo-instructions produced by ISel, fixes register | |
| /// reservations and may do machine frame information adjustments. | |
| /// The pseudo instructions are used to allow the expansion to contain control | |
| /// flow, such as a conditional move implemented with a conditional branch and a | |
| /// phi, or an atomic operation implemented with a loop. | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #include "llvm/CodeGen/FinalizeISel.h" | |
| #include "llvm/CodeGen/MachineFrameInfo.h" | |
| #include "llvm/CodeGen/MachineFunction.h" | |
| #include "llvm/CodeGen/MachineFunctionPass.h" | |
| #include "llvm/CodeGen/TargetInstrInfo.h" | |
| #include "llvm/CodeGen/TargetLowering.h" | |
| #include "llvm/CodeGen/TargetSubtargetInfo.h" | |
| #include "llvm/InitializePasses.h" | |
| using namespace llvm; | |
| #define DEBUG_TYPE "finalize-isel" | |
| namespace { | |
| class FinalizeISel : public MachineFunctionPass { | |
| public: | |
| static char ID; // Pass identification, replacement for typeid | |
| FinalizeISel() : MachineFunctionPass(ID) {} | |
| private: | |
| bool runOnMachineFunction(MachineFunction &MF) override; | |
| void getAnalysisUsage(AnalysisUsage &AU) const override { | |
| MachineFunctionPass::getAnalysisUsage(AU); | |
| } | |
| }; | |
| } // end anonymous namespace | |
| static std::pair<bool, bool> runImpl(MachineFunction &MF) { | |
| bool Changed = false; | |
| bool PreserveCFG = true; | |
| const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo(); | |
| const TargetLowering *TLI = MF.getSubtarget().getTargetLowering(); | |
| // GlobalISel finalizes lowering in InstructionSelect. | |
| if (!MF.getProperties().hasSelected()) | |
| TLI->finalizeLowering(MF); | |
| // Iterate through each instruction in the function, looking for pseudos. | |
| for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) { | |
| MachineBasicBlock *MBB = &*I; | |
| for (MachineBasicBlock::iterator MBBI = MBB->begin(), MBBE = MBB->end(); | |
| MBBI != MBBE; ) { | |
| MachineInstr &MI = *MBBI++; | |
| // Set AdjustsStack to true if the instruction selector emits a stack | |
| // frame setup instruction or a stack aligning inlineasm. | |
| if (TII->isFrameInstr(MI) || MI.isStackAligningInlineAsm()) | |
| MF.getFrameInfo().setAdjustsStack(true); | |
| // If MI is a pseudo, expand it. | |
| if (MI.usesCustomInsertionHook()) { | |
| Changed = true; | |
| MachineBasicBlock *NewMBB = TLI->EmitInstrWithCustomInserter(MI, MBB); | |
| // The expansion may involve new basic blocks. | |
| if (NewMBB != MBB) { | |
| PreserveCFG = false; | |
| MBB = NewMBB; | |
| I = NewMBB->getIterator(); | |
| MBBI = NewMBB->begin(); | |
| MBBE = NewMBB->end(); | |
| } | |
| } | |
| } | |
| } | |
| return {Changed, PreserveCFG}; | |
| } | |
| char FinalizeISel::ID = 0; | |
| char &llvm::FinalizeISelID = FinalizeISel::ID; | |
| INITIALIZE_PASS(FinalizeISel, DEBUG_TYPE, | |
| "Finalize ISel and expand pseudo-instructions", false, false) | |
| bool FinalizeISel::runOnMachineFunction(MachineFunction &MF) { | |
| return runImpl(MF).first; | |
| } | |
| PreservedAnalyses FinalizeISelPass::run(MachineFunction &MF, | |
| MachineFunctionAnalysisManager &) { | |
| auto [Changed, PreserveCFG] = runImpl(MF); | |
| if (!Changed) | |
| return PreservedAnalyses::all(); | |
| auto PA = getMachineFunctionPassPreservedAnalyses(); | |
| if (PreserveCFG) | |
| PA.preserveSet<CFGAnalyses>(); | |
| return PA; | |
| } |