xref: /freebsd-src/contrib/llvm-project/llvm/lib/CodeGen/FinalizeISel.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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