1 | //===- FunctionAttr.cpp ---------------------------------------------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | //===----------------------------------------------------------------------===// |
10 | /// \file |
11 | /// This is a generic pass for adding attributes to functions. |
12 | //===----------------------------------------------------------------------===// |
13 | #include "flang/Optimizer/Transforms/Passes.h" |
14 | #include "mlir/Dialect/LLVMIR/LLVMAttrs.h" |
15 | #include "mlir/Dialect/LLVMIR/LLVMDialect.h" |
16 | |
17 | namespace fir { |
18 | #define GEN_PASS_DECL_FUNCTIONATTR |
19 | #define GEN_PASS_DEF_FUNCTIONATTR |
20 | #include "flang/Optimizer/Transforms/Passes.h.inc" |
21 | } // namespace fir |
22 | |
23 | #define DEBUG_TYPE "func-attr" |
24 | |
25 | namespace { |
26 | |
27 | class FunctionAttrPass : public fir::impl::FunctionAttrBase<FunctionAttrPass> { |
28 | public: |
29 | FunctionAttrPass(const fir::FunctionAttrOptions &options) { |
30 | framePointerKind = options.framePointerKind; |
31 | noInfsFPMath = options.noInfsFPMath; |
32 | noNaNsFPMath = options.noNaNsFPMath; |
33 | approxFuncFPMath = options.approxFuncFPMath; |
34 | noSignedZerosFPMath = options.noSignedZerosFPMath; |
35 | unsafeFPMath = options.unsafeFPMath; |
36 | } |
37 | FunctionAttrPass() {} |
38 | void runOnOperation() override; |
39 | }; |
40 | |
41 | } // namespace |
42 | |
43 | void FunctionAttrPass::runOnOperation() { |
44 | LLVM_DEBUG(llvm::dbgs() << "=== Begin " DEBUG_TYPE " ===\n" ); |
45 | mlir::func::FuncOp func = getOperation(); |
46 | |
47 | LLVM_DEBUG(llvm::dbgs() << "Func-name:" << func.getSymName() << "\n" ); |
48 | |
49 | mlir::MLIRContext *context = &getContext(); |
50 | if (framePointerKind != mlir::LLVM::framePointerKind::FramePointerKind::None) |
51 | func->setAttr("frame_pointer" , mlir::LLVM::FramePointerKindAttr::get( |
52 | context, framePointerKind)); |
53 | |
54 | auto llvmFuncOpName = |
55 | mlir::OperationName(mlir::LLVM::LLVMFuncOp::getOperationName(), context); |
56 | if (noInfsFPMath) |
57 | func->setAttr( |
58 | mlir::LLVM::LLVMFuncOp::getNoInfsFpMathAttrName(llvmFuncOpName), |
59 | mlir::BoolAttr::get(context, true)); |
60 | if (noNaNsFPMath) |
61 | func->setAttr( |
62 | mlir::LLVM::LLVMFuncOp::getNoNansFpMathAttrName(llvmFuncOpName), |
63 | mlir::BoolAttr::get(context, true)); |
64 | if (approxFuncFPMath) |
65 | func->setAttr( |
66 | mlir::LLVM::LLVMFuncOp::getApproxFuncFpMathAttrName(llvmFuncOpName), |
67 | mlir::BoolAttr::get(context, true)); |
68 | if (noSignedZerosFPMath) |
69 | func->setAttr( |
70 | mlir::LLVM::LLVMFuncOp::getNoSignedZerosFpMathAttrName(llvmFuncOpName), |
71 | mlir::BoolAttr::get(context, true)); |
72 | if (unsafeFPMath) |
73 | func->setAttr( |
74 | mlir::LLVM::LLVMFuncOp::getUnsafeFpMathAttrName(llvmFuncOpName), |
75 | mlir::BoolAttr::get(context, true)); |
76 | |
77 | LLVM_DEBUG(llvm::dbgs() << "=== End " DEBUG_TYPE " ===\n" ); |
78 | } |
79 | |
80 | std::unique_ptr<mlir::Pass> fir::createFunctionAttrPass( |
81 | fir::FunctionAttrTypes &functionAttr, bool noInfsFPMath, bool noNaNsFPMath, |
82 | bool approxFuncFPMath, bool noSignedZerosFPMath, bool unsafeFPMath) { |
83 | FunctionAttrOptions opts; |
84 | // Frame pointer |
85 | opts.framePointerKind = functionAttr.framePointerKind; |
86 | opts.noInfsFPMath = noInfsFPMath; |
87 | opts.noNaNsFPMath = noNaNsFPMath; |
88 | opts.approxFuncFPMath = approxFuncFPMath; |
89 | opts.noSignedZerosFPMath = noSignedZerosFPMath; |
90 | opts.unsafeFPMath = unsafeFPMath; |
91 | |
92 | return std::make_unique<FunctionAttrPass>(opts); |
93 | } |
94 | |
95 | std::unique_ptr<mlir::Pass> fir::createFunctionAttrPass() { |
96 | return std::make_unique<FunctionAttrPass>(); |
97 | } |
98 | |