xref: /src/contrib/llvm-project/llvm/lib/CodeGen/MachineFunctionPass.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
159850d08SRoman Divacky //===-- MachineFunctionPass.cpp -------------------------------------------===//
259850d08SRoman Divacky //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
659850d08SRoman Divacky //
759850d08SRoman Divacky //===----------------------------------------------------------------------===//
859850d08SRoman Divacky //
959850d08SRoman Divacky // This file contains the definitions of the MachineFunctionPass members.
1059850d08SRoman Divacky //
1159850d08SRoman Divacky //===----------------------------------------------------------------------===//
1259850d08SRoman Divacky 
1359850d08SRoman Divacky #include "llvm/CodeGen/MachineFunctionPass.h"
14dd58ef01SDimitry Andric #include "llvm/Analysis/BasicAliasAnalysis.h"
15ec304151SDimitry Andric #include "llvm/Analysis/DominanceFrontier.h"
16dd58ef01SDimitry Andric #include "llvm/Analysis/GlobalsModRef.h"
17ec304151SDimitry Andric #include "llvm/Analysis/IVUsers.h"
18ec304151SDimitry Andric #include "llvm/Analysis/LoopInfo.h"
19ec304151SDimitry Andric #include "llvm/Analysis/MemoryDependenceAnalysis.h"
20145449b1SDimitry Andric #include "llvm/Analysis/OptimizationRemarkEmitter.h"
21ec304151SDimitry Andric #include "llvm/Analysis/ScalarEvolution.h"
22dd58ef01SDimitry Andric #include "llvm/Analysis/ScalarEvolutionAliasAnalysis.h"
2301095a5dSDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
24b915e9e0SDimitry Andric #include "llvm/CodeGen/MachineModuleInfo.h"
25d8e91e46SDimitry Andric #include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h"
26b5efedafSRoman Divacky #include "llvm/CodeGen/Passes.h"
27ec304151SDimitry Andric #include "llvm/IR/Dominators.h"
28ec304151SDimitry Andric #include "llvm/IR/Function.h"
29ac9a064cSDimitry Andric #include "llvm/IR/Module.h"
3008e8dd7bSDimitry Andric #include "llvm/IR/PrintPasses.h"
3101095a5dSDimitry Andric 
3259850d08SRoman Divacky using namespace llvm;
33d8e91e46SDimitry Andric using namespace ore;
3459850d08SRoman Divacky 
createPrinterPass(raw_ostream & O,const std::string & Banner) const35b5efedafSRoman Divacky Pass *MachineFunctionPass::createPrinterPass(raw_ostream &O,
36b5efedafSRoman Divacky                                              const std::string &Banner) const {
37b5efedafSRoman Divacky   return createMachineFunctionPrinterPass(O, Banner);
38b5efedafSRoman Divacky }
39b5efedafSRoman Divacky 
runOnFunction(Function & F)4059850d08SRoman Divacky bool MachineFunctionPass::runOnFunction(Function &F) {
4159850d08SRoman Divacky   // Do not codegen any 'available_externally' functions at all, they have
4259850d08SRoman Divacky   // definitions outside the translation unit.
4359850d08SRoman Divacky   if (F.hasAvailableExternallyLinkage())
4459850d08SRoman Divacky     return false;
4559850d08SRoman Divacky 
461d5ae102SDimitry Andric   MachineModuleInfo &MMI = getAnalysis<MachineModuleInfoWrapperPass>().getMMI();
477ab83427SDimitry Andric   MachineFunction &MF = MMI.getOrCreateMachineFunction(F);
48b915e9e0SDimitry Andric 
4901095a5dSDimitry Andric   MachineFunctionProperties &MFProps = MF.getProperties();
5001095a5dSDimitry Andric 
5101095a5dSDimitry Andric #ifndef NDEBUG
5201095a5dSDimitry Andric   if (!MFProps.verifyRequiredProperties(RequiredProperties)) {
5301095a5dSDimitry Andric     errs() << "MachineFunctionProperties required by " << getPassName()
5401095a5dSDimitry Andric            << " pass are not met by function " << F.getName() << ".\n"
5501095a5dSDimitry Andric            << "Required properties: ";
56b915e9e0SDimitry Andric     RequiredProperties.print(errs());
5701095a5dSDimitry Andric     errs() << "\nCurrent properties: ";
5801095a5dSDimitry Andric     MFProps.print(errs());
5901095a5dSDimitry Andric     errs() << "\n";
6001095a5dSDimitry Andric     llvm_unreachable("MachineFunctionProperties check failed");
6101095a5dSDimitry Andric   }
6201095a5dSDimitry Andric #endif
63d8e91e46SDimitry Andric   // Collect the MI count of the function before the pass.
64d8e91e46SDimitry Andric   unsigned CountBefore, CountAfter;
65d8e91e46SDimitry Andric 
66d8e91e46SDimitry Andric   // Check if the user asked for size remarks.
67d8e91e46SDimitry Andric   bool ShouldEmitSizeRemarks =
68d8e91e46SDimitry Andric       F.getParent()->shouldEmitInstrCountChangedRemark();
69d8e91e46SDimitry Andric 
70d8e91e46SDimitry Andric   // If we want size remarks, collect the number of MachineInstrs in our
71d8e91e46SDimitry Andric   // MachineFunction before the pass runs.
72d8e91e46SDimitry Andric   if (ShouldEmitSizeRemarks)
73d8e91e46SDimitry Andric     CountBefore = MF.getInstructionCount();
7401095a5dSDimitry Andric 
7508e8dd7bSDimitry Andric   // For --print-changed, if the function name is a candidate, save the
7608e8dd7bSDimitry Andric   // serialized MF to be compared later.
7708e8dd7bSDimitry Andric   SmallString<0> BeforeStr, AfterStr;
78e3b55780SDimitry Andric   StringRef PassID;
79e3b55780SDimitry Andric   if (PrintChanged != ChangePrinter::None) {
80e3b55780SDimitry Andric     if (const PassInfo *PI = Pass::lookupPassInfo(getPassID()))
81e3b55780SDimitry Andric       PassID = PI->getPassArgument();
82e3b55780SDimitry Andric   }
83e3b55780SDimitry Andric   const bool IsInterestingPass = isPassInPrintList(PassID);
84e3b55780SDimitry Andric   const bool ShouldPrintChanged = PrintChanged != ChangePrinter::None &&
85e3b55780SDimitry Andric                                   IsInterestingPass &&
8608e8dd7bSDimitry Andric                                   isFunctionInPrintList(MF.getName());
8708e8dd7bSDimitry Andric   if (ShouldPrintChanged) {
8808e8dd7bSDimitry Andric     raw_svector_ostream OS(BeforeStr);
8908e8dd7bSDimitry Andric     MF.print(OS);
9008e8dd7bSDimitry Andric   }
9108e8dd7bSDimitry Andric 
92b1c73532SDimitry Andric   MFProps.reset(ClearedProperties);
93b1c73532SDimitry Andric 
9401095a5dSDimitry Andric   bool RV = runOnMachineFunction(MF);
9501095a5dSDimitry Andric 
96d8e91e46SDimitry Andric   if (ShouldEmitSizeRemarks) {
97d8e91e46SDimitry Andric     // We wanted size remarks. Check if there was a change to the number of
98d8e91e46SDimitry Andric     // MachineInstrs in the module. Emit a remark if there was a change.
99d8e91e46SDimitry Andric     CountAfter = MF.getInstructionCount();
100d8e91e46SDimitry Andric     if (CountBefore != CountAfter) {
101d8e91e46SDimitry Andric       MachineOptimizationRemarkEmitter MORE(MF, nullptr);
102d8e91e46SDimitry Andric       MORE.emit([&]() {
103d8e91e46SDimitry Andric         int64_t Delta = static_cast<int64_t>(CountAfter) -
104d8e91e46SDimitry Andric                         static_cast<int64_t>(CountBefore);
105d8e91e46SDimitry Andric         MachineOptimizationRemarkAnalysis R("size-info", "FunctionMISizeChange",
106d8e91e46SDimitry Andric                                             MF.getFunction().getSubprogram(),
107d8e91e46SDimitry Andric                                             &MF.front());
108d8e91e46SDimitry Andric         R << NV("Pass", getPassName())
109d8e91e46SDimitry Andric           << ": Function: " << NV("Function", F.getName()) << ": "
110d8e91e46SDimitry Andric           << "MI Instruction count changed from "
111d8e91e46SDimitry Andric           << NV("MIInstrsBefore", CountBefore) << " to "
112d8e91e46SDimitry Andric           << NV("MIInstrsAfter", CountAfter)
113d8e91e46SDimitry Andric           << "; Delta: " << NV("Delta", Delta);
114d8e91e46SDimitry Andric         return R;
115d8e91e46SDimitry Andric       });
116d8e91e46SDimitry Andric     }
117d8e91e46SDimitry Andric   }
118d8e91e46SDimitry Andric 
11901095a5dSDimitry Andric   MFProps.set(SetProperties);
12008e8dd7bSDimitry Andric 
12108e8dd7bSDimitry Andric   // For --print-changed, print if the serialized MF has changed. Modes other
12208e8dd7bSDimitry Andric   // than quiet/verbose are unimplemented and treated the same as 'quiet'.
123e3b55780SDimitry Andric   if (ShouldPrintChanged || !IsInterestingPass) {
12408e8dd7bSDimitry Andric     if (ShouldPrintChanged) {
12508e8dd7bSDimitry Andric       raw_svector_ostream OS(AfterStr);
12608e8dd7bSDimitry Andric       MF.print(OS);
127e3b55780SDimitry Andric     }
128e3b55780SDimitry Andric     if (IsInterestingPass && BeforeStr != AfterStr) {
129e3b55780SDimitry Andric       errs() << ("*** IR Dump After " + getPassName() + " (" + PassID +
130e3b55780SDimitry Andric                  ") on " + MF.getName() + " ***\n");
131e3b55780SDimitry Andric       switch (PrintChanged) {
132e3b55780SDimitry Andric       case ChangePrinter::None:
133e3b55780SDimitry Andric         llvm_unreachable("");
134e3b55780SDimitry Andric       case ChangePrinter::Quiet:
135e3b55780SDimitry Andric       case ChangePrinter::Verbose:
136e3b55780SDimitry Andric       case ChangePrinter::DotCfgQuiet:   // unimplemented
137e3b55780SDimitry Andric       case ChangePrinter::DotCfgVerbose: // unimplemented
138e3b55780SDimitry Andric         errs() << AfterStr;
139e3b55780SDimitry Andric         break;
140e3b55780SDimitry Andric       case ChangePrinter::DiffQuiet:
141e3b55780SDimitry Andric       case ChangePrinter::DiffVerbose:
142e3b55780SDimitry Andric       case ChangePrinter::ColourDiffQuiet:
143e3b55780SDimitry Andric       case ChangePrinter::ColourDiffVerbose: {
144e3b55780SDimitry Andric         bool Color = llvm::is_contained(
145e3b55780SDimitry Andric             {ChangePrinter::ColourDiffQuiet, ChangePrinter::ColourDiffVerbose},
146e3b55780SDimitry Andric             PrintChanged.getValue());
147e3b55780SDimitry Andric         StringRef Removed = Color ? "\033[31m-%l\033[0m\n" : "-%l\n";
148e3b55780SDimitry Andric         StringRef Added = Color ? "\033[32m+%l\033[0m\n" : "+%l\n";
149e3b55780SDimitry Andric         StringRef NoChange = " %l\n";
150e3b55780SDimitry Andric         errs() << doSystemDiff(BeforeStr, AfterStr, Removed, Added, NoChange);
151e3b55780SDimitry Andric         break;
152e3b55780SDimitry Andric       }
153e3b55780SDimitry Andric       }
154e3b55780SDimitry Andric     } else if (llvm::is_contained({ChangePrinter::Verbose,
155e3b55780SDimitry Andric                                    ChangePrinter::DiffVerbose,
156e3b55780SDimitry Andric                                    ChangePrinter::ColourDiffVerbose},
157e3b55780SDimitry Andric                                   PrintChanged.getValue())) {
158e3b55780SDimitry Andric       const char *Reason =
159e3b55780SDimitry Andric           IsInterestingPass ? " omitted because no change" : " filtered out";
160e3b55780SDimitry Andric       errs() << "*** IR Dump After " << getPassName();
161e3b55780SDimitry Andric       if (!PassID.empty())
162e3b55780SDimitry Andric         errs() << " (" << PassID << ")";
163e3b55780SDimitry Andric       errs() << " on " << MF.getName() + Reason + " ***\n";
16408e8dd7bSDimitry Andric     }
16508e8dd7bSDimitry Andric   }
16601095a5dSDimitry Andric   return RV;
16759850d08SRoman Divacky }
16859850d08SRoman Divacky 
getAnalysisUsage(AnalysisUsage & AU) const16959850d08SRoman Divacky void MachineFunctionPass::getAnalysisUsage(AnalysisUsage &AU) const {
1701d5ae102SDimitry Andric   AU.addRequired<MachineModuleInfoWrapperPass>();
1711d5ae102SDimitry Andric   AU.addPreserved<MachineModuleInfoWrapperPass>();
17259850d08SRoman Divacky 
17359850d08SRoman Divacky   // MachineFunctionPass preserves all LLVM IR passes, but there's no
17459850d08SRoman Divacky   // high-level way to express this. Instead, just list a bunch of
17559850d08SRoman Divacky   // passes explicitly. This does not include setPreservesCFG,
17659850d08SRoman Divacky   // because CodeGen overloads that to mean preserving the MachineBasicBlock
17759850d08SRoman Divacky   // CFG in addition to the LLVM IR CFG.
178dd58ef01SDimitry Andric   AU.addPreserved<BasicAAWrapperPass>();
17901095a5dSDimitry Andric   AU.addPreserved<DominanceFrontierWrapperPass>();
180ec304151SDimitry Andric   AU.addPreserved<DominatorTreeWrapperPass>();
181dd58ef01SDimitry Andric   AU.addPreserved<AAResultsWrapperPass>();
182dd58ef01SDimitry Andric   AU.addPreserved<GlobalsAAWrapperPass>();
18301095a5dSDimitry Andric   AU.addPreserved<IVUsersWrapperPass>();
1845a5ac124SDimitry Andric   AU.addPreserved<LoopInfoWrapperPass>();
18501095a5dSDimitry Andric   AU.addPreserved<MemoryDependenceWrapperPass>();
186dd58ef01SDimitry Andric   AU.addPreserved<ScalarEvolutionWrapperPass>();
187dd58ef01SDimitry Andric   AU.addPreserved<SCEVAAWrapperPass>();
18859850d08SRoman Divacky 
18959850d08SRoman Divacky   FunctionPass::getAnalysisUsage(AU);
19059850d08SRoman Divacky }
191