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#ifndef SOURCE_OPT_CONSTANTS_H_
16#define SOURCE_OPT_CONSTANTS_H_
17
18#include <cinttypes>
19#include <map>
20#include <memory>
21#include <unordered_map>
22#include <unordered_set>
23#include <utility>
24#include <vector>
25
26#include "source/opt/module.h"
27#include "source/opt/type_manager.h"
28#include "source/opt/types.h"
29#include "source/util/hex_float.h"
30#include "source/util/make_unique.h"
31
32namespace spvtools {
33namespace opt {
34
35class IRContext;
36
37namespace analysis {
38
39// Class hierarchy to represent the normal constants defined through
40// OpConstantTrue, OpConstantFalse, OpConstant, OpConstantNull and
41// OpConstantComposite instructions.
42// TODO(qining): Add class for constants defined with OpConstantSampler.
43class Constant;
44class ScalarConstant;
45class IntConstant;
46class FloatConstant;
47class BoolConstant;
48class CompositeConstant;
49class StructConstant;
50class VectorConstant;
51class MatrixConstant;
52class ArrayConstant;
53class NullConstant;
54class ConstantManager;
55
56// Abstract class for a SPIR-V constant. It has a bunch of As<subclass> methods,
57// which is used as a way to probe the actual <subclass>
58class Constant {
59 public:
60 Constant() = delete;
61 virtual ~Constant() {}
62
63 // Make a deep copy of this constant.
64 virtual std::unique_ptr<Constant> Copy() const = 0;
65
66 // reflections
67 virtual ScalarConstant* AsScalarConstant() { return nullptr; }
68 virtual IntConstant* AsIntConstant() { return nullptr; }
69 virtual FloatConstant* AsFloatConstant() { return nullptr; }
70 virtual BoolConstant* AsBoolConstant() { return nullptr; }
71 virtual CompositeConstant* AsCompositeConstant() { return nullptr; }
72 virtual StructConstant* AsStructConstant() { return nullptr; }
73 virtual VectorConstant* AsVectorConstant() { return nullptr; }
74 virtual MatrixConstant* AsMatrixConstant() { return nullptr; }
75 virtual ArrayConstant* AsArrayConstant() { return nullptr; }
76 virtual NullConstant* AsNullConstant() { return nullptr; }
77
78 virtual const ScalarConstant* AsScalarConstant() const { return nullptr; }
79 virtual const IntConstant* AsIntConstant() const { return nullptr; }
80 virtual const FloatConstant* AsFloatConstant() const { return nullptr; }
81 virtual const BoolConstant* AsBoolConstant() const { return nullptr; }
82 virtual const CompositeConstant* AsCompositeConstant() const {
83 return nullptr;
84 }
85 virtual const StructConstant* AsStructConstant() const { return nullptr; }
86 virtual const VectorConstant* AsVectorConstant() const { return nullptr; }
87 virtual const MatrixConstant* AsMatrixConstant() const { return nullptr; }
88 virtual const ArrayConstant* AsArrayConstant() const { return nullptr; }
89 virtual const NullConstant* AsNullConstant() const { return nullptr; }
90
91 // Returns the float representation of the constant. Must be a 32 bit
92 // Float type.
93 float GetFloat() const;
94
95 // Returns the double representation of the constant. Must be a 64 bit
96 // Float type.
97 double GetDouble() const;
98
99 // Returns the double representation of the constant. Must be a 32-bit or
100 // 64-bit Float type.
101 double GetValueAsDouble() const;
102
103 // Returns uint32_t representation of the constant. Must be a 32 bit
104 // Integer type.
105 uint32_t GetU32() const;
106
107 // Returns uint64_t representation of the constant. Must be a 64 bit
108 // Integer type.
109 uint64_t GetU64() const;
110
111 // Returns int32_t representation of the constant. Must be a 32 bit
112 // Integer type.
113 int32_t GetS32() const;
114
115 // Returns int64_t representation of the constant. Must be a 64 bit
116 // Integer type.
117 int64_t GetS64() const;
118
119 // Returns the zero-extended representation of an integer constant. Must
120 // be an integral constant of at most 64 bits.
121 uint64_t GetZeroExtendedValue() const;
122
123 // Returns the sign-extended representation of an integer constant. Must
124 // be an integral constant of at most 64 bits.
125 int64_t GetSignExtendedValue() const;
126
127 // Returns true if the constant is a zero or a composite containing 0s.
128 virtual bool IsZero() const { return false; }
129
130 const Type* type() const { return type_; }
131
132 // Returns an std::vector containing the elements of |constant|. The type of
133 // |constant| must be |Vector|.
134 std::vector<const Constant*> GetVectorComponents(
135 ConstantManager* const_mgr) const;
136
137 protected:
138 Constant(const Type* ty) : type_(ty) {}
139
140 // The type of this constant.
141 const Type* type_;
142};
143
144// Abstract class for scalar type constants.
145class ScalarConstant : public Constant {
146 public:
147 ScalarConstant() = delete;
148 ScalarConstant* AsScalarConstant() override { return this; }
149 const ScalarConstant* AsScalarConstant() const override { return this; }
150
151 // Returns a const reference of the value of this constant in 32-bit words.
152 virtual const std::vector<uint32_t>& words() const { return words_; }
153
154 // Returns true if the value is zero.
155 bool IsZero() const override {
156 bool is_zero = true;
157 for (uint32_t v : words()) {
158 if (v != 0) {
159 is_zero = false;
160 break;
161 }
162 }
163 return is_zero;
164 }
165
166 protected:
167 ScalarConstant(const Type* ty, const std::vector<uint32_t>& w)
168 : Constant(ty), words_(w) {}
169 ScalarConstant(const Type* ty, std::vector<uint32_t>&& w)
170 : Constant(ty), words_(std::move(w)) {}
171 std::vector<uint32_t> words_;
172};
173
174// Integer type constant.
175class IntConstant : public ScalarConstant {
176 public:
177 IntConstant(const Integer* ty, const std::vector<uint32_t>& w)
178 : ScalarConstant(ty, w) {}
179 IntConstant(const Integer* ty, std::vector<uint32_t>&& w)
180 : ScalarConstant(ty, std::move(w)) {}
181
182 IntConstant* AsIntConstant() override { return this; }
183 const IntConstant* AsIntConstant() const override { return this; }
184
185 int32_t GetS32BitValue() const {
186 // Relies on signed values smaller than 32-bit being sign extended. See
187 // section 2.2.1 of the SPIR-V spec.
188 assert(words().size() == 1);
189 return words()[0];
190 }
191
192 uint32_t GetU32BitValue() const {
193 // Relies on unsigned values smaller than 32-bit being zero extended. See
194 // section 2.2.1 of the SPIR-V spec.
195 assert(words().size() == 1);
196 return words()[0];
197 }
198
199 int64_t GetS64BitValue() const {
200 // Relies on unsigned values smaller than 64-bit being sign extended. See
201 // section 2.2.1 of the SPIR-V spec.
202 assert(words().size() == 2);
203 return static_cast<uint64_t>(words()[1]) << 32 |
204 static_cast<uint64_t>(words()[0]);
205 }
206
207 uint64_t GetU64BitValue() const {
208 // Relies on unsigned values smaller than 64-bit being zero extended. See
209 // section 2.2.1 of the SPIR-V spec.
210 assert(words().size() == 2);
211 return static_cast<uint64_t>(words()[1]) << 32 |
212 static_cast<uint64_t>(words()[0]);
213 }
214
215 // Make a copy of this IntConstant instance.
216 std::unique_ptr<IntConstant> CopyIntConstant() const {
217 return MakeUnique<IntConstant>(type_->AsInteger(), words_);
218 }
219 std::unique_ptr<Constant> Copy() const override {
220 return std::unique_ptr<Constant>(CopyIntConstant().release());
221 }
222};
223
224// Float type constant.
225class FloatConstant : public ScalarConstant {
226 public:
227 FloatConstant(const Float* ty, const std::vector<uint32_t>& w)
228 : ScalarConstant(ty, w) {}
229 FloatConstant(const Float* ty, std::vector<uint32_t>&& w)
230 : ScalarConstant(ty, std::move(w)) {}
231
232 FloatConstant* AsFloatConstant() override { return this; }
233 const FloatConstant* AsFloatConstant() const override { return this; }
234
235 // Make a copy of this FloatConstant instance.
236 std::unique_ptr<FloatConstant> CopyFloatConstant() const {
237 return MakeUnique<FloatConstant>(type_->AsFloat(), words_);
238 }
239 std::unique_ptr<Constant> Copy() const override {
240 return std::unique_ptr<Constant>(CopyFloatConstant().release());
241 }
242
243 // Returns the float value of |this|. The type of |this| must be |Float| with
244 // width of 32.
245 float GetFloatValue() const {
246 assert(type()->AsFloat()->width() == 32 &&
247 "Not a 32-bit floating point value.");
248 utils::FloatProxy<float> a(words()[0]);
249 return a.getAsFloat();
250 }
251
252 // Returns the double value of |this|. The type of |this| must be |Float|
253 // with width of 64.
254 double GetDoubleValue() const {
255 assert(type()->AsFloat()->width() == 64 &&
256 "Not a 32-bit floating point value.");
257 uint64_t combined_words = words()[1];
258 combined_words = combined_words << 32;
259 combined_words |= words()[0];
260 utils::FloatProxy<double> a(combined_words);
261 return a.getAsFloat();
262 }
263};
264
265// Bool type constant.
266class BoolConstant : public ScalarConstant {
267 public:
268 BoolConstant(const Bool* ty, bool v)
269 : ScalarConstant(ty, {static_cast<uint32_t>(v)}), value_(v) {}
270
271 BoolConstant* AsBoolConstant() override { return this; }
272 const BoolConstant* AsBoolConstant() const override { return this; }
273
274 // Make a copy of this BoolConstant instance.
275 std::unique_ptr<BoolConstant> CopyBoolConstant() const {
276 return MakeUnique<BoolConstant>(type_->AsBool(), value_);
277 }
278 std::unique_ptr<Constant> Copy() const override {
279 return std::unique_ptr<Constant>(CopyBoolConstant().release());
280 }
281
282 bool value() const { return value_; }
283
284 private:
285 bool value_;
286};
287
288// Abstract class for composite constants.
289class CompositeConstant : public Constant {
290 public:
291 CompositeConstant() = delete;
292 CompositeConstant* AsCompositeConstant() override { return this; }
293 const CompositeConstant* AsCompositeConstant() const override { return this; }
294
295 // Returns a const reference of the components held in this composite
296 // constant.
297 virtual const std::vector<const Constant*>& GetComponents() const {
298 return components_;
299 }
300
301 bool IsZero() const override {
302 for (const Constant* c : GetComponents()) {
303 if (!c->IsZero()) {
304 return false;
305 }
306 }
307 return true;
308 }
309
310 protected:
311 CompositeConstant(const Type* ty) : Constant(ty), components_() {}
312 CompositeConstant(const Type* ty,
313 const std::vector<const Constant*>& components)
314 : Constant(ty), components_(components) {}
315 CompositeConstant(const Type* ty, std::vector<const Constant*>&& components)
316 : Constant(ty), components_(std::move(components)) {}
317 std::vector<const Constant*> components_;
318};
319
320// Struct type constant.
321class StructConstant : public CompositeConstant {
322 public:
323 StructConstant(const Struct* ty) : CompositeConstant(ty) {}
324 StructConstant(const Struct* ty,
325 const std::vector<const Constant*>& components)
326 : CompositeConstant(ty, components) {}
327 StructConstant(const Struct* ty, std::vector<const Constant*>&& components)
328 : CompositeConstant(ty, std::move(components)) {}
329
330 StructConstant* AsStructConstant() override { return this; }
331 const StructConstant* AsStructConstant() const override { return this; }
332
333 // Make a copy of this StructConstant instance.
334 std::unique_ptr<StructConstant> CopyStructConstant() const {
335 return MakeUnique<StructConstant>(type_->AsStruct(), components_);
336 }
337 std::unique_ptr<Constant> Copy() const override {
338 return std::unique_ptr<Constant>(CopyStructConstant().release());
339 }
340};
341
342// Vector type constant.
343class VectorConstant : public CompositeConstant {
344 public:
345 VectorConstant(const Vector* ty)
346 : CompositeConstant(ty), component_type_(ty->element_type()) {}
347 VectorConstant(const Vector* ty,
348 const std::vector<const Constant*>& components)
349 : CompositeConstant(ty, components),
350 component_type_(ty->element_type()) {}
351 VectorConstant(const Vector* ty, std::vector<const Constant*>&& components)
352 : CompositeConstant(ty, std::move(components)),
353 component_type_(ty->element_type()) {}
354
355 VectorConstant* AsVectorConstant() override { return this; }
356 const VectorConstant* AsVectorConstant() const override { return this; }
357
358 // Make a copy of this VectorConstant instance.
359 std::unique_ptr<VectorConstant> CopyVectorConstant() const {
360 auto another = MakeUnique<VectorConstant>(type_->AsVector());
361 another->components_.insert(another->components_.end(), components_.begin(),
362 components_.end());
363 return another;
364 }
365 std::unique_ptr<Constant> Copy() const override {
366 return std::unique_ptr<Constant>(CopyVectorConstant().release());
367 }
368
369 const Type* component_type() const { return component_type_; }
370
371 private:
372 const Type* component_type_;
373};
374
375// Matrix type constant.
376class MatrixConstant : public CompositeConstant {
377 public:
378 MatrixConstant(const Matrix* ty)
379 : CompositeConstant(ty), component_type_(ty->element_type()) {}
380 MatrixConstant(const Matrix* ty,
381 const std::vector<const Constant*>& components)
382 : CompositeConstant(ty, components),
383 component_type_(ty->element_type()) {}
384 MatrixConstant(const Vector* ty, std::vector<const Constant*>&& components)
385 : CompositeConstant(ty, std::move(components)),
386 component_type_(ty->element_type()) {}
387
388 MatrixConstant* AsMatrixConstant() override { return this; }
389 const MatrixConstant* AsMatrixConstant() const override { return this; }
390
391 // Make a copy of this MatrixConstant instance.
392 std::unique_ptr<MatrixConstant> CopyMatrixConstant() const {
393 auto another = MakeUnique<MatrixConstant>(type_->AsMatrix());
394 another->components_.insert(another->components_.end(), components_.begin(),
395 components_.end());
396 return another;
397 }
398 std::unique_ptr<Constant> Copy() const override {
399 return std::unique_ptr<Constant>(CopyMatrixConstant().release());
400 }
401
402 const Type* component_type() { return component_type_; }
403
404 private:
405 const Type* component_type_;
406};
407
408// Array type constant.
409class ArrayConstant : public CompositeConstant {
410 public:
411 ArrayConstant(const Array* ty) : CompositeConstant(ty) {}
412 ArrayConstant(const Array* ty, const std::vector<const Constant*>& components)
413 : CompositeConstant(ty, components) {}
414 ArrayConstant(const Array* ty, std::vector<const Constant*>&& components)
415 : CompositeConstant(ty, std::move(components)) {}
416
417 ArrayConstant* AsArrayConstant() override { return this; }
418 const ArrayConstant* AsArrayConstant() const override { return this; }
419
420 // Make a copy of this ArrayConstant instance.
421 std::unique_ptr<ArrayConstant> CopyArrayConstant() const {
422 return MakeUnique<ArrayConstant>(type_->AsArray(), components_);
423 }
424 std::unique_ptr<Constant> Copy() const override {
425 return std::unique_ptr<Constant>(CopyArrayConstant().release());
426 }
427};
428
429// Null type constant.
430class NullConstant : public Constant {
431 public:
432 NullConstant(const Type* ty) : Constant(ty) {}
433 NullConstant* AsNullConstant() override { return this; }
434 const NullConstant* AsNullConstant() const override { return this; }
435
436 // Make a copy of this NullConstant instance.
437 std::unique_ptr<NullConstant> CopyNullConstant() const {
438 return MakeUnique<NullConstant>(type_);
439 }
440 std::unique_ptr<Constant> Copy() const override {
441 return std::unique_ptr<Constant>(CopyNullConstant().release());
442 }
443 bool IsZero() const override { return true; }
444};
445
446// Hash function for Constant instances. Use the structure of the constant as
447// the key.
448struct ConstantHash {
449 void add_pointer(std::u32string* h, const void* p) const {
450 uint64_t ptr_val = reinterpret_cast<uint64_t>(p);
451 h->push_back(static_cast<uint32_t>(ptr_val >> 32));
452 h->push_back(static_cast<uint32_t>(ptr_val));
453 }
454
455 size_t operator()(const Constant* const_val) const {
456 std::u32string h;
457 add_pointer(&h, const_val->type());
458 if (const auto scalar = const_val->AsScalarConstant()) {
459 for (const auto& w : scalar->words()) {
460 h.push_back(w);
461 }
462 } else if (const auto composite = const_val->AsCompositeConstant()) {
463 for (const auto& c : composite->GetComponents()) {
464 add_pointer(&h, c);
465 }
466 } else if (const_val->AsNullConstant()) {
467 h.push_back(0);
468 } else {
469 assert(
470 false &&
471 "Tried to compute the hash value of an invalid Constant instance.");
472 }
473
474 return std::hash<std::u32string>()(h);
475 }
476};
477
478// Equality comparison structure for two constants.
479struct ConstantEqual {
480 bool operator()(const Constant* c1, const Constant* c2) const {
481 if (c1->type() != c2->type()) {
482 return false;
483 }
484
485 if (const auto& s1 = c1->AsScalarConstant()) {
486 const auto& s2 = c2->AsScalarConstant();
487 return s2 && s1->words() == s2->words();
488 } else if (const auto& composite1 = c1->AsCompositeConstant()) {
489 const auto& composite2 = c2->AsCompositeConstant();
490 return composite2 &&
491 composite1->GetComponents() == composite2->GetComponents();
492 } else if (c1->AsNullConstant()) {
493 return c2->AsNullConstant() != nullptr;
494 } else {
495 assert(false && "Tried to compare two invalid Constant instances.");
496 }
497 return false;
498 }
499};
500
501// This class represents a pool of constants.
502class ConstantManager {
503 public:
504 ConstantManager(IRContext* ctx);
505
506 IRContext* context() const { return ctx_; }
507
508 // Gets or creates a unique Constant instance of type |type| and a vector of
509 // constant defining words |words|. If a Constant instance existed already in
510 // the constant pool, it returns a pointer to it. Otherwise, it creates one
511 // using CreateConstant. If a new Constant instance cannot be created, it
512 // returns nullptr.
513 const Constant* GetConstant(
514 const Type* type, const std::vector<uint32_t>& literal_words_or_ids);
515
516 template <class C>
517 const Constant* GetConstant(const Type* type, const C& literal_words_or_ids) {
518 return GetConstant(type, std::vector<uint32_t>(literal_words_or_ids.begin(),
519 literal_words_or_ids.end()));
520 }
521
522 // Gets or creates a Constant instance to hold the constant value of the given
523 // instruction. It returns a pointer to a Constant instance or nullptr if it
524 // could not create the constant.
525 const Constant* GetConstantFromInst(const Instruction* inst);
526
527 // Gets or creates a constant defining instruction for the given Constant |c|.
528 // If |c| had already been defined, it returns a pointer to the existing
529 // declaration. Otherwise, it calls BuildInstructionAndAddToModule. If the
530 // optional |pos| is given, it will insert any newly created instructions at
531 // the given instruction iterator position. Otherwise, it inserts the new
532 // instruction at the end of the current module's types section.
533 //
534 // |type_id| is an optional argument for disambiguating equivalent types. If
535 // |type_id| is specified, the contant returned will have that type id.
536 Instruction* GetDefiningInstruction(const Constant* c, uint32_t type_id = 0,
537 Module::inst_iterator* pos = nullptr);
538
539 // Creates a constant defining instruction for the given Constant instance
540 // and inserts the instruction at the position specified by the given
541 // instruction iterator. Returns a pointer to the created instruction if
542 // succeeded, otherwise returns a null pointer. The instruction iterator
543 // points to the same instruction before and after the insertion. This is the
544 // only method that actually manages id creation/assignment and instruction
545 // creation/insertion for a new Constant instance.
546 //
547 // |type_id| is an optional argument for disambiguating equivalent types. If
548 // |type_id| is specified, it is used as the type of the constant. Otherwise
549 // the type of the constant is derived by getting an id from the type manager
550 // for |c|.
551 Instruction* BuildInstructionAndAddToModule(const Constant* c,
552 Module::inst_iterator* pos,
553 uint32_t type_id = 0);
554
555 // A helper function to get the result type of the given instruction. Returns
556 // nullptr if the instruction does not have a type id (type id is 0).
557 Type* GetType(const Instruction* inst) const;
558
559 // A helper function to get the collected normal constant with the given id.
560 // Returns the pointer to the Constant instance in case it is found.
561 // Otherwise, it returns a null pointer.
562 const Constant* FindDeclaredConstant(uint32_t id) const {
563 auto iter = id_to_const_val_.find(id);
564 return (iter != id_to_const_val_.end()) ? iter->second : nullptr;
565 }
566
567 // A helper function to get the id of a collected constant with the pointer
568 // to the Constant instance. Returns 0 in case the constant is not found.
569 uint32_t FindDeclaredConstant(const Constant* c, uint32_t type_id) const;
570
571 // Returns the canonical constant that has the same structure and value as the
572 // given Constant |cst|. If none is found, it returns nullptr.
573 //
574 // TODO: Should be able to give a type id to disambiguate types with the same
575 // structure.
576 const Constant* FindConstant(const Constant* c) const {
577 auto it = const_pool_.find(c);
578 return (it != const_pool_.end()) ? *it : nullptr;
579 }
580
581 // Registers a new constant |cst| in the constant pool. If the constant
582 // existed already, it returns a pointer to the previously existing Constant
583 // in the pool. Otherwise, it returns |cst|.
584 const Constant* RegisterConstant(std::unique_ptr<Constant> cst) {
585 auto ret = const_pool_.insert(cst.get());
586 if (ret.second) {
587 owned_constants_.emplace_back(std::move(cst));
588 }
589 return *ret.first;
590 }
591
592 // A helper function to get a vector of Constant instances with the specified
593 // ids. If it can not find the Constant instance for any one of the ids,
594 // it returns an empty vector.
595 std::vector<const Constant*> GetConstantsFromIds(
596 const std::vector<uint32_t>& ids) const;
597
598 // Returns a vector of constants representing each in operand. If an operand
599 // is not constant its entry is nullptr.
600 std::vector<const Constant*> GetOperandConstants(
601 const Instruction* inst) const;
602
603 // Records a mapping between |inst| and the constant value generated by it.
604 // It returns true if a new Constant was successfully mapped, false if |inst|
605 // generates no constant values.
606 bool MapInst(Instruction* inst) {
607 if (auto cst = GetConstantFromInst(inst)) {
608 MapConstantToInst(cst, inst);
609 return true;
610 }
611 return false;
612 }
613
614 void RemoveId(uint32_t id) {
615 auto it = id_to_const_val_.find(id);
616 if (it != id_to_const_val_.end()) {
617 const_val_to_id_.erase(it->second);
618 id_to_const_val_.erase(it);
619 }
620 }
621
622 // Records a new mapping between |inst| and |const_value|. This updates the
623 // two mappings |id_to_const_val_| and |const_val_to_id_|.
624 void MapConstantToInst(const Constant* const_value, Instruction* inst) {
625 if (id_to_const_val_.insert({inst->result_id(), const_value}).second) {
626 const_val_to_id_.insert({const_value, inst->result_id()});
627 }
628 }
629
630 // Returns the id of a 32-bit floating point constant with value |val|.
631 uint32_t GetFloatConst(float val);
632
633 private:
634 // Creates a Constant instance with the given type and a vector of constant
635 // defining words. Returns a unique pointer to the created Constant instance
636 // if the Constant instance can be created successfully. To create scalar
637 // type constants, the vector should contain the constant value in 32 bit
638 // words and the given type must be of type Bool, Integer or Float. To create
639 // composite type constants, the vector should contain the component ids, and
640 // those component ids should have been recorded before as Normal Constants.
641 // And the given type must be of type Struct, Vector or Array. When creating
642 // VectorType Constant instance, the components must be scalars of the same
643 // type, either Bool, Integer or Float. If any of the rules above failed, the
644 // creation will fail and nullptr will be returned. If the vector is empty,
645 // a NullConstant instance will be created with the given type.
646 std::unique_ptr<Constant> CreateConstant(
647 const Type* type,
648 const std::vector<uint32_t>& literal_words_or_ids) const;
649
650 // Creates an instruction with the given result id to declare a constant
651 // represented by the given Constant instance. Returns an unique pointer to
652 // the created instruction if the instruction can be created successfully.
653 // Otherwise, returns a null pointer.
654 //
655 // |type_id| is an optional argument for disambiguating equivalent types. If
656 // |type_id| is specified, it is used as the type of the constant. Otherwise
657 // the type of the constant is derived by getting an id from the type manager
658 // for |c|.
659 std::unique_ptr<Instruction> CreateInstruction(uint32_t result_id,
660 const Constant* c,
661 uint32_t type_id = 0) const;
662
663 // Creates an OpConstantComposite instruction with the given result id and
664 // the CompositeConst instance which represents a composite constant. Returns
665 // an unique pointer to the created instruction if succeeded. Otherwise
666 // returns a null pointer.
667 //
668 // |type_id| is an optional argument for disambiguating equivalent types. If
669 // |type_id| is specified, it is used as the type of the constant. Otherwise
670 // the type of the constant is derived by getting an id from the type manager
671 // for |c|.
672 std::unique_ptr<Instruction> CreateCompositeInstruction(
673 uint32_t result_id, const CompositeConstant* cc,
674 uint32_t type_id = 0) const;
675
676 // IR context that owns this constant manager.
677 IRContext* ctx_;
678
679 // A mapping from the result ids of Normal Constants to their
680 // Constant instances. All Normal Constants in the module, either
681 // existing ones before optimization or the newly generated ones, should have
682 // their Constant instance stored and their result id registered in this map.
683 std::unordered_map<uint32_t, const Constant*> id_to_const_val_;
684
685 // A mapping from the Constant instance of Normal Constants to their
686 // result id in the module. This is a mirror map of |id_to_const_val_|. All
687 // Normal Constants that defining instructions in the module should have
688 // their Constant and their result id registered here.
689 std::multimap<const Constant*, uint32_t> const_val_to_id_;
690
691 // The constant pool. All created constants are registered here.
692 std::unordered_set<const Constant*, ConstantHash, ConstantEqual> const_pool_;
693
694 // The constant that are owned by the constant manager. Every constant in
695 // |const_pool_| should be in |owned_constants_| as well.
696 std::vector<std::unique_ptr<Constant>> owned_constants_;
697};
698
699} // namespace analysis
700} // namespace opt
701} // namespace spvtools
702
703#endif // SOURCE_OPT_CONSTANTS_H_
704