-
Notifications
You must be signed in to change notification settings - Fork 13.6k
[flang][Driver] Preliminary support for -ftime-report #107270
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
//===-- CompilerInstance.h - Flang Compiler Instance ------------*- C++ -*-===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/ | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#ifndef FORTRAN_SUPPORT_STRINGOSTREAM_H | ||
#define FORTRAN_SUPPORT_STRINGOSTREAM_H | ||
|
||
#include <llvm/Support/raw_ostream.h> | ||
|
||
namespace Fortran::support { | ||
|
||
/// Helper class to maintain both the an llvm::raw_string_ostream object and | ||
/// its associated buffer. | ||
class string_ostream : public llvm::raw_string_ostream { | ||
private: | ||
std::string buf; | ||
|
||
public: | ||
string_ostream() : llvm::raw_string_ostream(buf) {} | ||
}; | ||
|
||
} // namespace Fortran::support | ||
|
||
#endif // FORTRAN_SUPPORT_STRINGOSTREAM_H |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
//===- Timing.h - Execution time measurement facilities ---------*- C++ -*-===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// Facilities to measure and provide statistics on execution time. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#ifndef FORTRAN_SUPPORT_TIMING_H | ||
#define FORTRAN_SUPPORT_TIMING_H | ||
|
||
#include "mlir/Support/Timing.h" | ||
|
||
namespace Fortran::support { | ||
|
||
/// Create a strategy to render the captured times in plain text. This is | ||
/// intended to be passed to a TimingManager. | ||
std::unique_ptr<mlir::OutputStrategy> createTimingFormatterText( | ||
llvm::raw_ostream &os); | ||
|
||
} // namespace Fortran::support | ||
|
||
#endif // FORTRAN_SUPPORT_TIMING_H |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,9 +17,12 @@ | |
#include "flang/Parser/parsing.h" | ||
#include "flang/Parser/provenance.h" | ||
#include "flang/Semantics/semantics.h" | ||
#include "flang/Support/Timing.h" | ||
#include "mlir/Support/RawOstreamExtras.h" | ||
#include "clang/Basic/DiagnosticFrontend.h" | ||
#include "llvm/ADT/StringExtras.h" | ||
#include "llvm/MC/TargetRegistry.h" | ||
#include "llvm/Pass.h" | ||
#include "llvm/Support/Errc.h" | ||
#include "llvm/Support/Error.h" | ||
#include "llvm/Support/FileSystem.h" | ||
|
@@ -147,7 +150,7 @@ void CompilerInstance::clearOutputFiles(bool eraseFiles) { | |
} | ||
|
||
bool CompilerInstance::executeAction(FrontendAction &act) { | ||
auto &invoc = this->getInvocation(); | ||
CompilerInvocation &invoc = this->getInvocation(); | ||
|
||
llvm::Triple targetTriple{llvm::Triple(invoc.getTargetOpts().triple)}; | ||
if (targetTriple.getArch() == llvm::Triple::ArchType::x86_64) { | ||
|
@@ -167,6 +170,31 @@ bool CompilerInstance::executeAction(FrontendAction &act) { | |
// Set options controlling lowering to FIR. | ||
invoc.setLoweringOptions(); | ||
|
||
if (invoc.getEnableTimers()) { | ||
// FIXME: Currently, enabling these results in a duplicate registration | ||
// error of the "sort-timers" command line option. It is not clear why that | ||
// is occurring. Without setting these, we cannot get detailed information | ||
// about the runtime of the LLVM IR optimization and code generation passes. | ||
// Once the root cause of this is determined, we should enable this to have | ||
// behavior that is comparable to clang. | ||
// llvm::TimePassesIsEnabled = true; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @tarunprabhu #121663 has been merged which fixes the assert you were seeing. You should be able to uncomment this line (and remove preceding comment). |
||
|
||
timingStreamMLIR = std::make_unique<Fortran::support::string_ostream>(); | ||
timingStreamLLVM = std::make_unique<Fortran::support::string_ostream>(); | ||
timingStreamCodeGen = std::make_unique<Fortran::support::string_ostream>(); | ||
|
||
timingMgr.setEnabled(true); | ||
timingMgr.setDisplayMode(mlir::DefaultTimingManager::DisplayMode::Tree); | ||
timingMgr.setOutput( | ||
Fortran::support::createTimingFormatterText(*timingStreamMLIR)); | ||
|
||
// Creating a new TimingScope will automatically start the timer. Since this | ||
// is the top-level timer, this is ok because it will end up capturing the | ||
// time for all the bookkeeping and other tasks that take place between | ||
// parsing, lowering etc. for which finer-grained timers will be created. | ||
timingScopeRoot = timingMgr.getRootScope(); | ||
} | ||
|
||
// Run the frontend action `act` for every input file. | ||
for (const FrontendInputFile &fif : getFrontendOpts().inputs) { | ||
if (act.beginSourceFile(*this, fif)) { | ||
|
@@ -176,6 +204,34 @@ bool CompilerInstance::executeAction(FrontendAction &act) { | |
act.endSourceFile(); | ||
} | ||
} | ||
|
||
if (timingMgr.isEnabled()) { | ||
timingScopeRoot.stop(); | ||
|
||
// Write the timings to the associated output stream and clear all timers. | ||
// We need to provide another stream because the TimingManager will attempt | ||
// to print in its destructor even if it has been cleared. By the time that | ||
// destructor runs, the output streams will have been destroyed, so give it | ||
// a null stream. | ||
timingMgr.print(); | ||
timingMgr.setOutput( | ||
Fortran::support::createTimingFormatterText(mlir::thread_safe_nulls())); | ||
|
||
// This prints the timings in "reverse" order, starting from code | ||
// generation, followed by LLVM-IR optimizations, then MLIR optimizations | ||
// and transformations and the frontend. If any of the steps are disabled, | ||
// for instance because code generation was not performed, the strings | ||
// will be empty. | ||
if (!timingStreamCodeGen->str().empty()) | ||
llvm::errs() << timingStreamCodeGen->str() << "\n"; | ||
|
||
if (!timingStreamLLVM->str().empty()) | ||
llvm::errs() << timingStreamLLVM->str() << "\n"; | ||
|
||
if (!timingStreamMLIR->str().empty()) | ||
llvm::errs() << timingStreamMLIR->str() << "\n"; | ||
} | ||
|
||
return !getDiagnostics().getClient()->getNumErrors(); | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1358,6 +1358,12 @@ bool CompilerInvocation::createFromArgs( | |
} | ||
} | ||
|
||
// Process the timing-related options. | ||
if (const llvm::opt::Arg *a = | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
args.getLastArg(clang::driver::options::OPT_ftime_report)) { | ||
invoc.enableTimers = true; | ||
} | ||
|
||
invoc.setArgv0(argv0); | ||
|
||
return success; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: non-const getter is not needed.