blob: 9552d5c9af9e30bdd5b8df0fa9e894f449e58952 [file] [log] [blame]
jeanPerier57f536a2020-03-12 04:47:221//===- 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.
11//
12//===----------------------------------------------------------------------===//
13
Valentin Clement853e79d2022-01-24 13:14:4914#include "flang/Optimizer/CodeGen/CodeGen.h"
Renaud-Kb07ef9e2023-03-09 02:39:4015#include "flang/Optimizer/Dialect/Support/FIRContext.h"
16#include "flang/Optimizer/Dialect/Support/KindMapping.h"
Eric Schweitzf800a9b2021-02-12 21:09:1017#include "flang/Optimizer/Support/InitFIR.h"
Valentin Clement853e79d2022-01-24 13:14:4918#include "flang/Optimizer/Support/InternalNames.h"
Valentin Clement853e79d2022-01-24 13:14:4919#include "flang/Optimizer/Transforms/Passes.h"
Valentin Clement853e79d2022-01-24 13:14:4920#include "mlir/IR/AsmState.h"
River Riddle65fcddf2020-11-19 18:43:1221#include "mlir/IR/BuiltinOps.h"
jeanPerier57f536a2020-03-12 04:47:2222#include "mlir/IR/MLIRContext.h"
River Riddle9eaff422022-03-04 20:53:2223#include "mlir/Parser/Parser.h"
jeanPerier57f536a2020-03-12 04:47:2224#include "mlir/Pass/Pass.h"
25#include "mlir/Pass/PassManager.h"
26#include "mlir/Transforms/Passes.h"
Slava Zakharin9c0acc42022-07-14 23:50:4127#include "llvm/Passes/OptimizationLevel.h"
jeanPerier57f536a2020-03-12 04:47:2228#include "llvm/Support/CommandLine.h"
29#include "llvm/Support/ErrorOr.h"
Matthias Springerb44eb5a2021-08-04 13:11:2730#include "llvm/Support/FileSystem.h"
jeanPerier57f536a2020-03-12 04:47:2231#include "llvm/Support/InitLLVM.h"
32#include "llvm/Support/MemoryBuffer.h"
33#include "llvm/Support/SourceMgr.h"
Valentin Clement853e79d2022-01-24 13:14:4934#include "llvm/Support/TargetSelect.h"
jeanPerier57f536a2020-03-12 04:47:2235#include "llvm/Support/ToolOutputFile.h"
36#include "llvm/Support/raw_ostream.h"
37
38using namespace llvm;
39
40static cl::opt<std::string>
41 inputFilename(cl::Positional, cl::desc("<input file>"), cl::init("-"));
42
43static cl::opt<std::string> outputFilename("o",
44 cl::desc("Specify output filename"),
45 cl::value_desc("filename"),
46 cl::init("-"));
47
48static cl::opt<bool> emitFir("emit-fir",
49 cl::desc("Parse and pretty-print the input"),
50 cl::init(false));
51
Valentin Clement853e79d2022-01-24 13:14:4952static cl::opt<std::string> targetTriple("target",
53 cl::desc("specify a target triple"),
54 cl::init("native"));
55
Slava Zakharin42fead62022-10-03 23:54:1256static cl::opt<bool> codeGenLLVM(
57 "code-gen-llvm",
58 cl::desc("Run only CodeGen passes and translate FIR to LLVM IR"),
59 cl::init(false));
60
Valentin Clement853e79d2022-01-24 13:14:4961#include "flang/Tools/CLOptions.inc"
62
jeanPerier57f536a2020-03-12 04:47:2263static void printModuleBody(mlir::ModuleOp mod, raw_ostream &output) {
Valentin Clement853e79d2022-01-24 13:14:4964 for (auto &op : *mod.getBody())
jeanPerier57f536a2020-03-12 04:47:2265 output << op << '\n';
66}
67
68// compile a .fir file
Sourabh Singh Tomarbca06192021-02-04 19:25:2269static mlir::LogicalResult
70compileFIR(const mlir::PassPipelineCLParser &passPipeline) {
jeanPerier57f536a2020-03-12 04:47:2271 // check that there is a file to load
72 ErrorOr<std::unique_ptr<MemoryBuffer>> fileOrErr =
73 MemoryBuffer::getFileOrSTDIN(inputFilename);
74
75 if (std::error_code EC = fileOrErr.getError()) {
76 errs() << "Could not open file: " << EC.message() << '\n';
Sourabh Singh Tomarbca06192021-02-04 19:25:2277 return mlir::failure();
jeanPerier57f536a2020-03-12 04:47:2278 }
79
80 // load the file into a module
81 SourceMgr sourceMgr;
82 sourceMgr.AddNewSourceBuffer(std::move(*fileOrErr), SMLoc());
Alex Zinenko2996a8d2021-02-10 09:11:5083 mlir::DialectRegistry registry;
Eric Schweitzf800a9b2021-02-12 21:09:1084 fir::support::registerDialects(registry);
Alex Zinenko2996a8d2021-02-10 09:11:5085 mlir::MLIRContext context(registry);
Valentin Clement853e79d2022-01-24 13:14:4986 fir::support::loadDialects(context);
87 fir::support::registerLLVMTranslation(context);
Diana Picusaf4ddd512022-03-07 12:53:4988 auto owningRef = mlir::parseSourceFile<mlir::ModuleOp>(sourceMgr, &context);
jeanPerier57f536a2020-03-12 04:47:2289
90 if (!owningRef) {
91 errs() << "Error can't load file " << inputFilename << '\n';
Sourabh Singh Tomarbca06192021-02-04 19:25:2292 return mlir::failure();
jeanPerier57f536a2020-03-12 04:47:2293 }
River Riddle42e5f1d2022-02-01 23:01:3094 if (mlir::failed(owningRef->verifyInvariants())) {
jeanPerier57f536a2020-03-12 04:47:2295 errs() << "Error verifying FIR module\n";
Sourabh Singh Tomarbca06192021-02-04 19:25:2296 return mlir::failure();
jeanPerier57f536a2020-03-12 04:47:2297 }
98
99 std::error_code ec;
100 ToolOutputFile out(outputFilename, ec, sys::fs::OF_None);
101
102 // run passes
Valentin Clement853e79d2022-01-24 13:14:49103 fir::KindMapping kindMap{&context};
104 fir::setTargetTriple(*owningRef, targetTriple);
105 fir::setKindMapping(*owningRef, kindMap);
rkayaith94a30922022-11-09 04:23:28106 mlir::PassManager pm((*owningRef)->getName(),
107 mlir::OpPassManager::Nesting::Implicit);
Valentin Clement853e79d2022-01-24 13:14:49108 pm.enableVerifier(/*verifyPasses=*/true);
Jie Fud270d362023-04-02 08:30:33109 (void)mlir::applyPassManagerCLOptions(pm);
jeanPerier57f536a2020-03-12 04:47:22110 if (emitFir) {
111 // parse the input and pretty-print it back out
112 // -emit-fir intentionally disables all the passes
Valentin Clement853e79d2022-01-24 13:14:49113 } else if (passPipeline.hasAnyOccurrences()) {
114 auto errorHandler = [&](const Twine &msg) {
115 mlir::emitError(mlir::UnknownLoc::get(pm.getContext())) << msg;
116 return mlir::failure();
117 };
118 if (mlir::failed(passPipeline.addToPipeline(pm, errorHandler)))
119 return mlir::failure();
jeanPerier57f536a2020-03-12 04:47:22120 } else {
Slava Zakharin42fead62022-10-03 23:54:12121 if (codeGenLLVM) {
122 // Run only CodeGen passes.
123 fir::createDefaultFIRCodeGenPassPipeline(pm);
124 } else {
125 // Run tco with O2 by default.
126 fir::createMLIRToLLVMPassPipeline(pm, llvm::OptimizationLevel::O2);
127 }
Valentin Clement853e79d2022-01-24 13:14:49128 fir::addLLVMDialectToLLVMPass(pm, out.os());
jeanPerier57f536a2020-03-12 04:47:22129 }
130
131 // run the pass manager
132 if (mlir::succeeded(pm.run(*owningRef))) {
133 // passes ran successfully, so keep the output
Slava Zakharin42fead62022-10-03 23:54:12134 if ((emitFir || passPipeline.hasAnyOccurrences()) && !codeGenLLVM)
jeanPerier57f536a2020-03-12 04:47:22135 printModuleBody(*owningRef, out.os());
136 out.keep();
Sourabh Singh Tomarbca06192021-02-04 19:25:22137 return mlir::success();
jeanPerier57f536a2020-03-12 04:47:22138 }
139
140 // pass manager failed
141 printModuleBody(*owningRef, errs());
142 errs() << "\n\nFAILED: " << inputFilename << '\n';
Sourabh Singh Tomarbca06192021-02-04 19:25:22143 return mlir::failure();
jeanPerier57f536a2020-03-12 04:47:22144}
145
146int main(int argc, char **argv) {
Diana Picusf1d4cef2022-03-02 11:02:59147 // Disable the ExternalNameConversion pass by default until all the tests have
148 // been updated to pass with it enabled.
149 disableExternalNameConversion = true;
150
Valentin Clement3c90ae52022-01-21 19:34:17151 [[maybe_unused]] InitLLVM y(argc, argv);
Valentin Clement853e79d2022-01-24 13:14:49152 fir::support::registerMLIRPassesForFortranTools();
153 fir::registerOptCodeGenPasses();
154 fir::registerOptTransformPasses();
Valentin Clement853e79d2022-01-24 13:14:49155 mlir::registerMLIRContextCLOptions();
jeanPerier57f536a2020-03-12 04:47:22156 mlir::registerPassManagerCLOptions();
157 mlir::PassPipelineCLParser passPipe("", "Compiler passes to run");
158 cl::ParseCommandLineOptions(argc, argv, "Tilikum Crossing Optimizer\n");
Sourabh Singh Tomarbca06192021-02-04 19:25:22159 return mlir::failed(compileFIR(passPipe));
jeanPerier57f536a2020-03-12 04:47:22160}