MLIR 24.0.0git
LLVMInterfaces.cpp
Go to the documentation of this file.
1//===- LLVMInterfaces.cpp - LLVM Interfaces ---------------------*- C++ -*-===//
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// This file defines op interfaces for the LLVM dialect in MLIR.
10//
11//===----------------------------------------------------------------------===//
12
14
17
18using namespace mlir;
19using namespace mlir::LLVM;
20
21/// Verifies that all elements of `array` are instances of `Attr`.
22template <class AttrT>
23static LogicalResult isArrayOf(Operation *op, ArrayAttr array) {
24 for (Attribute iter : array)
25 if (!isa<AttrT>(iter))
26 return op->emitOpError("expected op to return array of ")
27 << AttrT::getMnemonic() << " attributes";
28 return success();
29}
30
31//===----------------------------------------------------------------------===//
32// AccessGroupOpInterface
33//===----------------------------------------------------------------------===//
34
36 auto iface = cast<AccessGroupOpInterface>(op);
37 ArrayAttr accessGroups = iface.getAccessGroupsOrNull();
38 if (!accessGroups)
39 return success();
40
41 return isArrayOf<AccessGroupAttr>(op, accessGroups);
42}
43
44//===----------------------------------------------------------------------===//
45// AliasAnalysisOpInterface
46//===----------------------------------------------------------------------===//
47
48LogicalResult
50 auto iface = cast<AliasAnalysisOpInterface>(op);
51
52 if (auto aliasScopes = iface.getAliasScopesOrNull())
53 if (failed(isArrayOf<AliasScopeAttr>(op, aliasScopes)))
54 return failure();
55
56 if (auto noAliasScopes = iface.getNoAliasScopesOrNull())
57 if (failed(isArrayOf<AliasScopeAttr>(op, noAliasScopes)))
58 return failure();
59
60 ArrayAttr tags = iface.getTBAATagsOrNull();
61 if (!tags)
62 return success();
63
64 return isArrayOf<TBAATagAttr>(op, tags);
65}
66
67//===----------------------------------------------------------------------===//
68// TBAAStructOpInterface
69//===----------------------------------------------------------------------===//
70
72 auto iface = cast<TBAAStructOpInterface>(op);
73 ArrayAttr fields = iface.getTBAAStructOrNull();
74 if (!fields)
75 return success();
76
77 if (failed(isArrayOf<TBAAStructFieldAttr>(op, fields)))
78 return failure();
79
80 // Field offsets must be non-decreasing, matching LLVM's verifier rule.
81 // Compare unsigned: LLVM zero-extends the offsets before comparing.
82 std::optional<uint64_t> prevOffset;
83 for (Attribute field : fields) {
84 uint64_t offset = cast<TBAAStructFieldAttr>(field).getOffset();
85 if (prevOffset && offset < *prevOffset)
86 return op->emitOpError(
87 "tbaa.struct field offsets must be non-decreasing");
88 prevOffset = offset;
89 }
90 return success();
91}
92
93//===----------------------------------------------------------------------===//
94// DereferenceableOpInterface
95//===----------------------------------------------------------------------===//
96
97LogicalResult
99 auto iface = cast<DereferenceableOpInterface>(op);
100
101 if (auto derefAttr = iface.getDereferenceableOrNull())
102 if (op->getNumResults() != 1 ||
103 !mlir::isa<LLVMPointerType>(op->getResult(0).getType()))
104 return op->emitOpError(
105 "expected op to return a single LLVM pointer type");
106
107 return success();
108}
109
110//===----------------------------------------------------------------------===//
111// RangeOpInterface
112//===----------------------------------------------------------------------===//
113
115 auto iface = cast<RangeOpInterface>(op);
116
117 ConstantRangeAttr range = iface.getRangeOrNull();
118 if (!range)
119 return success();
120 if (op->getNumResults() != 1)
121 return op->emitOpError("expected op to have a single result");
122 auto intType =
123 dyn_cast<IntegerType>(getElementTypeOrSelf(op->getResult(0).getType()));
124 if (!intType || intType.getWidth() != range.getLower().getBitWidth())
125 return op->emitOpError(
126 "expected range bitwidth to match the integer (element) result type");
127 if (range.getLower() == range.getUpper())
128 return op->emitOpError("expected range to be neither empty nor full");
129 return success();
130}
131
132SmallVector<Value> mlir::LLVM::AtomicCmpXchgOp::getAccessedOperands() {
133 return {getPtr()};
134}
135
136SmallVector<Value> mlir::LLVM::AtomicRMWOp::getAccessedOperands() {
137 return {getPtr()};
138}
139
140SmallVector<Value> mlir::LLVM::LoadOp::getAccessedOperands() {
141 return {getAddr()};
142}
143
144SmallVector<Value> mlir::LLVM::StoreOp::getAccessedOperands() {
145 return {getAddr()};
146}
147
148SmallVector<Value> mlir::LLVM::MemcpyOp::getAccessedOperands() {
149 return {getDst(), getSrc()};
150}
151
152SmallVector<Value> mlir::LLVM::MemcpyInlineOp::getAccessedOperands() {
153 return {getDst(), getSrc()};
154}
155
156SmallVector<Value> mlir::LLVM::MemmoveOp::getAccessedOperands() {
157 return {getDst(), getSrc()};
158}
159
160SmallVector<Value> mlir::LLVM::MemsetOp::getAccessedOperands() {
161 return {getDst()};
162}
163
164SmallVector<Value> mlir::LLVM::MemsetInlineOp::getAccessedOperands() {
165 return {getDst()};
166}
167
168SmallVector<Value> mlir::LLVM::MaskedLoadOp::getAccessedOperands() {
169 return {getData()};
170}
171
172SmallVector<Value> mlir::LLVM::MaskedStoreOp::getAccessedOperands() {
173 return {getData()};
174}
175
176SmallVector<Value> mlir::LLVM::masked_gather::getAccessedOperands() {
177 return {getPtrs()};
178}
179
180SmallVector<Value> mlir::LLVM::masked_scatter::getAccessedOperands() {
181 return {getPtrs()};
182}
183
184SmallVector<Value> mlir::LLVM::CallOp::getAccessedOperands() {
185 // Note: This must not use `getArgOperands`, which excludes the variadic
186 // arguments of a call to a variadic callee. Those are passed to the callee
187 // and may well be accessed by it.
188 Operation::operand_range operands = getCalleeOperands();
189 // In an indirect call, the first callee operand is the callee itself.
190 if (!getCallee().has_value() && !operands.empty())
191 operands = operands.drop_front();
192 return llvm::filter_to_vector(
193 operands, [](Value arg) { return isa<LLVMPointerType>(arg.getType()); });
194}
195
196#include "mlir/Dialect/LLVMIR/LLVMInterfaces.cpp.inc"
return success()
static LogicalResult isArrayOf(Operation *op, ArrayAttr array)
Verifies that all elements of array are instances of Attr.
ArrayAttr()
Attributes are known-constant values of operations.
Definition Attributes.h:25
Operation is the basic unit of execution within MLIR.
Definition Operation.h:87
OpResult getResult(unsigned idx)
Get the 'idx'th result of this operation.
Definition Operation.h:434
OperandRange operand_range
Definition Operation.h:398
InFlightDiagnostic emitOpError(const Twine &message={})
Emit an error with the op name prefixed, like "'dim' op " which is convenient for verifiers.
unsigned getNumResults()
Return the number of results held by this operation.
Definition Operation.h:431
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition Value.h:96
Type getType() const
Return the type of this value.
Definition Value.h:105
LogicalResult verifyAliasAnalysisOpInterface(Operation *op)
Verifies the alias analysis attributes of memory operations that implement the alias analysis interfa...
LogicalResult verifyTBAAStructOpInterface(Operation *op)
Verifies that the tbaa.struct field offsets of memory operations that implement the tbaa....
LogicalResult verifyRangeOpInterface(Operation *op)
Verifies that the range of an operation implementing the range interface matches the bitwidth of its ...
LogicalResult verifyAccessGroupOpInterface(Operation *op)
Verifies the access groups attribute of memory operations that implement the access group interface.
LogicalResult verifyDereferenceableOpInterface(Operation *op)
Verifies that the operation implementing the dereferenceable interface has exactly one result of LLVM...
Include the generated interface declarations.
Type getElementTypeOrSelf(Type type)
Return the element type or return the type itself.