Reassociate floating point mul/div instructions, which have mul/div inputs, both of which contain a constant. e.g: (a * C0) / (C1 / b) = (C0 / C1) * (a * b) (C0 / a) * (b / C1) = (C0 / C1) * (b / a) (a / C0) / (b * C1) = (1 / (C0 * C1)) * (a / b)
| 1729 | // (C0 / a) * (b / C1) = (C0 / C1) * (b / a) |
| 1730 | // (a / C0) / (b * C1) = (1 / (C0 * C1)) * (a / b) |
| 1731 | FoldingRule ReassociateNestedMulDivFloat() { |
| 1732 | return [](IRContext* context, Instruction* inst, |
| 1733 | const std::vector<const analysis::Constant*>& constants) { |
| 1734 | assert(inst->opcode() == spv::Op::OpFMul || |
| 1735 | inst->opcode() == spv::Op::OpFDiv); |
| 1736 | |
| 1737 | // Handled by other folding rules. |
| 1738 | if (constants[0] || constants[1]) { |
| 1739 | return false; |
| 1740 | } |
| 1741 | |
| 1742 | const analysis::Type* type = |
| 1743 | context->get_type_mgr()->GetType(inst->type_id()); |
| 1744 | |
| 1745 | if (type->IsCooperativeMatrix()) { |
| 1746 | return false; |
| 1747 | } |
| 1748 | |
| 1749 | uint32_t width = ElementWidth(type); |
| 1750 | if (width != 32 && width != 64) return false; |
| 1751 | |
| 1752 | if (!inst->IsFloatingPointFoldingAllowed()) return false; |
| 1753 | |
| 1754 | analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr(); |
| 1755 | Instruction* lhs = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0)); |
| 1756 | Instruction* rhs = def_use_mgr->GetDef(inst->GetSingleWordInOperand(1)); |
| 1757 | |
| 1758 | bool lhs_is_mul = lhs->opcode() == spv::Op::OpFMul; |
| 1759 | bool lhs_is_div = lhs->opcode() == spv::Op::OpFDiv; |
| 1760 | bool rhs_is_mul = rhs->opcode() == spv::Op::OpFMul; |
| 1761 | bool rhs_is_div = rhs->opcode() == spv::Op::OpFDiv; |
| 1762 | if (!(lhs_is_mul || lhs_is_div) || !(rhs_is_mul || rhs_is_div)) { |
| 1763 | return false; |
| 1764 | } |
| 1765 | |
| 1766 | if (!lhs->IsFloatingPointFoldingAllowed() || |
| 1767 | !rhs->IsFloatingPointFoldingAllowed()) { |
| 1768 | return false; |
| 1769 | } |
| 1770 | |
| 1771 | analysis::ConstantManager* const_mgr = context->get_constant_mgr(); |
| 1772 | std::vector<const analysis::Constant*> lhs_constants = |
| 1773 | const_mgr->GetOperandConstants(lhs); |
| 1774 | if (!lhs_constants[0] && !lhs_constants[1]) { |
| 1775 | return false; |
| 1776 | } |
| 1777 | |
| 1778 | std::vector<const analysis::Constant*> rhs_constants = |
| 1779 | const_mgr->GetOperandConstants(rhs); |
| 1780 | if (!rhs_constants[0] && !rhs_constants[1]) { |
| 1781 | return false; |
| 1782 | } |
| 1783 | |
| 1784 | const analysis::Constant* lhs_const = |
| 1785 | lhs_constants[0] ? lhs_constants[0] : lhs_constants[1]; |
| 1786 | const analysis::Constant* rhs_const = |
| 1787 | rhs_constants[0] ? rhs_constants[0] : rhs_constants[1]; |
| 1788 | if (!lhs_const || !rhs_const) return false; |
no test coverage detected