1 | //===-- TBAABuilder.cpp -- TBAA builder definitions -----------------------===// |
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 | // Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/ |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #include "flang/Optimizer/CodeGen/TBAABuilder.h" |
14 | #include "flang/Optimizer/Dialect/FIRType.h" |
15 | #include "llvm/ADT/TypeSwitch.h" |
16 | #include "llvm/Support/CommandLine.h" |
17 | #include "llvm/Support/Debug.h" |
18 | #include <mlir/Dialect/LLVMIR/LLVMAttrs.h> |
19 | #include <mlir/Dialect/LLVMIR/LLVMDialect.h> |
20 | #include <mlir/Dialect/LLVMIR/LLVMTypes.h> |
21 | |
22 | #define DEBUG_TYPE "flang-tbaa-builder" |
23 | |
24 | using namespace mlir; |
25 | using namespace mlir::LLVM; |
26 | |
27 | static llvm::cl::opt<bool> disableTBAA( |
28 | "disable-tbaa" , |
29 | llvm::cl::desc("disable attaching TBAA tags to memory accessing operations " |
30 | "to override default Flang behavior" ), |
31 | llvm::cl::init(Val: false)); |
32 | |
33 | // disabling this will play badly with the FIR TBAA pass, leading to worse |
34 | // performance |
35 | static llvm::cl::opt<bool> perFunctionTBAATrees( |
36 | "per-function-tbaa-trees" , |
37 | llvm::cl::desc("Give each function an independent TBAA tree (default)" ), |
38 | llvm::cl::init(Val: true), llvm::cl::Hidden); |
39 | |
40 | // tagAttachmentLimit is a debugging option that allows limiting |
41 | // the number of TBAA access tag attributes attached to operations. |
42 | // It is set to kTagAttachmentUnlimited by default denoting "no limit". |
43 | static constexpr unsigned kTagAttachmentUnlimited = |
44 | std::numeric_limits<unsigned>::max(); |
45 | static llvm::cl::opt<unsigned> |
46 | tagAttachmentLimit("tbaa-attach-tag-max" , llvm::cl::desc("" ), |
47 | llvm::cl::init(Val: kTagAttachmentUnlimited)); |
48 | |
49 | namespace fir { |
50 | |
51 | TBAABuilder::TBAABuilder(MLIRContext *context, bool applyTBAA, |
52 | bool forceUnifiedTree) |
53 | : enableTBAA(applyTBAA && !disableTBAA), |
54 | trees(/*separatePerFunction=*/perFunctionTBAATrees && !forceUnifiedTree) { |
55 | if (!enableTBAA) |
56 | return; |
57 | } |
58 | |
59 | TBAATagAttr TBAABuilder::getAccessTag(TBAATypeDescriptorAttr baseTypeDesc, |
60 | TBAATypeDescriptorAttr accessTypeDesc, |
61 | int64_t offset) { |
62 | TBAATagAttr &tag = tagsMap[{baseTypeDesc, accessTypeDesc, offset}]; |
63 | if (tag) |
64 | return tag; |
65 | |
66 | // Initialize new tag. |
67 | tag = TBAATagAttr::get(baseTypeDesc, accessTypeDesc, offset); |
68 | return tag; |
69 | } |
70 | |
71 | TBAATagAttr TBAABuilder::getAnyBoxAccessTag(mlir::LLVM::LLVMFuncOp func) { |
72 | TBAATypeDescriptorAttr boxMemberTypeDesc = trees[func].boxMemberTypeDesc; |
73 | return getAccessTag(boxMemberTypeDesc, boxMemberTypeDesc, /*offset=*/0); |
74 | } |
75 | |
76 | TBAATagAttr TBAABuilder::getBoxAccessTag(Type baseFIRType, Type accessFIRType, |
77 | GEPOp gep, |
78 | mlir::LLVM::LLVMFuncOp func) { |
79 | return getAnyBoxAccessTag(func); |
80 | } |
81 | |
82 | TBAATagAttr TBAABuilder::getAnyDataAccessTag(mlir::LLVM::LLVMFuncOp func) { |
83 | TBAATypeDescriptorAttr anyDataAccessTypeDesc = trees[func].anyDataTypeDesc; |
84 | return getAccessTag(anyDataAccessTypeDesc, anyDataAccessTypeDesc, |
85 | /*offset=*/0); |
86 | } |
87 | |
88 | TBAATagAttr TBAABuilder::getDataAccessTag(Type baseFIRType, Type accessFIRType, |
89 | GEPOp gep, |
90 | mlir::LLVM::LLVMFuncOp func) { |
91 | return getAnyDataAccessTag(func); |
92 | } |
93 | |
94 | TBAATagAttr TBAABuilder::getAnyAccessTag(mlir::LLVM::LLVMFuncOp func) { |
95 | TBAATypeDescriptorAttr anyAccessTypeDesc = trees[func].anyAccessDesc; |
96 | return getAccessTag(anyAccessTypeDesc, anyAccessTypeDesc, /*offset=*/0); |
97 | } |
98 | |
99 | void TBAABuilder::attachTBAATag(AliasAnalysisOpInterface op, Type baseFIRType, |
100 | Type accessFIRType, GEPOp gep) { |
101 | if (!enableTBAA) |
102 | return; |
103 | |
104 | mlir::LLVM::LLVMFuncOp func = op->getParentOfType<mlir::LLVM::LLVMFuncOp>(); |
105 | if (!func) |
106 | return; |
107 | |
108 | ++tagAttachmentCounter; |
109 | if (tagAttachmentLimit != kTagAttachmentUnlimited && |
110 | tagAttachmentCounter > tagAttachmentLimit) |
111 | return; |
112 | |
113 | LLVM_DEBUG(llvm::dbgs() << "Attaching TBAA tag #" << tagAttachmentCounter |
114 | << "\n" ); |
115 | |
116 | TBAATagAttr tbaaTagSym; |
117 | if (fir::isRecordWithDescriptorMember(baseFIRType)) { |
118 | // A memory access that addresses an aggregate that contains |
119 | // a mix of data members and descriptor members may alias |
120 | // with both data and descriptor accesses. |
121 | // Conservatively set any-access tag if there is any descriptor member. |
122 | tbaaTagSym = getAnyAccessTag(func); |
123 | } else if (baseFIRType.isa<fir::BaseBoxType>()) { |
124 | tbaaTagSym = getBoxAccessTag(baseFIRType, accessFIRType, gep, func); |
125 | } else { |
126 | tbaaTagSym = getDataAccessTag(baseFIRType, accessFIRType, gep, func); |
127 | } |
128 | |
129 | if (!tbaaTagSym) |
130 | return; |
131 | |
132 | op.setTBAATags(ArrayAttr::get(op->getContext(), tbaaTagSym)); |
133 | } |
134 | |
135 | } // namespace fir |
136 | |