Coverage Report

Created: 2026-02-14 06:30

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/spirv-tools/source/opt/constants.cpp
Line
Count
Source
1
// Copyright (c) 2017 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/constants.h"
16
17
#include <vector>
18
19
#include "source/opt/ir_context.h"
20
21
namespace spvtools {
22
namespace opt {
23
namespace analysis {
24
25
851k
float Constant::GetFloat() const {
26
851k
  assert(type()->AsFloat() != nullptr && type()->AsFloat()->width() == 32);
27
28
851k
  if (const FloatConstant* fc = AsFloatConstant()) {
29
830k
    return fc->GetFloatValue();
30
830k
  } else {
31
20.4k
    assert(AsNullConstant() && "Must be a floating point constant.");
32
20.4k
    return 0.0f;
33
20.4k
  }
34
851k
}
35
36
0
double Constant::GetDouble() const {
37
0
  assert(type()->AsFloat() != nullptr && type()->AsFloat()->width() == 64);
38
39
0
  if (const FloatConstant* fc = AsFloatConstant()) {
40
0
    return fc->GetDoubleValue();
41
0
  } else {
42
0
    assert(AsNullConstant() && "Must be a floating point constant.");
43
0
    return 0.0;
44
0
  }
45
0
}
46
47
16.1k
double Constant::GetValueAsDouble() const {
48
16.1k
  assert(type()->AsFloat() != nullptr);
49
16.1k
  if (type()->AsFloat()->width() == 32) {
50
16.1k
    return GetFloat();
51
16.1k
  } else {
52
0
    assert(type()->AsFloat()->width() == 64);
53
0
    return GetDouble();
54
0
  }
55
16.1k
}
56
57
243k
uint32_t Constant::GetU32() const {
58
243k
  assert(type()->AsInteger() != nullptr);
59
243k
  assert(type()->AsInteger()->width() == 32);
60
61
243k
  if (const IntConstant* ic = AsIntConstant()) {
62
242k
    return ic->GetU32BitValue();
63
242k
  } else {
64
808
    assert(AsNullConstant() && "Must be an integer constant.");
65
808
    return 0u;
66
808
  }
67
243k
}
68
69
0
uint64_t Constant::GetU64() const {
70
0
  assert(type()->AsInteger() != nullptr);
71
0
  assert(type()->AsInteger()->width() == 64);
72
73
0
  if (const IntConstant* ic = AsIntConstant()) {
74
0
    return ic->GetU64BitValue();
75
0
  } else {
76
0
    assert(AsNullConstant() && "Must be an integer constant.");
77
0
    return 0u;
78
0
  }
79
0
}
80
81
0
int32_t Constant::GetS32() const {
82
0
  assert(type()->AsInteger() != nullptr);
83
0
  assert(type()->AsInteger()->width() == 32);
84
85
0
  if (const IntConstant* ic = AsIntConstant()) {
86
0
    return ic->GetS32BitValue();
87
0
  } else {
88
0
    assert(AsNullConstant() && "Must be an integer constant.");
89
0
    return 0;
90
0
  }
91
0
}
92
93
0
int64_t Constant::GetS64() const {
94
0
  assert(type()->AsInteger() != nullptr);
95
0
  assert(type()->AsInteger()->width() == 64);
96
97
0
  if (const IntConstant* ic = AsIntConstant()) {
98
0
    return ic->GetS64BitValue();
99
0
  } else {
100
0
    assert(AsNullConstant() && "Must be an integer constant.");
101
0
    return 0;
102
0
  }
103
0
}
104
105
1.44M
uint64_t Constant::GetZeroExtendedValue() const {
106
1.44M
  const auto* int_type = type()->AsInteger();
107
1.44M
  assert(int_type != nullptr);
108
1.44M
  const auto width = int_type->width();
109
1.44M
  assert(width <= 64);
110
111
1.44M
  uint64_t value = 0;
112
1.44M
  if (const IntConstant* ic = AsIntConstant()) {
113
1.44M
    if (width <= 32) {
114
1.44M
      value = ic->GetU32BitValue();
115
1.44M
    } else {
116
0
      value = ic->GetU64BitValue();
117
0
    }
118
1.44M
  } else {
119
456
    assert(AsNullConstant() && "Must be an integer constant.");
120
456
  }
121
1.44M
  return value;
122
1.44M
}
123
124
505k
int64_t Constant::GetSignExtendedValue() const {
125
505k
  const auto* int_type = type()->AsInteger();
126
505k
  assert(int_type != nullptr);
127
505k
  const auto width = int_type->width();
128
505k
  assert(width <= 64);
129
130
505k
  int64_t value = 0;
131
505k
  if (const IntConstant* ic = AsIntConstant()) {
132
505k
    if (width <= 32) {
133
      // Let the C++ compiler do the sign extension.
134
505k
      value = int64_t(ic->GetS32BitValue());
135
505k
    } else {
136
0
      value = ic->GetS64BitValue();
137
0
    }
138
505k
  } else {
139
413
    assert(AsNullConstant() && "Must be an integer constant.");
140
413
  }
141
505k
  return value;
142
505k
}
143
144
28.8k
ConstantManager::ConstantManager(IRContext* ctx) : ctx_(ctx) {
145
  // Populate the constant table with values from constant declarations in the
146
  // module.  The values of each OpConstant declaration is the identity
147
  // assignment (i.e., each constant is its own value).
148
377k
  for (const auto& inst : ctx_->module()->GetConstants()) {
149
377k
    MapInst(inst);
150
377k
  }
151
28.8k
}
152
153
1.15M
Type* ConstantManager::GetType(const Instruction* inst) const {
154
1.15M
  return context()->get_type_mgr()->GetType(inst->type_id());
155
1.15M
}
156
157
std::vector<const Constant*> ConstantManager::GetOperandConstants(
158
8.95M
    const Instruction* inst) const {
159
8.95M
  std::vector<const Constant*> constants;
160
8.95M
  constants.reserve(inst->NumInOperands());
161
24.3M
  for (uint32_t i = 0; i < inst->NumInOperands(); i++) {
162
15.3M
    const Operand* operand = &inst->GetInOperand(i);
163
15.3M
    if (operand->type != SPV_OPERAND_TYPE_ID) {
164
1.48M
      constants.push_back(nullptr);
165
13.9M
    } else {
166
13.9M
      uint32_t id = operand->words[0];
167
13.9M
      const analysis::Constant* constant = FindDeclaredConstant(id);
168
13.9M
      constants.push_back(constant);
169
13.9M
    }
170
15.3M
  }
171
8.95M
  return constants;
172
8.95M
}
173
174
uint32_t ConstantManager::FindDeclaredConstant(const Constant* c,
175
2.43M
                                               uint32_t type_id) const {
176
2.43M
  c = FindConstant(c);
177
2.43M
  if (c == nullptr) {
178
0
    return 0;
179
0
  }
180
181
2.43M
  for (auto range = const_val_to_id_.equal_range(c);
182
2.43M
       range.first != range.second; ++range.first) {
183
2.12M
    Instruction* const_def =
184
2.12M
        context()->get_def_use_mgr()->GetDef(range.first->second);
185
2.12M
    if (type_id == 0 || const_def->type_id() == type_id) {
186
2.12M
      return range.first->second;
187
2.12M
    }
188
2.12M
  }
189
305k
  return 0;
190
2.43M
}
191
192
std::vector<const Constant*> ConstantManager::GetConstantsFromIds(
193
248k
    const std::vector<uint32_t>& ids) const {
194
248k
  std::vector<const Constant*> constants;
195
700k
  for (uint32_t id : ids) {
196
700k
    if (const Constant* c = FindDeclaredConstant(id)) {
197
698k
      constants.push_back(c);
198
698k
    } else {
199
2.02k
      return {};
200
2.02k
    }
201
700k
  }
202
246k
  return constants;
203
248k
}
204
205
Instruction* ConstantManager::BuildInstructionAndAddToModule(
206
305k
    const Constant* new_const, Module::inst_iterator* pos, uint32_t type_id) {
207
  // TODO(1841): Handle id overflow.
208
305k
  uint32_t new_id = context()->TakeNextId();
209
305k
  if (new_id == 0) {
210
0
    return nullptr;
211
0
  }
212
213
305k
  auto new_inst = CreateInstruction(new_id, new_const, type_id);
214
305k
  if (!new_inst) {
215
2
    return nullptr;
216
2
  }
217
305k
  auto* new_inst_ptr = new_inst.get();
218
305k
  *pos = pos->InsertBefore(std::move(new_inst));
219
305k
  ++(*pos);
220
305k
  if (context()->AreAnalysesValid(IRContext::Analysis::kAnalysisDefUse))
221
305k
    context()->get_def_use_mgr()->AnalyzeInstDefUse(new_inst_ptr);
222
305k
  MapConstantToInst(new_const, new_inst_ptr);
223
305k
  return new_inst_ptr;
224
305k
}
225
226
Instruction* ConstantManager::GetDefiningInstruction(
227
2.01M
    const Constant* c, uint32_t type_id, Module::inst_iterator* pos) {
228
2.01M
  uint32_t decl_id = FindDeclaredConstant(c, type_id);
229
2.01M
  if (decl_id == 0) {
230
305k
    auto iter = context()->types_values_end();
231
305k
    if (pos == nullptr) pos = &iter;
232
305k
    return BuildInstructionAndAddToModule(c, pos, type_id);
233
1.71M
  } else {
234
1.71M
    auto def = context()->get_def_use_mgr()->GetDef(decl_id);
235
1.71M
    assert(def != nullptr);
236
1.71M
    assert((type_id == 0 || def->type_id() == type_id) &&
237
1.71M
           "This constant already has an instruction with a different type.");
238
1.71M
    return def;
239
1.71M
  }
240
2.01M
}
241
242
std::unique_ptr<Constant> ConstantManager::CreateConstant(
243
2.72M
    const Type* type, const std::vector<uint32_t>& literal_words_or_ids) const {
244
2.72M
  if (literal_words_or_ids.size() == 0) {
245
    // Constant declared with OpConstantNull
246
20.1k
    return MakeUnique<NullConstant>(type);
247
2.70M
  } else if (auto* bt = type->AsBool()) {
248
349k
    assert(literal_words_or_ids.size() == 1 &&
249
349k
           "Bool constant should be declared with one operand");
250
349k
    return MakeUnique<BoolConstant>(bt, literal_words_or_ids.front());
251
2.35M
  } else if (auto* it = type->AsInteger()) {
252
1.33M
    return MakeUnique<IntConstant>(it, literal_words_or_ids);
253
1.33M
  } else if (auto* ft = type->AsFloat()) {
254
776k
    return MakeUnique<FloatConstant>(ft, literal_words_or_ids);
255
776k
  } else if (auto* vt = type->AsVector()) {
256
237k
    auto components = GetConstantsFromIds(literal_words_or_ids);
257
237k
    if (components.empty()) return nullptr;
258
    // All components of VectorConstant must be of type Bool, Integer or Float.
259
235k
    if (!std::all_of(components.begin(), components.end(),
260
641k
                     [](const Constant* c) {
261
641k
                       if (c->type()->AsBool() || c->type()->AsInteger() ||
262
641k
                           c->type()->AsFloat()) {
263
641k
                         return true;
264
641k
                       } else {
265
0
                         return false;
266
0
                       }
267
641k
                     }))
268
0
      return nullptr;
269
    // All components of VectorConstant must be in the same type.
270
235k
    const auto* component_type = components.front()->type();
271
235k
    if (!std::all_of(components.begin(), components.end(),
272
641k
                     [&component_type](const Constant* c) {
273
641k
                       if (c->type() == component_type) return true;
274
0
                       return false;
275
641k
                     }))
276
0
      return nullptr;
277
235k
    return MakeUnique<VectorConstant>(vt, components);
278
235k
  } else if (auto* mt = type->AsMatrix()) {
279
227
    auto components = GetConstantsFromIds(literal_words_or_ids);
280
227
    if (components.empty()) return nullptr;
281
216
    return MakeUnique<MatrixConstant>(mt, components);
282
10.2k
  } else if (auto* st = type->AsStruct()) {
283
7.68k
    auto components = GetConstantsFromIds(literal_words_or_ids);
284
7.68k
    if (components.empty()) return nullptr;
285
7.64k
    return MakeUnique<StructConstant>(st, components);
286
7.68k
  } else if (auto* at = type->AsArray()) {
287
2.56k
    auto components = GetConstantsFromIds(literal_words_or_ids);
288
2.56k
    if (components.empty()) return nullptr;
289
2.34k
    return MakeUnique<ArrayConstant>(at, components);
290
2.56k
  } else {
291
23
    return nullptr;
292
23
  }
293
2.72M
}
294
295
825k
const Constant* ConstantManager::GetConstantFromInst(const Instruction* inst) {
296
825k
  std::vector<uint32_t> literal_words_or_ids;
297
298
  // Collect the constant defining literals or component ids.
299
1.81M
  for (uint32_t i = 0; i < inst->NumInOperands(); i++) {
300
994k
    literal_words_or_ids.insert(literal_words_or_ids.end(),
301
994k
                                inst->GetInOperand(i).words.begin(),
302
994k
                                inst->GetInOperand(i).words.end());
303
994k
  }
304
305
825k
  switch (inst->opcode()) {
306
    // OpConstant{True|False} have the value embedded in the opcode. So they
307
    // are not handled by the for-loop above. Here we add the value explicitly.
308
11.3k
    case spv::Op::OpConstantTrue:
309
11.3k
      literal_words_or_ids.push_back(true);
310
11.3k
      break;
311
7.50k
    case spv::Op::OpConstantFalse:
312
7.50k
      literal_words_or_ids.push_back(false);
313
7.50k
      break;
314
3.63k
    case spv::Op::OpConstantNull:
315
697k
    case spv::Op::OpConstant:
316
746k
    case spv::Op::OpConstantComposite:
317
747k
    case spv::Op::OpSpecConstantComposite:
318
747k
    case spv::Op::OpSpecConstantCompositeReplicateEXT:
319
747k
      break;
320
59.1k
    default:
321
59.1k
      return nullptr;
322
825k
  }
323
324
766k
  return GetConstant(GetType(inst), literal_words_or_ids);
325
825k
}
326
327
std::unique_ptr<Instruction> ConstantManager::CreateInstruction(
328
305k
    uint32_t id, const Constant* c, uint32_t type_id) const {
329
305k
  uint32_t type =
330
305k
      (type_id == 0) ? context()->get_type_mgr()->GetId(c->type()) : type_id;
331
305k
  if (c->AsNullConstant()) {
332
884
    return MakeUnique<Instruction>(context(), spv::Op::OpConstantNull, type, id,
333
884
                                   std::initializer_list<Operand>{});
334
304k
  } else if (const BoolConstant* bc = c->AsBoolConstant()) {
335
12.3k
    return MakeUnique<Instruction>(
336
12.3k
        context(),
337
12.3k
        bc->value() ? spv::Op::OpConstantTrue : spv::Op::OpConstantFalse, type,
338
12.3k
        id, std::initializer_list<Operand>{});
339
292k
  } else if (const IntConstant* ic = c->AsIntConstant()) {
340
158k
    return MakeUnique<Instruction>(
341
158k
        context(), spv::Op::OpConstant, type, id,
342
158k
        std::initializer_list<Operand>{
343
158k
            Operand(spv_operand_type_t::SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER,
344
158k
                    ic->words())});
345
158k
  } else if (const FloatConstant* fc = c->AsFloatConstant()) {
346
84.6k
    return MakeUnique<Instruction>(
347
84.6k
        context(), spv::Op::OpConstant, type, id,
348
84.6k
        std::initializer_list<Operand>{
349
84.6k
            Operand(spv_operand_type_t::SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER,
350
84.6k
                    fc->words())});
351
84.6k
  } else if (const CompositeConstant* cc = c->AsCompositeConstant()) {
352
48.7k
    return CreateCompositeInstruction(id, cc, type_id);
353
48.7k
  } else {
354
0
    return nullptr;
355
0
  }
356
305k
}
357
358
std::unique_ptr<Instruction> ConstantManager::CreateCompositeInstruction(
359
48.7k
    uint32_t result_id, const CompositeConstant* cc, uint32_t type_id) const {
360
48.7k
  std::vector<Operand> operands;
361
48.7k
  Instruction* type_inst = context()->get_def_use_mgr()->GetDef(type_id);
362
48.7k
  uint32_t component_index = 0;
363
141k
  for (const Constant* component_const : cc->GetComponents()) {
364
141k
    uint32_t component_type_id = 0;
365
141k
    if (type_inst && type_inst->opcode() == spv::Op::OpTypeStruct) {
366
7.31k
      component_type_id = type_inst->GetSingleWordInOperand(component_index);
367
134k
    } else if (type_inst && type_inst->opcode() == spv::Op::OpTypeArray) {
368
106
      component_type_id = type_inst->GetSingleWordInOperand(0);
369
106
    }
370
141k
    uint32_t id = FindDeclaredConstant(component_const, component_type_id);
371
372
141k
    if (id == 0) {
373
      // Cannot get the id of the component constant, while all components
374
      // should have been added to the module prior to the composite constant.
375
      // Cannot create OpConstantComposite instruction in this case.
376
2
      return nullptr;
377
2
    }
378
141k
    operands.emplace_back(spv_operand_type_t::SPV_OPERAND_TYPE_ID,
379
141k
                          std::initializer_list<uint32_t>{id});
380
141k
    component_index++;
381
141k
  }
382
48.7k
  uint32_t type =
383
48.7k
      (type_id == 0) ? context()->get_type_mgr()->GetId(cc->type()) : type_id;
384
48.7k
  return MakeUnique<Instruction>(context(), spv::Op::OpConstantComposite, type,
385
48.7k
                                 result_id, std::move(operands));
386
48.7k
}
387
388
const Constant* ConstantManager::GetConstant(
389
2.72M
    const Type* type, const std::vector<uint32_t>& literal_words_or_ids) {
390
2.72M
  auto cst = CreateConstant(type, literal_words_or_ids);
391
2.72M
  return cst ? RegisterConstant(std::move(cst)) : nullptr;
392
2.72M
}
393
394
25
const Constant* ConstantManager::GetNullCompositeConstant(const Type* type) {
395
25
  std::vector<uint32_t> literal_words_or_id;
396
397
25
  if (type->AsVector()) {
398
25
    const Type* element_type = type->AsVector()->element_type();
399
25
    const uint32_t null_id = GetNullConstId(element_type);
400
25
    const uint32_t element_count = type->AsVector()->element_count();
401
75
    for (uint32_t i = 0; i < element_count; i++) {
402
50
      literal_words_or_id.push_back(null_id);
403
50
    }
404
25
  } else if (type->AsMatrix()) {
405
0
    const Type* element_type = type->AsMatrix()->element_type();
406
0
    const uint32_t null_id = GetNullConstId(element_type);
407
0
    const uint32_t element_count = type->AsMatrix()->element_count();
408
0
    for (uint32_t i = 0; i < element_count; i++) {
409
0
      literal_words_or_id.push_back(null_id);
410
0
    }
411
0
  } else if (type->AsStruct()) {
412
    // TODO (sfricke-lunarg) add proper struct support
413
0
    return nullptr;
414
0
  } else if (type->AsArray()) {
415
0
    const Type* element_type = type->AsArray()->element_type();
416
0
    const uint32_t null_id = GetNullConstId(element_type);
417
0
    assert(type->AsArray()->length_info().words[0] ==
418
0
               analysis::Array::LengthInfo::kConstant &&
419
0
           "unexpected array length");
420
0
    const uint32_t element_count = type->AsArray()->length_info().words[0];
421
0
    for (uint32_t i = 0; i < element_count; i++) {
422
0
      literal_words_or_id.push_back(null_id);
423
0
    }
424
0
  } else {
425
0
    return nullptr;
426
0
  }
427
428
25
  return GetConstant(type, literal_words_or_id);
429
25
}
430
431
const Constant* ConstantManager::GetNumericVectorConstantWithWords(
432
676
    const Vector* type, const std::vector<uint32_t>& literal_words) {
433
676
  const auto* element_type = type->element_type();
434
676
  uint32_t words_per_element = 0;
435
676
  if (const auto* float_type = element_type->AsFloat())
436
34
    words_per_element = float_type->width() / 32;
437
642
  else if (const auto* int_type = element_type->AsInteger())
438
642
    words_per_element = int_type->width() / 32;
439
0
  else if (element_type->AsBool() != nullptr)
440
0
    words_per_element = 1;
441
442
676
  if (words_per_element != 1 && words_per_element != 2) return nullptr;
443
444
676
  if (words_per_element * type->element_count() !=
445
676
      static_cast<uint32_t>(literal_words.size())) {
446
0
    return nullptr;
447
0
  }
448
449
676
  std::vector<uint32_t> element_ids;
450
2.25k
  for (uint32_t i = 0; i < type->element_count(); ++i) {
451
1.57k
    auto first_word = literal_words.begin() + (words_per_element * i);
452
1.57k
    std::vector<uint32_t> const_data(first_word,
453
1.57k
                                     first_word + words_per_element);
454
1.57k
    const analysis::Constant* element_constant =
455
1.57k
        GetConstant(element_type, const_data);
456
1.57k
    auto element_id = GetDefiningInstruction(element_constant)->result_id();
457
1.57k
    element_ids.push_back(element_id);
458
1.57k
  }
459
460
676
  return GetConstant(type, element_ids);
461
676
}
462
463
0
uint32_t ConstantManager::GetFloatConstId(float val) {
464
0
  const Constant* c = GetFloatConst(val);
465
0
  Instruction* inst = GetDefiningInstruction(c);
466
0
  if (inst == nullptr) return 0;
467
0
  return inst->result_id();
468
0
}
469
470
8.19k
const Constant* ConstantManager::GetFloatConst(float val) {
471
8.19k
  Type* float_type = context()->get_type_mgr()->GetFloatType();
472
8.19k
  utils::FloatProxy<float> v(val);
473
8.19k
  const Constant* c = GetConstant(float_type, v.GetWords());
474
8.19k
  return c;
475
8.19k
}
476
477
0
uint32_t ConstantManager::GetDoubleConstId(double val) {
478
0
  const Constant* c = GetDoubleConst(val);
479
0
  Instruction* inst = GetDefiningInstruction(c);
480
0
  if (inst == nullptr) return 0;
481
0
  return inst->result_id();
482
0
}
483
484
0
const Constant* ConstantManager::GetDoubleConst(double val) {
485
0
  Type* float_type = context()->get_type_mgr()->GetDoubleType();
486
0
  utils::FloatProxy<double> v(val);
487
0
  const Constant* c = GetConstant(float_type, v.GetWords());
488
0
  return c;
489
0
}
490
491
0
uint32_t ConstantManager::GetSIntConstId(int32_t val) {
492
0
  Type* sint_type = context()->get_type_mgr()->GetSIntType();
493
0
  const Constant* c = GetConstant(sint_type, {static_cast<uint32_t>(val)});
494
0
  return GetDefiningInstruction(c)->result_id();
495
0
}
496
497
const Constant* ConstantManager::GetIntConst(uint64_t val, int32_t bitWidth,
498
2.43k
                                             bool isSigned) {
499
2.43k
  Type* int_type = context()->get_type_mgr()->GetIntType(bitWidth, isSigned);
500
501
2.43k
  if (isSigned) {
502
    // Sign extend the value.
503
2.06k
    int32_t num_of_bit_to_ignore = 64 - bitWidth;
504
2.06k
    val = static_cast<int64_t>(val << num_of_bit_to_ignore) >>
505
2.06k
          num_of_bit_to_ignore;
506
2.06k
  } else if (bitWidth < 64) {
507
    // Clear the upper bit that are not used.
508
368
    uint64_t mask = ((1ull << bitWidth) - 1);
509
368
    val &= mask;
510
368
  }
511
512
2.43k
  if (bitWidth <= 32) {
513
2.43k
    return GetConstant(int_type, {static_cast<uint32_t>(val)});
514
2.43k
  }
515
516
  // If the value is more than 32-bit, we need to split the operands into two
517
  // 32-bit integers.
518
0
  return GetConstant(
519
0
      int_type, {static_cast<uint32_t>(val), static_cast<uint32_t>(val >> 32)});
520
2.43k
}
521
522
0
uint32_t ConstantManager::GetUIntConstId(uint32_t val) {
523
0
  Type* uint_type = context()->get_type_mgr()->GetUIntType();
524
0
  const Constant* c = GetConstant(uint_type, {val});
525
0
  return GetDefiningInstruction(c)->result_id();
526
0
}
527
528
1.84k
uint32_t ConstantManager::GetNullConstId(const Type* type) {
529
1.84k
  const Constant* c = GetConstant(type, {});
530
1.84k
  return GetDefiningInstruction(c)->result_id();
531
1.84k
}
532
533
const Constant* ConstantManager::GenerateIntegerConstant(
534
645k
    const analysis::Integer* integer_type, uint64_t result) {
535
645k
  assert(integer_type != nullptr);
536
537
645k
  std::vector<uint32_t> words;
538
645k
  if (integer_type->width() == 64) {
539
    // In the 64-bit case, two words are needed to represent the value.
540
0
    words = {static_cast<uint32_t>(result),
541
0
             static_cast<uint32_t>(result >> 32)};
542
645k
  } else {
543
    // In all other cases, only a single word is needed.
544
645k
    assert(integer_type->width() <= 32);
545
645k
    if (integer_type->IsSigned()) {
546
630k
      result = utils::SignExtendValue(result, integer_type->width());
547
630k
    } else {
548
14.8k
      result = utils::ZeroExtendValue(result, integer_type->width());
549
14.8k
    }
550
645k
    words = {static_cast<uint32_t>(result)};
551
645k
  }
552
645k
  return GetConstant(integer_type, words);
553
645k
}
554
555
std::vector<const analysis::Constant*> Constant::GetVectorComponents(
556
91.9k
    analysis::ConstantManager* const_mgr) const {
557
91.9k
  std::vector<const analysis::Constant*> components;
558
91.9k
  const analysis::VectorConstant* a = this->AsVectorConstant();
559
91.9k
  const analysis::Vector* vector_type = this->type()->AsVector();
560
91.9k
  assert(vector_type != nullptr);
561
91.9k
  if (a != nullptr) {
562
372k
    for (uint32_t i = 0; i < vector_type->element_count(); ++i) {
563
290k
      components.push_back(a->GetComponents()[i]);
564
290k
    }
565
81.8k
  } else {
566
10.1k
    const analysis::Type* element_type = vector_type->element_type();
567
10.1k
    const analysis::Constant* element_null_const =
568
10.1k
        const_mgr->GetConstant(element_type, {});
569
36.2k
    for (uint32_t i = 0; i < vector_type->element_count(); ++i) {
570
26.0k
      components.push_back(element_null_const);
571
26.0k
    }
572
10.1k
  }
573
91.9k
  return components;
574
91.9k
}
575
576
}  // namespace analysis
577
}  // namespace opt
578
}  // namespace spvtools