xref: /llvm-project/flang/lib/Optimizer/CodeGen/TBAABuilder.cpp (revision 9c84d20fa69006adcbbaf424f3ef674298045f78)
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 "TBAABuilder.h"
14 #include "flang/Optimizer/Dialect/FIRType.h"
15 #include "llvm/Support/CommandLine.h"
16 
17 using namespace mlir;
18 using namespace mlir::LLVM;
19 
20 static llvm::cl::opt<bool> disableTBAA(
21     "disable-tbaa",
22     llvm::cl::desc("disable attaching TBAA tags to memory accessing operations "
23                    "to override default Flang behavior"),
24     llvm::cl::init(false));
25 
26 namespace fir {
27 std::string TBAABuilder::getNewTBAANodeName(llvm::StringRef basename) {
28   return (llvm::Twine(basename) + llvm::Twine('_') +
29           llvm::Twine(tbaaNodeCounter++))
30       .str();
31 }
32 
33 TBAABuilder::TBAABuilder(mlir::ModuleOp module, bool applyTBAA)
34     : enableTBAA(applyTBAA && !disableTBAA) {
35   if (!enableTBAA)
36     return;
37 
38   // In the usual Flang compilation flow, FIRToLLVMPass is run once,
39   // and the MetadataOp holding TBAA operations is created at the beginning
40   // of the pass. With tools like tco it is possible to invoke
41   // FIRToLLVMPass on already converted MLIR, so the MetadataOp
42   // already exists and creating a new one with the same name would
43   // be incorrect. If the TBAA MetadataOp is already present,
44   // we just disable all TBAABuilder actions (e.g. attachTBAATag()
45   // is a no-op).
46   if (llvm::any_of(
47           module.getBodyRegion().getOps<LLVM::MetadataOp>(),
48           [&](auto metaOp) { return metaOp.getSymName() == tbaaMetaOpName; })) {
49     enableTBAA = false;
50     return;
51   }
52 
53   // Create TBAA MetadataOp with the root and basic type descriptors.
54   Location loc = module.getLoc();
55   MLIRContext *context = module.getContext();
56   OpBuilder builder(module.getBody(), module.getBody()->end());
57   tbaaMetaOp = builder.create<MetadataOp>(loc, tbaaMetaOpName);
58   builder.setInsertionPointToStart(&tbaaMetaOp.getBody().front());
59 
60   // Root node.
61   auto rootOp = builder.create<TBAARootMetadataOp>(
62       loc, getNewTBAANodeName(kRootSymBasename), flangTBAARootId);
63   flangTBAARoot = FlatSymbolRefAttr::get(rootOp);
64 
65   // Any access node.
66   auto anyAccessOp = builder.create<TBAATypeDescriptorOp>(
67       loc, getNewTBAANodeName(kTypeDescSymBasename),
68       StringAttr::get(context, anyAccessTypeDescId),
69       ArrayAttr::get(context, flangTBAARoot), ArrayRef<int64_t>{0});
70   anyAccessTypeDesc = FlatSymbolRefAttr::get(anyAccessOp);
71 
72   // Any data access node.
73   auto anyDataAccessOp = builder.create<TBAATypeDescriptorOp>(
74       loc, getNewTBAANodeName(kTypeDescSymBasename),
75       StringAttr::get(context, anyDataAccessTypeDescId),
76       ArrayAttr::get(context, anyAccessTypeDesc), ArrayRef<int64_t>{0});
77   anyDataAccessTypeDesc = FlatSymbolRefAttr::get(anyDataAccessOp);
78 
79   // Box member access node.
80   auto boxMemberOp = builder.create<TBAATypeDescriptorOp>(
81       loc, getNewTBAANodeName(kTypeDescSymBasename),
82       StringAttr::get(context, boxMemberTypeDescId),
83       ArrayAttr::get(context, anyAccessTypeDesc), ArrayRef<int64_t>{0});
84   boxMemberTypeDesc = FlatSymbolRefAttr::get(boxMemberOp);
85 }
86 
87 SymbolRefAttr TBAABuilder::getAccessTag(SymbolRefAttr baseTypeDesc,
88                                         SymbolRefAttr accessTypeDesc,
89                                         int64_t offset) {
90   SymbolRefAttr &tag = tagsMap[{baseTypeDesc, accessTypeDesc, offset}];
91   if (tag)
92     return tag;
93 
94   // Initialize new tag.
95   Location loc = tbaaMetaOp.getLoc();
96   OpBuilder builder(&tbaaMetaOp.getBody().back(),
97                     tbaaMetaOp.getBody().back().end());
98   auto tagOp = builder.create<TBAATagOp>(
99       loc, getNewTBAANodeName(kTagSymBasename), baseTypeDesc.getLeafReference(),
100       accessTypeDesc.getLeafReference(), offset);
101   // TBAATagOp symbols must be referenced by their fully qualified
102   // names, so create a path to TBAATagOp symbol.
103   StringAttr metaOpName = SymbolTable::getSymbolName(tbaaMetaOp);
104   tag = SymbolRefAttr::get(builder.getContext(), metaOpName,
105                            FlatSymbolRefAttr::get(tagOp));
106   return tag;
107 }
108 
109 SymbolRefAttr TBAABuilder::getAnyBoxAccessTag() {
110   return getAccessTag(boxMemberTypeDesc, boxMemberTypeDesc, /*offset=*/0);
111 }
112 
113 SymbolRefAttr TBAABuilder::getBoxAccessTag(Type baseFIRType, Type accessFIRType,
114                                            GEPOp gep) {
115   return getAnyBoxAccessTag();
116 }
117 
118 SymbolRefAttr TBAABuilder::getAnyDataAccessTag() {
119   return getAccessTag(anyDataAccessTypeDesc, anyDataAccessTypeDesc,
120                       /*offset=*/0);
121 }
122 
123 SymbolRefAttr TBAABuilder::getDataAccessTag(Type baseFIRType,
124                                             Type accessFIRType, GEPOp gep) {
125   return getAnyDataAccessTag();
126 }
127 
128 void TBAABuilder::attachTBAATag(Operation *op, Type baseFIRType,
129                                 Type accessFIRType, GEPOp gep) {
130   if (!enableTBAA)
131     return;
132 
133   SymbolRefAttr tbaaTagSym;
134   if (baseFIRType.isa<fir::BaseBoxType>())
135     tbaaTagSym = getBoxAccessTag(baseFIRType, accessFIRType, gep);
136   else
137     tbaaTagSym = getDataAccessTag(baseFIRType, accessFIRType, gep);
138 
139   if (tbaaTagSym)
140     op->setAttr(LLVMDialect::getTBAAAttrName(),
141                 ArrayAttr::get(op->getContext(), tbaaTagSym));
142 }
143 
144 } // namespace fir
145