xref: /llvm-project/flang/lib/Optimizer/CodeGen/TBAABuilder.cpp (revision 6cd86d0fae8cbb752a713860f131b9b759b2cbb8)
19c84d20fSSlava Zakharin //===-- TBAABuilder.cpp -- TBAA builder definitions -----------------------===//
29c84d20fSSlava Zakharin //
39c84d20fSSlava Zakharin // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
49c84d20fSSlava Zakharin // See https://llvm.org/LICENSE.txt for license information.
59c84d20fSSlava Zakharin // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
69c84d20fSSlava Zakharin //
79c84d20fSSlava Zakharin //===----------------------------------------------------------------------===//
89c84d20fSSlava Zakharin //
99c84d20fSSlava Zakharin // Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/
109c84d20fSSlava Zakharin //
119c84d20fSSlava Zakharin //===----------------------------------------------------------------------===//
129c84d20fSSlava Zakharin 
1330408f5cSValentin Clement #include "flang/Optimizer/CodeGen/TBAABuilder.h"
149c84d20fSSlava Zakharin #include "flang/Optimizer/Dialect/FIRType.h"
15fef08da4STobias Gysi #include "llvm/ADT/TypeSwitch.h"
169c84d20fSSlava Zakharin #include "llvm/Support/CommandLine.h"
17b1476365SSlava Zakharin #include "llvm/Support/Debug.h"
186042c2ebSTom Eccles #include <mlir/Dialect/LLVMIR/LLVMAttrs.h>
196042c2ebSTom Eccles #include <mlir/Dialect/LLVMIR/LLVMDialect.h>
206042c2ebSTom Eccles #include <mlir/Dialect/LLVMIR/LLVMTypes.h>
21b1476365SSlava Zakharin 
22b1476365SSlava Zakharin #define DEBUG_TYPE "flang-tbaa-builder"
239c84d20fSSlava Zakharin 
249c84d20fSSlava Zakharin using namespace mlir;
259c84d20fSSlava Zakharin using namespace mlir::LLVM;
269c84d20fSSlava Zakharin 
279c84d20fSSlava Zakharin static llvm::cl::opt<bool> disableTBAA(
289c84d20fSSlava Zakharin     "disable-tbaa",
299c84d20fSSlava Zakharin     llvm::cl::desc("disable attaching TBAA tags to memory accessing operations "
309c84d20fSSlava Zakharin                    "to override default Flang behavior"),
319c84d20fSSlava Zakharin     llvm::cl::init(false));
329c84d20fSSlava Zakharin 
336042c2ebSTom Eccles // disabling this will play badly with the FIR TBAA pass, leading to worse
346042c2ebSTom Eccles // performance
356042c2ebSTom Eccles static llvm::cl::opt<bool> perFunctionTBAATrees(
366042c2ebSTom Eccles     "per-function-tbaa-trees",
376042c2ebSTom Eccles     llvm::cl::desc("Give each function an independent TBAA tree (default)"),
386042c2ebSTom Eccles     llvm::cl::init(true), llvm::cl::Hidden);
396042c2ebSTom Eccles 
40b1476365SSlava Zakharin // tagAttachmentLimit is a debugging option that allows limiting
41b1476365SSlava Zakharin // the number of TBAA access tag attributes attached to operations.
42b1476365SSlava Zakharin // It is set to kTagAttachmentUnlimited by default denoting "no limit".
43b1476365SSlava Zakharin static constexpr unsigned kTagAttachmentUnlimited =
44b1476365SSlava Zakharin     std::numeric_limits<unsigned>::max();
45b1476365SSlava Zakharin static llvm::cl::opt<unsigned>
46b1476365SSlava Zakharin     tagAttachmentLimit("tbaa-attach-tag-max", llvm::cl::desc(""),
47b1476365SSlava Zakharin                        llvm::cl::init(kTagAttachmentUnlimited));
48b1476365SSlava Zakharin 
499c84d20fSSlava Zakharin namespace fir {
509c84d20fSSlava Zakharin 
TBAABuilder(MLIRContext * context,bool applyTBAA,bool forceUnifiedTree)516042c2ebSTom Eccles TBAABuilder::TBAABuilder(MLIRContext *context, bool applyTBAA,
526042c2ebSTom Eccles                          bool forceUnifiedTree)
536042c2ebSTom Eccles     : enableTBAA(applyTBAA && !disableTBAA),
546042c2ebSTom Eccles       trees(/*separatePerFunction=*/perFunctionTBAATrees && !forceUnifiedTree) {
55*6cd86d0fSSlava Zakharin   // TODO: the TBAA tags created here are rooted in the root scope
56*6cd86d0fSSlava Zakharin   // of the enclosing function. This does not work best with MLIR inlining.
57*6cd86d0fSSlava Zakharin   // A better approach is to root them according to the scopes they belong to
58*6cd86d0fSSlava Zakharin   // and that were used by AddAliasTagsPass to create TBAA tags before
59*6cd86d0fSSlava Zakharin   // the CodeGen. For example:
60*6cd86d0fSSlava Zakharin   //   subroutine caller(a, b, ptr)
61*6cd86d0fSSlava Zakharin   //     real, target :: a(:), b(:)
62*6cd86d0fSSlava Zakharin   //     integer, pointer :: ptr(:)
63*6cd86d0fSSlava Zakharin   //     call callee(a, b, ptr)
64*6cd86d0fSSlava Zakharin   //   end
65*6cd86d0fSSlava Zakharin   //   subroutine callee(a, b, ptr)
66*6cd86d0fSSlava Zakharin   //     real :: a(:), b(:)
67*6cd86d0fSSlava Zakharin   //     integer, pointer :: ptr(:)
68*6cd86d0fSSlava Zakharin   //     do i=...
69*6cd86d0fSSlava Zakharin   //       a(ptr(i)) = b(ptr(i))
70*6cd86d0fSSlava Zakharin   //     end do
71*6cd86d0fSSlava Zakharin   //   end
72*6cd86d0fSSlava Zakharin   //
73*6cd86d0fSSlava Zakharin   // When callee is inlined, the dummy arguments 'a' and 'b' will
74*6cd86d0fSSlava Zakharin   // be rooted in TBAA tree corresponding to the `call callee` call site,
75*6cd86d0fSSlava Zakharin   // saying that the references to 'a' and 'b' cannot alias each other.
76*6cd86d0fSSlava Zakharin   // These tags will be created by AddAliasTagsPass, but it will not be able
77*6cd86d0fSSlava Zakharin   // to create any tags for 'ptr' references.
78*6cd86d0fSSlava Zakharin   // During the CodeGen, we create 'any data access' tags for the
79*6cd86d0fSSlava Zakharin   // 'ptr' acceses. If they are rooted within the root scope of `caller`,
80*6cd86d0fSSlava Zakharin   // they end up in a different TBAA tree with the 'a' and 'b' access
81*6cd86d0fSSlava Zakharin   // tags, so 'ptr', 'a' and 'b' references MayAlias. Moreover,
82*6cd86d0fSSlava Zakharin   // the box access of 'ptr' will also be in a different TBAA tree
83*6cd86d0fSSlava Zakharin   // with 'a' and 'b' tags, meaning they can also alias.
84*6cd86d0fSSlava Zakharin   // This will prevent LLVM vectorization even with memory conflict checks.
85*6cd86d0fSSlava Zakharin   // It seems that we'd better move all TBAA tags assignment to
86*6cd86d0fSSlava Zakharin   // AddAliasTagsPass, which can at least rely on the dummy arguments scopes.
879c84d20fSSlava Zakharin   if (!enableTBAA)
889c84d20fSSlava Zakharin     return;
899c84d20fSSlava Zakharin }
909c84d20fSSlava Zakharin 
getAccessTag(TBAATypeDescriptorAttr baseTypeDesc,TBAATypeDescriptorAttr accessTypeDesc,int64_t offset)911dda134fSMarkus Böck TBAATagAttr TBAABuilder::getAccessTag(TBAATypeDescriptorAttr baseTypeDesc,
921dda134fSMarkus Böck                                       TBAATypeDescriptorAttr accessTypeDesc,
939c84d20fSSlava Zakharin                                       int64_t offset) {
941dda134fSMarkus Böck   TBAATagAttr &tag = tagsMap[{baseTypeDesc, accessTypeDesc, offset}];
959c84d20fSSlava Zakharin   if (tag)
969c84d20fSSlava Zakharin     return tag;
979c84d20fSSlava Zakharin 
989c84d20fSSlava Zakharin   // Initialize new tag.
991dda134fSMarkus Böck   tag = TBAATagAttr::get(baseTypeDesc, accessTypeDesc, offset);
1009c84d20fSSlava Zakharin   return tag;
1019c84d20fSSlava Zakharin }
1029c84d20fSSlava Zakharin 
getAnyBoxAccessTag(mlir::LLVM::LLVMFuncOp func)1036042c2ebSTom Eccles TBAATagAttr TBAABuilder::getAnyBoxAccessTag(mlir::LLVM::LLVMFuncOp func) {
1046042c2ebSTom Eccles   TBAATypeDescriptorAttr boxMemberTypeDesc = trees[func].boxMemberTypeDesc;
1059c84d20fSSlava Zakharin   return getAccessTag(boxMemberTypeDesc, boxMemberTypeDesc, /*offset=*/0);
1069c84d20fSSlava Zakharin }
1079c84d20fSSlava Zakharin 
getBoxAccessTag(Type baseFIRType,Type accessFIRType,GEPOp gep,mlir::LLVM::LLVMFuncOp func)1081dda134fSMarkus Böck TBAATagAttr TBAABuilder::getBoxAccessTag(Type baseFIRType, Type accessFIRType,
1096042c2ebSTom Eccles                                          GEPOp gep,
1106042c2ebSTom Eccles                                          mlir::LLVM::LLVMFuncOp func) {
1116042c2ebSTom Eccles   return getAnyBoxAccessTag(func);
1129c84d20fSSlava Zakharin }
1139c84d20fSSlava Zakharin 
getAnyDataAccessTag(mlir::LLVM::LLVMFuncOp func)1146042c2ebSTom Eccles TBAATagAttr TBAABuilder::getAnyDataAccessTag(mlir::LLVM::LLVMFuncOp func) {
1156042c2ebSTom Eccles   TBAATypeDescriptorAttr anyDataAccessTypeDesc = trees[func].anyDataTypeDesc;
1169c84d20fSSlava Zakharin   return getAccessTag(anyDataAccessTypeDesc, anyDataAccessTypeDesc,
1179c84d20fSSlava Zakharin                       /*offset=*/0);
1189c84d20fSSlava Zakharin }
1199c84d20fSSlava Zakharin 
getDataAccessTag(Type baseFIRType,Type accessFIRType,GEPOp gep,mlir::LLVM::LLVMFuncOp func)1201dda134fSMarkus Böck TBAATagAttr TBAABuilder::getDataAccessTag(Type baseFIRType, Type accessFIRType,
1216042c2ebSTom Eccles                                           GEPOp gep,
1226042c2ebSTom Eccles                                           mlir::LLVM::LLVMFuncOp func) {
1236042c2ebSTom Eccles   return getAnyDataAccessTag(func);
1249c84d20fSSlava Zakharin }
1259c84d20fSSlava Zakharin 
getAnyAccessTag(mlir::LLVM::LLVMFuncOp func)1266042c2ebSTom Eccles TBAATagAttr TBAABuilder::getAnyAccessTag(mlir::LLVM::LLVMFuncOp func) {
1276042c2ebSTom Eccles   TBAATypeDescriptorAttr anyAccessTypeDesc = trees[func].anyAccessDesc;
128cfe8ae38SSlava Zakharin   return getAccessTag(anyAccessTypeDesc, anyAccessTypeDesc, /*offset=*/0);
129cfe8ae38SSlava Zakharin }
130cfe8ae38SSlava Zakharin 
attachTBAATag(AliasAnalysisOpInterface op,Type baseFIRType,Type accessFIRType,GEPOp gep)131ba0c082bSTobias Gysi void TBAABuilder::attachTBAATag(AliasAnalysisOpInterface op, Type baseFIRType,
1329c84d20fSSlava Zakharin                                 Type accessFIRType, GEPOp gep) {
1339c84d20fSSlava Zakharin   if (!enableTBAA)
1349c84d20fSSlava Zakharin     return;
1359c84d20fSSlava Zakharin 
1366042c2ebSTom Eccles   mlir::LLVM::LLVMFuncOp func = op->getParentOfType<mlir::LLVM::LLVMFuncOp>();
137c76d853cSTom Eccles   if (!func)
138c76d853cSTom Eccles     return;
1396042c2ebSTom Eccles 
140b1476365SSlava Zakharin   ++tagAttachmentCounter;
141b1476365SSlava Zakharin   if (tagAttachmentLimit != kTagAttachmentUnlimited &&
142b1476365SSlava Zakharin       tagAttachmentCounter > tagAttachmentLimit)
143b1476365SSlava Zakharin     return;
144b1476365SSlava Zakharin 
145b1476365SSlava Zakharin   LLVM_DEBUG(llvm::dbgs() << "Attaching TBAA tag #" << tagAttachmentCounter
146b1476365SSlava Zakharin                           << "\n");
147b1476365SSlava Zakharin 
1481dda134fSMarkus Böck   TBAATagAttr tbaaTagSym;
149cfe8ae38SSlava Zakharin   if (fir::isRecordWithDescriptorMember(baseFIRType)) {
150cfe8ae38SSlava Zakharin     // A memory access that addresses an aggregate that contains
151cfe8ae38SSlava Zakharin     // a mix of data members and descriptor members may alias
152cfe8ae38SSlava Zakharin     // with both data and descriptor accesses.
153cfe8ae38SSlava Zakharin     // Conservatively set any-access tag if there is any descriptor member.
1546042c2ebSTom Eccles     tbaaTagSym = getAnyAccessTag(func);
155fac349a1SChristian Sigg   } else if (mlir::isa<fir::BaseBoxType>(baseFIRType)) {
1566042c2ebSTom Eccles     tbaaTagSym = getBoxAccessTag(baseFIRType, accessFIRType, gep, func);
157cfe8ae38SSlava Zakharin   } else {
1586042c2ebSTom Eccles     tbaaTagSym = getDataAccessTag(baseFIRType, accessFIRType, gep, func);
159cfe8ae38SSlava Zakharin   }
1609c84d20fSSlava Zakharin 
161fef08da4STobias Gysi   if (!tbaaTagSym)
162fef08da4STobias Gysi     return;
163fef08da4STobias Gysi 
164ba0c082bSTobias Gysi   op.setTBAATags(ArrayAttr::get(op->getContext(), tbaaTagSym));
1659c84d20fSSlava Zakharin }
1669c84d20fSSlava Zakharin 
1679c84d20fSSlava Zakharin } // namespace fir
168