xref: /freebsd/contrib/llvm-project/llvm/lib/CodeGen/ResetMachineFunctionPass.cpp (revision a9d65c5fae5f70f544eee860b5db0c099c2e3a96)
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  using namespace llvm;
26  
27  #define DEBUG_TYPE "reset-machine-function"
28  
29  STATISTIC(NumFunctionsReset, "Number of functions reset");
30  STATISTIC(NumFunctionsVisited, "Number of functions visited");
31  
32  namespace {
33    class ResetMachineFunction : public MachineFunctionPass {
34      /// Tells whether or not this pass should emit a fallback
35      /// diagnostic when it resets a function.
36      bool EmitFallbackDiag;
37      /// Whether we should abort immediately instead of resetting the function.
38      bool AbortOnFailedISel;
39  
40    public:
41      static char ID; // Pass identification, replacement for typeid
42      ResetMachineFunction(bool EmitFallbackDiag = false,
43                           bool AbortOnFailedISel = false)
44          : MachineFunctionPass(ID), EmitFallbackDiag(EmitFallbackDiag),
45            AbortOnFailedISel(AbortOnFailedISel) {}
46  
47      StringRef getPassName() const override { return "ResetMachineFunction"; }
48  
49      void getAnalysisUsage(AnalysisUsage &AU) const override {
50        AU.addPreserved<StackProtector>();
51        MachineFunctionPass::getAnalysisUsage(AU);
52      }
53  
54      bool runOnMachineFunction(MachineFunction &MF) override {
55        ++NumFunctionsVisited;
56        // No matter what happened, whether we successfully selected the function
57        // or not, nothing is going to use the vreg types after us. Make sure they
58        // disappear.
59        auto ClearVRegTypesOnReturn =
60            make_scope_exit([&MF]() { MF.getRegInfo().clearVirtRegTypes(); });
61  
62        if (MF.getProperties().hasProperty(
63                MachineFunctionProperties::Property::FailedISel)) {
64          if (AbortOnFailedISel)
65            report_fatal_error("Instruction selection failed");
66          LLVM_DEBUG(dbgs() << "Resetting: " << MF.getName() << '\n');
67          ++NumFunctionsReset;
68          MF.reset();
69          if (EmitFallbackDiag) {
70            const Function &F = MF.getFunction();
71            DiagnosticInfoISelFallback DiagFallback(F);
72            F.getContext().diagnose(DiagFallback);
73          }
74          return true;
75        }
76        return false;
77      }
78  
79    };
80  } // end anonymous namespace
81  
82  char ResetMachineFunction::ID = 0;
83  INITIALIZE_PASS(ResetMachineFunction, DEBUG_TYPE,
84                  "Reset machine function if ISel failed", false, false)
85  
86  MachineFunctionPass *
87  llvm::createResetMachineFunctionPass(bool EmitFallbackDiag = false,
88                                       bool AbortOnFailedISel = false) {
89    return new ResetMachineFunction(EmitFallbackDiag, AbortOnFailedISel);
90  }
91