MCPcopy Create free account
hub / github.com/KhronosGroup/SPIRV-Tools / ReassociateNestedMulDivFloat

Function ReassociateNestedMulDivFloat

source/opt/folding_rules.cpp:1731–1870  ·  view source on GitHub ↗

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)

Source from the content-addressed store, hash-verified

1729// (C0 / a) * (b / C1) = (C0 / C1) * (b / a)
1730// (a / C0) / (b * C1) = (1 / (C0 * C1)) * (a / b)
1731FoldingRule 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;

Callers 1

AddFoldingRulesMethod · 0.85

Calls 15

ElementWidthFunction · 0.85
ReciprocalFunction · 0.85
PerformOperationFunction · 0.85
get_type_mgrMethod · 0.80
IsCooperativeMatrixMethod · 0.80
get_constant_mgrMethod · 0.80
GetOperandConstantsMethod · 0.80
AddBinaryOpMethod · 0.80
SetOpcodeMethod · 0.80
SetInOperandsMethod · 0.80

Tested by

no test coverage detected