--- /dev/null
+//===--- MathOptionsBase.def - Math options config ---------------- 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
+/// This file defines math options. Users of this file must define
+/// ENUM_MATHOPT macro to make use of this information.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef ENUM_MATHOPT
+# error Define the ENUM_MATHOPT macro to handle lowering options
+#endif
+
+/// Allow fusing FP operations (e.g. create FMAs from mul/add).
+ENUM_MATHOPT(FPContractEnabled, unsigned, 1, 0)
+
+/// Permit floating point optimizations without regard to infinities.
+ENUM_MATHOPT(NoHonorInfs, unsigned, 1, 0)
+
+#undef ENUM_MATHOPT
--- /dev/null
+//===- MathOptionsBase.h - Math options config ------------------*- 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 mathematical computations generated in FIR.
+/// This is intended to be header-only implementation without extra
+/// dependencies so that multiple components can use it to exchange
+/// math configuration.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef FORTRAN_COMMON_MATHOPTIONSBASE_H
+#define FORTRAN_COMMON_MATHOPTIONSBASE_H
+
+namespace Fortran::common {
+
+class MathOptionsBase {
+public:
+#define ENUM_MATHOPT(Name, Type, Bits, Default) \
+ Type get##Name() const { return static_cast<Type>(Name); } \
+ MathOptionsBase &set##Name(Type Value) { \
+ Name = static_cast<unsigned>(Value); \
+ return *this; \
+ }
+#include "flang/Common/MathOptionsBase.def"
+
+ MathOptionsBase() {
+#define ENUM_MATHOPT(Name, Type, Bits, Default) set##Name(Default);
+#include "flang/Common/MathOptionsBase.def"
+ }
+
+private:
+#define ENUM_MATHOPT(Name, Type, Bits, Default) unsigned Name : Bits;
+#include "flang/Common/MathOptionsBase.def"
+};
+
+} // namespace Fortran::common
+
+#endif // FORTRAN_COMMON_MATHOPTIONSBASE_H
#ifndef FLANG_LOWER_LOWERINGOPTIONS_H
#define FLANG_LOWER_LOWERINGOPTIONS_H
+#include "flang/Common/MathOptionsBase.h"
+
namespace Fortran::lower {
class LoweringOptionsBase {
#include "flang/Lower/LoweringOptions.def"
LoweringOptions();
+
+ const Fortran::common::MathOptionsBase &getMathOptions() const {
+ return MathOptions;
+ }
+
+ Fortran::common::MathOptionsBase &getMathOptions() { return MathOptions; }
+
+private:
+ /// Options for handling/optimizing mathematical computations.
+ Fortran::common::MathOptionsBase MathOptions;
};
} // namespace Fortran::lower
#ifndef FORTRAN_OPTIMIZER_BUILDER_FIRBUILDER_H
#define FORTRAN_OPTIMIZER_BUILDER_FIRBUILDER_H
+#include "flang/Common/MathOptionsBase.h"
#include "flang/Optimizer/Dialect/FIROps.h"
#include "flang/Optimizer/Dialect/FIRType.h"
#include "flang/Optimizer/Support/KindMapping.h"
fastMathFlags = flags;
}
+ /// Set default FastMathFlags value from the passed MathOptionsBase
+ /// config.
+ void setFastMathFlags(Fortran::common::MathOptionsBase options);
+
/// Dump the current function. (debug)
LLVM_DUMP_METHOD void dumpFunc();
/// Set \p loweringOptions controlling lowering behavior based
/// on the \p optimizationLevel.
void CompilerInvocation::setLoweringOptions() {
- const auto &codegenOpts = getCodeGenOpts();
+ const CodeGenOptions &codegenOpts = getCodeGenOpts();
// Lower TRANSPOSE as a runtime call under -O0.
loweringOpts.setOptimizeTranspose(codegenOpts.OptimizationLevel > 0);
+
+ const LangOptions &langOptions = getLangOpts();
+ Fortran::common::MathOptionsBase &mathOpts = loweringOpts.getMathOptions();
+ // TODO: when LangOptions are finalized, we can represent
+ // the math related options using Fortran::commmon::MathOptionsBase,
+ // so that we can just copy it into LoweringOptions.
+ mathOpts
+ .setFPContractEnabled(langOptions.getFPContractMode() ==
+ LangOptions::FPM_Fast)
+ .setNoHonorInfs(langOptions.NoHonorInfs);
}
mlir::func::FuncOp func = callee.addEntryBlockAndMapArguments();
builder = new fir::FirOpBuilder(func, bridge.getKindMap());
assert(builder && "FirOpBuilder did not instantiate");
+ builder->setFastMathFlags(bridge.getLoweringOptions().getMathOptions());
builder->setInsertionPointToStart(&func.front());
func.setVisibility(mlir::SymbolTable::Visibility::Public);
mlir::FunctionType::get(context, llvm::None, llvm::None));
func.addEntryBlock();
builder = new fir::FirOpBuilder(func, bridge.getKindMap());
+ assert(builder && "FirOpBuilder did not instantiate");
+ builder->setFastMathFlags(bridge.getLoweringOptions().getMathOptions());
createGlobals();
if (mlir::Region *region = func.getCallableRegion())
region->dropAllReferences();
namespace Fortran::lower {
-LoweringOptions::LoweringOptions() {
+LoweringOptions::LoweringOptions() : MathOptions{} {
#define LOWERINGOPT(Name, Bits, Default) Name = Default;
#define ENUM_LOWERINGOPT(Name, Type, Bits, Default) set##Name(Default);
#include "flang/Lower/LoweringOptions.def"
op->getContext(), fastMathFlags));
}
+void fir::FirOpBuilder::setFastMathFlags(
+ Fortran::common::MathOptionsBase options) {
+ mlir::arith::FastMathFlags arithFMF{};
+ if (options.getFPContractEnabled()) {
+ arithFMF = arithFMF | mlir::arith::FastMathFlags::contract;
+ }
+ if (options.getNoHonorInfs()) {
+ arithFMF = arithFMF | mlir::arith::FastMathFlags::ninf;
+ }
+ setFastMathFlags(arithFMF);
+}
+
//===--------------------------------------------------------------------===//
// ExtendedValue inquiry helper implementation
//===--------------------------------------------------------------------===//
--- /dev/null
+! RUN: %flang_fc1 -emit-fir -ffp-contract=fast %s -o - 2>&1 | FileCheck --check-prefixes=CONTRACT,ALL %s
+! RUN: %flang_fc1 -emit-fir -menable-no-infs %s -o - 2>&1 | FileCheck --check-prefixes=NINF,ALL %s
+
+! ALL-LABEL: func.func @_QPtest
+subroutine test(x)
+ real x
+! CONTRACT: arith.mulf{{.*}}, {{.*}} fastmath<[[ATTRS:contract]]> : f32
+! NINF: arith.mulf{{.*}}, {{.*}} fastmath<[[ATTRS:ninf]]> : f32
+! ALL: arith.divf{{.*}}, {{.*}} fastmath<[[ATTRS]]> : f32
+! ALL: arith.addf{{.*}}, {{.*}} fastmath<[[ATTRS]]> : f32
+! ALL: arith.subf{{.*}}, {{.*}} fastmath<[[ATTRS]]> : f32
+ x = x * x + x / x - x
+end subroutine test