Coverage Report

Created: 2020-06-26 05:44

/home/arjun/llvm-project/mlir/include/mlir/IR/OperationSupport.h
Line
Count
Source (jump to first uncovered line)
1
//===- OperationSupport.h ---------------------------------------*- 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 a number of support types that Operation and related
10
// classes build on top of.
11
//
12
//===----------------------------------------------------------------------===//
13
14
#ifndef MLIR_IR_OPERATION_SUPPORT_H
15
#define MLIR_IR_OPERATION_SUPPORT_H
16
17
#include "mlir/IR/Attributes.h"
18
#include "mlir/IR/Identifier.h"
19
#include "mlir/IR/Location.h"
20
#include "mlir/IR/Types.h"
21
#include "mlir/IR/Value.h"
22
#include "mlir/Support/LogicalResult.h"
23
#include "llvm/ADT/BitmaskEnum.h"
24
#include "llvm/ADT/PointerUnion.h"
25
#include "llvm/Support/PointerLikeTypeTraits.h"
26
#include "llvm/Support/TrailingObjects.h"
27
#include <memory>
28
29
namespace mlir {
30
class Block;
31
class Dialect;
32
class Operation;
33
struct OperationState;
34
class OpAsmParser;
35
class OpAsmParserResult;
36
class OpAsmPrinter;
37
class OperandRange;
38
class OpFoldResult;
39
class ParseResult;
40
class Pattern;
41
class Region;
42
class ResultRange;
43
class RewritePattern;
44
class SuccessorRange;
45
class Type;
46
class Value;
47
class ValueRange;
48
template <typename ValueRangeT> class ValueTypeRange;
49
50
/// This is an adaptor from a list of values to named operands of OpTy.  In a
51
/// generic operation context, e.g., in dialect conversions, an ordered array of
52
/// `Value`s is treated as operands of `OpTy`.  This adaptor takes a reference
53
/// to the array and provides accessors with the same names as `OpTy` for
54
/// operands.  This makes possible to create function templates that operate on
55
/// either OpTy or OperandAdaptor<OpTy> seamlessly.
56
template <typename OpTy> using OperandAdaptor = typename OpTy::OperandAdaptor;
57
58
class OwningRewritePatternList;
59
60
//===----------------------------------------------------------------------===//
61
// AbstractOperation
62
//===----------------------------------------------------------------------===//
63
64
enum class OperationProperty {
65
  /// This bit is set for an operation if it is a commutative
66
  /// operation: that is an operator where order of operands does not
67
  /// change the result of the operation.  For example, in a binary
68
  /// commutative operation, "a op b" and "b op a" produce the same
69
  /// results.
70
  Commutative = 0x1,
71
72
  /// This bit is set for an operation if it is a terminator: that means
73
  /// an operation at the end of a block.
74
  Terminator = 0x2,
75
76
  /// This bit is set for operations that are completely isolated from above.
77
  /// This is used for operations whose regions are explicit capture only, i.e.
78
  /// they are never allowed to implicitly reference values defined above the
79
  /// parent operation.
80
  IsolatedFromAbove = 0x4,
81
};
82
83
/// This is a "type erased" representation of a registered operation.  This
84
/// should only be used by things like the AsmPrinter and other things that need
85
/// to be parameterized by generic operation hooks.  Most user code should use
86
/// the concrete operation types.
87
class AbstractOperation {
88
public:
89
  using OperationProperties = uint32_t;
90
91
  /// This is the name of the operation.
92
  const StringRef name;
93
94
  /// This is the dialect that this operation belongs to.
95
  Dialect &dialect;
96
97
  /// The unique identifier of the derived Op class.
98
  TypeID typeID;
99
100
  /// Use the specified object to parse this ops custom assembly format.
101
  ParseResult (&parseAssembly)(OpAsmParser &parser, OperationState &result);
102
103
  /// This hook implements the AsmPrinter for this operation.
104
  void (&printAssembly)(Operation *op, OpAsmPrinter &p);
105
106
  /// This hook implements the verifier for this operation.  It should emits an
107
  /// error message and returns failure if a problem is detected, or returns
108
  /// success if everything is ok.
109
  LogicalResult (&verifyInvariants)(Operation *op);
110
111
  /// This hook implements a generalized folder for this operation.  Operations
112
  /// can implement this to provide simplifications rules that are applied by
113
  /// the Builder::createOrFold API and the canonicalization pass.
114
  ///
115
  /// This is an intentionally limited interface - implementations of this hook
116
  /// can only perform the following changes to the operation:
117
  ///
118
  ///  1. They can leave the operation alone and without changing the IR, and
119
  ///     return failure.
120
  ///  2. They can mutate the operation in place, without changing anything else
121
  ///     in the IR.  In this case, return success.
122
  ///  3. They can return a list of existing values that can be used instead of
123
  ///     the operation.  In this case, fill in the results list and return
124
  ///     success.  The caller will remove the operation and use those results
125
  ///     instead.
126
  ///
127
  /// This allows expression of some simple in-place canonicalizations (e.g.
128
  /// "x+0 -> x", "min(x,y,x,z) -> min(x,y,z)", "x+y-x -> y", etc), as well as
129
  /// generalized constant folding.
130
  LogicalResult (&foldHook)(Operation *op, ArrayRef<Attribute> operands,
131
                            SmallVectorImpl<OpFoldResult> &results);
132
133
  /// This hook returns any canonicalization pattern rewrites that the operation
134
  /// supports, for use by the canonicalization pass.
135
  void (&getCanonicalizationPatterns)(OwningRewritePatternList &results,
136
                                      MLIRContext *context);
137
138
  /// Returns whether the operation has a particular property.
139
0
  bool hasProperty(OperationProperty property) const {
140
0
    return opProperties & static_cast<OperationProperties>(property);
141
0
  }
142
143
  /// Returns an instance of the concept object for the given interface if it
144
  /// was registered to this operation, null otherwise. This should not be used
145
  /// directly.
146
0
  template <typename T> typename T::Concept *getInterface() const {
147
0
    return reinterpret_cast<typename T::Concept *>(
148
0
        getRawInterface(T::getInterfaceID()));
149
0
  }
Unexecuted instantiation: _ZNK4mlir17AbstractOperation12getInterfaceINS_23MemoryEffectOpInterfaceEEEPNT_7ConceptEv
Unexecuted instantiation: _ZNK4mlir17AbstractOperation12getInterfaceINS_17SymbolOpInterfaceEEEPNT_7ConceptEv
Unexecuted instantiation: _ZNK4mlir17AbstractOperation12getInterfaceINS_17BranchOpInterfaceEEEPNT_7ConceptEv
Unexecuted instantiation: _ZNK4mlir17AbstractOperation12getInterfaceINS_16OpAsmOpInterfaceEEEPNT_7ConceptEv
150
151
  /// Returns if the operation has a particular trait.
152
0
  template <template <typename T> class Trait> bool hasTrait() const {
153
0
    return hasRawTrait(TypeID::get<Trait>());
154
0
  }
Unexecuted instantiation: _ZNK4mlir17AbstractOperation8hasTraitINS_7OpTrait23HasRecursiveSideEffectsEEEbv
Unexecuted instantiation: _ZNK4mlir17AbstractOperation8hasTraitINS_7OpTrait12ConstantLikeEEEbv
Unexecuted instantiation: _ZNK4mlir17AbstractOperation8hasTraitINS_7OpTrait11AffineScopeEEEbv
Unexecuted instantiation: _ZNK4mlir17AbstractOperation8hasTraitINS_7OpTrait24AutomaticAllocationScopeEEEbv
Unexecuted instantiation: _ZNK4mlir17AbstractOperation8hasTraitINS_7OpTrait10ZeroRegionEEEbv
Unexecuted instantiation: _ZNK4mlir17AbstractOperation8hasTraitINS_7OpTrait12ZeroOperandsEEEbv
Unexecuted instantiation: _ZNK4mlir17AbstractOperation8hasTraitINS_7OpTrait11SymbolTableEEEbv
155
156
  /// Look up the specified operation in the specified MLIRContext and return a
157
  /// pointer to it if present.  Otherwise, return a null pointer.
158
  static const AbstractOperation *lookup(StringRef opName,
159
                                         MLIRContext *context);
160
161
  /// This constructor is used by Dialect objects when they register the list of
162
  /// operations they contain.
163
0
  template <typename T> static AbstractOperation get(Dialect &dialect) {
164
0
    return AbstractOperation(
165
0
        T::getOperationName(), dialect, T::getOperationProperties(),
166
0
        TypeID::get<T>(), T::parseAssembly, T::printAssembly,
167
0
        T::verifyInvariants, T::foldHook, T::getCanonicalizationPatterns,
168
0
        T::getRawInterface, T::hasTrait);
169
0
  }
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_16AffineDmaStartOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_15AffineDmaWaitOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_13AffineApplyOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_11AffineForOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_10AffineIfOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_12AffineLoadOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_11AffineMaxOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_11AffineMinOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_16AffineParallelOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_16AffinePrefetchOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_13AffineStoreOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_18AffineTerminatorOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_18AffineVectorLoadOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_19AffineVectorStoreOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_10DmaStartOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_9DmaWaitOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_6AbsFOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_7AddCFOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_6AddFOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_6AddIOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_7AllocOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_8AllocaOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_5AndOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_17AssumeAlignmentOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_11AtomicRMWOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_13AtomicYieldOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_8BranchOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_14CallIndirectOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_6CallOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_7CeilFOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_6CmpFOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_6CmpIOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_12CondBranchOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_10ConstantOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_10CopySignOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_5CosOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_15CreateComplexOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_9DeallocOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_5DimOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_6DivFOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_6Exp2OpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_5ExpOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_16ExtractElementOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_7FPExtOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_8FPToSIOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_9FPTruncOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_18GenericAtomicRMWOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_4ImOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_11IndexCastOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_6LoadOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_7Log10OpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_6Log2OpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_5LogOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_12MemRefCastOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_6MulFOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_6MulIOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_6NegFOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_4OrOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_10PrefetchOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_6RankOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_4ReOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_6RemFOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_8ReturnOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_7RsqrtOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_8SIToFPOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_8SelectOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_11ShiftLeftOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_13SignExtendIOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_12SignedDivIOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_12SignedRemIOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_18SignedShiftRightOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_5SinOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_7SplatOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_6SqrtOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_7StoreOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_7SubCFOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_6SubFOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_6SubIOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_9SubViewOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_6TanhOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_12TensorCastOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_20TensorFromElementsOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_12TensorLoadOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_13TensorStoreOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_11TruncateIOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_14UnsignedDivIOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_14UnsignedRemIOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_20UnsignedShiftRightOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_6ViewOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_5XOrOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_13ZeroExtendIOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_6FuncOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_8ModuleOpEEES0_RNS_7DialectE
Unexecuted instantiation: _ZN4mlir17AbstractOperation3getINS_18ModuleTerminatorOpEEES0_RNS_7DialectE
170
171
private:
172
  AbstractOperation(
173
      StringRef name, Dialect &dialect, OperationProperties opProperties,
174
      TypeID typeID,
175
      ParseResult (&parseAssembly)(OpAsmParser &parser, OperationState &result),
176
      void (&printAssembly)(Operation *op, OpAsmPrinter &p),
177
      LogicalResult (&verifyInvariants)(Operation *op),
178
      LogicalResult (&foldHook)(Operation *op, ArrayRef<Attribute> operands,
179
                                SmallVectorImpl<OpFoldResult> &results),
180
      void (&getCanonicalizationPatterns)(OwningRewritePatternList &results,
181
                                          MLIRContext *context),
182
      void *(&getRawInterface)(TypeID interfaceID),
183
      bool (&hasTrait)(TypeID traitID))
184
      : name(name), dialect(dialect), typeID(typeID),
185
        parseAssembly(parseAssembly), printAssembly(printAssembly),
186
        verifyInvariants(verifyInvariants), foldHook(foldHook),
187
        getCanonicalizationPatterns(getCanonicalizationPatterns),
188
        opProperties(opProperties), getRawInterface(getRawInterface),
189
0
        hasRawTrait(hasTrait) {}
190
191
  /// The properties of the operation.
192
  const OperationProperties opProperties;
193
194
  /// Returns a raw instance of the concept for the given interface id if it is
195
  /// registered to this operation, nullptr otherwise. This should not be used
196
  /// directly.
197
  void *(&getRawInterface)(TypeID interfaceID);
198
199
  /// This hook returns if the operation contains the trait corresponding
200
  /// to the given TypeID.
201
  bool (&hasRawTrait)(TypeID traitID);
202
};
203
204
//===----------------------------------------------------------------------===//
205
// NamedAttrList
206
//===----------------------------------------------------------------------===//
207
208
/// NamedAttrList is array of NamedAttributes that tracks whether it is sorted
209
/// and does some basic work to remain sorted.
210
class NamedAttrList {
211
public:
212
  using const_iterator = SmallVectorImpl<NamedAttribute>::const_iterator;
213
  using const_reference = const NamedAttribute &;
214
  using reference = NamedAttribute &;
215
  using size_type = size_t;
216
217
0
  NamedAttrList() : dictionarySorted({}, true) {}
218
  NamedAttrList(ArrayRef<NamedAttribute> attributes);
219
  NamedAttrList(const_iterator in_start, const_iterator in_end);
220
221
0
  bool operator!=(const NamedAttrList &other) const {
222
0
    return !(*this == other);
223
0
  }
224
0
  bool operator==(const NamedAttrList &other) const {
225
0
    return attrs == other.attrs;
226
0
  }
227
228
  /// Add an attribute with the specified name.
229
  void append(StringRef name, Attribute attr);
230
231
  /// Add an attribute with the specified name.
232
  void append(Identifier name, Attribute attr);
233
234
  /// Add an array of named attributes.
235
  void append(ArrayRef<NamedAttribute> newAttributes);
236
237
  /// Add a range of named attributes.
238
  void append(const_iterator in_start, const_iterator in_end);
239
240
  /// Replaces the attributes with new list of attributes.
241
  void assign(const_iterator in_start, const_iterator in_end);
242
243
  /// Replaces the attributes with new list of attributes.
244
0
  void assign(ArrayRef<NamedAttribute> range) {
245
0
    append(range.begin(), range.end());
246
0
  }
247
248
0
  bool empty() const { return attrs.empty(); }
249
250
0
  void reserve(size_type N) { attrs.reserve(N); }
251
252
  /// Add an attribute with the specified name.
253
  void push_back(NamedAttribute newAttribute);
254
255
  /// Pop last element from list.
256
0
  void pop_back() { attrs.pop_back(); }
257
258
  /// Return a dictionary attribute for the underlying dictionary. This will
259
  /// return an empty dictionary attribute if empty rather than null.
260
  DictionaryAttr getDictionary(MLIRContext *context) const;
261
262
  /// Return all of the attributes on this operation.
263
  ArrayRef<NamedAttribute> getAttrs() const;
264
265
  /// Return the specified attribute if present, null otherwise.
266
  Attribute get(Identifier name) const;
267
  Attribute get(StringRef name) const;
268
269
  /// Return the specified named attribute if present, None otherwise.
270
  Optional<NamedAttribute> getNamed(StringRef name) const;
271
  Optional<NamedAttribute> getNamed(Identifier name) const;
272
273
  /// If the an attribute exists with the specified name, change it to the new
274
  /// value.  Otherwise, add a new attribute with the specified name/value.
275
  void set(Identifier name, Attribute value);
276
  void set(StringRef name, Attribute value);
277
278
0
  const_iterator begin() const { return attrs.begin(); }
279
0
  const_iterator end() const { return attrs.end(); }
280
281
  NamedAttrList &operator=(const SmallVectorImpl<NamedAttribute> &rhs);
282
  operator ArrayRef<NamedAttribute>() const;
283
  operator MutableDictionaryAttr() const;
284
285
private:
286
  /// Return whether the attributes are sorted.
287
0
  bool isSorted() const { return dictionarySorted.getInt(); }
288
289
  // These are marked mutable as they may be modified (e.g., sorted)
290
  mutable SmallVector<NamedAttribute, 4> attrs;
291
  // Pair with cached DictionaryAttr and status of whether attrs is sorted.
292
  // Note: just because sorted does not mean a DictionaryAttr has been created
293
  // but the case where there is a DictionaryAttr but attrs isn't sorted should
294
  // not occur.
295
  mutable llvm::PointerIntPair<Attribute, 1, bool> dictionarySorted;
296
};
297
298
//===----------------------------------------------------------------------===//
299
// OperationName
300
//===----------------------------------------------------------------------===//
301
302
class OperationName {
303
public:
304
  using RepresentationUnion =
305
      PointerUnion<Identifier, const AbstractOperation *>;
306
307
0
  OperationName(AbstractOperation *op) : representation(op) {}
308
  OperationName(StringRef name, MLIRContext *context);
309
310
  /// Return the name of the dialect this operation is registered to.
311
  StringRef getDialect() const;
312
313
  /// Return the name of this operation.  This always succeeds.
314
  StringRef getStringRef() const;
315
316
  /// If this operation has a registered operation description, return it.
317
  /// Otherwise return null.
318
  const AbstractOperation *getAbstractOperation() const;
319
320
  void print(raw_ostream &os) const;
321
  void dump() const;
322
323
0
  void *getAsOpaquePointer() const {
324
0
    return static_cast<void *>(representation.getOpaqueValue());
325
0
  }
326
  static OperationName getFromOpaquePointer(void *pointer);
327
328
private:
329
  RepresentationUnion representation;
330
  OperationName(RepresentationUnion representation)
331
0
      : representation(representation) {}
332
};
333
334
0
inline raw_ostream &operator<<(raw_ostream &os, OperationName identifier) {
335
0
  identifier.print(os);
336
0
  return os;
337
0
}
338
339
0
inline bool operator==(OperationName lhs, OperationName rhs) {
340
0
  return lhs.getAsOpaquePointer() == rhs.getAsOpaquePointer();
341
0
}
342
343
0
inline bool operator!=(OperationName lhs, OperationName rhs) {
344
0
  return lhs.getAsOpaquePointer() != rhs.getAsOpaquePointer();
345
0
}
346
347
// Make operation names hashable.
348
0
inline llvm::hash_code hash_value(OperationName arg) {
349
0
  return llvm::hash_value(arg.getAsOpaquePointer());
350
0
}
351
352
//===----------------------------------------------------------------------===//
353
// OperationState
354
//===----------------------------------------------------------------------===//
355
356
/// This represents an operation in an abstracted form, suitable for use with
357
/// the builder APIs.  This object is a large and heavy weight object meant to
358
/// be used as a temporary object on the stack.  It is generally unwise to put
359
/// this in a collection.
360
struct OperationState {
361
  Location location;
362
  OperationName name;
363
  SmallVector<Value, 4> operands;
364
  /// Types of the results of this operation.
365
  SmallVector<Type, 4> types;
366
  NamedAttrList attributes;
367
  /// Successors of this operation and their respective operands.
368
  SmallVector<Block *, 1> successors;
369
  /// Regions that the op will hold.
370
  SmallVector<std::unique_ptr<Region>, 1> regions;
371
372
public:
373
  OperationState(Location location, StringRef name);
374
375
  OperationState(Location location, OperationName name);
376
377
  OperationState(Location location, StringRef name, ValueRange operands,
378
                 ArrayRef<Type> types, ArrayRef<NamedAttribute> attributes,
379
                 ArrayRef<Block *> successors = {},
380
                 MutableArrayRef<std::unique_ptr<Region>> regions = {});
381
382
  void addOperands(ValueRange newOperands);
383
384
0
  void addTypes(ArrayRef<Type> newTypes) {
385
0
    types.append(newTypes.begin(), newTypes.end());
386
0
  }
387
  template <typename RangeT>
388
  std::enable_if_t<!std::is_convertible<RangeT, ArrayRef<Type>>::value>
389
  addTypes(RangeT &&newTypes) {
390
    types.append(newTypes.begin(), newTypes.end());
391
  }
392
393
  /// Add an attribute with the specified name.
394
0
  void addAttribute(StringRef name, Attribute attr) {
395
0
    addAttribute(Identifier::get(name, getContext()), attr);
396
0
  }
397
398
  /// Add an attribute with the specified name.
399
0
  void addAttribute(Identifier name, Attribute attr) {
400
0
    attributes.append(name, attr);
401
0
  }
402
403
  /// Add an array of named attributes.
404
0
  void addAttributes(ArrayRef<NamedAttribute> newAttributes) {
405
0
    attributes.append(newAttributes);
406
0
  }
407
408
  /// Add an array of successors.
409
0
  void addSuccessors(ArrayRef<Block *> newSuccessors) {
410
0
    successors.append(newSuccessors.begin(), newSuccessors.end());
411
0
  }
412
0
  void addSuccessors(Block *successor) { successors.push_back(successor); }
413
  void addSuccessors(SuccessorRange newSuccessors);
414
415
  /// Create a region that should be attached to the operation.  These regions
416
  /// can be filled in immediately without waiting for Operation to be
417
  /// created.  When it is, the region bodies will be transferred.
418
  Region *addRegion();
419
420
  /// Take a region that should be attached to the Operation.  The body of the
421
  /// region will be transferred when the Operation is constructed.  If the
422
  /// region is null, a new empty region will be attached to the Operation.
423
  void addRegion(std::unique_ptr<Region> &&region);
424
425
  /// Get the context held by this operation state.
426
0
  MLIRContext *getContext() const { return location->getContext(); }
427
};
428
429
//===----------------------------------------------------------------------===//
430
// OperandStorage
431
//===----------------------------------------------------------------------===//
432
433
namespace detail {
434
/// This class contains the information for a trailing operand storage.
435
struct TrailingOperandStorage final
436
    : public llvm::TrailingObjects<TrailingOperandStorage, OpOperand> {
437
0
  ~TrailingOperandStorage() {
438
0
    for (auto &operand : getOperands())
439
0
      operand.~OpOperand();
440
0
  }
441
442
  /// Return the operands held by this storage.
443
0
  MutableArrayRef<OpOperand> getOperands() {
444
0
    return {getTrailingObjects<OpOperand>(), numOperands};
445
0
  }
446
447
  /// The number of operands within the storage.
448
  unsigned numOperands;
449
  /// The total capacity number of operands that the storage can hold.
450
  unsigned capacity : 31;
451
  /// We reserve a range of bits for use by the operand storage.
452
  unsigned reserved : 1;
453
};
454
455
/// This class handles the management of operation operands. Operands are
456
/// stored either in a trailing array, or a dynamically resizable vector.
457
class OperandStorage final
458
    : private llvm::TrailingObjects<OperandStorage, OpOperand> {
459
public:
460
  OperandStorage(Operation *owner, ValueRange values);
461
  ~OperandStorage();
462
463
  /// Replace the operands contained in the storage with the ones provided in
464
  /// 'values'.
465
  void setOperands(Operation *owner, ValueRange values);
466
467
  /// Replace the operands beginning at 'start' and ending at 'start' + 'length'
468
  /// with the ones provided in 'operands'. 'operands' may be smaller or larger
469
  /// than the range pointed to by 'start'+'length'.
470
  void setOperands(Operation *owner, unsigned start, unsigned length,
471
                   ValueRange operands);
472
473
  /// Erase the operands held by the storage within the given range.
474
  void eraseOperands(unsigned start, unsigned length);
475
476
  /// Get the operation operands held by the storage.
477
0
  MutableArrayRef<OpOperand> getOperands() {
478
0
    return getStorage().getOperands();
479
0
  }
480
481
  /// Return the number of operands held in the storage.
482
0
  unsigned size() { return getStorage().numOperands; }
483
484
  /// Returns the additional size necessary for allocating this object.
485
0
  static size_t additionalAllocSize(unsigned numOperands) {
486
0
    return additionalSizeToAlloc<OpOperand>(numOperands);
487
0
  }
488
489
private:
490
  enum : uint64_t {
491
    /// The bit used to mark the storage as dynamic.
492
    DynamicStorageBit = 1ull << 63ull
493
  };
494
495
  /// Resize the storage to the given size. Returns the array containing the new
496
  /// operands.
497
  MutableArrayRef<OpOperand> resize(Operation *owner, unsigned newSize);
498
499
  /// Returns the current internal storage instance.
500
0
  TrailingOperandStorage &getStorage() {
501
0
    return LLVM_UNLIKELY(isDynamicStorage()) ? getDynamicStorage()
502
0
                                             : getInlineStorage();
503
0
  }
504
505
  /// Returns the storage container if the storage is inline.
506
0
  TrailingOperandStorage &getInlineStorage() {
507
0
    assert(!isDynamicStorage() && "expected storage to be inline");
508
0
    static_assert(sizeof(TrailingOperandStorage) == sizeof(uint64_t),
509
0
                  "inline storage representation must match the opaque "
510
0
                  "representation");
511
0
    return inlineStorage;
512
0
  }
513
514
  /// Returns the storage container if this storage is dynamic.
515
0
  TrailingOperandStorage &getDynamicStorage() {
516
0
    assert(isDynamicStorage() && "expected dynamic storage");
517
0
    uint64_t maskedRepresentation = representation & ~DynamicStorageBit;
518
0
    return *reinterpret_cast<TrailingOperandStorage *>(maskedRepresentation);
519
0
  }
520
521
  /// Returns true if the storage is currently dynamic.
522
0
  bool isDynamicStorage() const { return representation & DynamicStorageBit; }
523
524
  /// The current representation of the storage. This is either a
525
  /// InlineOperandStorage, or a pointer to a InlineOperandStorage.
526
  union {
527
    TrailingOperandStorage inlineStorage;
528
    uint64_t representation;
529
  };
530
531
  /// This stuff is used by the TrailingObjects template.
532
  friend llvm::TrailingObjects<OperandStorage, OpOperand>;
533
};
534
} // end namespace detail
535
536
//===----------------------------------------------------------------------===//
537
// ResultStorage
538
//===----------------------------------------------------------------------===//
539
540
namespace detail {
541
/// This class provides the implementation for an in-line operation result. This
542
/// is an operation result whose number can be stored inline inside of the bits
543
/// of an Operation*.
544
struct InLineOpResult : public IRObjectWithUseList<OpOperand> {};
545
/// This class provides the implementation for an out-of-line operation result.
546
/// This is an operation result whose number cannot be stored inline inside of
547
/// the bits of an Operation*.
548
struct TrailingOpResult : public IRObjectWithUseList<OpOperand> {
549
  TrailingOpResult(uint64_t trailingResultNumber)
550
0
      : trailingResultNumber(trailingResultNumber) {}
551
552
  /// Returns the parent operation of this trailing result.
553
  Operation *getOwner();
554
555
  /// Return the proper result number of this op result.
556
0
  unsigned getResultNumber() {
557
0
    return trailingResultNumber + OpResult::getMaxInlineResults();
558
0
  }
559
560
  /// The trailing result number, or the offset from the beginning of the
561
  /// trailing array.
562
  uint64_t trailingResultNumber;
563
};
564
} // end namespace detail
565
566
//===----------------------------------------------------------------------===//
567
// OpPrintingFlags
568
//===----------------------------------------------------------------------===//
569
570
/// Set of flags used to control the behavior of the various IR print methods
571
/// (e.g. Operation::Print).
572
class OpPrintingFlags {
573
public:
574
  OpPrintingFlags();
575
0
  OpPrintingFlags(llvm::NoneType) : OpPrintingFlags() {}
576
577
  /// Enable the elision of large elements attributes, by printing a '...'
578
  /// instead of the element data. Note: The IR generated with this option is
579
  /// not parsable. `largeElementLimit` is used to configure what is considered
580
  /// to be a "large" ElementsAttr by providing an upper limit to the number of
581
  /// elements.
582
  OpPrintingFlags &elideLargeElementsAttrs(int64_t largeElementLimit = 16);
583
584
  /// Enable printing of debug information. If 'prettyForm' is set to true,
585
  /// debug information is printed in a more readable 'pretty' form. Note: The
586
  /// IR generated with 'prettyForm' is not parsable.
587
  OpPrintingFlags &enableDebugInfo(bool prettyForm = false);
588
589
  /// Always print operations in the generic form.
590
  OpPrintingFlags &printGenericOpForm();
591
592
  /// Use local scope when printing the operation. This allows for using the
593
  /// printer in a more localized and thread-safe setting, but may not
594
  /// necessarily be identical to what the IR will look like when dumping
595
  /// the full module.
596
  OpPrintingFlags &useLocalScope();
597
598
  /// Return if the given ElementsAttr should be elided.
599
  bool shouldElideElementsAttr(ElementsAttr attr) const;
600
601
  /// Return the size limit for printing large ElementsAttr.
602
  Optional<int64_t> getLargeElementsAttrLimit() const;
603
604
  /// Return if debug information should be printed.
605
  bool shouldPrintDebugInfo() const;
606
607
  /// Return if debug information should be printed in the pretty form.
608
  bool shouldPrintDebugInfoPrettyForm() const;
609
610
  /// Return if operations should be printed in the generic form.
611
  bool shouldPrintGenericOpForm() const;
612
613
  /// Return if the printer should use local scope when dumping the IR.
614
  bool shouldUseLocalScope() const;
615
616
private:
617
  /// Elide large elements attributes if the number of elements is larger than
618
  /// the upper limit.
619
  Optional<int64_t> elementsAttrElementLimit;
620
621
  /// Print debug information.
622
  bool printDebugInfoFlag : 1;
623
  bool printDebugInfoPrettyFormFlag : 1;
624
625
  /// Print operations in the generic form.
626
  bool printGenericOpFormFlag : 1;
627
628
  /// Print operations with numberings local to the current operation.
629
  bool printLocalScope : 1;
630
};
631
632
//===----------------------------------------------------------------------===//
633
// Operation Value-Iterators
634
//===----------------------------------------------------------------------===//
635
636
//===----------------------------------------------------------------------===//
637
// TypeRange
638
639
/// This class provides an abstraction over the various different ranges of
640
/// value types. In many cases, this prevents the need to explicitly materialize
641
/// a SmallVector/std::vector. This class should be used in places that are not
642
/// suitable for a more derived type (e.g. ArrayRef) or a template range
643
/// parameter.
644
class TypeRange
645
    : public llvm::detail::indexed_accessor_range_base<
646
          TypeRange,
647
          llvm::PointerUnion<const Value *, const Type *, OpOperand *>, Type,
648
          Type, Type> {
649
public:
650
  using RangeBaseT::RangeBaseT;
651
  TypeRange(ArrayRef<Type> types = llvm::None);
652
  explicit TypeRange(OperandRange values);
653
  explicit TypeRange(ResultRange values);
654
  explicit TypeRange(ValueRange values);
655
  explicit TypeRange(ArrayRef<Value> values);
656
  explicit TypeRange(ArrayRef<BlockArgument> values)
657
0
      : TypeRange(ArrayRef<Value>(values.data(), values.size())) {}
658
  template <typename ValueRangeT>
659
  TypeRange(ValueTypeRange<ValueRangeT> values)
660
      : TypeRange(ValueRangeT(values.begin().getCurrent(),
661
                              values.end().getCurrent())) {}
662
  template <typename Arg,
663
            typename = typename std::enable_if_t<
664
                std::is_constructible<ArrayRef<Type>, Arg>::value>>
665
0
  TypeRange(Arg &&arg) : TypeRange(ArrayRef<Type>(std::forward<Arg>(arg))) {}
666
  TypeRange(std::initializer_list<Type> types)
667
0
      : TypeRange(ArrayRef<Type>(types)) {}
668
669
private:
670
  /// The owner of the range is either:
671
  /// * A pointer to the first element of an array of values.
672
  /// * A pointer to the first element of an array of types.
673
  /// * A pointer to the first element of an array of operands.
674
  using OwnerT = llvm::PointerUnion<const Value *, const Type *, OpOperand *>;
675
676
  /// See `llvm::detail::indexed_accessor_range_base` for details.
677
  static OwnerT offset_base(OwnerT object, ptrdiff_t index);
678
  /// See `llvm::detail::indexed_accessor_range_base` for details.
679
  static Type dereference_iterator(OwnerT object, ptrdiff_t index);
680
681
  /// Allow access to `offset_base` and `dereference_iterator`.
682
  friend RangeBaseT;
683
};
684
685
//===----------------------------------------------------------------------===//
686
// ValueTypeRange
687
688
/// This class implements iteration on the types of a given range of values.
689
template <typename ValueIteratorT>
690
class ValueTypeIterator final
691
    : public llvm::mapped_iterator<ValueIteratorT, Type (*)(Value)> {
692
0
  static Type unwrap(Value value) { return value.getType(); }
Unexecuted instantiation: _ZN4mlir17ValueTypeIteratorIN4llvm6detail27indexed_accessor_range_baseINS_12OperandRangeEPNS_9OpOperandENS_5ValueES7_S7_E8iteratorEE6unwrapES7_
Unexecuted instantiation: _ZN4mlir17ValueTypeIteratorIN4llvm6detail27indexed_accessor_range_baseINS_10ValueRangeENS_6detail15ValueRangeOwnerENS_5ValueES7_S7_E8iteratorEE6unwrapES7_
Unexecuted instantiation: _ZN4mlir17ValueTypeIteratorIPNS_13BlockArgumentEE6unwrapENS_5ValueE
693
694
public:
695
  using reference = Type;
696
697
  /// Provide a const dereference method.
698
0
  Type operator*() const { return unwrap(*this->I); }
Unexecuted instantiation: _ZNK4mlir17ValueTypeIteratorIN4llvm6detail27indexed_accessor_range_baseINS_12OperandRangeEPNS_9OpOperandENS_5ValueES7_S7_E8iteratorEEdeEv
Unexecuted instantiation: _ZNK4mlir17ValueTypeIteratorIN4llvm6detail27indexed_accessor_range_baseINS_10ValueRangeENS_6detail15ValueRangeOwnerENS_5ValueES7_S7_E8iteratorEEdeEv
699
700
  /// Initializes the type iterator to the specified value iterator.
701
  ValueTypeIterator(ValueIteratorT it)
702
0
      : llvm::mapped_iterator<ValueIteratorT, Type (*)(Value)>(it, &unwrap) {}
Unexecuted instantiation: _ZN4mlir17ValueTypeIteratorIN4llvm6detail27indexed_accessor_range_baseINS_12OperandRangeEPNS_9OpOperandENS_5ValueES7_S7_E8iteratorEEC2ES9_
Unexecuted instantiation: _ZN4mlir17ValueTypeIteratorIN4llvm6detail27indexed_accessor_range_baseINS_10ValueRangeENS_6detail15ValueRangeOwnerENS_5ValueES7_S7_E8iteratorEEC2ES9_
Unexecuted instantiation: _ZN4mlir17ValueTypeIteratorIPNS_13BlockArgumentEEC2ES2_
703
};
704
705
/// This class implements iteration on the types of a given range of values.
706
template <typename ValueRangeT>
707
class ValueTypeRange final
708
    : public llvm::iterator_range<
709
          ValueTypeIterator<typename ValueRangeT::iterator>> {
710
public:
711
  using llvm::iterator_range<
712
      ValueTypeIterator<typename ValueRangeT::iterator>>::iterator_range;
713
  template <typename Container>
714
0
  ValueTypeRange(Container &&c) : ValueTypeRange(c.begin(), c.end()) {}
715
716
  /// Compare this range with another.
717
  template <typename OtherT>
718
  bool operator==(const OtherT &other) const {
719
    return llvm::size(*this) == llvm::size(other) &&
720
           std::equal(this->begin(), this->end(), other.begin());
721
  }
722
  template <typename OtherT>
723
  bool operator!=(const OtherT &other) const {
724
    return !(*this == other);
725
  }
726
};
727
728
template <typename RangeT>
729
0
inline bool operator==(ArrayRef<Type> lhs, const ValueTypeRange<RangeT> &rhs) {
730
0
  return lhs.size() == static_cast<size_t>(llvm::size(rhs)) &&
731
0
         std::equal(lhs.begin(), lhs.end(), rhs.begin());
732
0
}
733
734
//===----------------------------------------------------------------------===//
735
// OperandRange
736
737
/// This class implements the operand iterators for the Operation class.
738
class OperandRange final : public llvm::detail::indexed_accessor_range_base<
739
                               OperandRange, OpOperand *, Value, Value, Value> {
740
public:
741
  using RangeBaseT::RangeBaseT;
742
  OperandRange(Operation *op);
743
744
  /// Returns the types of the values within this range.
745
  using type_iterator = ValueTypeIterator<iterator>;
746
  using type_range = ValueTypeRange<OperandRange>;
747
0
  type_range getTypes() const { return {begin(), end()}; }
748
0
  auto getType() const { return getTypes(); }
749
750
  /// Return the operand index of the first element of this range. The range
751
  /// must not be empty.
752
  unsigned getBeginOperandIndex() const;
753
754
private:
755
  /// See `llvm::detail::indexed_accessor_range_base` for details.
756
0
  static OpOperand *offset_base(OpOperand *object, ptrdiff_t index) {
757
0
    return object + index;
758
0
  }
759
  /// See `llvm::detail::indexed_accessor_range_base` for details.
760
0
  static Value dereference_iterator(OpOperand *object, ptrdiff_t index) {
761
0
    return object[index].get();
762
0
  }
763
764
  /// Allow access to `offset_base` and `dereference_iterator`.
765
  friend RangeBaseT;
766
};
767
768
//===----------------------------------------------------------------------===//
769
// MutableOperandRange
770
771
/// This class provides a mutable adaptor for a range of operands. It allows for
772
/// setting, inserting, and erasing operands from the given range.
773
class MutableOperandRange {
774
public:
775
  /// A pair of a named attribute corresponding to an operand segment attribute,
776
  /// and the index within that attribute. The attribute should correspond to an
777
  /// i32 DenseElementsAttr.
778
  using OperandSegment = std::pair<unsigned, NamedAttribute>;
779
780
  /// Construct a new mutable range from the given operand, operand start index,
781
  /// and range length. `operandSegments` is an optional set of operand segments
782
  /// to be updated when mutating the operand list.
783
  MutableOperandRange(Operation *owner, unsigned start, unsigned length,
784
                      ArrayRef<OperandSegment> operandSegments = llvm::None);
785
  MutableOperandRange(Operation *owner);
786
787
  /// Slice this range into a sub range, with the additional operand segment.
788
  MutableOperandRange slice(unsigned subStart, unsigned subLen,
789
                            Optional<OperandSegment> segment = llvm::None);
790
791
  /// Append the given values to the range.
792
  void append(ValueRange values);
793
794
  /// Assign this range to the given values.
795
  void assign(ValueRange values);
796
797
  /// Assign the range to the given value.
798
  void assign(Value value);
799
800
  /// Erase the operands within the given sub-range.
801
  void erase(unsigned subStart, unsigned subLen = 1);
802
803
  /// Clear this range and erase all of the operands.
804
  void clear();
805
806
  /// Returns the current size of the range.
807
0
  unsigned size() const { return length; }
808
809
  /// Allow implicit conversion to an OperandRange.
810
  operator OperandRange() const;
811
812
  /// Returns the owning operation.
813
0
  Operation *getOwner() const { return owner; }
814
815
private:
816
  /// Update the length of this range to the one provided.
817
  void updateLength(unsigned newLength);
818
819
  /// The owning operation of this range.
820
  Operation *owner;
821
822
  /// The start index of the operand range within the owner operand list, and
823
  /// the length starting from `start`.
824
  unsigned start, length;
825
826
  /// Optional set of operand segments that should be updated when mutating the
827
  /// length of this range.
828
  SmallVector<std::pair<unsigned, NamedAttribute>, 1> operandSegments;
829
};
830
831
//===----------------------------------------------------------------------===//
832
// ResultRange
833
834
/// This class implements the result iterators for the Operation class.
835
class ResultRange final
836
    : public llvm::indexed_accessor_range<ResultRange, Operation *, OpResult,
837
                                          OpResult, OpResult> {
838
public:
839
  using indexed_accessor_range<ResultRange, Operation *, OpResult, OpResult,
840
                               OpResult>::indexed_accessor_range;
841
  ResultRange(Operation *op);
842
843
  /// Returns the types of the values within this range.
844
  using type_iterator = ArrayRef<Type>::iterator;
845
  using type_range = ArrayRef<Type>;
846
  type_range getTypes() const;
847
0
  auto getType() const { return getTypes(); }
848
849
private:
850
  /// See `llvm::indexed_accessor_range` for details.
851
  static OpResult dereference(Operation *op, ptrdiff_t index);
852
853
  /// Allow access to `dereference_iterator`.
854
  friend llvm::indexed_accessor_range<ResultRange, Operation *, OpResult,
855
                                      OpResult, OpResult>;
856
};
857
858
//===----------------------------------------------------------------------===//
859
// ValueRange
860
861
namespace detail {
862
/// The type representing the owner of a ValueRange. This is either a list of
863
/// values, operands, or an Operation+start index for results.
864
struct ValueRangeOwner {
865
0
  ValueRangeOwner(const Value *owner) : ptr(owner), startIndex(0) {}
866
0
  ValueRangeOwner(OpOperand *owner) : ptr(owner), startIndex(0) {}
867
  ValueRangeOwner(Operation *owner, unsigned startIndex)
868
0
      : ptr(owner), startIndex(startIndex) {}
869
0
  bool operator==(const ValueRangeOwner &rhs) const { return ptr == rhs.ptr; }
870
871
  /// The owner pointer of the range. The owner has represents three distinct
872
  /// states:
873
  /// const Value *: The owner is the base to a contiguous array of Value.
874
  /// OpOperand *  : The owner is the base to a contiguous array of operands.
875
  /// void*        : This owner is an Operation*. It is marked as void* here
876
  ///                because the definition of Operation is not visible here.
877
  PointerUnion<const Value *, OpOperand *, void *> ptr;
878
879
  /// Ths start index into the range. This is only used for Operation* owners.
880
  unsigned startIndex;
881
};
882
} // end namespace detail
883
884
/// This class provides an abstraction over the different types of ranges over
885
/// Values. In many cases, this prevents the need to explicitly materialize a
886
/// SmallVector/std::vector. This class should be used in places that are not
887
/// suitable for a more derived type (e.g. ArrayRef) or a template range
888
/// parameter.
889
class ValueRange final
890
    : public llvm::detail::indexed_accessor_range_base<
891
          ValueRange, detail::ValueRangeOwner, Value, Value, Value> {
892
public:
893
  using RangeBaseT::RangeBaseT;
894
895
  template <typename Arg,
896
            typename = typename std::enable_if_t<
897
                std::is_constructible<ArrayRef<Value>, Arg>::value &&
898
                !std::is_convertible<Arg, Value>::value>>
899
0
  ValueRange(Arg &&arg) : ValueRange(ArrayRef<Value>(std::forward<Arg>(arg))) {}
Unexecuted instantiation: _ZN4mlir10ValueRangeC2IRN4llvm11SmallVectorINS_5ValueELj4EEEvEEOT_
Unexecuted instantiation: _ZN4mlir10ValueRangeC2IRN4llvm11SmallVectorINS_5ValueELj8EEEvEEOT_
Unexecuted instantiation: _ZN4mlir10ValueRangeC2IRN4llvm11SmallVectorINS_5ValueELj2EEEvEEOT_
Unexecuted instantiation: _ZN4mlir10ValueRangeC2IRN4llvm15SmallVectorImplINS_5ValueEEEvEEOT_
Unexecuted instantiation: _ZN4mlir10ValueRangeC2IRKN4llvm8NoneTypeEvEEOT_
900
0
  ValueRange(const Value &value) : ValueRange(&value, /*count=*/1) {}
901
  ValueRange(const std::initializer_list<Value> &values)
902
0
      : ValueRange(ArrayRef<Value>(values)) {}
903
  ValueRange(iterator_range<OperandRange::iterator> values)
904
0
      : ValueRange(OperandRange(values)) {}
905
  ValueRange(iterator_range<ResultRange::iterator> values)
906
0
      : ValueRange(ResultRange(values)) {}
907
  ValueRange(ArrayRef<BlockArgument> values)
908
0
      : ValueRange(ArrayRef<Value>(values.data(), values.size())) {}
909
  ValueRange(ArrayRef<Value> values = llvm::None);
910
  ValueRange(OperandRange values);
911
  ValueRange(ResultRange values);
912
913
  /// Returns the types of the values within this range.
914
  using type_iterator = ValueTypeIterator<iterator>;
915
  using type_range = ValueTypeRange<ValueRange>;
916
0
  type_range getTypes() const { return {begin(), end()}; }
917
0
  auto getType() const { return getTypes(); }
918
919
private:
920
  using OwnerT = detail::ValueRangeOwner;
921
922
  /// See `llvm::detail::indexed_accessor_range_base` for details.
923
  static OwnerT offset_base(const OwnerT &owner, ptrdiff_t index);
924
  /// See `llvm::detail::indexed_accessor_range_base` for details.
925
  static Value dereference_iterator(const OwnerT &owner, ptrdiff_t index);
926
927
  /// Allow access to `offset_base` and `dereference_iterator`.
928
  friend RangeBaseT;
929
};
930
931
//===----------------------------------------------------------------------===//
932
// Operation Equivalency
933
//===----------------------------------------------------------------------===//
934
935
/// This class provides utilities for computing if two operations are
936
/// equivalent.
937
struct OperationEquivalence {
938
  enum Flags {
939
    None = 0,
940
941
    /// This flag signals that operands should not be considered when checking
942
    /// for equivalence. This allows for users to implement there own
943
    /// equivalence schemes for operand values. The number of operands are still
944
    /// checked, just not the operands themselves.
945
    IgnoreOperands = 1,
946
947
    LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ IgnoreOperands)
948
  };
949
950
  /// Compute a hash for the given operation.
951
  static llvm::hash_code computeHash(Operation *op, Flags flags = Flags::None);
952
953
  /// Compare two operations and return if they are equivalent.
954
  static bool isEquivalentTo(Operation *lhs, Operation *rhs,
955
                             Flags flags = Flags::None);
956
};
957
958
/// Enable Bitmask enums for OperationEquivalence::Flags.
959
LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
960
961
} // end namespace mlir
962
963
namespace llvm {
964
// Identifiers hash just like pointers, there is no need to hash the bytes.
965
template <> struct DenseMapInfo<mlir::OperationName> {
966
0
  static mlir::OperationName getEmptyKey() {
967
0
    auto pointer = llvm::DenseMapInfo<void *>::getEmptyKey();
968
0
    return mlir::OperationName::getFromOpaquePointer(pointer);
969
0
  }
970
0
  static mlir::OperationName getTombstoneKey() {
971
0
    auto pointer = llvm::DenseMapInfo<void *>::getTombstoneKey();
972
0
    return mlir::OperationName::getFromOpaquePointer(pointer);
973
0
  }
974
0
  static unsigned getHashValue(mlir::OperationName Val) {
975
0
    return DenseMapInfo<void *>::getHashValue(Val.getAsOpaquePointer());
976
0
  }
977
0
  static bool isEqual(mlir::OperationName LHS, mlir::OperationName RHS) {
978
0
    return LHS == RHS;
979
0
  }
980
};
981
982
/// The pointer inside of an identifier comes from a StringMap, so its alignment
983
/// is always at least 4 and probably 8 (on 64-bit machines).  Allow LLVM to
984
/// steal the low bits.
985
template <> struct PointerLikeTypeTraits<mlir::OperationName> {
986
public:
987
0
  static inline void *getAsVoidPointer(mlir::OperationName I) {
988
0
    return const_cast<void *>(I.getAsOpaquePointer());
989
0
  }
990
0
  static inline mlir::OperationName getFromVoidPointer(void *P) {
991
0
    return mlir::OperationName::getFromOpaquePointer(P);
992
0
  }
993
  static constexpr int NumLowBitsAvailable = PointerLikeTypeTraits<
994
      mlir::OperationName::RepresentationUnion>::NumLowBitsAvailable;
995
};
996
997
} // end namespace llvm
998
999
#endif