1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
|
//===-- TBAABuilder.cpp -- TBAA builder definitions -----------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/
//
//===----------------------------------------------------------------------===//
#include "TBAABuilder.h"
#include "flang/Optimizer/Dialect/FIRType.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#define DEBUG_TYPE "flang-tbaa-builder"
using namespace mlir;
using namespace mlir::LLVM;
static llvm::cl::opt<bool> disableTBAA(
"disable-tbaa",
llvm::cl::desc("disable attaching TBAA tags to memory accessing operations "
"to override default Flang behavior"),
llvm::cl::init(false));
// tagAttachmentLimit is a debugging option that allows limiting
// the number of TBAA access tag attributes attached to operations.
// It is set to kTagAttachmentUnlimited by default denoting "no limit".
static constexpr unsigned kTagAttachmentUnlimited =
std::numeric_limits<unsigned>::max();
static llvm::cl::opt<unsigned>
tagAttachmentLimit("tbaa-attach-tag-max", llvm::cl::desc(""),
llvm::cl::init(kTagAttachmentUnlimited));
namespace fir {
std::string TBAABuilder::getNewTBAANodeName(llvm::StringRef basename) {
return (llvm::Twine(basename) + llvm::Twine('_') +
llvm::Twine(tbaaNodeCounter++))
.str();
}
TBAABuilder::TBAABuilder(mlir::ModuleOp module, bool applyTBAA)
: enableTBAA(applyTBAA && !disableTBAA) {
if (!enableTBAA)
return;
// In the usual Flang compilation flow, FIRToLLVMPass is run once,
// and the MetadataOp holding TBAA operations is created at the beginning
// of the pass. With tools like tco it is possible to invoke
// FIRToLLVMPass on already converted MLIR, so the MetadataOp
// already exists and creating a new one with the same name would
// be incorrect. If the TBAA MetadataOp is already present,
// we just disable all TBAABuilder actions (e.g. attachTBAATag()
// is a no-op).
if (llvm::any_of(
module.getBodyRegion().getOps<LLVM::MetadataOp>(),
[&](auto metaOp) { return metaOp.getSymName() == tbaaMetaOpName; })) {
enableTBAA = false;
return;
}
LLVM_DEBUG(llvm::dbgs() << "Creating TBAA MetadataOp for module '"
<< module.getName().value_or("<unknown>") << "'\n");
// Create TBAA MetadataOp with the root and basic type descriptors.
Location loc = module.getLoc();
MLIRContext *context = module.getContext();
OpBuilder builder(module.getBody(), module.getBody()->end());
tbaaMetaOp = builder.create<MetadataOp>(loc, tbaaMetaOpName);
builder.setInsertionPointToStart(&tbaaMetaOp.getBody().front());
// Root node.
auto rootOp = builder.create<TBAARootMetadataOp>(
loc, getNewTBAANodeName(kRootSymBasename), flangTBAARootId);
flangTBAARoot = FlatSymbolRefAttr::get(rootOp);
// Any access node.
auto anyAccessOp = builder.create<TBAATypeDescriptorOp>(
loc, getNewTBAANodeName(kTypeDescSymBasename),
StringAttr::get(context, anyAccessTypeDescId),
ArrayAttr::get(context, flangTBAARoot), ArrayRef<int64_t>{0});
anyAccessTypeDesc = FlatSymbolRefAttr::get(anyAccessOp);
// Any data access node.
auto anyDataAccessOp = builder.create<TBAATypeDescriptorOp>(
loc, getNewTBAANodeName(kTypeDescSymBasename),
StringAttr::get(context, anyDataAccessTypeDescId),
ArrayAttr::get(context, anyAccessTypeDesc), ArrayRef<int64_t>{0});
anyDataAccessTypeDesc = FlatSymbolRefAttr::get(anyDataAccessOp);
// Box member access node.
auto boxMemberOp = builder.create<TBAATypeDescriptorOp>(
loc, getNewTBAANodeName(kTypeDescSymBasename),
StringAttr::get(context, boxMemberTypeDescId),
ArrayAttr::get(context, anyAccessTypeDesc), ArrayRef<int64_t>{0});
boxMemberTypeDesc = FlatSymbolRefAttr::get(boxMemberOp);
}
SymbolRefAttr TBAABuilder::getAccessTag(SymbolRefAttr baseTypeDesc,
SymbolRefAttr accessTypeDesc,
int64_t offset) {
SymbolRefAttr &tag = tagsMap[{baseTypeDesc, accessTypeDesc, offset}];
if (tag)
return tag;
// Initialize new tag.
Location loc = tbaaMetaOp.getLoc();
OpBuilder builder(&tbaaMetaOp.getBody().back(),
tbaaMetaOp.getBody().back().end());
auto tagOp = builder.create<TBAATagOp>(
loc, getNewTBAANodeName(kTagSymBasename), baseTypeDesc.getLeafReference(),
accessTypeDesc.getLeafReference(), offset);
// TBAATagOp symbols must be referenced by their fully qualified
// names, so create a path to TBAATagOp symbol.
StringAttr metaOpName = SymbolTable::getSymbolName(tbaaMetaOp);
tag = SymbolRefAttr::get(builder.getContext(), metaOpName,
FlatSymbolRefAttr::get(tagOp));
return tag;
}
SymbolRefAttr TBAABuilder::getAnyBoxAccessTag() {
return getAccessTag(boxMemberTypeDesc, boxMemberTypeDesc, /*offset=*/0);
}
SymbolRefAttr TBAABuilder::getBoxAccessTag(Type baseFIRType, Type accessFIRType,
GEPOp gep) {
return getAnyBoxAccessTag();
}
SymbolRefAttr TBAABuilder::getAnyDataAccessTag() {
return getAccessTag(anyDataAccessTypeDesc, anyDataAccessTypeDesc,
/*offset=*/0);
}
SymbolRefAttr TBAABuilder::getDataAccessTag(Type baseFIRType,
Type accessFIRType, GEPOp gep) {
return getAnyDataAccessTag();
}
void TBAABuilder::attachTBAATag(Operation *op, Type baseFIRType,
Type accessFIRType, GEPOp gep) {
if (!enableTBAA)
return;
++tagAttachmentCounter;
if (tagAttachmentLimit != kTagAttachmentUnlimited &&
tagAttachmentCounter > tagAttachmentLimit)
return;
LLVM_DEBUG(llvm::dbgs() << "Attaching TBAA tag #" << tagAttachmentCounter
<< "\n");
SymbolRefAttr tbaaTagSym;
if (baseFIRType.isa<fir::BaseBoxType>())
tbaaTagSym = getBoxAccessTag(baseFIRType, accessFIRType, gep);
else
tbaaTagSym = getDataAccessTag(baseFIRType, accessFIRType, gep);
if (tbaaTagSym)
op->setAttr(LLVMDialect::getTBAAAttrName(),
ArrayAttr::get(op->getContext(), tbaaTagSym));
}
} // namespace fir
|