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/Dialect/FIROpsSupport.h"
14#include "flang/Optimizer/Support/InternalNames.h"
15#include "flang/Optimizer/Transforms/Passes.h"
16#include "mlir/Dialect/LLVMIR/LLVMAttrs.h"
17#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
18
19namespace fir {
20#define GEN_PASS_DEF_FUNCTIONATTR
21#include "flang/Optimizer/Transforms/Passes.h.inc"
22} // namespace fir
23
24#define DEBUG_TYPE "func-attr"
25
26namespace {
27
28class FunctionAttrPass : public fir::impl::FunctionAttrBase<FunctionAttrPass> {
29public:
30 FunctionAttrPass(const fir::FunctionAttrOptions &options) : Base{options} {}
31 FunctionAttrPass() = default;
32 void runOnOperation() override;
33};
34
35} // namespace
36
37void FunctionAttrPass::runOnOperation() {
38 LLVM_DEBUG(llvm::dbgs() << "=== Begin " DEBUG_TYPE " ===\n");
39 mlir::func::FuncOp func = getOperation();
40
41 LLVM_DEBUG(llvm::dbgs() << "Func-name:" << func.getSymName() << "\n");
42
43 llvm::StringRef name = func.getSymName();
44 auto deconstructed = fir::NameUniquer::deconstruct(name);
45 bool isFromModule = !deconstructed.second.modules.empty();
46
47 if ((isFromModule || !func.isDeclaration()) &&
48 !fir::hasBindcAttr(func.getOperation())) {
49 llvm::StringRef nocapture = mlir::LLVM::LLVMDialect::getNoCaptureAttrName();
50 llvm::StringRef noalias = mlir::LLVM::LLVMDialect::getNoAliasAttrName();
51 mlir::UnitAttr unitAttr = mlir::UnitAttr::get(func.getContext());
52
53 for (auto [index, argType] : llvm::enumerate(func.getArgumentTypes())) {
54 bool isNoCapture = false;
55 bool isNoAlias = false;
56 if (mlir::isa<fir::ReferenceType>(argType) &&
57 !func.getArgAttr(index, fir::getTargetAttrName()) &&
58 !func.getArgAttr(index, fir::getAsynchronousAttrName()) &&
59 !func.getArgAttr(index, fir::getVolatileAttrName())) {
60 isNoCapture = true;
61 isNoAlias = !fir::isPointerType(argType);
62 } else if (mlir::isa<fir::BaseBoxType>(argType)) {
63 // !fir.box arguments will be passed as descriptor pointers
64 // at LLVM IR dialect level - they cannot be captured,
65 // and cannot alias with anything within the function.
66 isNoCapture = isNoAlias = true;
67 }
68 if (isNoCapture && setNoCapture)
69 func.setArgAttr(index, nocapture, unitAttr);
70 if (isNoAlias && setNoAlias)
71 func.setArgAttr(index, noalias, unitAttr);
72 }
73 }
74
75 mlir::MLIRContext *context = &getContext();
76 if (framePointerKind != mlir::LLVM::framePointerKind::FramePointerKind::None)
77 func->setAttr("frame_pointer", mlir::LLVM::FramePointerKindAttr::get(
78 context, framePointerKind));
79
80 auto llvmFuncOpName =
81 mlir::OperationName(mlir::LLVM::LLVMFuncOp::getOperationName(), context);
82 if (!instrumentFunctionEntry.empty())
83 func->setAttr(mlir::LLVM::LLVMFuncOp::getInstrumentFunctionEntryAttrName(
84 llvmFuncOpName),
85 mlir::StringAttr::get(context, instrumentFunctionEntry));
86 if (!instrumentFunctionExit.empty())
87 func->setAttr(mlir::LLVM::LLVMFuncOp::getInstrumentFunctionExitAttrName(
88 llvmFuncOpName),
89 mlir::StringAttr::get(context, instrumentFunctionExit));
90 if (noInfsFPMath)
91 func->setAttr(
92 mlir::LLVM::LLVMFuncOp::getNoInfsFpMathAttrName(llvmFuncOpName),
93 mlir::BoolAttr::get(context, true));
94 if (noNaNsFPMath)
95 func->setAttr(
96 mlir::LLVM::LLVMFuncOp::getNoNansFpMathAttrName(llvmFuncOpName),
97 mlir::BoolAttr::get(context, true));
98 if (approxFuncFPMath)
99 func->setAttr(
100 mlir::LLVM::LLVMFuncOp::getApproxFuncFpMathAttrName(llvmFuncOpName),
101 mlir::BoolAttr::get(context, true));
102 if (noSignedZerosFPMath)
103 func->setAttr(
104 mlir::LLVM::LLVMFuncOp::getNoSignedZerosFpMathAttrName(llvmFuncOpName),
105 mlir::BoolAttr::get(context, true));
106 if (unsafeFPMath)
107 func->setAttr(
108 mlir::LLVM::LLVMFuncOp::getUnsafeFpMathAttrName(llvmFuncOpName),
109 mlir::BoolAttr::get(context, true));
110 if (!reciprocals.empty())
111 func->setAttr(
112 mlir::LLVM::LLVMFuncOp::getReciprocalEstimatesAttrName(llvmFuncOpName),
113 mlir::StringAttr::get(context, reciprocals));
114 if (!preferVectorWidth.empty())
115 func->setAttr(
116 mlir::LLVM::LLVMFuncOp::getPreferVectorWidthAttrName(llvmFuncOpName),
117 mlir::StringAttr::get(context, preferVectorWidth));
118
119 LLVM_DEBUG(llvm::dbgs() << "=== End " DEBUG_TYPE " ===\n");
120}
121

source code of flang/lib/Optimizer/Transforms/FunctionAttr.cpp