Coverage Report

Created: 2024-09-11 07:09

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