[flang-commits] [mlir] [flang] [flang][Draft/RFC] Set unsafe_fp_math attribute for -ffast-math (PR #79301)
Alex Bradbury via flang-commits
flang-commits at lists.llvm.org
Wed Jan 24 07:51:47 PST 2024
https://github.com/asb updated https://github.com/llvm/llvm-project/pull/79301
>From 505283264f90bb05b33954dc664b19b3016d1725 Mon Sep 17 00:00:00 2001
From: Alex Bradbury <asb at igalia.com>
Date: Wed, 24 Jan 2024 13:19:29 +0000
Subject: [PATCH 1/3] [MLIR][LLVM] Add unsafe-fp-math attribute support
---
mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td | 3 ++-
mlir/lib/Target/LLVMIR/ModuleTranslation.cpp | 4 ++++
mlir/test/Dialect/LLVMIR/func.mlir | 6 ++++++
3 files changed, 12 insertions(+), 1 deletion(-)
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
index 01d476f530b1c57..aad633a3bf8a589 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
@@ -1428,7 +1428,8 @@ def LLVM_LLVMFuncOp : LLVM_Op<"func", [
OptionalAttr<LLVM_VScaleRangeAttr>:$vscale_range,
OptionalAttr<FramePointerKindAttr>:$frame_pointer,
OptionalAttr<StrAttr>:$target_cpu,
- OptionalAttr<LLVM_TargetFeaturesAttr>:$target_features
+ OptionalAttr<LLVM_TargetFeaturesAttr>:$target_features,
+ OptionalAttr<BoolAttr>:$unsafe_fp_math
);
let regions = (region AnyRegion:$body);
diff --git a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
index 69a1cbe5969e859..bcb97f8e422f824 100644
--- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
@@ -37,6 +37,7 @@
#include "llvm/ADT/PostOrderIterator.h"
#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/TypeSwitch.h"
#include "llvm/Frontend/OpenMP/OMPIRBuilder.h"
#include "llvm/IR/BasicBlock.h"
@@ -1214,6 +1215,9 @@ LogicalResult ModuleTranslation::convertOneFunction(LLVMFuncOp func) {
getLLVMContext(), attr->getMinRange().getInt(),
attr->getMaxRange().getInt()));
+ if (auto unsafeFpMath = func.getUnsafeFpMath())
+ llvmFunc->addFnAttr("unsafe-fp-math", llvm::toStringRef(*unsafeFpMath));
+
// Add function attribute frame-pointer, if found.
if (FramePointerKindAttr attr = func.getFramePointerAttr())
llvmFunc->addFnAttr("frame-pointer",
diff --git a/mlir/test/Dialect/LLVMIR/func.mlir b/mlir/test/Dialect/LLVMIR/func.mlir
index 9dc1bc57034e02f..5177b166f088980 100644
--- a/mlir/test/Dialect/LLVMIR/func.mlir
+++ b/mlir/test/Dialect/LLVMIR/func.mlir
@@ -257,6 +257,12 @@ module {
llvm.func @frame_pointer_roundtrip() attributes {frame_pointer = #llvm.framePointerKind<"non-leaf">} {
llvm.return
}
+
+ llvm.func @unsafe_fp_math_roundtrip() attributes {unsafe_fp_math = true} {
+ // CHECK: @unsafe_fp_math_roundtrip
+ // CHECK-SAME: attributes {unsafe_fp_math = true}
+ llvm.return
+ }
}
// -----
>From 6ad7944b59a2c095cda41c633589620778d87977 Mon Sep 17 00:00:00 2001
From: Alex Bradbury <asb at igalia.com>
Date: Wed, 24 Jan 2024 15:04:17 +0000
Subject: [PATCH 2/3] [flang] Set the unsafe-fp-math=true if -ffast-math is set
Although the fast-math flag is set on individual IR operations, the
function attribute isn't set. Clang sets both, and matching that seems
sensible.
Currently investigating if the lack of the function-level attribute is
causing missed optimisations (although this would indicate an LLVM
bug/omission, matching clang's IR codegen approach still doesn't seem a
bad strategy).
---
flang/include/flang/Optimizer/Transforms/Passes.h | 2 +-
flang/include/flang/Optimizer/Transforms/Passes.td | 3 +++
flang/include/flang/Tools/CLOptions.inc | 4 ++--
flang/include/flang/Tools/CrossToolHelpers.h | 12 +++++++++++-
flang/lib/Frontend/FrontendActions.cpp | 3 ++-
flang/lib/Optimizer/Transforms/FunctionAttr.cpp | 8 +++++++-
6 files changed, 26 insertions(+), 6 deletions(-)
diff --git a/flang/include/flang/Optimizer/Transforms/Passes.h b/flang/include/flang/Optimizer/Transforms/Passes.h
index 6970da8698ae84d..4e4670bcb47ced6 100644
--- a/flang/include/flang/Optimizer/Transforms/Passes.h
+++ b/flang/include/flang/Optimizer/Transforms/Passes.h
@@ -91,7 +91,7 @@ struct FunctionAttrTypes {
std::unique_ptr<mlir::Pass> createFunctionAttrPass();
std::unique_ptr<mlir::Pass>
-createFunctionAttrPass(FunctionAttrTypes &functionAttr);
+createFunctionAttrPass(FunctionAttrTypes &functionAttr, bool unsafeFPMath);
// declarative passes
#define GEN_PASS_REGISTRATION
diff --git a/flang/include/flang/Optimizer/Transforms/Passes.td b/flang/include/flang/Optimizer/Transforms/Passes.td
index e3c45d41f04cc71..53fb8aa6ac78fe8 100644
--- a/flang/include/flang/Optimizer/Transforms/Passes.td
+++ b/flang/include/flang/Optimizer/Transforms/Passes.td
@@ -366,6 +366,9 @@ def FunctionAttr : Pass<"function-attr", "mlir::func::FuncOp"> {
"mlir::LLVM::framePointerKind::FramePointerKind",
/*default=*/"mlir::LLVM::framePointerKind::FramePointerKind{}",
"frame pointer">,
+ Option<"unsafeFPMath", "unsafe-fp-math",
+ "bool", /*default=*/"false",
+ "Set the unsafe-fp-math attribute on functions in the module.">,
];
let constructor = "::fir::createFunctionAttrPass()";
}
diff --git a/flang/include/flang/Tools/CLOptions.inc b/flang/include/flang/Tools/CLOptions.inc
index 96d3869cd093912..69be13cb1d014e8 100644
--- a/flang/include/flang/Tools/CLOptions.inc
+++ b/flang/include/flang/Tools/CLOptions.inc
@@ -315,7 +315,7 @@ inline void createDefaultFIRCodeGenPassPipeline(
// Add function attributes
fir::FunctionAttrTypes functionAttrs;
- if (config.FramePointerKind != llvm::FramePointerKind::None) {
+ if (config.FramePointerKind != llvm::FramePointerKind::None || config.UnsafeFPMath) {
if (config.FramePointerKind == llvm::FramePointerKind::NonLeaf)
functionAttrs.framePointerKind =
mlir::LLVM::framePointerKind::FramePointerKind::NonLeaf;
@@ -323,7 +323,7 @@ inline void createDefaultFIRCodeGenPassPipeline(
functionAttrs.framePointerKind =
mlir::LLVM::framePointerKind::FramePointerKind::All;
- pm.addPass(fir::createFunctionAttrPass(functionAttrs));
+ pm.addPass(fir::createFunctionAttrPass(functionAttrs, config.UnsafeFPMath));
}
fir::addFIRToLLVMPass(pm, config);
diff --git a/flang/include/flang/Tools/CrossToolHelpers.h b/flang/include/flang/Tools/CrossToolHelpers.h
index b61224ff4f1b3cd..4b3423a737ed353 100644
--- a/flang/include/flang/Tools/CrossToolHelpers.h
+++ b/flang/include/flang/Tools/CrossToolHelpers.h
@@ -13,6 +13,7 @@
#ifndef FORTRAN_TOOLS_CROSS_TOOL_HELPERS_H
#define FORTRAN_TOOLS_CROSS_TOOL_HELPERS_H
+#include "flang/Common/MathOptionsBase.h"
#include "flang/Frontend/CodeGenOptions.h"
#include "flang/Frontend/LangOptions.h"
#include <cstdint>
@@ -28,7 +29,8 @@ struct MLIRToLLVMPassPipelineConfig {
OptLevel = level;
}
explicit MLIRToLLVMPassPipelineConfig(llvm::OptimizationLevel level,
- const Fortran::frontend::CodeGenOptions &opts) {
+ const Fortran::frontend::CodeGenOptions &opts,
+ const Fortran::common::MathOptionsBase &mathOpts) {
OptLevel = level;
StackArrays = opts.StackArrays;
Underscoring = opts.Underscoring;
@@ -36,6 +38,13 @@ struct MLIRToLLVMPassPipelineConfig {
DebugInfo = opts.getDebugInfo();
AliasAnalysis = opts.AliasAnalysis;
FramePointerKind = opts.getFramePointer();
+ // TODO: This matches the set of options enabled for Ofast, but this is
+ // probably overkill. Sadly the precise semantics of unsafe-fp-math=true
+ // don't seem to be clearly documented.
+ UnsafeFPMath = mathOpts.getNoHonorNaNs() && mathOpts.getNoHonorInfs() &&
+ mathOpts.getNoSignedZeros() && mathOpts.getReciprocalMath() &&
+ mathOpts.getFPContractEnabled() && mathOpts.getApproxFunc() &&
+ mathOpts.getAssociativeMath();
}
llvm::OptimizationLevel OptLevel; ///< optimisation level
@@ -49,6 +58,7 @@ struct MLIRToLLVMPassPipelineConfig {
llvm::FramePointerKind::None; ///< Add frame pointer to functions.
unsigned VScaleMin = 0; ///< SVE vector range minimum.
unsigned VScaleMax = 0; ///< SVE vector range maximum.
+ bool UnsafeFPMath = false; ///< Set unsafe-fp-math attribute for functions.
};
struct OffloadModuleOpts {
diff --git a/flang/lib/Frontend/FrontendActions.cpp b/flang/lib/Frontend/FrontendActions.cpp
index 65c4df7388f97b2..17d5670b4134d86 100644
--- a/flang/lib/Frontend/FrontendActions.cpp
+++ b/flang/lib/Frontend/FrontendActions.cpp
@@ -787,6 +787,7 @@ void CodeGenAction::generateLLVMIR() {
CompilerInstance &ci = this->getInstance();
auto opts = ci.getInvocation().getCodeGenOpts();
+ auto mathOpts = ci.getInvocation().getLoweringOpts().getMathOptions();
llvm::OptimizationLevel level = mapToLevel(opts);
fir::support::loadDialects(*mlirCtx);
@@ -799,7 +800,7 @@ void CodeGenAction::generateLLVMIR() {
pm.addPass(std::make_unique<Fortran::lower::VerifierPass>());
pm.enableVerifier(/*verifyPasses=*/true);
- MLIRToLLVMPassPipelineConfig config(level, opts);
+ MLIRToLLVMPassPipelineConfig config(level, opts, mathOpts);
if (auto vsr = getVScaleRange(ci)) {
config.VScaleMin = vsr->first;
diff --git a/flang/lib/Optimizer/Transforms/FunctionAttr.cpp b/flang/lib/Optimizer/Transforms/FunctionAttr.cpp
index 55b908ba5d86139..bf7a83d6e47dcd7 100644
--- a/flang/lib/Optimizer/Transforms/FunctionAttr.cpp
+++ b/flang/lib/Optimizer/Transforms/FunctionAttr.cpp
@@ -27,6 +27,7 @@ class FunctionAttrPass : public fir::impl::FunctionAttrBase<FunctionAttrPass> {
public:
FunctionAttrPass(const fir::FunctionAttrOptions &options) {
framePointerKind = options.framePointerKind;
+ unsafeFPMath = options.unsafeFPMath;
}
FunctionAttrPass() {}
void runOnOperation() override;
@@ -45,14 +46,19 @@ void FunctionAttrPass::runOnOperation() {
func->setAttr("frame_pointer", mlir::LLVM::FramePointerKindAttr::get(
context, framePointerKind));
+ if (unsafeFPMath)
+ func->setAttr("unsafe_fp_math", mlir::BoolAttr::get(context, true));
+
LLVM_DEBUG(llvm::dbgs() << "=== End " DEBUG_TYPE " ===\n");
}
std::unique_ptr<mlir::Pass>
-fir::createFunctionAttrPass(fir::FunctionAttrTypes &functionAttr) {
+fir::createFunctionAttrPass(fir::FunctionAttrTypes &functionAttr,
+ bool unsafeFPMath) {
FunctionAttrOptions opts;
// Frame pointer
opts.framePointerKind = functionAttr.framePointerKind;
+ opts.unsafeFPMath = unsafeFPMath;
return std::make_unique<FunctionAttrPass>(opts);
}
>From 082b789a99993c1b6fd49341b26d5176e9ef8028 Mon Sep 17 00:00:00 2001
From: Alex Bradbury <asb at igalia.com>
Date: Wed, 24 Jan 2024 15:51:33 +0000
Subject: [PATCH 3/3] Add missed test
---
mlir/test/Target/LLVMIR/unsafe-fp-math.mlir | 8 ++++++++
1 file changed, 8 insertions(+)
create mode 100644 mlir/test/Target/LLVMIR/unsafe-fp-math.mlir
diff --git a/mlir/test/Target/LLVMIR/unsafe-fp-math.mlir b/mlir/test/Target/LLVMIR/unsafe-fp-math.mlir
new file mode 100644
index 000000000000000..70c42354cf90b63
--- /dev/null
+++ b/mlir/test/Target/LLVMIR/unsafe-fp-math.mlir
@@ -0,0 +1,8 @@
+// RUN: mlir-translate -mlir-to-llvmir %s | FileCheck %s
+
+// CHECK-LABEL: define void @unsafe_fp_math_func()
+// CHECK-SAME: #[[ATTRS:[0-9]+]]
+llvm.func @unsafe_fp_math_func() attributes {unsafe_fp_math = true} {
+ llvm.return
+}
+// CHECK: attributes #[[ATTRS]] = { "unsafe-fp-math"="true" }
More information about the flang-commits
mailing list