xref: /llvm-project/flang/lib/Optimizer/CodeGen/TBAABuilder.cpp (revision 6042c2eb9edc5c5f743c209b37a72dca664864cb)
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(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(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(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   assert(func && "func.func should have already been converted to llvm.func");
106 
107   ++tagAttachmentCounter;
108   if (tagAttachmentLimit != kTagAttachmentUnlimited &&
109       tagAttachmentCounter > tagAttachmentLimit)
110     return;
111 
112   LLVM_DEBUG(llvm::dbgs() << "Attaching TBAA tag #" << tagAttachmentCounter
113                           << "\n");
114 
115   TBAATagAttr tbaaTagSym;
116   if (fir::isRecordWithDescriptorMember(baseFIRType)) {
117     // A memory access that addresses an aggregate that contains
118     // a mix of data members and descriptor members may alias
119     // with both data and descriptor accesses.
120     // Conservatively set any-access tag if there is any descriptor member.
121     tbaaTagSym = getAnyAccessTag(func);
122   } else if (baseFIRType.isa<fir::BaseBoxType>()) {
123     tbaaTagSym = getBoxAccessTag(baseFIRType, accessFIRType, gep, func);
124   } else {
125     tbaaTagSym = getDataAccessTag(baseFIRType, accessFIRType, gep, func);
126   }
127 
128   if (!tbaaTagSym)
129     return;
130 
131   op.setTBAATags(ArrayAttr::get(op->getContext(), tbaaTagSym));
132 }
133 
134 } // namespace fir
135