xref: /freebsd/contrib/llvm-project/llvm/lib/CodeGen/ResetMachineFunctionPass.cpp (revision 21817992b3314c908ab50f0bb88d2ee750b9c4ac)
1  //===-- ResetMachineFunctionPass.cpp - Reset Machine Function ----*- C++ -*-==//
2  //
3  // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4  // See https://llvm.org/LICENSE.txt for license information.
5  // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6  //
7  //===----------------------------------------------------------------------===//
8  /// \file
9  /// This file implements a pass that will conditionally reset a machine
10  /// function as if it was just created. This is used to provide a fallback
11  /// mechanism when GlobalISel fails, thus the condition for the reset to
12  /// happen is that the MachineFunction has the FailedISel property.
13  //===----------------------------------------------------------------------===//
14  
15  #include "llvm/ADT/ScopeExit.h"
16  #include "llvm/ADT/Statistic.h"
17  #include "llvm/CodeGen/MachineFunction.h"
18  #include "llvm/CodeGen/MachineFunctionPass.h"
19  #include "llvm/CodeGen/MachineRegisterInfo.h"
20  #include "llvm/CodeGen/Passes.h"
21  #include "llvm/CodeGen/StackProtector.h"
22  #include "llvm/IR/DiagnosticInfo.h"
23  #include "llvm/InitializePasses.h"
24  #include "llvm/Support/Debug.h"
25  #include "llvm/Target/TargetMachine.h"
26  using namespace llvm;
27  
28  #define DEBUG_TYPE "reset-machine-function"
29  
30  STATISTIC(NumFunctionsReset, "Number of functions reset");
31  STATISTIC(NumFunctionsVisited, "Number of functions visited");
32  
33  namespace {
34    class ResetMachineFunction : public MachineFunctionPass {
35      /// Tells whether or not this pass should emit a fallback
36      /// diagnostic when it resets a function.
37      bool EmitFallbackDiag;
38      /// Whether we should abort immediately instead of resetting the function.
39      bool AbortOnFailedISel;
40  
41    public:
42      static char ID; // Pass identification, replacement for typeid
43      ResetMachineFunction(bool EmitFallbackDiag = false,
44                           bool AbortOnFailedISel = false)
45          : MachineFunctionPass(ID), EmitFallbackDiag(EmitFallbackDiag),
46            AbortOnFailedISel(AbortOnFailedISel) {}
47  
48      StringRef getPassName() const override { return "ResetMachineFunction"; }
49  
50      void getAnalysisUsage(AnalysisUsage &AU) const override {
51        AU.addPreserved<StackProtector>();
52        MachineFunctionPass::getAnalysisUsage(AU);
53      }
54  
55      bool runOnMachineFunction(MachineFunction &MF) override {
56        ++NumFunctionsVisited;
57        // No matter what happened, whether we successfully selected the function
58        // or not, nothing is going to use the vreg types after us. Make sure they
59        // disappear.
60        auto ClearVRegTypesOnReturn =
61            make_scope_exit([&MF]() { MF.getRegInfo().clearVirtRegTypes(); });
62  
63        if (MF.getProperties().hasProperty(
64                MachineFunctionProperties::Property::FailedISel)) {
65          if (AbortOnFailedISel)
66            report_fatal_error("Instruction selection failed");
67          LLVM_DEBUG(dbgs() << "Resetting: " << MF.getName() << '\n');
68          ++NumFunctionsReset;
69          MF.reset();
70          MF.initTargetMachineFunctionInfo(MF.getSubtarget());
71  
72          const LLVMTargetMachine &TM = MF.getTarget();
73          // MRI callback for target specific initializations.
74          TM.registerMachineRegisterInfoCallback(MF);
75  
76          if (EmitFallbackDiag) {
77            const Function &F = MF.getFunction();
78            DiagnosticInfoISelFallback DiagFallback(F);
79            F.getContext().diagnose(DiagFallback);
80          }
81          return true;
82        }
83        return false;
84      }
85  
86    };
87  } // end anonymous namespace
88  
89  char ResetMachineFunction::ID = 0;
90  INITIALIZE_PASS(ResetMachineFunction, DEBUG_TYPE,
91                  "Reset machine function if ISel failed", false, false)
92  
93  MachineFunctionPass *
94  llvm::createResetMachineFunctionPass(bool EmitFallbackDiag = false,
95                                       bool AbortOnFailedISel = false) {
96    return new ResetMachineFunction(EmitFallbackDiag, AbortOnFailedISel);
97  }
98