xref: /llvm-project/flang/include/flang/Optimizer/Analysis/TBAAForest.h (revision 6cd86d0fae8cbb752a713860f131b9b759b2cbb8)
1 //===-- TBAAForest.h - A TBAA tree for each function -----------*- C++ -*-===//
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 #ifndef FORTRAN_OPTIMIZER_ANALYSIS_TBAA_FOREST_H
10 #define FORTRAN_OPTIMIZER_ANALYSIS_TBAA_FOREST_H
11 
12 #include "flang/Optimizer/Dialect/FIROpsSupport.h"
13 #include "mlir/Dialect/Func/IR/FuncOps.h"
14 #include "mlir/Dialect/LLVMIR/LLVMAttrs.h"
15 #include "mlir/Dialect/LLVMIR/LLVMDialect.h"
16 #include "mlir/IR/Attributes.h"
17 #include "mlir/IR/MLIRContext.h"
18 #include "llvm/ADT/DenseMap.h"
19 #include <string>
20 
21 namespace fir {
22 
23 //===----------------------------------------------------------------------===//
24 // TBAATree
25 //===----------------------------------------------------------------------===//
26 /// Per-function TBAA tree. Each tree contains branches for data (of various
27 /// kinds) and descriptor access
28 struct TBAATree {
29   //===----------------------------------------------------------------------===//
30   // TBAAForrest::TBAATree::SubtreeState
31   //===----------------------------------------------------------------------===//
32   /// This contains a TBAA subtree based on some parent. New tags can be added
33   /// under the parent using getTag.
34   class SubtreeState {
35     friend TBAATree; // only allow construction by TBAATree
36   public:
37     SubtreeState() = delete;
38     SubtreeState(const SubtreeState &) = delete;
39     SubtreeState(SubtreeState &&) = default;
40 
41     mlir::LLVM::TBAATagAttr getTag(llvm::StringRef uniqueId) const;
42 
43   private:
SubtreeStateTBAATree44     SubtreeState(mlir::MLIRContext *ctx, std::string name,
45                  mlir::LLVM::TBAANodeAttr grandParent)
46         : parentId{std::move(name)}, context(ctx) {
47       parent = mlir::LLVM::TBAATypeDescriptorAttr::get(
48           context, parentId, mlir::LLVM::TBAAMemberAttr::get(grandParent, 0));
49     }
50 
51     const std::string parentId;
52     mlir::MLIRContext *const context;
53     mlir::LLVM::TBAATypeDescriptorAttr parent;
54     llvm::DenseMap<llvm::StringRef, mlir::LLVM::TBAATagAttr> tagDedup;
55   };
56 
57   SubtreeState globalDataTree;
58   SubtreeState allocatedDataTree;
59   SubtreeState dummyArgDataTree;
60   SubtreeState directDataTree;
61   mlir::LLVM::TBAATypeDescriptorAttr anyAccessDesc;
62   mlir::LLVM::TBAATypeDescriptorAttr boxMemberTypeDesc;
63   mlir::LLVM::TBAATypeDescriptorAttr anyDataTypeDesc;
64 
65   static TBAATree buildTree(mlir::StringAttr functionName);
66 
67 private:
68   TBAATree(mlir::LLVM::TBAATypeDescriptorAttr anyAccess,
69            mlir::LLVM::TBAATypeDescriptorAttr dataRoot,
70            mlir::LLVM::TBAATypeDescriptorAttr boxMemberTypeDesc);
71 };
72 
73 //===----------------------------------------------------------------------===//
74 // TBAAForrest
75 //===----------------------------------------------------------------------===//
76 /// Collection of TBAATrees, usually indexed by function (so that each function
77 /// has a different TBAATree)
78 class TBAAForrest {
79 public:
80   explicit TBAAForrest(bool separatePerFunction = true)
81       : separatePerFunction{separatePerFunction} {}
82 
83   inline const TBAATree &operator[](mlir::func::FuncOp func) {
84     return getFuncTree(func.getSymNameAttr());
85   }
86   inline const TBAATree &operator[](mlir::LLVM::LLVMFuncOp func) {
87     // the external name conversion pass may rename some functions. Their old
88     // name must be used so that we add to the tbaa tree added in the FIR pass
89     mlir::Attribute attr = func->getAttr(getInternalFuncNameAttrName());
90     if (attr) {
91       return getFuncTree(mlir::cast<mlir::StringAttr>(attr));
92     }
93     return getFuncTree(func.getSymNameAttr());
94   }
95   // Returns the TBAA tree associated with the scope enclosed
96   // within the given function. With MLIR inlining, there may
97   // be multiple scopes within a single function. It is the caller's
98   // responsibility to provide unique name for the scope.
99   // If the scope string is empty, returns the TBAA tree for the
100   // "root" scope of the given function.
getFuncTreeWithScope(mlir::func::FuncOp func,llvm::StringRef scope)101   inline const TBAATree &getFuncTreeWithScope(mlir::func::FuncOp func,
102                                               llvm::StringRef scope) {
103     mlir::StringAttr name = func.getSymNameAttr();
104     if (!scope.empty())
105       name = mlir::StringAttr::get(name.getContext(),
106                                    llvm::Twine(name) + " - " + scope);
107     return getFuncTree(name);
108   }
109 
110 private:
getFuncTree(mlir::StringAttr symName)111   const TBAATree &getFuncTree(mlir::StringAttr symName) {
112     if (!separatePerFunction)
113       symName = mlir::StringAttr::get(symName.getContext(), "");
114     if (!trees.contains(symName))
115       trees.insert({symName, TBAATree::buildTree(symName)});
116     return trees.at(symName);
117   }
118 
119   // Should each function use a different tree?
120   const bool separatePerFunction;
121   // TBAA tree per function
122   llvm::DenseMap<mlir::StringAttr, TBAATree> trees;
123 };
124 
125 } // namespace fir
126 
127 #endif // FORTRAN_OPTIMIZER_ANALYSIS_TBAA_FOREST_H
128