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

Function MergeNegateAddSubArithmetic

source/opt/folding_rules.cpp:509–571  ·  view source on GitHub ↗

Merges negate into a add or sub operation if that operation contains a constant operand. Cases: -(x + 2) = -2 - x -(2 + x) = -2 - x -(x - 2) = 2 - x -(2 - x) = x - 2

Source from the content-addressed store, hash-verified

507// -(x - 2) = 2 - x
508// -(2 - x) = x - 2
509FoldingRule MergeNegateAddSubArithmetic() {
510 return [](IRContext* context, Instruction* inst,
511 const std::vector<const analysis::Constant*>& constants) {
512 assert(inst->opcode() == spv::Op::OpFNegate ||
513 inst->opcode() == spv::Op::OpSNegate);
514 (void)constants;
515 analysis::ConstantManager* const_mgr = context->get_constant_mgr();
516 const analysis::Type* type =
517 context->get_type_mgr()->GetType(inst->type_id());
518
519 if (type->IsCooperativeMatrix()) {
520 return false;
521 }
522
523 if (HasFloatingPoint(type) && !inst->IsFloatingPointFoldingAllowed())
524 return false;
525
526 Instruction* op_inst =
527 context->get_def_use_mgr()->GetDef(inst->GetSingleWordInOperand(0u));
528 if (HasFloatingPoint(type) && !op_inst->IsFloatingPointFoldingAllowed())
529 return false;
530
531 uint32_t width = ElementWidth(type);
532 if (width != 32 && width != 64) return false;
533
534 if (op_inst->opcode() == spv::Op::OpFAdd ||
535 op_inst->opcode() == spv::Op::OpFSub ||
536 op_inst->opcode() == spv::Op::OpIAdd ||
537 op_inst->opcode() == spv::Op::OpISub) {
538 std::vector<const analysis::Constant*> op_constants =
539 const_mgr->GetOperandConstants(op_inst);
540 if (op_constants[0] || op_constants[1]) {
541 bool zero_is_variable = op_constants[0] == nullptr;
542 bool is_add = (op_inst->opcode() == spv::Op::OpFAdd) ||
543 (op_inst->opcode() == spv::Op::OpIAdd);
544 bool swap_operands = !is_add || zero_is_variable;
545 bool negate_const = is_add;
546 const analysis::Constant* c = ConstInput(op_constants);
547 uint32_t const_id = 0;
548 if (negate_const) {
549 const_id = NegateConstant(const_mgr, c);
550 } else {
551 const_id = zero_is_variable ? op_inst->GetSingleWordInOperand(1u)
552 : op_inst->GetSingleWordInOperand(0u);
553 }
554
555 // Swap operands if necessary and make the instruction a subtraction.
556 uint32_t op0 =
557 zero_is_variable ? op_inst->GetSingleWordInOperand(0u) : const_id;
558 uint32_t op1 =
559 zero_is_variable ? const_id : op_inst->GetSingleWordInOperand(1u);
560 if (swap_operands) std::swap(op0, op1);
561 inst->SetOpcode(HasFloatingPoint(type) ? spv::Op::OpFSub
562 : spv::Op::OpISub);
563 inst->SetInOperands(
564 {{SPV_OPERAND_TYPE_ID, {op0}}, {SPV_OPERAND_TYPE_ID, {op1}}});
565 return true;
566 }

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