1 //===- Attributes.cpp - MLIR Affine Expr Classes --------------------------===//
2 //
3 // Copyright 2019 The MLIR Authors.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //   http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 // =============================================================================
17 
18 #include "mlir/IR/Attributes.h"
19 #include "AttributeDetail.h"
20 #include "mlir/IR/AffineMap.h"
21 #include "mlir/IR/Diagnostics.h"
22 #include "mlir/IR/Dialect.h"
23 #include "mlir/IR/Function.h"
24 #include "mlir/IR/IntegerSet.h"
25 #include "mlir/IR/Types.h"
26 #include "llvm/ADT/Sequence.h"
27 #include "llvm/ADT/Twine.h"
28 
29 using namespace mlir;
30 using namespace mlir::detail;
31 
32 //===----------------------------------------------------------------------===//
33 // AttributeStorage
34 //===----------------------------------------------------------------------===//
35 
36 AttributeStorage::AttributeStorage(Type type)
37     : type(type.getAsOpaquePointer()) {}
38 AttributeStorage::AttributeStorage() : type(nullptr) {}
39 
40 Type AttributeStorage::getType() const {
41   return Type::getFromOpaquePointer(type);
42 }
43 void AttributeStorage::setType(Type newType) {
44   type = newType.getAsOpaquePointer();
45 }
46 
47 //===----------------------------------------------------------------------===//
48 // Attribute
49 //===----------------------------------------------------------------------===//
50 
51 /// Return the type of this attribute.
52 Type Attribute::getType() const { return impl->getType(); }
53 
54 /// Return the context this attribute belongs to.
55 MLIRContext *Attribute::getContext() const { return getType().getContext(); }
56 
57 /// Get the dialect this attribute is registered to.
58 Dialect &Attribute::getDialect() const { return impl->getDialect(); }
59 
60 //===----------------------------------------------------------------------===//
61 // AffineMapAttr
62 //===----------------------------------------------------------------------===//
63 
64 AffineMapAttr AffineMapAttr::get(AffineMap value) {
65   return Base::get(value.getContext(), StandardAttributes::AffineMap, value);
66 }
67 
68 AffineMap AffineMapAttr::getValue() const { return getImpl()->value; }
69 
70 //===----------------------------------------------------------------------===//
71 // ArrayAttr
72 //===----------------------------------------------------------------------===//
73 
74 ArrayAttr ArrayAttr::get(ArrayRef<Attribute> value, MLIRContext *context) {
75   return Base::get(context, StandardAttributes::Array, value);
76 }
77 
78 ArrayRef<Attribute> ArrayAttr::getValue() const { return getImpl()->value; }
79 
80 //===----------------------------------------------------------------------===//
81 // BoolAttr
82 //===----------------------------------------------------------------------===//
83 
84 bool BoolAttr::getValue() const { return getImpl()->value; }
85 
86 //===----------------------------------------------------------------------===//
87 // DictionaryAttr
88 //===----------------------------------------------------------------------===//
89 
90 /// Perform a three-way comparison between the names of the specified
91 /// NamedAttributes.
92 static int compareNamedAttributes(const NamedAttribute *lhs,
93                                   const NamedAttribute *rhs) {
94   return lhs->first.strref().compare(rhs->first.strref());
95 }
96 
97 DictionaryAttr DictionaryAttr::get(ArrayRef<NamedAttribute> value,
98                                    MLIRContext *context) {
99   assert(llvm::all_of(value,
100                       [](const NamedAttribute &attr) { return attr.second; }) &&
101          "value cannot have null entries");
102 
103   // We need to sort the element list to canonicalize it, but we also don't want
104   // to do a ton of work in the super common case where the element list is
105   // already sorted.
106   SmallVector<NamedAttribute, 8> storage;
107   switch (value.size()) {
108   case 0:
109     break;
110   case 1:
111     // A single element is already sorted.
112     break;
113   case 2:
114     assert(value[0].first != value[1].first &&
115            "DictionaryAttr element names must be unique");
116 
117     // Don't invoke a general sort for two element case.
118     if (value[0].first.strref() > value[1].first.strref()) {
119       storage.push_back(value[1]);
120       storage.push_back(value[0]);
121       value = storage;
122     }
123     break;
124   default:
125     // Check to see they are sorted already.
126     bool isSorted = true;
127     for (unsigned i = 0, e = value.size() - 1; i != e; ++i) {
128       if (value[i].first.strref() > value[i + 1].first.strref()) {
129         isSorted = false;
130         break;
131       }
132     }
133     // If not, do a general sort.
134     if (!isSorted) {
135       storage.append(value.begin(), value.end());
136       llvm::array_pod_sort(storage.begin(), storage.end(),
137                            compareNamedAttributes);
138       value = storage;
139     }
140 
141     // Ensure that the attribute elements are unique.
142     assert(std::adjacent_find(value.begin(), value.end(),
143                               [](NamedAttribute l, NamedAttribute r) {
144                                 return l.first == r.first;
145                               }) == value.end() &&
146            "DictionaryAttr element names must be unique");
147   }
148 
149   return Base::get(context, StandardAttributes::Dictionary, value);
150 }
151 
152 ArrayRef<NamedAttribute> DictionaryAttr::getValue() const {
153   return getImpl()->getElements();
154 }
155 
156 /// Return the specified attribute if present, null otherwise.
157 Attribute DictionaryAttr::get(StringRef name) const {
158   ArrayRef<NamedAttribute> values = getValue();
159   auto compare = [](NamedAttribute attr, StringRef name) {
160     return attr.first.strref() < name;
161   };
162   auto it = llvm::lower_bound(values, name, compare);
163   return it != values.end() && it->first.is(name) ? it->second : Attribute();
164 }
165 Attribute DictionaryAttr::get(Identifier name) const {
166   for (auto elt : getValue())
167     if (elt.first == name)
168       return elt.second;
169   return nullptr;
170 }
171 
172 DictionaryAttr::iterator DictionaryAttr::begin() const {
173   return getValue().begin();
174 }
175 DictionaryAttr::iterator DictionaryAttr::end() const {
176   return getValue().end();
177 }
178 size_t DictionaryAttr::size() const { return getValue().size(); }
179 
180 //===----------------------------------------------------------------------===//
181 // FloatAttr
182 //===----------------------------------------------------------------------===//
183 
184 FloatAttr FloatAttr::get(Type type, double value) {
185   return Base::get(type.getContext(), StandardAttributes::Float, type, value);
186 }
187 
188 FloatAttr FloatAttr::getChecked(Type type, double value, Location loc) {
189   return Base::getChecked(loc, type.getContext(), StandardAttributes::Float,
190                           type, value);
191 }
192 
193 FloatAttr FloatAttr::get(Type type, const APFloat &value) {
194   return Base::get(type.getContext(), StandardAttributes::Float, type, value);
195 }
196 
197 FloatAttr FloatAttr::getChecked(Type type, const APFloat &value, Location loc) {
198   return Base::getChecked(loc, type.getContext(), StandardAttributes::Float,
199                           type, value);
200 }
201 
202 APFloat FloatAttr::getValue() const { return getImpl()->getValue(); }
203 
204 double FloatAttr::getValueAsDouble() const {
205   return getValueAsDouble(getValue());
206 }
207 double FloatAttr::getValueAsDouble(APFloat value) {
208   if (&value.getSemantics() != &APFloat::IEEEdouble()) {
209     bool losesInfo = false;
210     value.convert(APFloat::IEEEdouble(), APFloat::rmNearestTiesToEven,
211                   &losesInfo);
212   }
213   return value.convertToDouble();
214 }
215 
216 /// Verify construction invariants.
217 static LogicalResult verifyFloatTypeInvariants(Optional<Location> loc,
218                                                Type type) {
219   if (!type.isa<FloatType>())
220     return emitOptionalError(loc, "expected floating point type");
221   return success();
222 }
223 
224 LogicalResult FloatAttr::verifyConstructionInvariants(Optional<Location> loc,
225                                                       MLIRContext *ctx,
226                                                       Type type, double value) {
227   return verifyFloatTypeInvariants(loc, type);
228 }
229 
230 LogicalResult FloatAttr::verifyConstructionInvariants(Optional<Location> loc,
231                                                       MLIRContext *ctx,
232                                                       Type type,
233                                                       const APFloat &value) {
234   // Verify that the type is correct.
235   if (failed(verifyFloatTypeInvariants(loc, type)))
236     return failure();
237 
238   // Verify that the type semantics match that of the value.
239   if (&type.cast<FloatType>().getFloatSemantics() != &value.getSemantics()) {
240     return emitOptionalError(
241         loc, "FloatAttr type doesn't match the type implied by its value");
242   }
243   return success();
244 }
245 
246 //===----------------------------------------------------------------------===//
247 // SymbolRefAttr
248 //===----------------------------------------------------------------------===//
249 
250 FlatSymbolRefAttr SymbolRefAttr::get(StringRef value, MLIRContext *ctx) {
251   return Base::get(ctx, StandardAttributes::SymbolRef, value, llvm::None)
252       .cast<FlatSymbolRefAttr>();
253 }
254 
255 SymbolRefAttr SymbolRefAttr::get(StringRef value,
256                                  ArrayRef<FlatSymbolRefAttr> nestedReferences,
257                                  MLIRContext *ctx) {
258   return Base::get(ctx, StandardAttributes::SymbolRef, value, nestedReferences);
259 }
260 
261 StringRef SymbolRefAttr::getRootReference() const { return getImpl()->value; }
262 
263 StringRef SymbolRefAttr::getLeafReference() const {
264   ArrayRef<FlatSymbolRefAttr> nestedRefs = getNestedReferences();
265   return nestedRefs.empty() ? getRootReference() : nestedRefs.back().getValue();
266 }
267 
268 ArrayRef<FlatSymbolRefAttr> SymbolRefAttr::getNestedReferences() const {
269   return getImpl()->getNestedRefs();
270 }
271 
272 //===----------------------------------------------------------------------===//
273 // IntegerAttr
274 //===----------------------------------------------------------------------===//
275 
276 IntegerAttr IntegerAttr::get(Type type, const APInt &value) {
277   return Base::get(type.getContext(), StandardAttributes::Integer, type, value);
278 }
279 
280 IntegerAttr IntegerAttr::get(Type type, int64_t value) {
281   // This uses 64 bit APInts by default for index type.
282   if (type.isIndex())
283     return get(type, APInt(64, value));
284 
285   auto intType = type.cast<IntegerType>();
286   return get(type, APInt(intType.getWidth(), value));
287 }
288 
289 APInt IntegerAttr::getValue() const { return getImpl()->getValue(); }
290 
291 int64_t IntegerAttr::getInt() const { return getValue().getSExtValue(); }
292 
293 //===----------------------------------------------------------------------===//
294 // IntegerSetAttr
295 //===----------------------------------------------------------------------===//
296 
297 IntegerSetAttr IntegerSetAttr::get(IntegerSet value) {
298   return Base::get(value.getConstraint(0).getContext(),
299                    StandardAttributes::IntegerSet, value);
300 }
301 
302 IntegerSet IntegerSetAttr::getValue() const { return getImpl()->value; }
303 
304 //===----------------------------------------------------------------------===//
305 // OpaqueAttr
306 //===----------------------------------------------------------------------===//
307 
308 OpaqueAttr OpaqueAttr::get(Identifier dialect, StringRef attrData, Type type,
309                            MLIRContext *context) {
310   return Base::get(context, StandardAttributes::Opaque, dialect, attrData,
311                    type);
312 }
313 
314 OpaqueAttr OpaqueAttr::getChecked(Identifier dialect, StringRef attrData,
315                                   Type type, Location location) {
316   return Base::getChecked(location, type.getContext(),
317                           StandardAttributes::Opaque, dialect, attrData, type);
318 }
319 
320 /// Returns the dialect namespace of the opaque attribute.
321 Identifier OpaqueAttr::getDialectNamespace() const {
322   return getImpl()->dialectNamespace;
323 }
324 
325 /// Returns the raw attribute data of the opaque attribute.
326 StringRef OpaqueAttr::getAttrData() const { return getImpl()->attrData; }
327 
328 /// Verify the construction of an opaque attribute.
329 LogicalResult OpaqueAttr::verifyConstructionInvariants(Optional<Location> loc,
330                                                        MLIRContext *context,
331                                                        Identifier dialect,
332                                                        StringRef attrData,
333                                                        Type type) {
334   if (!Dialect::isValidNamespace(dialect.strref()))
335     return emitOptionalError(loc, "invalid dialect namespace '", dialect, "'");
336   return success();
337 }
338 
339 //===----------------------------------------------------------------------===//
340 // StringAttr
341 //===----------------------------------------------------------------------===//
342 
343 StringAttr StringAttr::get(StringRef bytes, MLIRContext *context) {
344   return get(bytes, NoneType::get(context));
345 }
346 
347 /// Get an instance of a StringAttr with the given string and Type.
348 StringAttr StringAttr::get(StringRef bytes, Type type) {
349   return Base::get(type.getContext(), StandardAttributes::String, bytes, type);
350 }
351 
352 StringRef StringAttr::getValue() const { return getImpl()->value; }
353 
354 //===----------------------------------------------------------------------===//
355 // TypeAttr
356 //===----------------------------------------------------------------------===//
357 
358 TypeAttr TypeAttr::get(Type value) {
359   return Base::get(value.getContext(), StandardAttributes::Type, value);
360 }
361 
362 Type TypeAttr::getValue() const { return getImpl()->value; }
363 
364 //===----------------------------------------------------------------------===//
365 // ElementsAttr
366 //===----------------------------------------------------------------------===//
367 
368 ShapedType ElementsAttr::getType() const {
369   return Attribute::getType().cast<ShapedType>();
370 }
371 
372 /// Returns the number of elements held by this attribute.
373 int64_t ElementsAttr::getNumElements() const {
374   return getType().getNumElements();
375 }
376 
377 /// Return the value at the given index. If index does not refer to a valid
378 /// element, then a null attribute is returned.
379 Attribute ElementsAttr::getValue(ArrayRef<uint64_t> index) const {
380   switch (getKind()) {
381   case StandardAttributes::DenseElements:
382     return cast<DenseElementsAttr>().getValue(index);
383   case StandardAttributes::OpaqueElements:
384     return cast<OpaqueElementsAttr>().getValue(index);
385   case StandardAttributes::SparseElements:
386     return cast<SparseElementsAttr>().getValue(index);
387   default:
388     llvm_unreachable("unknown ElementsAttr kind");
389   }
390 }
391 
392 /// Return if the given 'index' refers to a valid element in this attribute.
393 bool ElementsAttr::isValidIndex(ArrayRef<uint64_t> index) const {
394   auto type = getType();
395 
396   // Verify that the rank of the indices matches the held type.
397   auto rank = type.getRank();
398   if (rank != static_cast<int64_t>(index.size()))
399     return false;
400 
401   // Verify that all of the indices are within the shape dimensions.
402   auto shape = type.getShape();
403   return llvm::all_of(llvm::seq<int>(0, rank), [&](int i) {
404     return static_cast<int64_t>(index[i]) < shape[i];
405   });
406 }
407 
408 ElementsAttr ElementsAttr::mapValues(
409     Type newElementType,
410     llvm::function_ref<APInt(const APInt &)> mapping) const {
411   switch (getKind()) {
412   case StandardAttributes::DenseElements:
413     return cast<DenseElementsAttr>().mapValues(newElementType, mapping);
414   default:
415     llvm_unreachable("unsupported ElementsAttr subtype");
416   }
417 }
418 
419 ElementsAttr ElementsAttr::mapValues(
420     Type newElementType,
421     llvm::function_ref<APInt(const APFloat &)> mapping) const {
422   switch (getKind()) {
423   case StandardAttributes::DenseElements:
424     return cast<DenseElementsAttr>().mapValues(newElementType, mapping);
425   default:
426     llvm_unreachable("unsupported ElementsAttr subtype");
427   }
428 }
429 
430 /// Returns the 1 dimensional flattened row-major index from the given
431 /// multi-dimensional index.
432 uint64_t ElementsAttr::getFlattenedIndex(ArrayRef<uint64_t> index) const {
433   assert(isValidIndex(index) && "expected valid multi-dimensional index");
434   auto type = getType();
435 
436   // Reduce the provided multidimensional index into a flattended 1D row-major
437   // index.
438   auto rank = type.getRank();
439   auto shape = type.getShape();
440   uint64_t valueIndex = 0;
441   uint64_t dimMultiplier = 1;
442   for (int i = rank - 1; i >= 0; --i) {
443     valueIndex += index[i] * dimMultiplier;
444     dimMultiplier *= shape[i];
445   }
446   return valueIndex;
447 }
448 
449 //===----------------------------------------------------------------------===//
450 // DenseElementAttr Utilities
451 //===----------------------------------------------------------------------===//
452 
453 static size_t getDenseElementBitwidth(Type eltType) {
454   // FIXME(b/121118307): using 64 bits for BF16 because it is currently stored
455   // with double semantics.
456   return eltType.isBF16() ? 64 : eltType.getIntOrFloatBitWidth();
457 }
458 
459 /// Get the bitwidth of a dense element type within the buffer.
460 /// DenseElementsAttr requires bitwidths greater than 1 to be aligned by 8.
461 static size_t getDenseElementStorageWidth(size_t origWidth) {
462   return origWidth == 1 ? origWidth : llvm::alignTo<8>(origWidth);
463 }
464 
465 /// Set a bit to a specific value.
466 static void setBit(char *rawData, size_t bitPos, bool value) {
467   if (value)
468     rawData[bitPos / CHAR_BIT] |= (1 << (bitPos % CHAR_BIT));
469   else
470     rawData[bitPos / CHAR_BIT] &= ~(1 << (bitPos % CHAR_BIT));
471 }
472 
473 /// Return the value of the specified bit.
474 static bool getBit(const char *rawData, size_t bitPos) {
475   return (rawData[bitPos / CHAR_BIT] & (1 << (bitPos % CHAR_BIT))) != 0;
476 }
477 
478 /// Writes value to the bit position `bitPos` in array `rawData`.
479 static void writeBits(char *rawData, size_t bitPos, APInt value) {
480   size_t bitWidth = value.getBitWidth();
481 
482   // If the bitwidth is 1 we just toggle the specific bit.
483   if (bitWidth == 1)
484     return setBit(rawData, bitPos, value.isOneValue());
485 
486   // Otherwise, the bit position is guaranteed to be byte aligned.
487   assert((bitPos % CHAR_BIT) == 0 && "expected bitPos to be 8-bit aligned");
488   std::copy_n(reinterpret_cast<const char *>(value.getRawData()),
489               llvm::divideCeil(bitWidth, CHAR_BIT),
490               rawData + (bitPos / CHAR_BIT));
491 }
492 
493 /// Reads the next `bitWidth` bits from the bit position `bitPos` in array
494 /// `rawData`.
495 static APInt readBits(const char *rawData, size_t bitPos, size_t bitWidth) {
496   // Handle a boolean bit position.
497   if (bitWidth == 1)
498     return APInt(1, getBit(rawData, bitPos) ? 1 : 0);
499 
500   // Otherwise, the bit position must be 8-bit aligned.
501   assert((bitPos % CHAR_BIT) == 0 && "expected bitPos to be 8-bit aligned");
502   APInt result(bitWidth, 0);
503   std::copy_n(
504       rawData + (bitPos / CHAR_BIT), llvm::divideCeil(bitWidth, CHAR_BIT),
505       const_cast<char *>(reinterpret_cast<const char *>(result.getRawData())));
506   return result;
507 }
508 
509 /// Returns if 'values' corresponds to a splat, i.e. one element, or has the
510 /// same element count as 'type'.
511 template <typename Values>
512 static bool hasSameElementsOrSplat(ShapedType type, const Values &values) {
513   return (values.size() == 1) ||
514          (type.getNumElements() == static_cast<int64_t>(values.size()));
515 }
516 
517 //===----------------------------------------------------------------------===//
518 // DenseElementAttr Iterators
519 //===----------------------------------------------------------------------===//
520 
521 /// Constructs a new iterator.
522 DenseElementsAttr::AttributeElementIterator::AttributeElementIterator(
523     DenseElementsAttr attr, size_t index)
524     : indexed_accessor_iterator<AttributeElementIterator, const void *,
525                                 Attribute, Attribute, Attribute>(
526           attr.getAsOpaquePointer(), index) {}
527 
528 /// Accesses the Attribute value at this iterator position.
529 Attribute DenseElementsAttr::AttributeElementIterator::operator*() const {
530   auto owner = getFromOpaquePointer(base).cast<DenseElementsAttr>();
531   Type eltTy = owner.getType().getElementType();
532   if (auto intEltTy = eltTy.dyn_cast<IntegerType>()) {
533     if (intEltTy.getWidth() == 1)
534       return BoolAttr::get((*IntElementIterator(owner, index)).isOneValue(),
535                            owner.getContext());
536     return IntegerAttr::get(eltTy, *IntElementIterator(owner, index));
537   }
538   if (auto floatEltTy = eltTy.dyn_cast<FloatType>()) {
539     IntElementIterator intIt(owner, index);
540     FloatElementIterator floatIt(floatEltTy.getFloatSemantics(), intIt);
541     return FloatAttr::get(eltTy, *floatIt);
542   }
543   llvm_unreachable("unexpected element type");
544 }
545 
546 /// Constructs a new iterator.
547 DenseElementsAttr::BoolElementIterator::BoolElementIterator(
548     DenseElementsAttr attr, size_t dataIndex)
549     : DenseElementIndexedIteratorImpl<BoolElementIterator, bool, bool, bool>(
550           attr.getRawData().data(), attr.isSplat(), dataIndex) {}
551 
552 /// Accesses the bool value at this iterator position.
553 bool DenseElementsAttr::BoolElementIterator::operator*() const {
554   return getBit(getData(), getDataIndex());
555 }
556 
557 /// Constructs a new iterator.
558 DenseElementsAttr::IntElementIterator::IntElementIterator(
559     DenseElementsAttr attr, size_t dataIndex)
560     : DenseElementIndexedIteratorImpl<IntElementIterator, APInt, APInt, APInt>(
561           attr.getRawData().data(), attr.isSplat(), dataIndex),
562       bitWidth(getDenseElementBitwidth(attr.getType().getElementType())) {}
563 
564 /// Accesses the raw APInt value at this iterator position.
565 APInt DenseElementsAttr::IntElementIterator::operator*() const {
566   return readBits(getData(),
567                   getDataIndex() * getDenseElementStorageWidth(bitWidth),
568                   bitWidth);
569 }
570 
571 DenseElementsAttr::FloatElementIterator::FloatElementIterator(
572     const llvm::fltSemantics &smt, IntElementIterator it)
573     : llvm::mapped_iterator<IntElementIterator,
574                             std::function<APFloat(const APInt &)>>(
575           it, [&](const APInt &val) { return APFloat(smt, val); }) {}
576 
577 //===----------------------------------------------------------------------===//
578 // DenseElementsAttr
579 //===----------------------------------------------------------------------===//
580 
581 DenseElementsAttr DenseElementsAttr::get(ShapedType type,
582                                          ArrayRef<Attribute> values) {
583   assert(type.getElementType().isIntOrFloat() &&
584          "expected int or float element type");
585   assert(hasSameElementsOrSplat(type, values));
586 
587   auto eltType = type.getElementType();
588   size_t bitWidth = getDenseElementBitwidth(eltType);
589   size_t storageBitWidth = getDenseElementStorageWidth(bitWidth);
590 
591   // Compress the attribute values into a character buffer.
592   SmallVector<char, 8> data(llvm::divideCeil(storageBitWidth, CHAR_BIT) *
593                             values.size());
594   APInt intVal;
595   for (unsigned i = 0, e = values.size(); i < e; ++i) {
596     assert(eltType == values[i].getType() &&
597            "expected attribute value to have element type");
598 
599     switch (eltType.getKind()) {
600     case StandardTypes::BF16:
601     case StandardTypes::F16:
602     case StandardTypes::F32:
603     case StandardTypes::F64:
604       intVal = values[i].cast<FloatAttr>().getValue().bitcastToAPInt();
605       break;
606     case StandardTypes::Integer:
607       intVal = values[i].isa<BoolAttr>()
608                    ? APInt(1, values[i].cast<BoolAttr>().getValue() ? 1 : 0)
609                    : values[i].cast<IntegerAttr>().getValue();
610       break;
611     default:
612       llvm_unreachable("unexpected element type");
613     }
614     assert(intVal.getBitWidth() == bitWidth &&
615            "expected value to have same bitwidth as element type");
616     writeBits(data.data(), i * storageBitWidth, intVal);
617   }
618   return getRaw(type, data, /*isSplat=*/(values.size() == 1));
619 }
620 
621 DenseElementsAttr DenseElementsAttr::get(ShapedType type,
622                                          ArrayRef<bool> values) {
623   assert(hasSameElementsOrSplat(type, values));
624   assert(type.getElementType().isInteger(1));
625 
626   std::vector<char> buff(llvm::divideCeil(values.size(), CHAR_BIT));
627   for (int i = 0, e = values.size(); i != e; ++i)
628     setBit(buff.data(), i, values[i]);
629   return getRaw(type, buff, /*isSplat=*/(values.size() == 1));
630 }
631 
632 /// Constructs a dense integer elements attribute from an array of APInt
633 /// values. Each APInt value is expected to have the same bitwidth as the
634 /// element type of 'type'.
635 DenseElementsAttr DenseElementsAttr::get(ShapedType type,
636                                          ArrayRef<APInt> values) {
637   assert(type.getElementType().isa<IntegerType>());
638   return getRaw(type, values);
639 }
640 
641 // Constructs a dense float elements attribute from an array of APFloat
642 // values. Each APFloat value is expected to have the same bitwidth as the
643 // element type of 'type'.
644 DenseElementsAttr DenseElementsAttr::get(ShapedType type,
645                                          ArrayRef<APFloat> values) {
646   assert(type.getElementType().isa<FloatType>());
647 
648   // Convert the APFloat values to APInt and create a dense elements attribute.
649   std::vector<APInt> intValues(values.size());
650   for (unsigned i = 0, e = values.size(); i != e; ++i)
651     intValues[i] = values[i].bitcastToAPInt();
652   return getRaw(type, intValues);
653 }
654 
655 // Constructs a dense elements attribute from an array of raw APInt values.
656 // Each APInt value is expected to have the same bitwidth as the element type
657 // of 'type'.
658 DenseElementsAttr DenseElementsAttr::getRaw(ShapedType type,
659                                             ArrayRef<APInt> values) {
660   assert(hasSameElementsOrSplat(type, values));
661 
662   size_t bitWidth = getDenseElementBitwidth(type.getElementType());
663   size_t storageBitWidth = getDenseElementStorageWidth(bitWidth);
664   std::vector<char> elementData(llvm::divideCeil(storageBitWidth, CHAR_BIT) *
665                                 values.size());
666   for (unsigned i = 0, e = values.size(); i != e; ++i) {
667     assert(values[i].getBitWidth() == bitWidth);
668     writeBits(elementData.data(), i * storageBitWidth, values[i]);
669   }
670   return getRaw(type, elementData, /*isSplat=*/(values.size() == 1));
671 }
672 
673 DenseElementsAttr DenseElementsAttr::getRaw(ShapedType type,
674                                             ArrayRef<char> data, bool isSplat) {
675   assert((type.isa<RankedTensorType>() || type.isa<VectorType>()) &&
676          "type must be ranked tensor or vector");
677   assert(type.hasStaticShape() && "type must have static shape");
678   return Base::get(type.getContext(), StandardAttributes::DenseElements, type,
679                    data, isSplat);
680 }
681 
682 /// Check the information for a c++ data type, check if this type is valid for
683 /// the current attribute. This method is used to verify specific type
684 /// invariants that the templatized 'getValues' method cannot.
685 static bool isValidIntOrFloat(ShapedType type, int64_t dataEltSize,
686                               bool isInt) {
687   // Make sure that the data element size is the same as the type element width.
688   if ((dataEltSize * CHAR_BIT) != type.getElementTypeBitWidth())
689     return false;
690 
691   // Check that the element type is valid.
692   return isInt ? type.getElementType().isa<IntegerType>()
693                : type.getElementType().isa<FloatType>();
694 }
695 
696 /// Overload of the 'getRaw' method that asserts that the given type is of
697 /// integer type. This method is used to verify type invariants that the
698 /// templatized 'get' method cannot.
699 DenseElementsAttr DenseElementsAttr::getRawIntOrFloat(ShapedType type,
700                                                       ArrayRef<char> data,
701                                                       int64_t dataEltSize,
702                                                       bool isInt) {
703   assert(::isValidIntOrFloat(type, dataEltSize, isInt));
704 
705   int64_t numElements = data.size() / dataEltSize;
706   assert(numElements == 1 || numElements == type.getNumElements());
707   return getRaw(type, data, /*isSplat=*/numElements == 1);
708 }
709 
710 /// A method used to verify specific type invariants that the templatized 'get'
711 /// method cannot.
712 bool DenseElementsAttr::isValidIntOrFloat(int64_t dataEltSize,
713                                           bool isInt) const {
714   return ::isValidIntOrFloat(getType(), dataEltSize, isInt);
715 }
716 
717 /// Return the raw storage data held by this attribute.
718 ArrayRef<char> DenseElementsAttr::getRawData() const {
719   return static_cast<ImplType *>(impl)->data;
720 }
721 
722 /// Returns if this attribute corresponds to a splat, i.e. if all element
723 /// values are the same.
724 bool DenseElementsAttr::isSplat() const { return getImpl()->isSplat; }
725 
726 /// Return the held element values as a range of Attributes.
727 auto DenseElementsAttr::getAttributeValues() const
728     -> llvm::iterator_range<AttributeElementIterator> {
729   return {attr_value_begin(), attr_value_end()};
730 }
731 auto DenseElementsAttr::attr_value_begin() const -> AttributeElementIterator {
732   return AttributeElementIterator(*this, 0);
733 }
734 auto DenseElementsAttr::attr_value_end() const -> AttributeElementIterator {
735   return AttributeElementIterator(*this, getNumElements());
736 }
737 
738 /// Return the held element values as a range of bool. The element type of
739 /// this attribute must be of integer type of bitwidth 1.
740 auto DenseElementsAttr::getBoolValues() const
741     -> llvm::iterator_range<BoolElementIterator> {
742   auto eltType = getType().getElementType().dyn_cast<IntegerType>();
743   assert(eltType && eltType.getWidth() == 1 && "expected i1 integer type");
744   (void)eltType;
745   return {BoolElementIterator(*this, 0),
746           BoolElementIterator(*this, getNumElements())};
747 }
748 
749 /// Return the held element values as a range of APInts. The element type of
750 /// this attribute must be of integer type.
751 auto DenseElementsAttr::getIntValues() const
752     -> llvm::iterator_range<IntElementIterator> {
753   assert(getType().getElementType().isa<IntegerType>() &&
754          "expected integer type");
755   return {raw_int_begin(), raw_int_end()};
756 }
757 auto DenseElementsAttr::int_value_begin() const -> IntElementIterator {
758   assert(getType().getElementType().isa<IntegerType>() &&
759          "expected integer type");
760   return raw_int_begin();
761 }
762 auto DenseElementsAttr::int_value_end() const -> IntElementIterator {
763   assert(getType().getElementType().isa<IntegerType>() &&
764          "expected integer type");
765   return raw_int_end();
766 }
767 
768 /// Return the held element values as a range of APFloat. The element type of
769 /// this attribute must be of float type.
770 auto DenseElementsAttr::getFloatValues() const
771     -> llvm::iterator_range<FloatElementIterator> {
772   auto elementType = getType().getElementType().cast<FloatType>();
773   assert(elementType.isa<FloatType>() && "expected float type");
774   const auto &elementSemantics = elementType.getFloatSemantics();
775   return {FloatElementIterator(elementSemantics, raw_int_begin()),
776           FloatElementIterator(elementSemantics, raw_int_end())};
777 }
778 auto DenseElementsAttr::float_value_begin() const -> FloatElementIterator {
779   return getFloatValues().begin();
780 }
781 auto DenseElementsAttr::float_value_end() const -> FloatElementIterator {
782   return getFloatValues().end();
783 }
784 
785 /// Return a new DenseElementsAttr that has the same data as the current
786 /// attribute, but has been reshaped to 'newType'. The new type must have the
787 /// same total number of elements as well as element type.
788 DenseElementsAttr DenseElementsAttr::reshape(ShapedType newType) {
789   ShapedType curType = getType();
790   if (curType == newType)
791     return *this;
792 
793   (void)curType;
794   assert(newType.getElementType() == curType.getElementType() &&
795          "expected the same element type");
796   assert(newType.getNumElements() == curType.getNumElements() &&
797          "expected the same number of elements");
798   return getRaw(newType, getRawData(), isSplat());
799 }
800 
801 DenseElementsAttr DenseElementsAttr::mapValues(
802     Type newElementType,
803     llvm::function_ref<APInt(const APInt &)> mapping) const {
804   return cast<DenseIntElementsAttr>().mapValues(newElementType, mapping);
805 }
806 
807 DenseElementsAttr DenseElementsAttr::mapValues(
808     Type newElementType,
809     llvm::function_ref<APInt(const APFloat &)> mapping) const {
810   return cast<DenseFPElementsAttr>().mapValues(newElementType, mapping);
811 }
812 
813 //===----------------------------------------------------------------------===//
814 // DenseFPElementsAttr
815 //===----------------------------------------------------------------------===//
816 
817 template <typename Fn, typename Attr>
818 static ShapedType mappingHelper(Fn mapping, Attr &attr, ShapedType inType,
819                                 Type newElementType,
820                                 llvm::SmallVectorImpl<char> &data) {
821   size_t bitWidth = getDenseElementBitwidth(newElementType);
822   size_t storageBitWidth = getDenseElementStorageWidth(bitWidth);
823 
824   ShapedType newArrayType;
825   if (inType.isa<RankedTensorType>())
826     newArrayType = RankedTensorType::get(inType.getShape(), newElementType);
827   else if (inType.isa<UnrankedTensorType>())
828     newArrayType = RankedTensorType::get(inType.getShape(), newElementType);
829   else if (inType.isa<VectorType>())
830     newArrayType = VectorType::get(inType.getShape(), newElementType);
831   else
832     assert(newArrayType && "Unhandled tensor type");
833 
834   size_t numRawElements = attr.isSplat() ? 1 : newArrayType.getNumElements();
835   data.resize(llvm::divideCeil(storageBitWidth, CHAR_BIT) * numRawElements);
836 
837   // Functor used to process a single element value of the attribute.
838   auto processElt = [&](decltype(*attr.begin()) value, size_t index) {
839     auto newInt = mapping(value);
840     assert(newInt.getBitWidth() == bitWidth);
841     writeBits(data.data(), index * storageBitWidth, newInt);
842   };
843 
844   // Check for the splat case.
845   if (attr.isSplat()) {
846     processElt(*attr.begin(), /*index=*/0);
847     return newArrayType;
848   }
849 
850   // Otherwise, process all of the element values.
851   uint64_t elementIdx = 0;
852   for (auto value : attr)
853     processElt(value, elementIdx++);
854   return newArrayType;
855 }
856 
857 DenseElementsAttr DenseFPElementsAttr::mapValues(
858     Type newElementType,
859     llvm::function_ref<APInt(const APFloat &)> mapping) const {
860   llvm::SmallVector<char, 8> elementData;
861   auto newArrayType =
862       mappingHelper(mapping, *this, getType(), newElementType, elementData);
863 
864   return getRaw(newArrayType, elementData, isSplat());
865 }
866 
867 /// Method for supporting type inquiry through isa, cast and dyn_cast.
868 bool DenseFPElementsAttr::classof(Attribute attr) {
869   return attr.isa<DenseElementsAttr>() &&
870          attr.getType().cast<ShapedType>().getElementType().isa<FloatType>();
871 }
872 
873 //===----------------------------------------------------------------------===//
874 // DenseIntElementsAttr
875 //===----------------------------------------------------------------------===//
876 
877 DenseElementsAttr DenseIntElementsAttr::mapValues(
878     Type newElementType,
879     llvm::function_ref<APInt(const APInt &)> mapping) const {
880   llvm::SmallVector<char, 8> elementData;
881   auto newArrayType =
882       mappingHelper(mapping, *this, getType(), newElementType, elementData);
883 
884   return getRaw(newArrayType, elementData, isSplat());
885 }
886 
887 /// Method for supporting type inquiry through isa, cast and dyn_cast.
888 bool DenseIntElementsAttr::classof(Attribute attr) {
889   return attr.isa<DenseElementsAttr>() &&
890          attr.getType().cast<ShapedType>().getElementType().isa<IntegerType>();
891 }
892 
893 //===----------------------------------------------------------------------===//
894 // OpaqueElementsAttr
895 //===----------------------------------------------------------------------===//
896 
897 OpaqueElementsAttr OpaqueElementsAttr::get(Dialect *dialect, ShapedType type,
898                                            StringRef bytes) {
899   assert(TensorType::isValidElementType(type.getElementType()) &&
900          "Input element type should be a valid tensor element type");
901   return Base::get(type.getContext(), StandardAttributes::OpaqueElements, type,
902                    dialect, bytes);
903 }
904 
905 StringRef OpaqueElementsAttr::getValue() const { return getImpl()->bytes; }
906 
907 /// Return the value at the given index. If index does not refer to a valid
908 /// element, then a null attribute is returned.
909 Attribute OpaqueElementsAttr::getValue(ArrayRef<uint64_t> index) const {
910   assert(isValidIndex(index) && "expected valid multi-dimensional index");
911   if (Dialect *dialect = getDialect())
912     return dialect->extractElementHook(*this, index);
913   return Attribute();
914 }
915 
916 Dialect *OpaqueElementsAttr::getDialect() const { return getImpl()->dialect; }
917 
918 bool OpaqueElementsAttr::decode(ElementsAttr &result) {
919   if (auto *d = getDialect())
920     return d->decodeHook(*this, result);
921   return true;
922 }
923 
924 //===----------------------------------------------------------------------===//
925 // SparseElementsAttr
926 //===----------------------------------------------------------------------===//
927 
928 SparseElementsAttr SparseElementsAttr::get(ShapedType type,
929                                            DenseElementsAttr indices,
930                                            DenseElementsAttr values) {
931   assert(indices.getType().getElementType().isInteger(64) &&
932          "expected sparse indices to be 64-bit integer values");
933   assert((type.isa<RankedTensorType>() || type.isa<VectorType>()) &&
934          "type must be ranked tensor or vector");
935   assert(type.hasStaticShape() && "type must have static shape");
936   return Base::get(type.getContext(), StandardAttributes::SparseElements, type,
937                    indices.cast<DenseIntElementsAttr>(), values);
938 }
939 
940 DenseIntElementsAttr SparseElementsAttr::getIndices() const {
941   return getImpl()->indices;
942 }
943 
944 DenseElementsAttr SparseElementsAttr::getValues() const {
945   return getImpl()->values;
946 }
947 
948 /// Return the value of the element at the given index.
949 Attribute SparseElementsAttr::getValue(ArrayRef<uint64_t> index) const {
950   assert(isValidIndex(index) && "expected valid multi-dimensional index");
951   auto type = getType();
952 
953   // The sparse indices are 64-bit integers, so we can reinterpret the raw data
954   // as a 1-D index array.
955   auto sparseIndices = getIndices();
956   auto sparseIndexValues = sparseIndices.getValues<uint64_t>();
957 
958   // Check to see if the indices are a splat.
959   if (sparseIndices.isSplat()) {
960     // If the index is also not a splat of the index value, we know that the
961     // value is zero.
962     auto splatIndex = *sparseIndexValues.begin();
963     if (llvm::any_of(index, [=](uint64_t i) { return i != splatIndex; }))
964       return getZeroAttr();
965 
966     // If the indices are a splat, we also expect the values to be a splat.
967     assert(getValues().isSplat() && "expected splat values");
968     return getValues().getSplatValue();
969   }
970 
971   // Build a mapping between known indices and the offset of the stored element.
972   llvm::SmallDenseMap<llvm::ArrayRef<uint64_t>, size_t> mappedIndices;
973   auto numSparseIndices = sparseIndices.getType().getDimSize(0);
974   size_t rank = type.getRank();
975   for (size_t i = 0, e = numSparseIndices; i != e; ++i)
976     mappedIndices.try_emplace(
977         {&*std::next(sparseIndexValues.begin(), i * rank), rank}, i);
978 
979   // Look for the provided index key within the mapped indices. If the provided
980   // index is not found, then return a zero attribute.
981   auto it = mappedIndices.find(index);
982   if (it == mappedIndices.end())
983     return getZeroAttr();
984 
985   // Otherwise, return the held sparse value element.
986   return getValues().getValue(it->second);
987 }
988 
989 /// Get a zero APFloat for the given sparse attribute.
990 APFloat SparseElementsAttr::getZeroAPFloat() const {
991   auto eltType = getType().getElementType().cast<FloatType>();
992   return APFloat(eltType.getFloatSemantics());
993 }
994 
995 /// Get a zero APInt for the given sparse attribute.
996 APInt SparseElementsAttr::getZeroAPInt() const {
997   auto eltType = getType().getElementType().cast<IntegerType>();
998   return APInt::getNullValue(eltType.getWidth());
999 }
1000 
1001 /// Get a zero attribute for the given attribute type.
1002 Attribute SparseElementsAttr::getZeroAttr() const {
1003   auto eltType = getType().getElementType();
1004 
1005   // Handle floating point elements.
1006   if (eltType.isa<FloatType>())
1007     return FloatAttr::get(eltType, 0);
1008 
1009   // Otherwise, this is an integer.
1010   auto intEltTy = eltType.cast<IntegerType>();
1011   if (intEltTy.getWidth() == 1)
1012     return BoolAttr::get(false, eltType.getContext());
1013   return IntegerAttr::get(eltType, 0);
1014 }
1015 
1016 /// Flatten, and return, all of the sparse indices in this attribute in
1017 /// row-major order.
1018 std::vector<ptrdiff_t> SparseElementsAttr::getFlattenedSparseIndices() const {
1019   std::vector<ptrdiff_t> flatSparseIndices;
1020 
1021   // The sparse indices are 64-bit integers, so we can reinterpret the raw data
1022   // as a 1-D index array.
1023   auto sparseIndices = getIndices();
1024   auto sparseIndexValues = sparseIndices.getValues<uint64_t>();
1025   if (sparseIndices.isSplat()) {
1026     SmallVector<uint64_t, 8> indices(getType().getRank(),
1027                                      *sparseIndexValues.begin());
1028     flatSparseIndices.push_back(getFlattenedIndex(indices));
1029     return flatSparseIndices;
1030   }
1031 
1032   // Otherwise, reinterpret each index as an ArrayRef when flattening.
1033   auto numSparseIndices = sparseIndices.getType().getDimSize(0);
1034   size_t rank = getType().getRank();
1035   for (size_t i = 0, e = numSparseIndices; i != e; ++i)
1036     flatSparseIndices.push_back(getFlattenedIndex(
1037         {&*std::next(sparseIndexValues.begin(), i * rank), rank}));
1038   return flatSparseIndices;
1039 }
1040 
1041 //===----------------------------------------------------------------------===//
1042 // NamedAttributeList
1043 //===----------------------------------------------------------------------===//
1044 
1045 NamedAttributeList::NamedAttributeList(ArrayRef<NamedAttribute> attributes) {
1046   setAttrs(attributes);
1047 }
1048 
1049 ArrayRef<NamedAttribute> NamedAttributeList::getAttrs() const {
1050   return attrs ? attrs.getValue() : llvm::None;
1051 }
1052 
1053 /// Replace the held attributes with ones provided in 'newAttrs'.
1054 void NamedAttributeList::setAttrs(ArrayRef<NamedAttribute> attributes) {
1055   // Don't create an attribute list if there are no attributes.
1056   if (attributes.empty())
1057     attrs = nullptr;
1058   else
1059     attrs = DictionaryAttr::get(attributes, attributes[0].second.getContext());
1060 }
1061 
1062 /// Return the specified attribute if present, null otherwise.
1063 Attribute NamedAttributeList::get(StringRef name) const {
1064   return attrs ? attrs.get(name) : nullptr;
1065 }
1066 
1067 /// Return the specified attribute if present, null otherwise.
1068 Attribute NamedAttributeList::get(Identifier name) const {
1069   return attrs ? attrs.get(name) : nullptr;
1070 }
1071 
1072 /// If the an attribute exists with the specified name, change it to the new
1073 /// value.  Otherwise, add a new attribute with the specified name/value.
1074 void NamedAttributeList::set(Identifier name, Attribute value) {
1075   assert(value && "attributes may never be null");
1076 
1077   // If we already have this attribute, replace it.
1078   auto origAttrs = getAttrs();
1079   SmallVector<NamedAttribute, 8> newAttrs(origAttrs.begin(), origAttrs.end());
1080   for (auto &elt : newAttrs)
1081     if (elt.first == name) {
1082       elt.second = value;
1083       attrs = DictionaryAttr::get(newAttrs, value.getContext());
1084       return;
1085     }
1086 
1087   // Otherwise, add it.
1088   newAttrs.push_back({name, value});
1089   attrs = DictionaryAttr::get(newAttrs, value.getContext());
1090 }
1091 
1092 /// Remove the attribute with the specified name if it exists.  The return
1093 /// value indicates whether the attribute was present or not.
1094 auto NamedAttributeList::remove(Identifier name) -> RemoveResult {
1095   auto origAttrs = getAttrs();
1096   for (unsigned i = 0, e = origAttrs.size(); i != e; ++i) {
1097     if (origAttrs[i].first == name) {
1098       // Handle the simple case of removing the only attribute in the list.
1099       if (e == 1) {
1100         attrs = nullptr;
1101         return RemoveResult::Removed;
1102       }
1103 
1104       SmallVector<NamedAttribute, 8> newAttrs;
1105       newAttrs.reserve(origAttrs.size() - 1);
1106       newAttrs.append(origAttrs.begin(), origAttrs.begin() + i);
1107       newAttrs.append(origAttrs.begin() + i + 1, origAttrs.end());
1108       attrs = DictionaryAttr::get(newAttrs, newAttrs[0].second.getContext());
1109       return RemoveResult::Removed;
1110     }
1111   }
1112   return RemoveResult::NotFound;
1113 }
1114