Folds addition, where one side is a negation. (-x) + y = y - x y + (-x) = y - x
| 1164 | // (-x) + y = y - x |
| 1165 | // y + (-x) = y - x |
| 1166 | FoldingRule MergeAddNegateArithmetic() { |
| 1167 | return [](IRContext* context, Instruction* inst, |
| 1168 | const std::vector<const analysis::Constant*>&) { |
| 1169 | assert(inst->opcode() == spv::Op::OpFAdd || |
| 1170 | inst->opcode() == spv::Op::OpIAdd); |
| 1171 | const analysis::Type* type = |
| 1172 | context->get_type_mgr()->GetType(inst->type_id()); |
| 1173 | bool uses_float = HasFloatingPoint(type); |
| 1174 | if (uses_float && !inst->IsFloatingPointFoldingAllowed()) return false; |
| 1175 | |
| 1176 | analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr(); |
| 1177 | Instruction* lhs = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0)); |
| 1178 | Instruction* rhs = def_use_mgr->GetDef(inst->GetSingleWordInOperand(1)); |
| 1179 | |
| 1180 | auto TrySubstitute = [inst, uses_float](Instruction* first, |
| 1181 | Instruction* second) { |
| 1182 | if (IsFoldableNegation(first)) { |
| 1183 | inst->SetOpcode(uses_float ? spv::Op::OpFSub : spv::Op::OpISub); |
| 1184 | inst->SetInOperands( |
| 1185 | {{SPV_OPERAND_TYPE_ID, {second->result_id()}}, |
| 1186 | {SPV_OPERAND_TYPE_ID, {first->GetSingleWordInOperand(0u)}}}); |
| 1187 | return true; |
| 1188 | } |
| 1189 | return false; |
| 1190 | }; |
| 1191 | |
| 1192 | return TrySubstitute(lhs, rhs) || TrySubstitute(rhs, lhs); |
| 1193 | }; |
| 1194 | } |
| 1195 | |
| 1196 | // Folds subtraction, where one side is a negation. |
| 1197 | // Cases: |
no test coverage detected