Merges consecutive multiplies where each contains one constant operand. Cases: 2 * (x * 2) = x * 4 2 * (2 * x) = x * 4 (x * 2) * 2 = x * 4 (2 * x) * 2 = x * 4
| 753 | // (x * 2) * 2 = x * 4 |
| 754 | // (2 * x) * 2 = x * 4 |
| 755 | FoldingRule MergeMulMulArithmetic() { |
| 756 | return [](IRContext* context, Instruction* inst, |
| 757 | const std::vector<const analysis::Constant*>& constants) { |
| 758 | assert(inst->opcode() == spv::Op::OpFMul || |
| 759 | inst->opcode() == spv::Op::OpIMul); |
| 760 | analysis::ConstantManager* const_mgr = context->get_constant_mgr(); |
| 761 | const analysis::Type* type = |
| 762 | context->get_type_mgr()->GetType(inst->type_id()); |
| 763 | |
| 764 | if (type->IsCooperativeMatrix()) { |
| 765 | return false; |
| 766 | } |
| 767 | |
| 768 | if (HasFloatingPoint(type) && !inst->IsFloatingPointFoldingAllowed()) |
| 769 | return false; |
| 770 | |
| 771 | uint32_t width = ElementWidth(type); |
| 772 | if (width != 32 && width != 64) return false; |
| 773 | |
| 774 | // Determine the constant input and the variable input in |inst|. |
| 775 | const analysis::Constant* const_input1 = ConstInput(constants); |
| 776 | if (!const_input1) return false; |
| 777 | Instruction* other_inst = NonConstInput(context, constants[0], inst); |
| 778 | if (HasFloatingPoint(type) && !other_inst->IsFloatingPointFoldingAllowed()) |
| 779 | return false; |
| 780 | |
| 781 | if (other_inst->opcode() == inst->opcode()) { |
| 782 | std::vector<const analysis::Constant*> other_constants = |
| 783 | const_mgr->GetOperandConstants(other_inst); |
| 784 | const analysis::Constant* const_input2 = ConstInput(other_constants); |
| 785 | if (!const_input2) return false; |
| 786 | |
| 787 | bool other_first_is_variable = other_constants[0] == nullptr; |
| 788 | uint32_t merged_id = PerformOperation(const_mgr, inst->opcode(), |
| 789 | const_input1, const_input2); |
| 790 | if (merged_id == 0) return false; |
| 791 | |
| 792 | uint32_t non_const_id = other_first_is_variable |
| 793 | ? other_inst->GetSingleWordInOperand(0u) |
| 794 | : other_inst->GetSingleWordInOperand(1u); |
| 795 | inst->SetInOperands({{SPV_OPERAND_TYPE_ID, {non_const_id}}, |
| 796 | {SPV_OPERAND_TYPE_ID, {merged_id}}}); |
| 797 | return true; |
| 798 | } |
| 799 | |
| 800 | return false; |
| 801 | }; |
| 802 | } |
| 803 | |
| 804 | // Merges divides into subsequent multiplies if each instruction contains one |
| 805 | // constant operand. Does not support integer operations. |
no test coverage detected