Files
clang-p2996/flang/lib/Optimizer/CodeGen/TBAABuilder.cpp
Tobias Gysi fef08da4b7 [mlir][llvm] Store memory op metadata using op attributes.
The revision introduces operation attributes to store tbaa metadata on
load and store operations rather than relying using dialect attributes.
At the same time, the change also ensures the provided getters and
setters instead are used instead of a string based lookup. The latter
is done for the tbaa, access groups, and alias scope attributes.

The goal of this change is to ensure the metadata attributes are only
placed on operations that have the corresponding operation attributes.
This is imported since only these operations later on translate these
attributes to LLVM IR. Dialect attributes placed on other operations
are lost during the translation.

Reviewed By: vzakhari, Dinistro

Differential Revision: https://reviews.llvm.org/D143654
2023-02-10 15:27:25 +01:00

173 lines
6.6 KiB
C++

//===-- 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/ADT/TypeSwitch.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)
return;
auto tbaaAttr = ArrayAttr::get(op->getContext(), tbaaTagSym);
llvm::TypeSwitch<Operation *>(op)
.Case<LoadOp, StoreOp>([&](auto memOp) { memOp.setTbaaAttr(tbaaAttr); })
.Default([](auto) { llvm_unreachable("expected LoadOp or StoreOp"); });
}
} // namespace fir