1 // Copyright (c) 2016 Google Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "source/opt/types.h"
16
17 #include <algorithm>
18 #include <cassert>
19 #include <cstdint>
20 #include <sstream>
21 #include <string>
22 #include <unordered_set>
23
24 #include "source/util/make_unique.h"
25 #include "spirv/unified1/spirv.h"
26
27 namespace spvtools {
28 namespace opt {
29 namespace analysis {
30
31 using U32VecVec = std::vector<std::vector<uint32_t>>;
32
33 namespace {
34
35 // Returns true if the two vector of vectors are identical.
CompareTwoVectors(const U32VecVec a,const U32VecVec b)36 bool CompareTwoVectors(const U32VecVec a, const U32VecVec b) {
37 const auto size = a.size();
38 if (size != b.size()) return false;
39
40 if (size == 0) return true;
41 if (size == 1) return a.front() == b.front();
42
43 std::vector<const std::vector<uint32_t>*> a_ptrs, b_ptrs;
44 a_ptrs.reserve(size);
45 a_ptrs.reserve(size);
46 for (uint32_t i = 0; i < size; ++i) {
47 a_ptrs.push_back(&a[i]);
48 b_ptrs.push_back(&b[i]);
49 }
50
51 const auto cmp = [](const std::vector<uint32_t>* m,
52 const std::vector<uint32_t>* n) {
53 return m->front() < n->front();
54 };
55
56 std::sort(a_ptrs.begin(), a_ptrs.end(), cmp);
57 std::sort(b_ptrs.begin(), b_ptrs.end(), cmp);
58
59 for (uint32_t i = 0; i < size; ++i) {
60 if (*a_ptrs[i] != *b_ptrs[i]) return false;
61 }
62 return true;
63 }
64
65 } // anonymous namespace
66
GetDecorationStr() const67 std::string Type::GetDecorationStr() const {
68 std::ostringstream oss;
69 oss << "[[";
70 for (const auto& decoration : decorations_) {
71 oss << "(";
72 for (size_t i = 0; i < decoration.size(); ++i) {
73 oss << (i > 0 ? ", " : "");
74 oss << decoration.at(i);
75 }
76 oss << ")";
77 }
78 oss << "]]";
79 return oss.str();
80 }
81
HasSameDecorations(const Type * that) const82 bool Type::HasSameDecorations(const Type* that) const {
83 return CompareTwoVectors(decorations_, that->decorations_);
84 }
85
IsUniqueType(bool allowVariablePointers) const86 bool Type::IsUniqueType(bool allowVariablePointers) const {
87 switch (kind_) {
88 case kPointer:
89 return !allowVariablePointers;
90 case kStruct:
91 case kArray:
92 case kRuntimeArray:
93 return false;
94 default:
95 return true;
96 }
97 }
98
Clone() const99 std::unique_ptr<Type> Type::Clone() const {
100 std::unique_ptr<Type> type;
101 switch (kind_) {
102 #define DeclareKindCase(kind) \
103 case k##kind: \
104 type = MakeUnique<kind>(*this->As##kind()); \
105 break
106 DeclareKindCase(Void);
107 DeclareKindCase(Bool);
108 DeclareKindCase(Integer);
109 DeclareKindCase(Float);
110 DeclareKindCase(Vector);
111 DeclareKindCase(Matrix);
112 DeclareKindCase(Image);
113 DeclareKindCase(Sampler);
114 DeclareKindCase(SampledImage);
115 DeclareKindCase(Array);
116 DeclareKindCase(RuntimeArray);
117 DeclareKindCase(Struct);
118 DeclareKindCase(Opaque);
119 DeclareKindCase(Pointer);
120 DeclareKindCase(Function);
121 DeclareKindCase(Event);
122 DeclareKindCase(DeviceEvent);
123 DeclareKindCase(ReserveId);
124 DeclareKindCase(Queue);
125 DeclareKindCase(Pipe);
126 DeclareKindCase(ForwardPointer);
127 DeclareKindCase(PipeStorage);
128 DeclareKindCase(NamedBarrier);
129 DeclareKindCase(AccelerationStructureNV);
130 DeclareKindCase(CooperativeMatrixNV);
131 #undef DeclareKindCase
132 default:
133 assert(false && "Unhandled type");
134 }
135 return type;
136 }
137
RemoveDecorations() const138 std::unique_ptr<Type> Type::RemoveDecorations() const {
139 std::unique_ptr<Type> type(Clone());
140 type->ClearDecorations();
141 return type;
142 }
143
operator ==(const Type & other) const144 bool Type::operator==(const Type& other) const {
145 if (kind_ != other.kind_) return false;
146
147 switch (kind_) {
148 #define DeclareKindCase(kind) \
149 case k##kind: \
150 return As##kind()->IsSame(&other)
151 DeclareKindCase(Void);
152 DeclareKindCase(Bool);
153 DeclareKindCase(Integer);
154 DeclareKindCase(Float);
155 DeclareKindCase(Vector);
156 DeclareKindCase(Matrix);
157 DeclareKindCase(Image);
158 DeclareKindCase(Sampler);
159 DeclareKindCase(SampledImage);
160 DeclareKindCase(Array);
161 DeclareKindCase(RuntimeArray);
162 DeclareKindCase(Struct);
163 DeclareKindCase(Opaque);
164 DeclareKindCase(Pointer);
165 DeclareKindCase(Function);
166 DeclareKindCase(Event);
167 DeclareKindCase(DeviceEvent);
168 DeclareKindCase(ReserveId);
169 DeclareKindCase(Queue);
170 DeclareKindCase(Pipe);
171 DeclareKindCase(ForwardPointer);
172 DeclareKindCase(PipeStorage);
173 DeclareKindCase(NamedBarrier);
174 DeclareKindCase(AccelerationStructureNV);
175 DeclareKindCase(CooperativeMatrixNV);
176 #undef DeclareKindCase
177 default:
178 assert(false && "Unhandled type");
179 return false;
180 }
181 }
182
GetHashWords(std::vector<uint32_t> * words,std::unordered_set<const Type * > * seen) const183 void Type::GetHashWords(std::vector<uint32_t>* words,
184 std::unordered_set<const Type*>* seen) const {
185 if (!seen->insert(this).second) {
186 return;
187 }
188
189 words->push_back(kind_);
190 for (const auto& d : decorations_) {
191 for (auto w : d) {
192 words->push_back(w);
193 }
194 }
195
196 switch (kind_) {
197 #define DeclareKindCase(type) \
198 case k##type: \
199 As##type()->GetExtraHashWords(words, seen); \
200 break
201 DeclareKindCase(Void);
202 DeclareKindCase(Bool);
203 DeclareKindCase(Integer);
204 DeclareKindCase(Float);
205 DeclareKindCase(Vector);
206 DeclareKindCase(Matrix);
207 DeclareKindCase(Image);
208 DeclareKindCase(Sampler);
209 DeclareKindCase(SampledImage);
210 DeclareKindCase(Array);
211 DeclareKindCase(RuntimeArray);
212 DeclareKindCase(Struct);
213 DeclareKindCase(Opaque);
214 DeclareKindCase(Pointer);
215 DeclareKindCase(Function);
216 DeclareKindCase(Event);
217 DeclareKindCase(DeviceEvent);
218 DeclareKindCase(ReserveId);
219 DeclareKindCase(Queue);
220 DeclareKindCase(Pipe);
221 DeclareKindCase(ForwardPointer);
222 DeclareKindCase(PipeStorage);
223 DeclareKindCase(NamedBarrier);
224 DeclareKindCase(AccelerationStructureNV);
225 DeclareKindCase(CooperativeMatrixNV);
226 #undef DeclareKindCase
227 default:
228 assert(false && "Unhandled type");
229 break;
230 }
231
232 seen->erase(this);
233 }
234
HashValue() const235 size_t Type::HashValue() const {
236 std::u32string h;
237 std::vector<uint32_t> words;
238 GetHashWords(&words);
239 for (auto w : words) {
240 h.push_back(w);
241 }
242
243 return std::hash<std::u32string>()(h);
244 }
245
IsSameImpl(const Type * that,IsSameCache *) const246 bool Integer::IsSameImpl(const Type* that, IsSameCache*) const {
247 const Integer* it = that->AsInteger();
248 return it && width_ == it->width_ && signed_ == it->signed_ &&
249 HasSameDecorations(that);
250 }
251
str() const252 std::string Integer::str() const {
253 std::ostringstream oss;
254 oss << (signed_ ? "s" : "u") << "int" << width_;
255 return oss.str();
256 }
257
GetExtraHashWords(std::vector<uint32_t> * words,std::unordered_set<const Type * > *) const258 void Integer::GetExtraHashWords(std::vector<uint32_t>* words,
259 std::unordered_set<const Type*>*) const {
260 words->push_back(width_);
261 words->push_back(signed_);
262 }
263
IsSameImpl(const Type * that,IsSameCache *) const264 bool Float::IsSameImpl(const Type* that, IsSameCache*) const {
265 const Float* ft = that->AsFloat();
266 return ft && width_ == ft->width_ && HasSameDecorations(that);
267 }
268
str() const269 std::string Float::str() const {
270 std::ostringstream oss;
271 oss << "float" << width_;
272 return oss.str();
273 }
274
GetExtraHashWords(std::vector<uint32_t> * words,std::unordered_set<const Type * > *) const275 void Float::GetExtraHashWords(std::vector<uint32_t>* words,
276 std::unordered_set<const Type*>*) const {
277 words->push_back(width_);
278 }
279
Vector(const Type * type,uint32_t count)280 Vector::Vector(const Type* type, uint32_t count)
281 : Type(kVector), element_type_(type), count_(count) {
282 assert(type->AsBool() || type->AsInteger() || type->AsFloat());
283 }
284
IsSameImpl(const Type * that,IsSameCache * seen) const285 bool Vector::IsSameImpl(const Type* that, IsSameCache* seen) const {
286 const Vector* vt = that->AsVector();
287 if (!vt) return false;
288 return count_ == vt->count_ &&
289 element_type_->IsSameImpl(vt->element_type_, seen) &&
290 HasSameDecorations(that);
291 }
292
str() const293 std::string Vector::str() const {
294 std::ostringstream oss;
295 oss << "<" << element_type_->str() << ", " << count_ << ">";
296 return oss.str();
297 }
298
GetExtraHashWords(std::vector<uint32_t> * words,std::unordered_set<const Type * > * seen) const299 void Vector::GetExtraHashWords(std::vector<uint32_t>* words,
300 std::unordered_set<const Type*>* seen) const {
301 element_type_->GetHashWords(words, seen);
302 words->push_back(count_);
303 }
304
Matrix(const Type * type,uint32_t count)305 Matrix::Matrix(const Type* type, uint32_t count)
306 : Type(kMatrix), element_type_(type), count_(count) {
307 assert(type->AsVector());
308 }
309
IsSameImpl(const Type * that,IsSameCache * seen) const310 bool Matrix::IsSameImpl(const Type* that, IsSameCache* seen) const {
311 const Matrix* mt = that->AsMatrix();
312 if (!mt) return false;
313 return count_ == mt->count_ &&
314 element_type_->IsSameImpl(mt->element_type_, seen) &&
315 HasSameDecorations(that);
316 }
317
str() const318 std::string Matrix::str() const {
319 std::ostringstream oss;
320 oss << "<" << element_type_->str() << ", " << count_ << ">";
321 return oss.str();
322 }
323
GetExtraHashWords(std::vector<uint32_t> * words,std::unordered_set<const Type * > * seen) const324 void Matrix::GetExtraHashWords(std::vector<uint32_t>* words,
325 std::unordered_set<const Type*>* seen) const {
326 element_type_->GetHashWords(words, seen);
327 words->push_back(count_);
328 }
329
Image(Type * type,SpvDim dimen,uint32_t d,bool array,bool multisample,uint32_t sampling,SpvImageFormat f,SpvAccessQualifier qualifier)330 Image::Image(Type* type, SpvDim dimen, uint32_t d, bool array, bool multisample,
331 uint32_t sampling, SpvImageFormat f, SpvAccessQualifier qualifier)
332 : Type(kImage),
333 sampled_type_(type),
334 dim_(dimen),
335 depth_(d),
336 arrayed_(array),
337 ms_(multisample),
338 sampled_(sampling),
339 format_(f),
340 access_qualifier_(qualifier) {
341 // TODO(antiagainst): check sampled_type
342 }
343
IsSameImpl(const Type * that,IsSameCache * seen) const344 bool Image::IsSameImpl(const Type* that, IsSameCache* seen) const {
345 const Image* it = that->AsImage();
346 if (!it) return false;
347 return dim_ == it->dim_ && depth_ == it->depth_ && arrayed_ == it->arrayed_ &&
348 ms_ == it->ms_ && sampled_ == it->sampled_ && format_ == it->format_ &&
349 access_qualifier_ == it->access_qualifier_ &&
350 sampled_type_->IsSameImpl(it->sampled_type_, seen) &&
351 HasSameDecorations(that);
352 }
353
str() const354 std::string Image::str() const {
355 std::ostringstream oss;
356 oss << "image(" << sampled_type_->str() << ", " << dim_ << ", " << depth_
357 << ", " << arrayed_ << ", " << ms_ << ", " << sampled_ << ", " << format_
358 << ", " << access_qualifier_ << ")";
359 return oss.str();
360 }
361
GetExtraHashWords(std::vector<uint32_t> * words,std::unordered_set<const Type * > * seen) const362 void Image::GetExtraHashWords(std::vector<uint32_t>* words,
363 std::unordered_set<const Type*>* seen) const {
364 sampled_type_->GetHashWords(words, seen);
365 words->push_back(dim_);
366 words->push_back(depth_);
367 words->push_back(arrayed_);
368 words->push_back(ms_);
369 words->push_back(sampled_);
370 words->push_back(format_);
371 words->push_back(access_qualifier_);
372 }
373
IsSameImpl(const Type * that,IsSameCache * seen) const374 bool SampledImage::IsSameImpl(const Type* that, IsSameCache* seen) const {
375 const SampledImage* sit = that->AsSampledImage();
376 if (!sit) return false;
377 return image_type_->IsSameImpl(sit->image_type_, seen) &&
378 HasSameDecorations(that);
379 }
380
str() const381 std::string SampledImage::str() const {
382 std::ostringstream oss;
383 oss << "sampled_image(" << image_type_->str() << ")";
384 return oss.str();
385 }
386
GetExtraHashWords(std::vector<uint32_t> * words,std::unordered_set<const Type * > * seen) const387 void SampledImage::GetExtraHashWords(
388 std::vector<uint32_t>* words, std::unordered_set<const Type*>* seen) const {
389 image_type_->GetHashWords(words, seen);
390 }
391
Array(const Type * type,const Array::LengthInfo & length_info_arg)392 Array::Array(const Type* type, const Array::LengthInfo& length_info_arg)
393 : Type(kArray), element_type_(type), length_info_(length_info_arg) {
394 assert(type != nullptr);
395 assert(!type->AsVoid());
396 // We always have a word to say which case we're in, followed
397 // by at least one more word.
398 assert(length_info_arg.words.size() >= 2);
399 }
400
IsSameImpl(const Type * that,IsSameCache * seen) const401 bool Array::IsSameImpl(const Type* that, IsSameCache* seen) const {
402 const Array* at = that->AsArray();
403 if (!at) return false;
404 bool is_same = element_type_->IsSameImpl(at->element_type_, seen);
405 is_same = is_same && HasSameDecorations(that);
406 is_same = is_same && (length_info_.words == at->length_info_.words);
407 return is_same;
408 }
409
str() const410 std::string Array::str() const {
411 std::ostringstream oss;
412 oss << "[" << element_type_->str() << ", id(" << LengthId() << "), words(";
413 const char* spacer = "";
414 for (auto w : length_info_.words) {
415 oss << spacer << w;
416 spacer = ",";
417 }
418 oss << ")]";
419 return oss.str();
420 }
421
GetExtraHashWords(std::vector<uint32_t> * words,std::unordered_set<const Type * > * seen) const422 void Array::GetExtraHashWords(std::vector<uint32_t>* words,
423 std::unordered_set<const Type*>* seen) const {
424 element_type_->GetHashWords(words, seen);
425 // This should mirror the logic in IsSameImpl
426 words->insert(words->end(), length_info_.words.begin(),
427 length_info_.words.end());
428 }
429
ReplaceElementType(const Type * type)430 void Array::ReplaceElementType(const Type* type) { element_type_ = type; }
431
RuntimeArray(const Type * type)432 RuntimeArray::RuntimeArray(const Type* type)
433 : Type(kRuntimeArray), element_type_(type) {
434 assert(!type->AsVoid());
435 }
436
IsSameImpl(const Type * that,IsSameCache * seen) const437 bool RuntimeArray::IsSameImpl(const Type* that, IsSameCache* seen) const {
438 const RuntimeArray* rat = that->AsRuntimeArray();
439 if (!rat) return false;
440 return element_type_->IsSameImpl(rat->element_type_, seen) &&
441 HasSameDecorations(that);
442 }
443
str() const444 std::string RuntimeArray::str() const {
445 std::ostringstream oss;
446 oss << "[" << element_type_->str() << "]";
447 return oss.str();
448 }
449
GetExtraHashWords(std::vector<uint32_t> * words,std::unordered_set<const Type * > * seen) const450 void RuntimeArray::GetExtraHashWords(
451 std::vector<uint32_t>* words, std::unordered_set<const Type*>* seen) const {
452 element_type_->GetHashWords(words, seen);
453 }
454
ReplaceElementType(const Type * type)455 void RuntimeArray::ReplaceElementType(const Type* type) {
456 element_type_ = type;
457 }
458
Struct(const std::vector<const Type * > & types)459 Struct::Struct(const std::vector<const Type*>& types)
460 : Type(kStruct), element_types_(types) {
461 for (const auto* t : types) {
462 (void)t;
463 assert(!t->AsVoid());
464 }
465 }
466
AddMemberDecoration(uint32_t index,std::vector<uint32_t> && decoration)467 void Struct::AddMemberDecoration(uint32_t index,
468 std::vector<uint32_t>&& decoration) {
469 if (index >= element_types_.size()) {
470 assert(0 && "index out of bound");
471 return;
472 }
473
474 element_decorations_[index].push_back(std::move(decoration));
475 }
476
IsSameImpl(const Type * that,IsSameCache * seen) const477 bool Struct::IsSameImpl(const Type* that, IsSameCache* seen) const {
478 const Struct* st = that->AsStruct();
479 if (!st) return false;
480 if (element_types_.size() != st->element_types_.size()) return false;
481 const auto size = element_decorations_.size();
482 if (size != st->element_decorations_.size()) return false;
483 if (!HasSameDecorations(that)) return false;
484
485 for (size_t i = 0; i < element_types_.size(); ++i) {
486 if (!element_types_[i]->IsSameImpl(st->element_types_[i], seen))
487 return false;
488 }
489 for (const auto& p : element_decorations_) {
490 if (st->element_decorations_.count(p.first) == 0) return false;
491 if (!CompareTwoVectors(p.second, st->element_decorations_.at(p.first)))
492 return false;
493 }
494 return true;
495 }
496
str() const497 std::string Struct::str() const {
498 std::ostringstream oss;
499 oss << "{";
500 const size_t count = element_types_.size();
501 for (size_t i = 0; i < count; ++i) {
502 oss << element_types_[i]->str();
503 if (i + 1 != count) oss << ", ";
504 }
505 oss << "}";
506 return oss.str();
507 }
508
GetExtraHashWords(std::vector<uint32_t> * words,std::unordered_set<const Type * > * seen) const509 void Struct::GetExtraHashWords(std::vector<uint32_t>* words,
510 std::unordered_set<const Type*>* seen) const {
511 for (auto* t : element_types_) {
512 t->GetHashWords(words, seen);
513 }
514 for (const auto& pair : element_decorations_) {
515 words->push_back(pair.first);
516 for (const auto& d : pair.second) {
517 for (auto w : d) {
518 words->push_back(w);
519 }
520 }
521 }
522 }
523
IsSameImpl(const Type * that,IsSameCache *) const524 bool Opaque::IsSameImpl(const Type* that, IsSameCache*) const {
525 const Opaque* ot = that->AsOpaque();
526 if (!ot) return false;
527 return name_ == ot->name_ && HasSameDecorations(that);
528 }
529
str() const530 std::string Opaque::str() const {
531 std::ostringstream oss;
532 oss << "opaque('" << name_ << "')";
533 return oss.str();
534 }
535
GetExtraHashWords(std::vector<uint32_t> * words,std::unordered_set<const Type * > *) const536 void Opaque::GetExtraHashWords(std::vector<uint32_t>* words,
537 std::unordered_set<const Type*>*) const {
538 for (auto c : name_) {
539 words->push_back(static_cast<char32_t>(c));
540 }
541 }
542
Pointer(const Type * type,SpvStorageClass sc)543 Pointer::Pointer(const Type* type, SpvStorageClass sc)
544 : Type(kPointer), pointee_type_(type), storage_class_(sc) {}
545
IsSameImpl(const Type * that,IsSameCache * seen) const546 bool Pointer::IsSameImpl(const Type* that, IsSameCache* seen) const {
547 const Pointer* pt = that->AsPointer();
548 if (!pt) return false;
549 if (storage_class_ != pt->storage_class_) return false;
550 auto p = seen->insert(std::make_pair(this, that->AsPointer()));
551 if (!p.second) {
552 return true;
553 }
554 bool same_pointee = pointee_type_->IsSameImpl(pt->pointee_type_, seen);
555 seen->erase(p.first);
556 if (!same_pointee) {
557 return false;
558 }
559 return HasSameDecorations(that);
560 }
561
str() const562 std::string Pointer::str() const {
563 std::ostringstream os;
564 os << pointee_type_->str() << " " << static_cast<uint32_t>(storage_class_)
565 << "*";
566 return os.str();
567 }
568
GetExtraHashWords(std::vector<uint32_t> * words,std::unordered_set<const Type * > * seen) const569 void Pointer::GetExtraHashWords(std::vector<uint32_t>* words,
570 std::unordered_set<const Type*>* seen) const {
571 pointee_type_->GetHashWords(words, seen);
572 words->push_back(storage_class_);
573 }
574
SetPointeeType(const Type * type)575 void Pointer::SetPointeeType(const Type* type) { pointee_type_ = type; }
576
Function(const Type * ret_type,const std::vector<const Type * > & params)577 Function::Function(const Type* ret_type, const std::vector<const Type*>& params)
578 : Type(kFunction), return_type_(ret_type), param_types_(params) {}
579
Function(const Type * ret_type,std::vector<const Type * > & params)580 Function::Function(const Type* ret_type, std::vector<const Type*>& params)
581 : Type(kFunction), return_type_(ret_type), param_types_(params) {}
582
IsSameImpl(const Type * that,IsSameCache * seen) const583 bool Function::IsSameImpl(const Type* that, IsSameCache* seen) const {
584 const Function* ft = that->AsFunction();
585 if (!ft) return false;
586 if (!return_type_->IsSameImpl(ft->return_type_, seen)) return false;
587 if (param_types_.size() != ft->param_types_.size()) return false;
588 for (size_t i = 0; i < param_types_.size(); ++i) {
589 if (!param_types_[i]->IsSameImpl(ft->param_types_[i], seen)) return false;
590 }
591 return HasSameDecorations(that);
592 }
593
str() const594 std::string Function::str() const {
595 std::ostringstream oss;
596 const size_t count = param_types_.size();
597 oss << "(";
598 for (size_t i = 0; i < count; ++i) {
599 oss << param_types_[i]->str();
600 if (i + 1 != count) oss << ", ";
601 }
602 oss << ") -> " << return_type_->str();
603 return oss.str();
604 }
605
GetExtraHashWords(std::vector<uint32_t> * words,std::unordered_set<const Type * > * seen) const606 void Function::GetExtraHashWords(std::vector<uint32_t>* words,
607 std::unordered_set<const Type*>* seen) const {
608 return_type_->GetHashWords(words, seen);
609 for (const auto* t : param_types_) {
610 t->GetHashWords(words, seen);
611 }
612 }
613
SetReturnType(const Type * type)614 void Function::SetReturnType(const Type* type) { return_type_ = type; }
615
IsSameImpl(const Type * that,IsSameCache *) const616 bool Pipe::IsSameImpl(const Type* that, IsSameCache*) const {
617 const Pipe* pt = that->AsPipe();
618 if (!pt) return false;
619 return access_qualifier_ == pt->access_qualifier_ && HasSameDecorations(that);
620 }
621
str() const622 std::string Pipe::str() const {
623 std::ostringstream oss;
624 oss << "pipe(" << access_qualifier_ << ")";
625 return oss.str();
626 }
627
GetExtraHashWords(std::vector<uint32_t> * words,std::unordered_set<const Type * > *) const628 void Pipe::GetExtraHashWords(std::vector<uint32_t>* words,
629 std::unordered_set<const Type*>*) const {
630 words->push_back(access_qualifier_);
631 }
632
IsSameImpl(const Type * that,IsSameCache *) const633 bool ForwardPointer::IsSameImpl(const Type* that, IsSameCache*) const {
634 const ForwardPointer* fpt = that->AsForwardPointer();
635 if (!fpt) return false;
636 return (pointer_ && fpt->pointer_ ? *pointer_ == *fpt->pointer_
637 : target_id_ == fpt->target_id_) &&
638 storage_class_ == fpt->storage_class_ && HasSameDecorations(that);
639 }
640
str() const641 std::string ForwardPointer::str() const {
642 std::ostringstream oss;
643 oss << "forward_pointer(";
644 if (pointer_ != nullptr) {
645 oss << pointer_->str();
646 } else {
647 oss << target_id_;
648 }
649 oss << ")";
650 return oss.str();
651 }
652
GetExtraHashWords(std::vector<uint32_t> * words,std::unordered_set<const Type * > * seen) const653 void ForwardPointer::GetExtraHashWords(
654 std::vector<uint32_t>* words, std::unordered_set<const Type*>* seen) const {
655 words->push_back(target_id_);
656 words->push_back(storage_class_);
657 if (pointer_) pointer_->GetHashWords(words, seen);
658 }
659
CooperativeMatrixNV(const Type * type,const uint32_t scope,const uint32_t rows,const uint32_t columns)660 CooperativeMatrixNV::CooperativeMatrixNV(const Type* type, const uint32_t scope,
661 const uint32_t rows,
662 const uint32_t columns)
663 : Type(kCooperativeMatrixNV),
664 component_type_(type),
665 scope_id_(scope),
666 rows_id_(rows),
667 columns_id_(columns) {
668 assert(type != nullptr);
669 assert(scope != 0);
670 assert(rows != 0);
671 assert(columns != 0);
672 }
673
str() const674 std::string CooperativeMatrixNV::str() const {
675 std::ostringstream oss;
676 oss << "<" << component_type_->str() << ", " << scope_id_ << ", " << rows_id_
677 << ", " << columns_id_ << ">";
678 return oss.str();
679 }
680
GetExtraHashWords(std::vector<uint32_t> * words,std::unordered_set<const Type * > * pSet) const681 void CooperativeMatrixNV::GetExtraHashWords(
682 std::vector<uint32_t>* words, std::unordered_set<const Type*>* pSet) const {
683 component_type_->GetHashWords(words, pSet);
684 words->push_back(scope_id_);
685 words->push_back(rows_id_);
686 words->push_back(columns_id_);
687 }
688
IsSameImpl(const Type * that,IsSameCache * seen) const689 bool CooperativeMatrixNV::IsSameImpl(const Type* that,
690 IsSameCache* seen) const {
691 const CooperativeMatrixNV* mt = that->AsCooperativeMatrixNV();
692 if (!mt) return false;
693 return component_type_->IsSameImpl(mt->component_type_, seen) &&
694 scope_id_ == mt->scope_id_ && rows_id_ == mt->rows_id_ &&
695 columns_id_ == mt->columns_id_ && HasSameDecorations(that);
696 }
697
698 } // namespace analysis
699 } // namespace opt
700 } // namespace spvtools
701