| 572 | } |
| 573 | |
| 574 | Instruction* InstructionFolder::FoldInstructionToConstant( |
| 575 | Instruction* inst, std::function<uint32_t(uint32_t)> id_map) const { |
| 576 | analysis::ConstantManager* const_mgr = context_->get_constant_mgr(); |
| 577 | |
| 578 | if (!inst->IsFoldableByFoldScalar() && !inst->IsFoldableByFoldVector() && |
| 579 | !GetConstantFoldingRules().HasFoldingRule(inst)) { |
| 580 | return nullptr; |
| 581 | } |
| 582 | // Collect the values of the constant parameters. |
| 583 | std::vector<const analysis::Constant*> constants; |
| 584 | bool missing_constants = false; |
| 585 | inst->ForEachInId([&constants, &missing_constants, const_mgr, |
| 586 | &id_map](uint32_t* op_id) { |
| 587 | uint32_t id = id_map(*op_id); |
| 588 | const analysis::Constant* const_op = const_mgr->FindDeclaredConstant(id); |
| 589 | if (!const_op) { |
| 590 | constants.push_back(nullptr); |
| 591 | missing_constants = true; |
| 592 | } else { |
| 593 | constants.push_back(const_op); |
| 594 | } |
| 595 | }); |
| 596 | |
| 597 | const analysis::Constant* folded_const = nullptr; |
| 598 | for (auto rule : GetConstantFoldingRules().GetRulesForInstruction(inst)) { |
| 599 | folded_const = rule(context_, inst, constants); |
| 600 | if (folded_const == nullptr && inst->context()->id_overflow()) { |
| 601 | return nullptr; |
| 602 | } |
| 603 | if (folded_const != nullptr) { |
| 604 | Instruction* const_inst = |
| 605 | const_mgr->GetDefiningInstruction(folded_const, inst->type_id()); |
| 606 | if (const_inst == nullptr) { |
| 607 | return nullptr; |
| 608 | } |
| 609 | assert(const_inst->type_id() == inst->type_id()); |
| 610 | // May be a new instruction that needs to be analysed. |
| 611 | context_->UpdateDefUse(const_inst); |
| 612 | return const_inst; |
| 613 | } |
| 614 | } |
| 615 | |
| 616 | bool successful = false; |
| 617 | |
| 618 | // If all parameters are constant, fold the instruction to a constant. |
| 619 | if (inst->IsFoldableByFoldScalar()) { |
| 620 | uint32_t result_val = 0; |
| 621 | |
| 622 | if (!missing_constants) { |
| 623 | result_val = FoldScalars(inst->opcode(), constants); |
| 624 | successful = true; |
| 625 | } |
| 626 | |
| 627 | if (!successful) { |
| 628 | successful = FoldIntegerOpToConstant(inst, id_map, &result_val); |
| 629 | } |
| 630 | |
| 631 | if (successful) { |