llvm-project/mlir/lib/Dialect/LLVMIR/IR/LLVMInterfaces.cpp
Markus Böck 78d00a160f [mlir][LLVM] Convert alias metadata to using attributes instead of ops
Using MLIR attributes instead of metadata has many advantages:
* No indirection: Attributes can simply refer to each other seemlessly without having to use the indirection of `SymbolRefAttr`. This also gives us correctness by construction in a lot of places as well
* Multithreading save: The Attribute infrastructure gives us thread-safety for free. Creating operations and inserting them into a block is not thread-safe. This is a major use case for e.g. the inliner in MLIR which runs in parallel
* Easier to create: There is no need for a builder or a metadata region

This patch therefore does exactly that. It leverages the new distinct attributes to create distinct alias domains and scopes in a deterministic and threadsafe manner.

Differential Revision: https://reviews.llvm.org/D155159
2023-07-14 11:14:42 +02:00

110 lines
4.3 KiB
C++

//===- LLVMInterfaces.cpp - LLVM Interfaces ---------------------*- C++ -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// This file defines op interfaces for the LLVM dialect in MLIR.
//
//===----------------------------------------------------------------------===//
#include "mlir/Dialect/LLVMIR/LLVMInterfaces.h"
#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
using namespace mlir;
using namespace mlir::LLVM;
/// Verifies the given array attribute contains symbol references and checks the
/// referenced symbol types using the provided verification function.
static LogicalResult
verifySymbolRefs(Operation *op, StringRef name, ArrayAttr symbolRefs,
llvm::function_ref<LogicalResult(Operation *, SymbolRefAttr)>
verifySymbolType) {
assert(symbolRefs && "expected a non-null attribute");
// Verify that the attribute is a symbol ref array attribute,
// because this constraint is not verified for all attribute
// names processed here (e.g. 'tbaa'). This verification
// is redundant in some cases.
if (!llvm::all_of(symbolRefs, [](Attribute attr) {
return attr && llvm::isa<SymbolRefAttr>(attr);
}))
return op->emitOpError() << name
<< " attribute failed to satisfy constraint: "
"symbol ref array attribute";
for (SymbolRefAttr symbolRef : symbolRefs.getAsRange<SymbolRefAttr>()) {
StringAttr metadataName = symbolRef.getRootReference();
StringAttr symbolName = symbolRef.getLeafReference();
// We want @metadata::@symbol, not just @symbol
if (metadataName == symbolName) {
return op->emitOpError() << "expected '" << symbolRef
<< "' to specify a fully qualified reference";
}
auto metadataOp = SymbolTable::lookupNearestSymbolFrom<LLVM::MetadataOp>(
op->getParentOp(), metadataName);
if (!metadataOp)
return op->emitOpError()
<< "expected '" << symbolRef << "' to reference a metadata op";
Operation *symbolOp =
SymbolTable::lookupNearestSymbolFrom(metadataOp, symbolName);
if (!symbolOp)
return op->emitOpError()
<< "expected '" << symbolRef << "' to be a valid reference";
if (failed(verifySymbolType(symbolOp, symbolRef))) {
return failure();
}
}
return success();
}
/// Verifies the given array attribute contains symbol references that point to
/// metadata operations of the given type.
template <typename OpTy>
LogicalResult verifySymbolRefsPointTo(Operation *op, StringRef name,
ArrayAttr symbolRefs) {
if (!symbolRefs)
return success();
auto verifySymbolType = [op](Operation *symbolOp,
SymbolRefAttr symbolRef) -> LogicalResult {
if (!isa<OpTy>(symbolOp)) {
return op->emitOpError()
<< "expected '" << symbolRef << "' to resolve to a "
<< OpTy::getOperationName();
}
return success();
};
return verifySymbolRefs(op, name, symbolRefs, verifySymbolType);
}
//===----------------------------------------------------------------------===//
// AccessGroupOpInterface
//===----------------------------------------------------------------------===//
LogicalResult mlir::LLVM::detail::verifyAccessGroupOpInterface(Operation *op) {
auto iface = cast<AccessGroupOpInterface>(op);
if (failed(verifySymbolRefsPointTo<LLVM::AccessGroupMetadataOp>(
iface, "access groups", iface.getAccessGroupsOrNull())))
return failure();
return success();
}
//===----------------------------------------------------------------------===//
// AliasAnalysisOpInterface
//===----------------------------------------------------------------------===//
LogicalResult
mlir::LLVM::detail::verifyAliasAnalysisOpInterface(Operation *op) {
auto iface = cast<AliasAnalysisOpInterface>(op);
if (failed(verifySymbolRefsPointTo<LLVM::TBAATagOp>(
iface, "tbaa tags", iface.getTBAATagsOrNull())))
return failure();
return success();
}
#include "mlir/Dialect/LLVMIR/LLVMInterfaces.cpp.inc"