| 285 | } |
| 286 | |
| 287 | ConstantFoldingRule FoldVectorTimesScalar() { |
| 288 | return [](IRContext* context, Instruction* inst, |
| 289 | const std::vector<const analysis::Constant*>& constants) |
| 290 | -> const analysis::Constant* { |
| 291 | assert(inst->opcode() == spv::Op::OpVectorTimesScalar); |
| 292 | analysis::ConstantManager* const_mgr = context->get_constant_mgr(); |
| 293 | analysis::TypeManager* type_mgr = context->get_type_mgr(); |
| 294 | |
| 295 | if (!inst->IsFloatingPointFoldingAllowed()) { |
| 296 | if (HasFloatingPoint(type_mgr->GetType(inst->type_id()))) { |
| 297 | return nullptr; |
| 298 | } |
| 299 | } |
| 300 | |
| 301 | const analysis::Constant* c1 = constants[0]; |
| 302 | const analysis::Constant* c2 = constants[1]; |
| 303 | |
| 304 | if (c1 && c1->IsZero()) { |
| 305 | return c1; |
| 306 | } |
| 307 | |
| 308 | if (c2 && c2->IsZero()) { |
| 309 | // Get or create the NullConstant for this type. |
| 310 | std::vector<uint32_t> ids; |
| 311 | return const_mgr->GetConstant(type_mgr->GetType(inst->type_id()), ids); |
| 312 | } |
| 313 | |
| 314 | if (c1 == nullptr || c2 == nullptr) { |
| 315 | return nullptr; |
| 316 | } |
| 317 | |
| 318 | // Check result type. |
| 319 | const analysis::Type* result_type = type_mgr->GetType(inst->type_id()); |
| 320 | const analysis::Vector* vector_type = result_type->AsVector(); |
| 321 | assert(vector_type != nullptr); |
| 322 | const analysis::Type* element_type = vector_type->element_type(); |
| 323 | assert(element_type != nullptr); |
| 324 | const analysis::Float* float_type = element_type->AsFloat(); |
| 325 | assert(float_type != nullptr); |
| 326 | |
| 327 | // Check types of c1 and c2. |
| 328 | assert(c1->type()->AsVector() == vector_type); |
| 329 | assert(c1->type()->AsVector()->element_type() == element_type && |
| 330 | c2->type() == element_type); |
| 331 | |
| 332 | // Get a float vector that is the result of vector-times-scalar. |
| 333 | std::vector<const analysis::Constant*> c1_components = |
| 334 | c1->GetVectorComponents(const_mgr); |
| 335 | std::vector<uint32_t> ids; |
| 336 | if (float_type->width() == 32) { |
| 337 | float scalar = c2->GetFloat(); |
| 338 | for (uint32_t i = 0; i < c1_components.size(); ++i) { |
| 339 | utils::FloatProxy<float> result(c1_components[i]->GetFloat() * scalar); |
| 340 | std::vector<uint32_t> words = result.GetWords(); |
| 341 | const analysis::Constant* new_elem = |
| 342 | const_mgr->GetConstant(float_type, words); |
| 343 | ids.push_back(const_mgr->GetDefiningInstruction(new_elem)->result_id()); |
| 344 | } |
no test coverage detected