aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSlava Zakharin <szakharin@nvidia.com>2022-07-19 20:39:58 -0700
committerSlava Zakharin <szakharin@nvidia.com>2022-08-05 11:29:45 -0700
commitf1eb945f9a5037b1fac6da02405047b24c0c2de5 (patch)
tree65fe255cbe27f7b8ac2ececf5cbc1f91f0ed6935
parent9c81b743e31a7dca288b37b6cf6cca3213bfd923 (diff)
[flang] Propagate lowering options from driver.
This commit addresses concerns raised in D129497. Propagate lowering options from driver to expressions lowering via AbstractConverter instance. A single use case so far is using optimized TRANSPOSE lowering with O1/O2/O3. bbc does not support optimization level switches, so it uses default LoweringOptions (e.g. optimized TRANSPOSE lowering is enabled by default, but an engineering -opt-transpose=false option can still override this). Differential Revision: https://reviews.llvm.org/D130204
-rw-r--r--flang/include/flang/Frontend/CompilerInvocation.h13
-rw-r--r--flang/include/flang/Lower/AbstractConverter.h16
-rw-r--r--flang/include/flang/Lower/Bridge.h14
-rw-r--r--flang/include/flang/Lower/LoweringOptions.h36
-rw-r--r--flang/lib/Frontend/CompilerInstance.cpp2
-rw-r--r--flang/lib/Frontend/CompilerInvocation.cpp9
-rw-r--r--flang/lib/Frontend/FrontendActions.cpp2
-rw-r--r--flang/lib/Lower/Bridge.cpp8
-rw-r--r--flang/lib/Lower/ConvertExpr.cpp44
-rw-r--r--flang/test/Lower/Intrinsics/transpose.f901
-rw-r--r--flang/test/Lower/Intrinsics/transpose_opt.f904
-rw-r--r--flang/tools/bbc/bbc.cpp4
12 files changed, 132 insertions, 21 deletions
diff --git a/flang/include/flang/Frontend/CompilerInvocation.h b/flang/include/flang/Frontend/CompilerInvocation.h
index cdc7878e93c3..3a6dafa301d3 100644
--- a/flang/include/flang/Frontend/CompilerInvocation.h
+++ b/flang/include/flang/Frontend/CompilerInvocation.h
@@ -17,6 +17,7 @@
#include "flang/Frontend/FrontendOptions.h"
#include "flang/Frontend/PreprocessorOptions.h"
#include "flang/Frontend/TargetOptions.h"
+#include "flang/Lower/LoweringOptions.h"
#include "flang/Parser/parsing.h"
#include "flang/Semantics/semantics.h"
#include "clang/Basic/Diagnostic.h"
@@ -68,6 +69,9 @@ class CompilerInvocation : public CompilerInvocationBase {
// of options.
Fortran::parser::Options parserOpts;
+ /// Options controlling lowering.
+ Fortran::lower::LoweringOptions loweringOpts;
+
/// Options controlling the target.
Fortran::frontend::TargetOptions targetOpts;
@@ -136,6 +140,11 @@ public:
CodeGenOptions &getCodeGenOpts() { return codeGenOpts; }
const CodeGenOptions &getCodeGenOpts() const { return codeGenOpts; }
+ Fortran::lower::LoweringOptions &getLoweringOpts() { return loweringOpts; }
+ const Fortran::lower::LoweringOptions &getLoweringOpts() const {
+ return loweringOpts;
+ }
+
Fortran::semantics::SemanticsContext &getSemanticsContext() {
return *semanticsContext;
}
@@ -226,6 +235,10 @@ public:
/// Set the Semantic Options
void setSemanticsOpts(Fortran::parser::AllCookedSources &);
+
+ /// Set \p loweringOptions controlling lowering behavior based
+ /// on the \p optimizationLevel.
+ void setLoweringOptions();
};
} // end namespace Fortran::frontend
diff --git a/flang/include/flang/Lower/AbstractConverter.h b/flang/include/flang/Lower/AbstractConverter.h
index 4ee4504608bc..0329e7497943 100644
--- a/flang/include/flang/Lower/AbstractConverter.h
+++ b/flang/include/flang/Lower/AbstractConverter.h
@@ -14,6 +14,7 @@
#define FORTRAN_LOWER_ABSTRACTCONVERTER_H
#include "flang/Common/Fortran.h"
+#include "flang/Lower/LoweringOptions.h"
#include "flang/Lower/PFTDefs.h"
#include "flang/Optimizer/Builder/BoxValue.h"
#include "flang/Semantics/symbol.h"
@@ -225,7 +226,22 @@ public:
/// Get the KindMap.
virtual const fir::KindMapping &getKindMap() = 0;
+ AbstractConverter(const Fortran::lower::LoweringOptions &loweringOptions)
+ : loweringOptions(loweringOptions) {}
virtual ~AbstractConverter() = default;
+
+ //===--------------------------------------------------------------------===//
+ // Miscellaneous
+ //===--------------------------------------------------------------------===//
+
+ /// Return options controlling lowering behavior.
+ const Fortran::lower::LoweringOptions &getLoweringOptions() const {
+ return loweringOptions;
+ }
+
+private:
+ /// Options controlling lowering behavior.
+ const Fortran::lower::LoweringOptions &loweringOptions;
};
} // namespace lower
diff --git a/flang/include/flang/Lower/Bridge.h b/flang/include/flang/Lower/Bridge.h
index 9b445e2177b4..70a171e598d3 100644
--- a/flang/include/flang/Lower/Bridge.h
+++ b/flang/include/flang/Lower/Bridge.h
@@ -15,6 +15,7 @@
#include "flang/Common/Fortran.h"
#include "flang/Lower/AbstractConverter.h"
+#include "flang/Lower/LoweringOptions.h"
#include "flang/Optimizer/Builder/FIRBuilder.h"
#include "flang/Optimizer/Support/KindMapping.h"
#include "mlir/IR/BuiltinOps.h"
@@ -52,9 +53,10 @@ public:
const Fortran::evaluate::IntrinsicProcTable &intrinsics,
const Fortran::evaluate::TargetCharacteristics &targetCharacteristics,
const Fortran::parser::AllCookedSources &allCooked,
- llvm::StringRef triple, fir::KindMapping &kindMap) {
+ llvm::StringRef triple, fir::KindMapping &kindMap,
+ const Fortran::lower::LoweringOptions &loweringOptions) {
return LoweringBridge(ctx, defaultKinds, intrinsics, targetCharacteristics,
- allCooked, triple, kindMap);
+ allCooked, triple, kindMap, loweringOptions);
}
//===--------------------------------------------------------------------===//
@@ -83,6 +85,10 @@ public:
/// Get the kind map.
const fir::KindMapping &getKindMap() const { return kindMap; }
+ const Fortran::lower::LoweringOptions &getLoweringOptions() const {
+ return loweringOptions;
+ }
+
/// Create a folding context. Careful: this is very expensive.
Fortran::evaluate::FoldingContext createFoldingContext() const;
@@ -107,7 +113,8 @@ private:
const Fortran::evaluate::IntrinsicProcTable &intrinsics,
const Fortran::evaluate::TargetCharacteristics &targetCharacteristics,
const Fortran::parser::AllCookedSources &cooked, llvm::StringRef triple,
- fir::KindMapping &kindMap);
+ fir::KindMapping &kindMap,
+ const Fortran::lower::LoweringOptions &loweringOptions);
LoweringBridge() = delete;
LoweringBridge(const LoweringBridge &) = delete;
@@ -118,6 +125,7 @@ private:
mlir::MLIRContext &context;
std::unique_ptr<mlir::ModuleOp> module;
fir::KindMapping &kindMap;
+ const Fortran::lower::LoweringOptions &loweringOptions;
};
} // namespace lower
diff --git a/flang/include/flang/Lower/LoweringOptions.h b/flang/include/flang/Lower/LoweringOptions.h
new file mode 100644
index 000000000000..5b70e9eabc18
--- /dev/null
+++ b/flang/include/flang/Lower/LoweringOptions.h
@@ -0,0 +1,36 @@
+//===- LoweringOptions.h ----------------------------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Options controlling lowering of front-end fragments to the FIR dialect
+/// of MLIR
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef FLANG_LOWER_LOWERINGOPTIONS_H
+#define FLANG_LOWER_LOWERINGOPTIONS_H
+
+namespace Fortran::lower {
+
+class LoweringOptions {
+ /// If true, lower transpose without a runtime call.
+ unsigned optimizeTranspose : 1;
+
+public:
+ LoweringOptions() : optimizeTranspose(true) {}
+
+ bool getOptimizeTranspose() const { return optimizeTranspose; }
+ LoweringOptions &setOptimizeTranspose(bool v) {
+ optimizeTranspose = v;
+ return *this;
+ }
+};
+
+} // namespace Fortran::lower
+
+#endif // FLANG_LOWER_LOWERINGOPTIONS_H
diff --git a/flang/lib/Frontend/CompilerInstance.cpp b/flang/lib/Frontend/CompilerInstance.cpp
index 418c83cfd844..5a33f5b26c9f 100644
--- a/flang/lib/Frontend/CompilerInstance.cpp
+++ b/flang/lib/Frontend/CompilerInstance.cpp
@@ -151,6 +151,8 @@ bool CompilerInstance::executeAction(FrontendAction &act) {
allSources->set_encoding(invoc.getFortranOpts().encoding);
// Create the semantics context and set semantic options.
invoc.setSemanticsOpts(*this->allCookedSources);
+ // Set options controlling lowering to FIR.
+ invoc.setLoweringOptions();
// Run the frontend action `act` for every input file.
for (const FrontendInputFile &fif : getFrontendOpts().inputs) {
diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp
index f794eb7d0c44..a75c04d5962e 100644
--- a/flang/lib/Frontend/CompilerInvocation.cpp
+++ b/flang/lib/Frontend/CompilerInvocation.cpp
@@ -794,3 +794,12 @@ void CompilerInvocation::setSemanticsOpts(
.set_warningsAreErrors(getWarnAsErr())
.set_moduleFileSuffix(getModuleFileSuffix());
}
+
+/// Set \p loweringOptions controlling lowering behavior based
+/// on the \p optimizationLevel.
+void CompilerInvocation::setLoweringOptions() {
+ const auto &codegenOpts = getCodeGenOpts();
+
+ // Lower TRANSPOSE as a runtime call under -O0.
+ loweringOpts.setOptimizeTranspose(codegenOpts.OptimizationLevel > 0);
+}
diff --git a/flang/lib/Frontend/FrontendActions.cpp b/flang/lib/Frontend/FrontendActions.cpp
index 7591e1a86622..4ebe2eaa2e9e 100644
--- a/flang/lib/Frontend/FrontendActions.cpp
+++ b/flang/lib/Frontend/FrontendActions.cpp
@@ -148,7 +148,7 @@ bool CodeGenAction::beginSourceFileAction() {
*mlirCtx, defKinds, ci.getInvocation().getSemanticsContext().intrinsics(),
ci.getInvocation().getSemanticsContext().targetCharacteristics(),
ci.getParsing().allCooked(), ci.getInvocation().getTargetOpts().triple,
- kindMap);
+ kindMap, ci.getInvocation().getLoweringOpts());
// Create a parse tree and lower it to FIR
Fortran::parser::Program &parseTree{*ci.getParsing().parseTree()};
diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp
index 5d88d20f931a..5dec92d90864 100644
--- a/flang/lib/Lower/Bridge.cpp
+++ b/flang/lib/Lower/Bridge.cpp
@@ -179,7 +179,8 @@ namespace {
class FirConverter : public Fortran::lower::AbstractConverter {
public:
explicit FirConverter(Fortran::lower::LoweringBridge &bridge)
- : bridge{bridge}, foldingContext{bridge.createFoldingContext()} {}
+ : Fortran::lower::AbstractConverter(bridge.getLoweringOptions()),
+ bridge{bridge}, foldingContext{bridge.createFoldingContext()} {}
virtual ~FirConverter() = default;
/// Convert the PFT to FIR.
@@ -3243,10 +3244,11 @@ Fortran::lower::LoweringBridge::LoweringBridge(
const Fortran::evaluate::IntrinsicProcTable &intrinsics,
const Fortran::evaluate::TargetCharacteristics &targetCharacteristics,
const Fortran::parser::AllCookedSources &cooked, llvm::StringRef triple,
- fir::KindMapping &kindMap)
+ fir::KindMapping &kindMap,
+ const Fortran::lower::LoweringOptions &loweringOptions)
: defaultKinds{defaultKinds}, intrinsics{intrinsics},
targetCharacteristics{targetCharacteristics}, cooked{&cooked},
- context{context}, kindMap{kindMap} {
+ context{context}, kindMap{kindMap}, loweringOptions{loweringOptions} {
// Register the diagnostic handler.
context.getDiagEngine().registerHandler([](mlir::Diagnostic &diag) {
llvm::raw_ostream &os = llvm::errs();
diff --git a/flang/lib/Lower/ConvertExpr.cpp b/flang/lib/Lower/ConvertExpr.cpp
index 309fd4042f23..5929b4bfa28d 100644
--- a/flang/lib/Lower/ConvertExpr.cpp
+++ b/flang/lib/Lower/ConvertExpr.cpp
@@ -88,8 +88,12 @@ static llvm::cl::opt<unsigned> clInitialBufferSize(
// from the "inline" FIR, e.g. it may diagnose out-of-memory conditions
// during the temporary allocation whereas the inline implementation
// relies on AllocMemOp that will silently return null in case
-// there is not enough memory. So it may be a good idea to set
-// this option to false for -O0.
+// there is not enough memory.
+//
+// If it is set to false, then TRANSPOSE will be lowered using
+// a runtime call. If it is set to true, then the lowering is controlled
+// by LoweringOptions::optimizeTranspose bit (see isTransposeOptEnabled
+// function in this file).
static llvm::cl::opt<bool> optimizeTranspose(
"opt-transpose",
llvm::cl::desc("lower transpose without using a runtime call"),
@@ -595,36 +599,50 @@ isIntrinsicModuleProcRef(const Fortran::evaluate::ProcedureRef &procRef) {
module->name().ToString().find("omp_lib") == std::string::npos;
}
+// Return true if TRANSPOSE should be lowered without a runtime call.
+static bool
+isTransposeOptEnabled(const Fortran::lower::AbstractConverter &converter) {
+ return optimizeTranspose &&
+ converter.getLoweringOptions().getOptimizeTranspose();
+}
+
// A set of visitors to detect if the given expression
// is a TRANSPOSE call that should be lowered without using
// runtime TRANSPOSE implementation.
template <typename T>
-static bool isOptimizableTranspose(const T &) {
+static bool isOptimizableTranspose(const T &,
+ const Fortran::lower::AbstractConverter &) {
return false;
}
static bool
-isOptimizableTranspose(const Fortran::evaluate::ProcedureRef &procRef) {
+isOptimizableTranspose(const Fortran::evaluate::ProcedureRef &procRef,
+ const Fortran::lower::AbstractConverter &converter) {
const Fortran::evaluate::SpecificIntrinsic *intrin =
procRef.proc().GetSpecificIntrinsic();
- return optimizeTranspose && intrin && intrin->name == "transpose";
+ return isTransposeOptEnabled(converter) && intrin &&
+ intrin->name == "transpose";
}
template <typename T>
static bool
-isOptimizableTranspose(const Fortran::evaluate::FunctionRef<T> &funcRef) {
+isOptimizableTranspose(const Fortran::evaluate::FunctionRef<T> &funcRef,
+ const Fortran::lower::AbstractConverter &converter) {
return isOptimizableTranspose(
- static_cast<const Fortran::evaluate::ProcedureRef &>(funcRef));
+ static_cast<const Fortran::evaluate::ProcedureRef &>(funcRef), converter);
}
template <typename T>
-static bool isOptimizableTranspose(Fortran::evaluate::Expr<T> expr) {
+static bool
+isOptimizableTranspose(Fortran::evaluate::Expr<T> expr,
+ const Fortran::lower::AbstractConverter &converter) {
// If optimizeTranspose is not enabled, return false right away.
- if (!optimizeTranspose)
+ if (!isTransposeOptEnabled(converter))
return false;
- return std::visit([&](const auto &e) { return isOptimizableTranspose(e); },
- expr.u);
+ return std::visit(
+ [&](const auto &e) { return isOptimizableTranspose(e, converter); },
+ expr.u);
}
namespace {
@@ -3289,7 +3307,7 @@ public:
// is used to not create a new temporary storage.
if (isScalar(x) ||
Fortran::evaluate::UnwrapWholeSymbolOrComponentDataRef(x) ||
- (isTransformationalRef(x) && !isOptimizableTranspose(x)))
+ (isTransformationalRef(x) && !isOptimizableTranspose(x, converter)))
return std::visit([&](const auto &e) { return genref(e); }, x.u);
if (useBoxArg)
return asArrayArg(x);
@@ -5139,7 +5157,7 @@ private:
llvm::Optional<mlir::Type> retTy) {
mlir::Location loc = getLoc();
- if (isOptimizableTranspose(procRef))
+ if (isOptimizableTranspose(procRef, converter))
return genTransposeProcRef(procRef);
if (procRef.IsElemental()) {
diff --git a/flang/test/Lower/Intrinsics/transpose.f90 b/flang/test/Lower/Intrinsics/transpose.f90
index a69613af5e56..cfd1fcd911d3 100644
--- a/flang/test/Lower/Intrinsics/transpose.f90
+++ b/flang/test/Lower/Intrinsics/transpose.f90
@@ -1,4 +1,5 @@
! RUN: bbc -emit-fir %s -opt-transpose=false -o - | FileCheck %s
+! RUN: %flang_fc1 -emit-fir -O0 %s -o - | FileCheck %s
! CHECK-LABEL: func @_QPtranspose_test(
! CHECK-SAME: %[[source:.*]]: !fir.ref<!fir.array<2x3xf32>>{{.*}}) {
diff --git a/flang/test/Lower/Intrinsics/transpose_opt.f90 b/flang/test/Lower/Intrinsics/transpose_opt.f90
index d2807e15d9cb..0a314a8a3ce3 100644
--- a/flang/test/Lower/Intrinsics/transpose_opt.f90
+++ b/flang/test/Lower/Intrinsics/transpose_opt.f90
@@ -1,4 +1,8 @@
! RUN: bbc -emit-fir %s -opt-transpose=true -o - | FileCheck %s
+! RUN: bbc -emit-fir %s -o - | FileCheck %s
+! RUN: %flang_fc1 -emit-fir -O1 %s -o - | FileCheck %s
+! RUN: %flang_fc1 -emit-fir -O2 %s -o - | FileCheck %s
+! RUN: %flang_fc1 -emit-fir -O3 %s -o - | FileCheck %s
! CHECK-LABEL: func.func @_QPtranspose_test(
! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.array<2x3xf32>> {fir.bindc_name = "mat"}) {
diff --git a/flang/tools/bbc/bbc.cpp b/flang/tools/bbc/bbc.cpp
index 2ad437aa6150..4fb3bc3ca843 100644
--- a/flang/tools/bbc/bbc.cpp
+++ b/flang/tools/bbc/bbc.cpp
@@ -217,10 +217,12 @@ static mlir::LogicalResult convertFortranSourceToMLIR(
auto &defKinds = semanticsContext.defaultKinds();
fir::KindMapping kindMap(
&ctx, llvm::ArrayRef<fir::KindTy>{fir::fromDefaultKinds(defKinds)});
+ // Use default lowering options for bbc.
+ Fortran::lower::LoweringOptions loweringOptions{};
auto burnside = Fortran::lower::LoweringBridge::create(
ctx, defKinds, semanticsContext.intrinsics(),
semanticsContext.targetCharacteristics(), parsing.allCooked(), "",
- kindMap);
+ kindMap, loweringOptions);
burnside.lower(parseTree, semanticsContext);
mlir::ModuleOp mlirModule = burnside.getModule();
std::error_code ec;