Merges multiply of constant and negation. Cases: (-x) * 2 = x * -2 2 * (-x) = x * -2
| 890 | // (-x) * 2 = x * -2 |
| 891 | // 2 * (-x) = x * -2 |
| 892 | FoldingRule MergeMulNegateArithmetic() { |
| 893 | return [](IRContext* context, Instruction* inst, |
| 894 | const std::vector<const analysis::Constant*>& constants) { |
| 895 | assert(inst->opcode() == spv::Op::OpFMul || |
| 896 | inst->opcode() == spv::Op::OpIMul); |
| 897 | analysis::ConstantManager* const_mgr = context->get_constant_mgr(); |
| 898 | const analysis::Type* type = |
| 899 | context->get_type_mgr()->GetType(inst->type_id()); |
| 900 | |
| 901 | if (type->IsCooperativeMatrix()) { |
| 902 | return false; |
| 903 | } |
| 904 | |
| 905 | bool uses_float = HasFloatingPoint(type); |
| 906 | if (uses_float && !inst->IsFloatingPointFoldingAllowed()) return false; |
| 907 | |
| 908 | uint32_t width = ElementWidth(type); |
| 909 | if (width != 32 && width != 64) return false; |
| 910 | |
| 911 | const analysis::Constant* const_input1 = ConstInput(constants); |
| 912 | if (!const_input1) return false; |
| 913 | Instruction* other_inst = NonConstInput(context, constants[0], inst); |
| 914 | if (uses_float && !other_inst->IsFloatingPointFoldingAllowed()) |
| 915 | return false; |
| 916 | |
| 917 | if (other_inst->opcode() == spv::Op::OpFNegate || |
| 918 | other_inst->opcode() == spv::Op::OpSNegate) { |
| 919 | uint32_t neg_id = NegateConstant(const_mgr, const_input1); |
| 920 | |
| 921 | inst->SetInOperands( |
| 922 | {{SPV_OPERAND_TYPE_ID, {other_inst->GetSingleWordInOperand(0u)}}, |
| 923 | {SPV_OPERAND_TYPE_ID, {neg_id}}}); |
| 924 | return true; |
| 925 | } |
| 926 | |
| 927 | return false; |
| 928 | }; |
| 929 | } |
| 930 | |
| 931 | // Returns true if |inst| is negation op and is safe to fold. |
| 932 | static bool IsFoldableNegation(const Instruction* inst) { |
no test coverage detected