10b57cec5SDimitry Andric //===-- llvm/CodeGen/FinalizeISel.cpp ---------------------------*- C++ -*-===// 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 /// This pass expands Pseudo-instructions produced by ISel, fixes register 100b57cec5SDimitry Andric /// reservations and may do machine frame information adjustments. 110b57cec5SDimitry Andric /// The pseudo instructions are used to allow the expansion to contain control 120b57cec5SDimitry Andric /// flow, such as a conditional move implemented with a conditional branch and a 130b57cec5SDimitry Andric /// phi, or an atomic operation implemented with a loop. 140b57cec5SDimitry Andric // 150b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 160b57cec5SDimitry Andric 17*0fca6ea1SDimitry Andric #include "llvm/CodeGen/FinalizeISel.h" 18*0fca6ea1SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h" 190b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 200b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h" 21*0fca6ea1SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h" 220b57cec5SDimitry Andric #include "llvm/CodeGen/TargetLowering.h" 230b57cec5SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h" 24480093f4SDimitry Andric #include "llvm/InitializePasses.h" 250b57cec5SDimitry Andric using namespace llvm; 260b57cec5SDimitry Andric 270b57cec5SDimitry Andric #define DEBUG_TYPE "finalize-isel" 280b57cec5SDimitry Andric 290b57cec5SDimitry Andric namespace { 300b57cec5SDimitry Andric class FinalizeISel : public MachineFunctionPass { 310b57cec5SDimitry Andric public: 320b57cec5SDimitry Andric static char ID; // Pass identification, replacement for typeid 330b57cec5SDimitry Andric FinalizeISel() : MachineFunctionPass(ID) {} 340b57cec5SDimitry Andric 350b57cec5SDimitry Andric private: 360b57cec5SDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override; 370b57cec5SDimitry Andric 380b57cec5SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override { 390b57cec5SDimitry Andric MachineFunctionPass::getAnalysisUsage(AU); 400b57cec5SDimitry Andric } 410b57cec5SDimitry Andric }; 420b57cec5SDimitry Andric } // end anonymous namespace 430b57cec5SDimitry Andric 44*0fca6ea1SDimitry Andric static std::pair<bool, bool> runImpl(MachineFunction &MF) { 450b57cec5SDimitry Andric bool Changed = false; 46*0fca6ea1SDimitry Andric bool PreserveCFG = true; 47*0fca6ea1SDimitry Andric const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo(); 480b57cec5SDimitry Andric const TargetLowering *TLI = MF.getSubtarget().getTargetLowering(); 490b57cec5SDimitry Andric 500b57cec5SDimitry Andric // Iterate through each instruction in the function, looking for pseudos. 510b57cec5SDimitry Andric for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) { 520b57cec5SDimitry Andric MachineBasicBlock *MBB = &*I; 530b57cec5SDimitry Andric for (MachineBasicBlock::iterator MBBI = MBB->begin(), MBBE = MBB->end(); 540b57cec5SDimitry Andric MBBI != MBBE; ) { 550b57cec5SDimitry Andric MachineInstr &MI = *MBBI++; 560b57cec5SDimitry Andric 57*0fca6ea1SDimitry Andric // Set AdjustsStack to true if the instruction selector emits a stack 58*0fca6ea1SDimitry Andric // frame setup instruction or a stack aligning inlineasm. 59*0fca6ea1SDimitry Andric if (TII->isFrameInstr(MI) || MI.isStackAligningInlineAsm()) 60*0fca6ea1SDimitry Andric MF.getFrameInfo().setAdjustsStack(true); 61*0fca6ea1SDimitry Andric 620b57cec5SDimitry Andric // If MI is a pseudo, expand it. 630b57cec5SDimitry Andric if (MI.usesCustomInsertionHook()) { 640b57cec5SDimitry Andric Changed = true; 650b57cec5SDimitry Andric MachineBasicBlock *NewMBB = TLI->EmitInstrWithCustomInserter(MI, MBB); 660b57cec5SDimitry Andric // The expansion may involve new basic blocks. 670b57cec5SDimitry Andric if (NewMBB != MBB) { 68*0fca6ea1SDimitry Andric PreserveCFG = false; 690b57cec5SDimitry Andric MBB = NewMBB; 700b57cec5SDimitry Andric I = NewMBB->getIterator(); 710b57cec5SDimitry Andric MBBI = NewMBB->begin(); 720b57cec5SDimitry Andric MBBE = NewMBB->end(); 730b57cec5SDimitry Andric } 740b57cec5SDimitry Andric } 750b57cec5SDimitry Andric } 760b57cec5SDimitry Andric } 770b57cec5SDimitry Andric 780b57cec5SDimitry Andric TLI->finalizeLowering(MF); 790b57cec5SDimitry Andric 80*0fca6ea1SDimitry Andric return {Changed, PreserveCFG}; 81*0fca6ea1SDimitry Andric } 82*0fca6ea1SDimitry Andric 83*0fca6ea1SDimitry Andric char FinalizeISel::ID = 0; 84*0fca6ea1SDimitry Andric char &llvm::FinalizeISelID = FinalizeISel::ID; 85*0fca6ea1SDimitry Andric INITIALIZE_PASS(FinalizeISel, DEBUG_TYPE, 86*0fca6ea1SDimitry Andric "Finalize ISel and expand pseudo-instructions", false, false) 87*0fca6ea1SDimitry Andric 88*0fca6ea1SDimitry Andric bool FinalizeISel::runOnMachineFunction(MachineFunction &MF) { 89*0fca6ea1SDimitry Andric return runImpl(MF).first; 90*0fca6ea1SDimitry Andric } 91*0fca6ea1SDimitry Andric 92*0fca6ea1SDimitry Andric PreservedAnalyses FinalizeISelPass::run(MachineFunction &MF, 93*0fca6ea1SDimitry Andric MachineFunctionAnalysisManager &) { 94*0fca6ea1SDimitry Andric auto [Changed, PreserveCFG] = runImpl(MF); 95*0fca6ea1SDimitry Andric if (!Changed) 96*0fca6ea1SDimitry Andric return PreservedAnalyses::all(); 97*0fca6ea1SDimitry Andric auto PA = getMachineFunctionPassPreservedAnalyses(); 98*0fca6ea1SDimitry Andric if (PreserveCFG) 99*0fca6ea1SDimitry Andric PA.preserveSet<CFGAnalyses>(); 100*0fca6ea1SDimitry Andric return PA; 1010b57cec5SDimitry Andric } 102