1 //===-- TBAABuilder.cpp -- TBAA builder definitions -----------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/
11 //===----------------------------------------------------------------------===//
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>
22 #define DEBUG_TYPE "flang-tbaa-builder"
25 using namespace mlir::LLVM
;
27 static llvm::cl::opt
<bool> disableTBAA(
29 llvm::cl::desc("disable attaching TBAA tags to memory accessing operations "
30 "to override default Flang behavior"),
31 llvm::cl::init(false));
33 // disabling this will play badly with the FIR TBAA pass, leading to worse
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
);
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
));
51 TBAABuilder::TBAABuilder(MLIRContext
*context
, bool applyTBAA
,
52 bool forceUnifiedTree
)
53 : enableTBAA(applyTBAA
&& !disableTBAA
),
54 trees(/*separatePerFunction=*/perFunctionTBAATrees
&& !forceUnifiedTree
) {
55 // TODO: the TBAA tags created here are rooted in the root scope
56 // of the enclosing function. This does not work best with MLIR inlining.
57 // A better approach is to root them according to the scopes they belong to
58 // and that were used by AddAliasTagsPass to create TBAA tags before
59 // the CodeGen. For example:
60 // subroutine caller(a, b, ptr)
61 // real, target :: a(:), b(:)
62 // integer, pointer :: ptr(:)
63 // call callee(a, b, ptr)
65 // subroutine callee(a, b, ptr)
67 // integer, pointer :: ptr(:)
69 // a(ptr(i)) = b(ptr(i))
73 // When callee is inlined, the dummy arguments 'a' and 'b' will
74 // be rooted in TBAA tree corresponding to the `call callee` call site,
75 // saying that the references to 'a' and 'b' cannot alias each other.
76 // These tags will be created by AddAliasTagsPass, but it will not be able
77 // to create any tags for 'ptr' references.
78 // During the CodeGen, we create 'any data access' tags for the
79 // 'ptr' acceses. If they are rooted within the root scope of `caller`,
80 // they end up in a different TBAA tree with the 'a' and 'b' access
81 // tags, so 'ptr', 'a' and 'b' references MayAlias. Moreover,
82 // the box access of 'ptr' will also be in a different TBAA tree
83 // with 'a' and 'b' tags, meaning they can also alias.
84 // This will prevent LLVM vectorization even with memory conflict checks.
85 // It seems that we'd better move all TBAA tags assignment to
86 // AddAliasTagsPass, which can at least rely on the dummy arguments scopes.
91 TBAATagAttr
TBAABuilder::getAccessTag(TBAATypeDescriptorAttr baseTypeDesc
,
92 TBAATypeDescriptorAttr accessTypeDesc
,
94 TBAATagAttr
&tag
= tagsMap
[{baseTypeDesc
, accessTypeDesc
, offset
}];
98 // Initialize new tag.
99 tag
= TBAATagAttr::get(baseTypeDesc
, accessTypeDesc
, offset
);
103 TBAATagAttr
TBAABuilder::getAnyBoxAccessTag(mlir::LLVM::LLVMFuncOp func
) {
104 TBAATypeDescriptorAttr boxMemberTypeDesc
= trees
[func
].boxMemberTypeDesc
;
105 return getAccessTag(boxMemberTypeDesc
, boxMemberTypeDesc
, /*offset=*/0);
108 TBAATagAttr
TBAABuilder::getBoxAccessTag(Type baseFIRType
, Type accessFIRType
,
110 mlir::LLVM::LLVMFuncOp func
) {
111 return getAnyBoxAccessTag(func
);
114 TBAATagAttr
TBAABuilder::getAnyDataAccessTag(mlir::LLVM::LLVMFuncOp func
) {
115 TBAATypeDescriptorAttr anyDataAccessTypeDesc
= trees
[func
].anyDataTypeDesc
;
116 return getAccessTag(anyDataAccessTypeDesc
, anyDataAccessTypeDesc
,
120 TBAATagAttr
TBAABuilder::getDataAccessTag(Type baseFIRType
, Type accessFIRType
,
122 mlir::LLVM::LLVMFuncOp func
) {
123 return getAnyDataAccessTag(func
);
126 TBAATagAttr
TBAABuilder::getAnyAccessTag(mlir::LLVM::LLVMFuncOp func
) {
127 TBAATypeDescriptorAttr anyAccessTypeDesc
= trees
[func
].anyAccessDesc
;
128 return getAccessTag(anyAccessTypeDesc
, anyAccessTypeDesc
, /*offset=*/0);
131 void TBAABuilder::attachTBAATag(AliasAnalysisOpInterface op
, Type baseFIRType
,
132 Type accessFIRType
, GEPOp gep
) {
136 mlir::LLVM::LLVMFuncOp func
= op
->getParentOfType
<mlir::LLVM::LLVMFuncOp
>();
140 ++tagAttachmentCounter
;
141 if (tagAttachmentLimit
!= kTagAttachmentUnlimited
&&
142 tagAttachmentCounter
> tagAttachmentLimit
)
145 LLVM_DEBUG(llvm::dbgs() << "Attaching TBAA tag #" << tagAttachmentCounter
148 TBAATagAttr tbaaTagSym
;
149 if (fir::isRecordWithDescriptorMember(baseFIRType
)) {
150 // A memory access that addresses an aggregate that contains
151 // a mix of data members and descriptor members may alias
152 // with both data and descriptor accesses.
153 // Conservatively set any-access tag if there is any descriptor member.
154 tbaaTagSym
= getAnyAccessTag(func
);
155 } else if (mlir::isa
<fir::BaseBoxType
>(baseFIRType
)) {
156 tbaaTagSym
= getBoxAccessTag(baseFIRType
, accessFIRType
, gep
, func
);
158 tbaaTagSym
= getDataAccessTag(baseFIRType
, accessFIRType
, gep
, func
);
164 op
.setTBAATags(ArrayAttr::get(op
->getContext(), tbaaTagSym
));