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

Function MergeNegateMulDivArithmetic

source/opt/folding_rules.cpp:442–500  ·  view source on GitHub ↗

Merges negate into a mul or div operation if that operation contains a constant operand. Cases: -(x * 2) = x * -2 -(2 * x) = x * -2 -(x / 2) = x / -2 -(2 / x) = -2 / x

Source from the content-addressed store, hash-verified

440// -(x / 2) = x / -2
441// -(2 / x) = -2 / x
442FoldingRule MergeNegateMulDivArithmetic() {
443 return [](IRContext* context, Instruction* inst,
444 const std::vector<const analysis::Constant*>& constants) {
445 assert(inst->opcode() == spv::Op::OpFNegate ||
446 inst->opcode() == spv::Op::OpSNegate);
447 (void)constants;
448 analysis::ConstantManager* const_mgr = context->get_constant_mgr();
449 const analysis::Type* type =
450 context->get_type_mgr()->GetType(inst->type_id());
451
452 if (type->IsCooperativeMatrix()) {
453 return false;
454 }
455
456 if (HasFloatingPoint(type) && !inst->IsFloatingPointFoldingAllowed())
457 return false;
458
459 Instruction* op_inst =
460 context->get_def_use_mgr()->GetDef(inst->GetSingleWordInOperand(0u));
461 if (HasFloatingPoint(type) && !op_inst->IsFloatingPointFoldingAllowed())
462 return false;
463
464 uint32_t width = ElementWidth(type);
465 if (width != 32 && width != 64) return false;
466
467 spv::Op opcode = op_inst->opcode();
468 if (opcode != spv::Op::OpFMul && opcode != spv::Op::OpFDiv &&
469 opcode != spv::Op::OpIMul && opcode != spv::Op::OpSDiv) {
470 return false;
471 }
472
473 std::vector<const analysis::Constant*> op_constants =
474 const_mgr->GetOperandConstants(op_inst);
475 // Merge negate into mul or div if one operand is constant.
476 if (op_constants[0] == nullptr && op_constants[1] == nullptr) {
477 return false;
478 }
479
480 bool zero_is_variable = op_constants[0] == nullptr;
481 const analysis::Constant* c = ConstInput(op_constants);
482 uint32_t neg_id = NegateConstant(const_mgr, c);
483 uint32_t non_const_id = zero_is_variable
484 ? op_inst->GetSingleWordInOperand(0u)
485 : op_inst->GetSingleWordInOperand(1u);
486 // Change this instruction to a mul/div.
487 inst->SetOpcode(op_inst->opcode());
488 if (opcode == spv::Op::OpFDiv || opcode == spv::Op::OpUDiv ||
489 opcode == spv::Op::OpSDiv) {
490 uint32_t op0 = zero_is_variable ? non_const_id : neg_id;
491 uint32_t op1 = zero_is_variable ? neg_id : non_const_id;
492 inst->SetInOperands(
493 {{SPV_OPERAND_TYPE_ID, {op0}}, {SPV_OPERAND_TYPE_ID, {op1}}});
494 } else {
495 inst->SetInOperands({{SPV_OPERAND_TYPE_ID, {non_const_id}},
496 {SPV_OPERAND_TYPE_ID, {neg_id}}});
497 }
498 return true;
499 };

Callers 1

AddFoldingRulesMethod · 0.85

Calls 15

ElementWidthFunction · 0.85
ConstInputFunction · 0.85
NegateConstantFunction · 0.85
get_constant_mgrMethod · 0.80
get_type_mgrMethod · 0.80
IsCooperativeMatrixMethod · 0.80
GetOperandConstantsMethod · 0.80
SetOpcodeMethod · 0.80
SetInOperandsMethod · 0.80
HasFloatingPointFunction · 0.70

Tested by

no test coverage detected