diff options
Diffstat (limited to 'flang')
-rw-r--r-- | flang/include/flang/Optimizer/Transforms/Passes.h | 4 | ||||
-rw-r--r-- | flang/include/flang/Optimizer/Transforms/Passes.td | 15 | ||||
-rw-r--r-- | flang/include/flang/Tools/CLOptions.inc | 13 | ||||
-rw-r--r-- | flang/include/flang/Tools/CrossToolHelpers.h | 20 | ||||
-rw-r--r-- | flang/lib/Frontend/FrontendActions.cpp | 3 | ||||
-rw-r--r-- | flang/lib/Optimizer/Transforms/FunctionAttr.cpp | 39 | ||||
-rw-r--r-- | flang/test/Driver/func-attr-fast-math.f90 | 18 |
7 files changed, 104 insertions, 8 deletions
diff --git a/flang/include/flang/Optimizer/Transforms/Passes.h b/flang/include/flang/Optimizer/Transforms/Passes.h index aefb277..e1d22c8 100644 --- a/flang/include/flang/Optimizer/Transforms/Passes.h +++ b/flang/include/flang/Optimizer/Transforms/Passes.h @@ -92,7 +92,9 @@ struct FunctionAttrTypes { std::unique_ptr<mlir::Pass> createFunctionAttrPass(); std::unique_ptr<mlir::Pass> -createFunctionAttrPass(FunctionAttrTypes &functionAttr); +createFunctionAttrPass(FunctionAttrTypes &functionAttr, bool noInfsFPMath, + bool noNaNsFPMath, bool approxFuncFPMath, + bool noSignedZerosFPMath, 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 270b837..5fb576f 100644 --- a/flang/include/flang/Optimizer/Transforms/Passes.td +++ b/flang/include/flang/Optimizer/Transforms/Passes.td @@ -378,6 +378,21 @@ def FunctionAttr : Pass<"function-attr", "mlir::func::FuncOp"> { "mlir::LLVM::framePointerKind::FramePointerKind", /*default=*/"mlir::LLVM::framePointerKind::FramePointerKind{}", "frame pointer">, + Option<"noInfsFPMath", "no-infs-fp-math", + "bool", /*default=*/"false", + "Set the no-infs-fp-math attribute on functions in the module.">, + Option<"noNaNsFPMath", "no-nans-fp-math", + "bool", /*default=*/"false", + "Set the no-nans-fp-math attribute on functions in the module.">, + Option<"approxFuncFPMath", "approx-func-fp-math", + "bool", /*default=*/"false", + "Set the approx-func-fp-math attribute on functions in the module.">, + Option<"noSignedZerosFPMath", "no-signed-zeros-fp-math", + "bool", /*default=*/"false", + "Set the no-signed-zeros-fp-math attribute on functions in the module.">, + 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 8dee307..68e504d 100644 --- a/flang/include/flang/Tools/CLOptions.inc +++ b/flang/include/flang/Tools/CLOptions.inc @@ -316,15 +316,22 @@ inline void createDefaultFIRCodeGenPassPipeline( // Add function attributes fir::FunctionAttrTypes functionAttrs; - if (config.FramePointerKind != llvm::FramePointerKind::None) { + if (config.FramePointerKind != llvm::FramePointerKind::None || + config.NoInfsFPMath || config.NoNaNsFPMath || config.ApproxFuncFPMath || + config.NoSignedZerosFPMath || config.UnsafeFPMath) { if (config.FramePointerKind == llvm::FramePointerKind::NonLeaf) functionAttrs.framePointerKind = mlir::LLVM::framePointerKind::FramePointerKind::NonLeaf; - else + else if (config.FramePointerKind == llvm::FramePointerKind::All) functionAttrs.framePointerKind = mlir::LLVM::framePointerKind::FramePointerKind::All; + else + functionAttrs.framePointerKind = + mlir::LLVM::framePointerKind::FramePointerKind::None; - pm.addPass(fir::createFunctionAttrPass(functionAttrs)); + pm.addPass(fir::createFunctionAttrPass(functionAttrs, config.NoInfsFPMath, + config.NoNaNsFPMath, config.ApproxFuncFPMath, + config.NoSignedZerosFPMath, config.UnsafeFPMath)); } fir::addFIRToLLVMPass(pm, config); diff --git a/flang/include/flang/Tools/CrossToolHelpers.h b/flang/include/flang/Tools/CrossToolHelpers.h index 5c59c99..b7d84af 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,15 @@ struct MLIRToLLVMPassPipelineConfig { DebugInfo = opts.getDebugInfo(); AliasAnalysis = opts.AliasAnalysis; FramePointerKind = opts.getFramePointer(); + // The logic for setting these attributes is intended to match the logic + // used in Clang. + NoInfsFPMath = mathOpts.getNoHonorInfs(); + NoNaNsFPMath = mathOpts.getNoHonorNaNs(); + ApproxFuncFPMath = mathOpts.getApproxFunc(); + NoSignedZerosFPMath = mathOpts.getNoSignedZeros(); + UnsafeFPMath = mathOpts.getAssociativeMath() && + mathOpts.getReciprocalMath() && NoSignedZerosFPMath && + ApproxFuncFPMath && mathOpts.getFPContractEnabled(); } llvm::OptimizationLevel OptLevel; ///< optimisation level @@ -49,6 +60,13 @@ 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 NoInfsFPMath = false; ///< Set no-infs-fp-math attribute for functions. + bool NoNaNsFPMath = false; ///< Set no-nans-fp-math attribute for functions. + bool ApproxFuncFPMath = + false; ///< Set approx-func-fp-math attribute for functions. + bool NoSignedZerosFPMath = + false; ///< Set no-signed-zeros-fp-math attribute for functions. + 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 09e861d..18bc168 100644 --- a/flang/lib/Frontend/FrontendActions.cpp +++ b/flang/lib/Frontend/FrontendActions.cpp @@ -782,6 +782,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); @@ -794,7 +795,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 55b908b..f54080f 100644 --- a/flang/lib/Optimizer/Transforms/FunctionAttr.cpp +++ b/flang/lib/Optimizer/Transforms/FunctionAttr.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "flang/Optimizer/Transforms/Passes.h" #include "mlir/Dialect/LLVMIR/LLVMAttrs.h" +#include "mlir/Dialect/LLVMIR/LLVMDialect.h" namespace fir { #define GEN_PASS_DECL_FUNCTIONATTR @@ -27,6 +28,11 @@ class FunctionAttrPass : public fir::impl::FunctionAttrBase<FunctionAttrPass> { public: FunctionAttrPass(const fir::FunctionAttrOptions &options) { framePointerKind = options.framePointerKind; + noInfsFPMath = options.noInfsFPMath; + noNaNsFPMath = options.noNaNsFPMath; + approxFuncFPMath = options.approxFuncFPMath; + noSignedZerosFPMath = options.noSignedZerosFPMath; + unsafeFPMath = options.unsafeFPMath; } FunctionAttrPass() {} void runOnOperation() override; @@ -45,14 +51,43 @@ void FunctionAttrPass::runOnOperation() { func->setAttr("frame_pointer", mlir::LLVM::FramePointerKindAttr::get( context, framePointerKind)); + auto llvmFuncOpName = + mlir::OperationName(mlir::LLVM::LLVMFuncOp::getOperationName(), context); + if (noInfsFPMath) + func->setAttr( + mlir::LLVM::LLVMFuncOp::getNoInfsFpMathAttrName(llvmFuncOpName), + mlir::BoolAttr::get(context, true)); + if (noNaNsFPMath) + func->setAttr( + mlir::LLVM::LLVMFuncOp::getNoNansFpMathAttrName(llvmFuncOpName), + mlir::BoolAttr::get(context, true)); + if (approxFuncFPMath) + func->setAttr( + mlir::LLVM::LLVMFuncOp::getApproxFuncFpMathAttrName(llvmFuncOpName), + mlir::BoolAttr::get(context, true)); + if (noSignedZerosFPMath) + func->setAttr( + mlir::LLVM::LLVMFuncOp::getNoSignedZerosFpMathAttrName(llvmFuncOpName), + mlir::BoolAttr::get(context, true)); + if (unsafeFPMath) + func->setAttr( + mlir::LLVM::LLVMFuncOp::getUnsafeFpMathAttrName(llvmFuncOpName), + mlir::BoolAttr::get(context, true)); + LLVM_DEBUG(llvm::dbgs() << "=== End " DEBUG_TYPE " ===\n"); } -std::unique_ptr<mlir::Pass> -fir::createFunctionAttrPass(fir::FunctionAttrTypes &functionAttr) { +std::unique_ptr<mlir::Pass> fir::createFunctionAttrPass( + fir::FunctionAttrTypes &functionAttr, bool noInfsFPMath, bool noNaNsFPMath, + bool approxFuncFPMath, bool noSignedZerosFPMath, bool unsafeFPMath) { FunctionAttrOptions opts; // Frame pointer opts.framePointerKind = functionAttr.framePointerKind; + opts.noInfsFPMath = noInfsFPMath; + opts.noNaNsFPMath = noNaNsFPMath; + opts.approxFuncFPMath = approxFuncFPMath; + opts.noSignedZerosFPMath = noSignedZerosFPMath; + opts.unsafeFPMath = unsafeFPMath; return std::make_unique<FunctionAttrPass>(opts); } diff --git a/flang/test/Driver/func-attr-fast-math.f90 b/flang/test/Driver/func-attr-fast-math.f90 new file mode 100644 index 0000000..05824a6 --- /dev/null +++ b/flang/test/Driver/func-attr-fast-math.f90 @@ -0,0 +1,18 @@ +! RUN: %flang -O1 -emit-llvm -S -o - %s 2>&1| FileCheck %s --check-prefix=CHECK-NOFASTMATH +! RUN: %flang -Ofast -emit-llvm -S -o - %s 2>&1| FileCheck %s --check-prefix=CHECK-OFAST +! RUN: %flang -O1 -ffast-math -emit-llvm -S -o - %s 2>&1| FileCheck %s --check-prefix=CHECK-FFAST-MATH + +subroutine func +end subroutine func + +! CHECK-NOFASTMATH-LABEL: define void @func_() local_unnamed_addr +! CHECK-NOFASTMATH-SAME: #[[ATTRS:[0-9]+]] +! CHECK-NOT fp-math"= + +! CHECK-OFAST-LABEL: define void @func_() local_unnamed_addr +! CHECK-OFAST-SAME: #[[ATTRS:[0-9]+]] +! CHECK-OFAST: attributes #[[ATTRS]] = { {{.*}}"approx-func-fp-math"="true" {{.*}}"no-infs-fp-math"="true" {{.*}}"no-nans-fp-math"="true" {{.*}}"no-signed-zeros-fp-math"="true" {{.*}}"unsafe-fp-math"="true"{{.*}} } + +! CHECK-FFAST-MATH-LABEL: define void @func_() local_unnamed_addr +! CHECK-FFAST-MATH-SAME: #[[ATTRS:[0-9]+]] +! CHECK-FFAST-MATH: attributes #[[ATTRS]] = { {{.*}}"approx-func-fp-math"="true" {{.*}}"no-infs-fp-math"="true" {{.*}}"no-nans-fp-math"="true" {{.*}}"no-signed-zeros-fp-math"="true" {{.*}}"unsafe-fp-math"="true"{{.*}} } |