Files
clang-p2996/mlir/lib/Dialect/LLVMIR/IR/LLVMInterfaces.cpp
Markus Böck f9173c2958 [mlir][LLVM] Convert noalias parameters into alias scopes during inlining
Currently, inlining a function with a `noalias` parameter leads to a large loss of optimization potential as the `noalias` parameter, an important hint for alias analysis, is lost completely.

This patch fixes this with the same approach as LLVM by annotating all users of the `noalias` parameter with appropriate alias and noalias scope lists.
The implementation done here is not as sophisticated as LLVMs, which has more infrastructure related to escaping and captured pointers, but should work in the majority of important cases.
Any deficiency can be addressed in future patches.

Related LLVM code: 27ade4b554/llvm/lib/Transforms/Utils/InlineFunction.cpp (L1090)

Differential Revision: https://reviews.llvm.org/D155712
2023-07-20 15:05:28 +02:00

105 lines
3.2 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 that all elements of `array` are instances of `Attr`.
template <class AttrT>
static LogicalResult isArrayOf(Operation *op, ArrayAttr array) {
for (Attribute iter : array)
if (!isa<AttrT>(iter))
return op->emitOpError("expected op to return array of ")
<< AttrT::getMnemonic() << " attributes";
return success();
}
//===----------------------------------------------------------------------===//
// AccessGroupOpInterface
//===----------------------------------------------------------------------===//
LogicalResult mlir::LLVM::detail::verifyAccessGroupOpInterface(Operation *op) {
auto iface = cast<AccessGroupOpInterface>(op);
ArrayAttr accessGroups = iface.getAccessGroupsOrNull();
if (!accessGroups)
return success();
return isArrayOf<AccessGroupAttr>(op, accessGroups);
}
//===----------------------------------------------------------------------===//
// AliasAnalysisOpInterface
//===----------------------------------------------------------------------===//
LogicalResult
mlir::LLVM::detail::verifyAliasAnalysisOpInterface(Operation *op) {
auto iface = cast<AliasAnalysisOpInterface>(op);
if (auto aliasScopes = iface.getAliasScopesOrNull())
if (failed(isArrayOf<AliasScopeAttr>(op, aliasScopes)))
return failure();
if (auto noAliasScopes = iface.getNoAliasScopesOrNull())
if (failed(isArrayOf<AliasScopeAttr>(op, noAliasScopes)))
return failure();
ArrayAttr tags = iface.getTBAATagsOrNull();
if (!tags)
return success();
return isArrayOf<TBAATagAttr>(op, tags);
}
SmallVector<Value> mlir::LLVM::AtomicCmpXchgOp::getAccessedOperands() {
return {getPtr()};
}
SmallVector<Value> mlir::LLVM::AtomicRMWOp::getAccessedOperands() {
return {getPtr()};
}
SmallVector<Value> mlir::LLVM::LoadOp::getAccessedOperands() {
return {getAddr()};
}
SmallVector<Value> mlir::LLVM::StoreOp::getAccessedOperands() {
return {getAddr()};
}
SmallVector<Value> mlir::LLVM::MemcpyOp::getAccessedOperands() {
return {getDst(), getSrc()};
}
SmallVector<Value> mlir::LLVM::MemcpyInlineOp::getAccessedOperands() {
return {getDst(), getSrc()};
}
SmallVector<Value> mlir::LLVM::MemmoveOp::getAccessedOperands() {
return {getDst(), getSrc()};
}
SmallVector<Value> mlir::LLVM::MemsetOp::getAccessedOperands() {
return {getDst()};
}
SmallVector<Value> mlir::LLVM::CallOp::getAccessedOperands() {
return llvm::to_vector(
llvm::make_filter_range(getArgOperands(), [](Value arg) {
return isa<LLVMPointerType>(arg.getType());
}));
}
#include "mlir/Dialect/LLVMIR/LLVMInterfaces.cpp.inc"