Coverage Report

Created: 2023-10-30 17:15

/builds/2mk6rsew/0/parcoach/parcoach/src/tools/launcher/Parcoacht.cpp
Line
Count
Source (jump to first uncovered line)
1
#include "parcoach/Passes.h"
2
3
#include "llvm/ADT/Triple.h"
4
#include "llvm/Analysis/CallGraph.h"
5
#include "llvm/Analysis/CallGraphSCCPass.h"
6
#include "llvm/Analysis/LoopPass.h"
7
#include "llvm/Analysis/RegionPass.h"
8
#include "llvm/Analysis/TargetLibraryInfo.h"
9
#include "llvm/Analysis/TargetTransformInfo.h"
10
#include "llvm/AsmParser/Parser.h"
11
#include "llvm/CodeGen/CommandFlags.h"
12
#include "llvm/CodeGen/TargetPassConfig.h"
13
#include "llvm/Config/llvm-config.h"
14
#include "llvm/IR/DataLayout.h"
15
#include "llvm/IR/DebugInfo.h"
16
#include "llvm/IR/LLVMContext.h"
17
#include "llvm/IR/LLVMRemarkStreamer.h"
18
#include "llvm/IR/LegacyPassManager.h"
19
#include "llvm/IR/LegacyPassNameParser.h"
20
#include "llvm/IR/Module.h"
21
#include "llvm/IR/ModuleSummaryIndex.h"
22
#include "llvm/IR/Verifier.h"
23
#include "llvm/IRReader/IRReader.h"
24
#include "llvm/InitializePasses.h"
25
#include "llvm/LinkAllIR.h"
26
#include "llvm/LinkAllPasses.h"
27
#include "llvm/Passes/PassBuilder.h"
28
#include "llvm/Remarks/HotnessThresholdParser.h"
29
#include "llvm/Support/Debug.h"
30
#include "llvm/Support/FileSystem.h"
31
#include "llvm/Support/Host.h"
32
#include "llvm/Support/InitLLVM.h"
33
#include "llvm/Support/PluginLoader.h"
34
#include "llvm/Support/SourceMgr.h"
35
#include "llvm/Support/SystemUtils.h"
36
#include "llvm/Support/TargetSelect.h"
37
#include "llvm/Support/ToolOutputFile.h"
38
#include "llvm/Support/YAMLTraits.h"
39
#include "llvm/Target/TargetMachine.h"
40
#include "llvm/Transforms/IPO/AlwaysInliner.h"
41
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
42
#include "llvm/Transforms/IPO/WholeProgramDevirt.h"
43
#include "llvm/Transforms/Utils/Cloning.h"
44
#include "llvm/Transforms/Utils/Debugify.h"
45
46
using namespace llvm;
47
48
namespace {
49
50
cl::opt<std::string> InputFilename(cl::Positional,
51
                                   cl::desc("<input bitcode file>"),
52
                                   cl::init("-"), cl::value_desc("filename"));
53
54
cl::opt<std::string> OutputFilename("o", cl::desc("Override output filename"),
55
                                    cl::value_desc("filename"));
56
57
cl::opt<bool> OutputAssembly("S", cl::desc("Write output as LLVM assembly"));
58
59
cl::opt<bool> NoOutput("disable-output",
60
                       cl::desc("Do not write result bitcode file"),
61
                       cl::Hidden);
62
63
cl::opt<bool> TimeTrace("time-trace", cl::desc("Record time trace"));
64
65
cl::opt<unsigned> TimeTraceGranularity(
66
    "time-trace-granularity",
67
    cl::desc(
68
        "Minimum time granularity (in microseconds) traced by time profiler"),
69
    cl::init(500), cl::Hidden);
70
71
cl::opt<std::string>
72
    TimeTraceFile("time-trace-file",
73
                  cl::desc("Specify time trace file destination"),
74
                  cl::value_desc("filename"));
75
76
static cl::opt<bool> ShowVersion("parcoach-version",
77
                                 cl::desc("Show PARCOACH version"));
78
79
enum OutputKind {
80
  OK_NoOutput,
81
  OK_OutputAssembly,
82
  OK_OutputBitcode,
83
};
84
85
struct TimeTracer {
86
  StringRef InputFilename;
87
1.83k
  TimeTracer(StringRef ProgramName, StringRef Input) : InputFilename(Input) {
88
1.83k
    if (TimeTrace)
89
2
      timeTraceProfilerInitialize(TimeTraceGranularity, ProgramName);
90
1.83k
  }
91
1.83k
  ~TimeTracer() {
92
1.83k
    if (TimeTrace) {
93
2
      if (auto E = timeTraceProfilerWrite(TimeTraceFile, InputFilename)) {
94
1
        handleAllErrors(std::move(E), [&](StringError const &SE) {
95
1
          errs() << SE.getMessage() << "\n";
96
1
        });
97
1
        return;
98
1
      }
99
1
      timeTraceProfilerCleanup();
100
1
    }
101
1.83k
  }
102
};
103
} // namespace
104
105
1.83k
int main(int argc, char **argv) {
106
1.83k
  InitLLVM X(argc, argv);
107
108
  // Enable debug stream buffering.
109
1.83k
  EnableDebugBuffering = true;
110
111
1.83k
  InitializeAllTargets();
112
1.83k
  InitializeAllTargetMCs();
113
1.83k
  InitializeAllAsmPrinters();
114
1.83k
  InitializeAllAsmParsers();
115
116
  // Initialize passes
117
1.83k
  PassRegistry &Registry = *PassRegistry::getPassRegistry();
118
1.83k
  initializeCore(Registry);
119
1.83k
  initializeAnalysis(Registry);
120
1.83k
  initializeTransformUtils(Registry);
121
1.83k
  initializeInstrumentation(Registry);
122
1.83k
  initializeTarget(Registry);
123
124
1.83k
  cl::ParseCommandLineOptions(
125
1.83k
      argc, argv, "parcoach: a static/dynamic analyzer for MPI collectives\n");
126
127
1.83k
  if (ShowVersion) {
128
1
    parcoach::PrintVersion(outs());
129
1
    return 0;
130
1
  }
131
132
1.83k
  LLVMContext Context;
133
134
1.83k
  SMDiagnostic Err;
135
  // Load the input module...
136
1.83k
  std::unique_ptr<Module> M = parseIRFile(InputFilename, Err, Context);
137
138
1.83k
  if (!M) {
139
1
    Err.print(argv[0], errs());
140
1
    return 1;
141
1
  }
142
143
1.83k
  TimeTracer Tracer(argv[0], InputFilename);
144
1.83k
  TimeTraceScope TTS("Parcoach", "The main entry point of the tool.");
145
146
  // Immediately run the verifier to catch any problems before starting up the
147
  // pass pipelines.  Otherwise we can crash on broken code during
148
  // doInitialization().
149
1.83k
  if (verifyModule(*M, &errs())) {
150
1
    errs() << argv[0] << ": " << InputFilename
151
1
           << ": error: input module is broken!\n";
152
1
    return 1;
153
1
  }
154
155
  // Figure out what stream we are supposed to write to...
156
1.82k
  std::unique_ptr<ToolOutputFile> Out;
157
1.82k
  OutputKind OK{OK_NoOutput};
158
159
1.82k
  if (OutputFilename.empty()) {
160
    // By default we don't necessarily instrument the code, so if we don't
161
    // explicitly specify an output, just assume we just print the analysis
162
    // result.
163
71
    NoOutput = true;
164
71
  }
165
166
1.82k
  if (!NoOutput) {
167
1.75k
    std::error_code EC;
168
1.75k
    sys::fs::OpenFlags Flags =
169
1.75k
        OutputAssembly ? sys::fs::OF_TextWithCRLF : sys::fs::OF_None;
170
1.75k
    Out.reset(new ToolOutputFile(OutputFilename, EC, Flags));
171
1.75k
    if (EC) {
172
1
      errs() << EC.message() << '\n';
173
1
      return 1;
174
1
    }
175
1.75k
    OK = OutputAssembly ? OK_OutputAssembly : OK_OutputBitcode;
176
1.75k
  }
177
178
1.82k
  Triple ModuleTriple(M->getTargetTriple());
179
180
  // Add an appropriate TargetLibraryInfo pass for the module's triple.
181
1.82k
  TargetLibraryInfoImpl TLII(ModuleTriple);
182
183
1.82k
  LoopAnalysisManager LAM;
184
1.82k
  FunctionAnalysisManager FAM;
185
1.82k
  CGSCCAnalysisManager CGAM;
186
1.82k
  ModuleAnalysisManager MAM;
187
188
1.82k
  PassInstrumentationCallbacks PIC;
189
1.82k
  PipelineTuningOptions PTO;
190
1.82k
  PassBuilder PB(nullptr, PTO, None, &PIC);
191
192
  // Register our TargetLibraryInfoImpl.
193
1.82k
  FAM.registerPass([&] { return TargetLibraryAnalysis(TLII); });
194
195
  // Register all the basic analyses with the managers.
196
1.82k
  PB.registerModuleAnalyses(MAM);
197
1.82k
  parcoach::RegisterModuleAnalyses(MAM);
198
1.82k
  PB.registerCGSCCAnalyses(CGAM);
199
1.82k
  PB.registerFunctionAnalyses(FAM);
200
1.82k
  parcoach::RegisterFunctionAnalyses(FAM);
201
1.82k
  PB.registerLoopAnalyses(LAM);
202
1.82k
  PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
203
204
1.82k
  ModulePassManager MPM;
205
1.82k
  parcoach::RegisterPasses(MPM);
206
207
1.82k
  switch (OK) {
208
71
  case OK_NoOutput:
209
71
    break; // No output pass needed.
210
1
  case OK_OutputAssembly:
211
1
    MPM.addPass(PrintModulePass(Out->os(), "", false));
212
1
    break;
213
1.75k
  case OK_OutputBitcode:
214
1.75k
    MPM.addPass(BitcodeWriterPass(Out->os(), false, false, false));
215
1.75k
    break;
216
1.82k
  }
217
218
1.82k
  MPM.run(*M, MAM);
219
220
1.82k
  if (Out) {
221
1.75k
    Out->keep();
222
1.75k
  }
223
1.82k
  return 0;
224
1.82k
}