Folds addition of an addition where each operation has a constant operand. Cases: (x + 2) + 2 = x + 4 (2 + x) + 2 = x + 4 2 + (x + 2) = x + 4 2 + (2 + x) = x + 4
| 1245 | // 2 + (x + 2) = x + 4 |
| 1246 | // 2 + (2 + x) = x + 4 |
| 1247 | FoldingRule MergeAddAddArithmetic() { |
| 1248 | return [](IRContext* context, Instruction* inst, |
| 1249 | const std::vector<const analysis::Constant*>& constants) { |
| 1250 | assert(inst->opcode() == spv::Op::OpFAdd || |
| 1251 | inst->opcode() == spv::Op::OpIAdd); |
| 1252 | const analysis::Type* type = |
| 1253 | context->get_type_mgr()->GetType(inst->type_id()); |
| 1254 | |
| 1255 | if (type->IsCooperativeMatrix()) { |
| 1256 | return false; |
| 1257 | } |
| 1258 | |
| 1259 | analysis::ConstantManager* const_mgr = context->get_constant_mgr(); |
| 1260 | bool uses_float = HasFloatingPoint(type); |
| 1261 | if (uses_float && !inst->IsFloatingPointFoldingAllowed()) return false; |
| 1262 | |
| 1263 | uint32_t width = ElementWidth(type); |
| 1264 | if (width != 32 && width != 64) return false; |
| 1265 | |
| 1266 | const analysis::Constant* const_input1 = ConstInput(constants); |
| 1267 | if (!const_input1) return false; |
| 1268 | Instruction* other_inst = NonConstInput(context, constants[0], inst); |
| 1269 | if (uses_float && !other_inst->IsFloatingPointFoldingAllowed()) |
| 1270 | return false; |
| 1271 | |
| 1272 | if (other_inst->opcode() == spv::Op::OpFAdd || |
| 1273 | other_inst->opcode() == spv::Op::OpIAdd) { |
| 1274 | std::vector<const analysis::Constant*> other_constants = |
| 1275 | const_mgr->GetOperandConstants(other_inst); |
| 1276 | const analysis::Constant* const_input2 = ConstInput(other_constants); |
| 1277 | if (!const_input2) return false; |
| 1278 | |
| 1279 | Instruction* non_const_input = |
| 1280 | NonConstInput(context, other_constants[0], other_inst); |
| 1281 | uint32_t merged_id = PerformOperation(const_mgr, inst->opcode(), |
| 1282 | const_input1, const_input2); |
| 1283 | if (merged_id == 0) return false; |
| 1284 | |
| 1285 | inst->SetInOperands( |
| 1286 | {{SPV_OPERAND_TYPE_ID, {non_const_input->result_id()}}, |
| 1287 | {SPV_OPERAND_TYPE_ID, {merged_id}}}); |
| 1288 | return true; |
| 1289 | } |
| 1290 | return false; |
| 1291 | }; |
| 1292 | } |
| 1293 | |
| 1294 | // Folds addition of a subtraction where each operation has a constant operand. |
| 1295 | // Cases: |
no test coverage detected