1//===-- MachineFunctionPass.cpp -------------------------------------------===//
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//
9// This file contains the definitions of the MachineFunctionPass members.
10//
11//===----------------------------------------------------------------------===//
12
13#include "llvm/CodeGen/MachineFunctionPass.h"
14#include "llvm/Analysis/BasicAliasAnalysis.h"
15#include "llvm/Analysis/DominanceFrontier.h"
16#include "llvm/Analysis/GlobalsModRef.h"
17#include "llvm/Analysis/IVUsers.h"
18#include "llvm/Analysis/LoopInfo.h"
19#include "llvm/Analysis/MemoryDependenceAnalysis.h"
20#include "llvm/Analysis/OptimizationRemarkEmitter.h"
21#include "llvm/Analysis/ScalarEvolution.h"
22#include "llvm/Analysis/ScalarEvolutionAliasAnalysis.h"
23#include "llvm/CodeGen/MachineFunction.h"
24#include "llvm/CodeGen/MachineModuleInfo.h"
25#include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h"
26#include "llvm/CodeGen/Passes.h"
27#include "llvm/IR/Dominators.h"
28#include "llvm/IR/Function.h"
29#include "llvm/IR/PrintPasses.h"
30
31using namespace llvm;
32using namespace ore;
33
34Pass *MachineFunctionPass::createPrinterPass(raw_ostream &O,
35                                             const std::string &Banner) const {
36  return createMachineFunctionPrinterPass(O, Banner);
37}
38
39bool MachineFunctionPass::runOnFunction(Function &F) {
40  // Do not codegen any 'available_externally' functions at all, they have
41  // definitions outside the translation unit.
42  if (F.hasAvailableExternallyLinkage())
43    return false;
44
45  MachineModuleInfo &MMI = getAnalysis<MachineModuleInfoWrapperPass>().getMMI();
46  MachineFunction &MF = MMI.getOrCreateMachineFunction(F);
47
48  MachineFunctionProperties &MFProps = MF.getProperties();
49
50#ifndef NDEBUG
51  if (!MFProps.verifyRequiredProperties(RequiredProperties)) {
52    errs() << "MachineFunctionProperties required by " << getPassName()
53           << " pass are not met by function " << F.getName() << ".\n"
54           << "Required properties: ";
55    RequiredProperties.print(errs());
56    errs() << "\nCurrent properties: ";
57    MFProps.print(errs());
58    errs() << "\n";
59    llvm_unreachable("MachineFunctionProperties check failed");
60  }
61#endif
62  // Collect the MI count of the function before the pass.
63  unsigned CountBefore, CountAfter;
64
65  // Check if the user asked for size remarks.
66  bool ShouldEmitSizeRemarks =
67      F.getParent()->shouldEmitInstrCountChangedRemark();
68
69  // If we want size remarks, collect the number of MachineInstrs in our
70  // MachineFunction before the pass runs.
71  if (ShouldEmitSizeRemarks)
72    CountBefore = MF.getInstructionCount();
73
74  // For --print-changed, if the function name is a candidate, save the
75  // serialized MF to be compared later.
76  SmallString<0> BeforeStr, AfterStr;
77  StringRef PassID;
78  if (PrintChanged != ChangePrinter::None) {
79    if (const PassInfo *PI = Pass::lookupPassInfo(getPassID()))
80      PassID = PI->getPassArgument();
81  }
82  const bool IsInterestingPass = isPassInPrintList(PassID);
83  const bool ShouldPrintChanged = PrintChanged != ChangePrinter::None &&
84                                  IsInterestingPass &&
85                                  isFunctionInPrintList(MF.getName());
86  if (ShouldPrintChanged) {
87    raw_svector_ostream OS(BeforeStr);
88    MF.print(OS);
89  }
90
91  MFProps.reset(ClearedProperties);
92
93  bool RV = runOnMachineFunction(MF);
94
95  if (ShouldEmitSizeRemarks) {
96    // We wanted size remarks. Check if there was a change to the number of
97    // MachineInstrs in the module. Emit a remark if there was a change.
98    CountAfter = MF.getInstructionCount();
99    if (CountBefore != CountAfter) {
100      MachineOptimizationRemarkEmitter MORE(MF, nullptr);
101      MORE.emit([&]() {
102        int64_t Delta = static_cast<int64_t>(CountAfter) -
103                        static_cast<int64_t>(CountBefore);
104        MachineOptimizationRemarkAnalysis R("size-info", "FunctionMISizeChange",
105                                            MF.getFunction().getSubprogram(),
106                                            &MF.front());
107        R << NV("Pass", getPassName())
108          << ": Function: " << NV("Function", F.getName()) << ": "
109          << "MI Instruction count changed from "
110          << NV("MIInstrsBefore", CountBefore) << " to "
111          << NV("MIInstrsAfter", CountAfter)
112          << "; Delta: " << NV("Delta", Delta);
113        return R;
114      });
115    }
116  }
117
118  MFProps.set(SetProperties);
119
120  // For --print-changed, print if the serialized MF has changed. Modes other
121  // than quiet/verbose are unimplemented and treated the same as 'quiet'.
122  if (ShouldPrintChanged || !IsInterestingPass) {
123    if (ShouldPrintChanged) {
124      raw_svector_ostream OS(AfterStr);
125      MF.print(OS);
126    }
127    if (IsInterestingPass && BeforeStr != AfterStr) {
128      errs() << ("*** IR Dump After " + getPassName() + " (" + PassID +
129                 ") on " + MF.getName() + " ***\n");
130      switch (PrintChanged) {
131      case ChangePrinter::None:
132        llvm_unreachable("");
133      case ChangePrinter::Quiet:
134      case ChangePrinter::Verbose:
135      case ChangePrinter::DotCfgQuiet:   // unimplemented
136      case ChangePrinter::DotCfgVerbose: // unimplemented
137        errs() << AfterStr;
138        break;
139      case ChangePrinter::DiffQuiet:
140      case ChangePrinter::DiffVerbose:
141      case ChangePrinter::ColourDiffQuiet:
142      case ChangePrinter::ColourDiffVerbose: {
143        bool Color = llvm::is_contained(
144            {ChangePrinter::ColourDiffQuiet, ChangePrinter::ColourDiffVerbose},
145            PrintChanged.getValue());
146        StringRef Removed = Color ? "\033[31m-%l\033[0m\n" : "-%l\n";
147        StringRef Added = Color ? "\033[32m+%l\033[0m\n" : "+%l\n";
148        StringRef NoChange = " %l\n";
149        errs() << doSystemDiff(BeforeStr, AfterStr, Removed, Added, NoChange);
150        break;
151      }
152      }
153    } else if (llvm::is_contained({ChangePrinter::Verbose,
154                                   ChangePrinter::DiffVerbose,
155                                   ChangePrinter::ColourDiffVerbose},
156                                  PrintChanged.getValue())) {
157      const char *Reason =
158          IsInterestingPass ? " omitted because no change" : " filtered out";
159      errs() << "*** IR Dump After " << getPassName();
160      if (!PassID.empty())
161        errs() << " (" << PassID << ")";
162      errs() << " on " << MF.getName() + Reason + " ***\n";
163    }
164  }
165  return RV;
166}
167
168void MachineFunctionPass::getAnalysisUsage(AnalysisUsage &AU) const {
169  AU.addRequired<MachineModuleInfoWrapperPass>();
170  AU.addPreserved<MachineModuleInfoWrapperPass>();
171
172  // MachineFunctionPass preserves all LLVM IR passes, but there's no
173  // high-level way to express this. Instead, just list a bunch of
174  // passes explicitly. This does not include setPreservesCFG,
175  // because CodeGen overloads that to mean preserving the MachineBasicBlock
176  // CFG in addition to the LLVM IR CFG.
177  AU.addPreserved<BasicAAWrapperPass>();
178  AU.addPreserved<DominanceFrontierWrapperPass>();
179  AU.addPreserved<DominatorTreeWrapperPass>();
180  AU.addPreserved<AAResultsWrapperPass>();
181  AU.addPreserved<GlobalsAAWrapperPass>();
182  AU.addPreserved<IVUsersWrapperPass>();
183  AU.addPreserved<LoopInfoWrapperPass>();
184  AU.addPreserved<MemoryDependenceWrapperPass>();
185  AU.addPreserved<ScalarEvolutionWrapperPass>();
186  AU.addPreserved<SCEVAAWrapperPass>();
187
188  FunctionPass::getAnalysisUsage(AU);
189}
190