Skip to content
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

[flang][Driver] Preliminary support for -ftime-report #122894

Merged
merged 1 commit into from
Jan 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -4108,7 +4108,7 @@ defm ms_tls_guards : BoolFOption<"ms-tls-guards",
"Do not emit code to perform on-demand initialization of thread-local variables">,
PosFlag<SetTrue>>;
def ftime_report : Flag<["-"], "ftime-report">, Group<f_Group>,
Visibility<[ClangOption, CC1Option]>,
Visibility<[ClangOption, CC1Option, FlangOption, FC1Option]>,
MarshallingInfoFlag<CodeGenOpts<"TimePasses">>;
def ftime_report_EQ: Joined<["-"], "ftime-report=">, Group<f_Group>,
Visibility<[ClangOption, CC1Option]>, Values<"per-pass,per-pass-run">,
Expand Down
10 changes: 6 additions & 4 deletions clang/lib/Driver/ToolChains/Flang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,10 +150,12 @@ void Flang::addCodegenOptions(const ArgList &Args,
if (shouldLoopVersion(Args))
CmdArgs.push_back("-fversion-loops-for-stride");

Args.addAllArgs(CmdArgs, {options::OPT_flang_experimental_hlfir,
options::OPT_flang_deprecated_no_hlfir,
options::OPT_fno_ppc_native_vec_elem_order,
options::OPT_fppc_native_vec_elem_order});
Args.addAllArgs(CmdArgs,
{options::OPT_flang_experimental_hlfir,
options::OPT_flang_deprecated_no_hlfir,
options::OPT_fno_ppc_native_vec_elem_order,
options::OPT_fppc_native_vec_elem_order,
options::OPT_ftime_report, options::OPT_ftime_report_EQ});
}

void Flang::addPicOptions(const ArgList &Args, ArgStringList &CmdArgs) const {
Expand Down
58 changes: 58 additions & 0 deletions flang/include/flang/Frontend/CompilerInstance.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "flang/Parser/provenance.h"
#include "flang/Semantics/runtime-type-info.h"
#include "flang/Semantics/semantics.h"
#include "flang/Support/StringOstream.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetMachine.h"

Expand Down Expand Up @@ -85,6 +86,27 @@ class CompilerInstance {
/// facilitate this. It is optional and will normally be just a nullptr.
std::unique_ptr<llvm::raw_pwrite_stream> outputStream;

/// @name Timing
/// Objects needed when timing is enabled.
/// @{
/// The timing manager.
mlir::DefaultTimingManager timingMgr;

/// The root of the timingScope. This will be reset in @ref executeAction if
/// timers have been enabled.
mlir::TimingScope timingScopeRoot;

/// @name Timing stream
/// The output streams to capture the timing. Three different streams are
/// needed because the timing classes all work slightly differently. We create
/// these streams so we have control over when and how the timing is
/// displayed. Otherwise, the timing is only displayed when the corresponding
/// managers/timers go out of scope.
std::unique_ptr<Fortran::support::string_ostream> timingStreamMLIR;
std::unique_ptr<Fortran::support::string_ostream> timingStreamLLVM;
std::unique_ptr<Fortran::support::string_ostream> timingStreamCodeGen;
/// @}

public:
explicit CompilerInstance();

Expand Down Expand Up @@ -254,6 +276,42 @@ class CompilerInstance {
/// Produces the string which represents target feature
std::string getTargetFeatures();

/// {
/// @name Timing
/// @{
bool isTimingEnabled() const { return timingMgr.isEnabled(); }

mlir::DefaultTimingManager &getTimingManager() { return timingMgr; }
const mlir::DefaultTimingManager &getTimingManager() const {
return timingMgr;
}

mlir::TimingScope &getTimingScopeRoot() { return timingScopeRoot; }
const mlir::TimingScope &getTimingScopeRoot() const {
return timingScopeRoot;
}

/// Get the timing stream for the MLIR pass manager.
llvm::raw_ostream &getTimingStreamMLIR() {
assert(timingStreamMLIR && "Timing stream for MLIR was not set");
return *timingStreamMLIR;
}

/// Get the timing stream for the new LLVM pass manager.
llvm::raw_ostream &getTimingStreamLLVM() {
assert(timingStreamLLVM && "Timing stream for LLVM was not set");
return *timingStreamLLVM;
}

/// Get the timing stream fro the legacy LLVM pass manager.
/// NOTE: If the codegen is updated to use the new pass manager, this should
/// no longer be needed.
llvm::raw_ostream &getTimingStreamCodeGen() {
assert(timingStreamCodeGen && "Timing stream for codegen was not set");
return *timingStreamCodeGen;
}
/// @}

private:
/// Create a new output file
///
Expand Down
7 changes: 7 additions & 0 deletions flang/include/flang/Frontend/CompilerInvocation.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "flang/Lower/LoweringOptions.h"
#include "flang/Parser/parsing.h"
#include "flang/Semantics/semantics.h"
#include "mlir/Support/Timing.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "llvm/Option/ArgList.h"
Expand Down Expand Up @@ -143,6 +144,10 @@ class CompilerInvocation : public CompilerInvocationBase {
},
};

/// Whether to time the invocation. Set when -ftime-report or -ftime-report=
/// is enabled.
bool enableTimers;

public:
CompilerInvocation() = default;

Expand Down Expand Up @@ -222,6 +227,8 @@ class CompilerInvocation : public CompilerInvocationBase {
return defaultKinds;
}

bool getEnableTimers() const { return enableTimers; }

/// Create a compiler invocation from a list of input options.
/// \returns true on success.
/// \returns false if an error was encountered while parsing the arguments
Expand Down
32 changes: 32 additions & 0 deletions flang/include/flang/Support/StringOstream.h
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
27 changes: 27 additions & 0 deletions flang/include/flang/Support/Timing.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
1 change: 1 addition & 0 deletions flang/lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ add_subdirectory(Decimal)
add_subdirectory(Lower)
add_subdirectory(Parser)
add_subdirectory(Semantics)
add_subdirectory(Support)
add_subdirectory(Frontend)
add_subdirectory(FrontendTool)

Expand Down
1 change: 1 addition & 0 deletions flang/lib/Frontend/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ add_flang_library(flangFrontend
FortranEvaluate
FortranCommon
FortranLower
FortranSupport
FIRDialect
FIRDialectSupport
FIRSupport
Expand Down
52 changes: 51 additions & 1 deletion flang/lib/Frontend/CompilerInstance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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) {
Expand All @@ -167,6 +170,25 @@ bool CompilerInstance::executeAction(FrontendAction &act) {
// Set options controlling lowering to FIR.
invoc.setLoweringOptions();

if (invoc.getEnableTimers()) {
llvm::TimePassesIsEnabled = true;

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)) {
Expand All @@ -176,6 +198,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();
}

Expand Down
4 changes: 4 additions & 0 deletions flang/lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1436,6 +1436,10 @@ bool CompilerInvocation::createFromArgs(
}
}

// Process the timing-related options.
if (args.hasArg(clang::driver::options::OPT_ftime_report))
invoc.enableTimers = true;

invoc.setArgv0(argv0);

return success;
Expand Down
Loading
Loading