[CodeGen] Update a comment from NoSSA to IsSSA
[llvm-project.git] / flang / tools / tco / tco.cpp
blob31d6bac142dc421b5d7ca40d780cd0d9e17acae7
1 //===- tco.cpp - Tilikum Crossing Opt ---------------------------*- 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 //
9 // This is to be like LLVM's opt program, only for FIR. Such a program is
10 // required for roundtrip testing, etc.
12 //===----------------------------------------------------------------------===//
14 #include "flang/Optimizer/CodeGen/CodeGen.h"
15 #include "flang/Optimizer/Dialect/Support/FIRContext.h"
16 #include "flang/Optimizer/Dialect/Support/KindMapping.h"
17 #include "flang/Optimizer/Support/InitFIR.h"
18 #include "flang/Optimizer/Support/InternalNames.h"
19 #include "flang/Optimizer/Transforms/Passes.h"
20 #include "flang/Tools/CrossToolHelpers.h"
21 #include "mlir/IR/AsmState.h"
22 #include "mlir/IR/BuiltinOps.h"
23 #include "mlir/IR/MLIRContext.h"
24 #include "mlir/Parser/Parser.h"
25 #include "mlir/Pass/Pass.h"
26 #include "mlir/Pass/PassManager.h"
27 #include "mlir/Transforms/Passes.h"
28 #include "llvm/Passes/OptimizationLevel.h"
29 #include "llvm/Support/CommandLine.h"
30 #include "llvm/Support/ErrorOr.h"
31 #include "llvm/Support/FileSystem.h"
32 #include "llvm/Support/InitLLVM.h"
33 #include "llvm/Support/MemoryBuffer.h"
34 #include "llvm/Support/SourceMgr.h"
35 #include "llvm/Support/TargetSelect.h"
36 #include "llvm/Support/ToolOutputFile.h"
37 #include "llvm/Support/raw_ostream.h"
39 using namespace llvm;
41 static cl::opt<std::string>
42 inputFilename(cl::Positional, cl::desc("<input file>"), cl::init("-"));
44 static cl::opt<std::string> outputFilename("o",
45 cl::desc("Specify output filename"),
46 cl::value_desc("filename"),
47 cl::init("-"));
49 static cl::opt<bool> emitFir("emit-fir",
50 cl::desc("Parse and pretty-print the input"),
51 cl::init(false));
53 static cl::opt<std::string> targetTriple("target",
54 cl::desc("specify a target triple"),
55 cl::init("native"));
57 static cl::opt<bool> codeGenLLVM(
58 "code-gen-llvm",
59 cl::desc("Run only CodeGen passes and translate FIR to LLVM IR"),
60 cl::init(false));
62 #include "flang/Tools/CLOptions.inc"
64 static void printModuleBody(mlir::ModuleOp mod, raw_ostream &output) {
65 for (auto &op : *mod.getBody())
66 output << op << '\n';
69 // compile a .fir file
70 static mlir::LogicalResult
71 compileFIR(const mlir::PassPipelineCLParser &passPipeline) {
72 // check that there is a file to load
73 ErrorOr<std::unique_ptr<MemoryBuffer>> fileOrErr =
74 MemoryBuffer::getFileOrSTDIN(inputFilename);
76 if (std::error_code EC = fileOrErr.getError()) {
77 errs() << "Could not open file: " << EC.message() << '\n';
78 return mlir::failure();
81 // load the file into a module
82 SourceMgr sourceMgr;
83 sourceMgr.AddNewSourceBuffer(std::move(*fileOrErr), SMLoc());
84 mlir::DialectRegistry registry;
85 fir::support::registerDialects(registry);
86 mlir::MLIRContext context(registry);
87 fir::support::loadDialects(context);
88 fir::support::registerLLVMTranslation(context);
89 auto owningRef = mlir::parseSourceFile<mlir::ModuleOp>(sourceMgr, &context);
91 if (!owningRef) {
92 errs() << "Error can't load file " << inputFilename << '\n';
93 return mlir::failure();
95 if (mlir::failed(owningRef->verifyInvariants())) {
96 errs() << "Error verifying FIR module\n";
97 return mlir::failure();
100 std::error_code ec;
101 ToolOutputFile out(outputFilename, ec, sys::fs::OF_None);
103 // run passes
104 fir::KindMapping kindMap{&context};
105 fir::setTargetTriple(*owningRef, targetTriple);
106 fir::setKindMapping(*owningRef, kindMap);
107 mlir::PassManager pm((*owningRef)->getName(),
108 mlir::OpPassManager::Nesting::Implicit);
109 pm.enableVerifier(/*verifyPasses=*/true);
110 (void)mlir::applyPassManagerCLOptions(pm);
111 if (emitFir) {
112 // parse the input and pretty-print it back out
113 // -emit-fir intentionally disables all the passes
114 } else if (passPipeline.hasAnyOccurrences()) {
115 auto errorHandler = [&](const Twine &msg) {
116 mlir::emitError(mlir::UnknownLoc::get(pm.getContext())) << msg;
117 return mlir::failure();
119 if (mlir::failed(passPipeline.addToPipeline(pm, errorHandler)))
120 return mlir::failure();
121 } else {
122 MLIRToLLVMPassPipelineConfig config(llvm::OptimizationLevel::O2);
123 if (codeGenLLVM) {
124 // Run only CodeGen passes.
125 fir::createDefaultFIRCodeGenPassPipeline(pm, config);
126 } else {
127 // Run tco with O2 by default.
128 fir::createMLIRToLLVMPassPipeline(pm, config);
130 fir::addLLVMDialectToLLVMPass(pm, out.os());
133 // run the pass manager
134 if (mlir::succeeded(pm.run(*owningRef))) {
135 // passes ran successfully, so keep the output
136 if ((emitFir || passPipeline.hasAnyOccurrences()) && !codeGenLLVM)
137 printModuleBody(*owningRef, out.os());
138 out.keep();
139 return mlir::success();
142 // pass manager failed
143 printModuleBody(*owningRef, errs());
144 errs() << "\n\nFAILED: " << inputFilename << '\n';
145 return mlir::failure();
148 int main(int argc, char **argv) {
149 // Disable the ExternalNameConversion pass by default until all the tests have
150 // been updated to pass with it enabled.
151 disableExternalNameConversion = true;
153 [[maybe_unused]] InitLLVM y(argc, argv);
154 fir::support::registerMLIRPassesForFortranTools();
155 fir::registerOptCodeGenPasses();
156 fir::registerOptTransformPasses();
157 mlir::registerMLIRContextCLOptions();
158 mlir::registerPassManagerCLOptions();
159 mlir::PassPipelineCLParser passPipe("", "Compiler passes to run");
160 cl::ParseCommandLineOptions(argc, argv, "Tilikum Crossing Optimizer\n");
161 return mlir::failed(compileFIR(passPipe));