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