| 2393 | } |
| 2394 | |
| 2395 | void Differ::MatchConstants() { |
| 2396 | // Bunch all of constant ids as potential matches. |
| 2397 | PotentialIdMap potential_id_map; |
| 2398 | auto get_result_id = [](const opt::Instruction& inst) { |
| 2399 | return inst.result_id(); |
| 2400 | }; |
| 2401 | auto accept_type_ops = [](const opt::Instruction& inst) { |
| 2402 | return spvOpcodeIsConstant(inst.opcode()); |
| 2403 | }; |
| 2404 | |
| 2405 | PoolPotentialIds(src_->types_values(), potential_id_map.src_ids, true, |
| 2406 | accept_type_ops, get_result_id); |
| 2407 | PoolPotentialIds(dst_->types_values(), potential_id_map.dst_ids, false, |
| 2408 | accept_type_ops, get_result_id); |
| 2409 | |
| 2410 | // Then match the ids. Constants are matched exactly, except for float types |
| 2411 | // that are first matched exactly, then leftovers are matched with a small |
| 2412 | // error. |
| 2413 | for (uint32_t flexibility = 0; flexibility < 2; ++flexibility) { |
| 2414 | MatchIds(potential_id_map, [this, flexibility]( |
| 2415 | const opt::Instruction* src_inst, |
| 2416 | const opt::Instruction* dst_inst) { |
| 2417 | const spv::Op src_op = src_inst->opcode(); |
| 2418 | const spv::Op dst_op = dst_inst->opcode(); |
| 2419 | |
| 2420 | // Don't match if the opcode is not the same. |
| 2421 | if (src_op != dst_op) { |
| 2422 | return false; |
| 2423 | } |
| 2424 | |
| 2425 | switch (src_op) { |
| 2426 | case spv::Op::OpConstantTrue: |
| 2427 | case spv::Op::OpConstantFalse: |
| 2428 | // true and false are unique, match them. |
| 2429 | return true; |
| 2430 | case spv::Op::OpConstant: |
| 2431 | return MatchOpConstant(src_inst, dst_inst, flexibility); |
| 2432 | case spv::Op::OpConstantComposite: |
| 2433 | case spv::Op::OpSpecConstantComposite: |
| 2434 | // Composite constants must match in type and value. |
| 2435 | // |
| 2436 | // TODO: match OpConstantNull with OpConstantComposite with all zeros |
| 2437 | // at flexibility == 1 |
| 2438 | // TODO: match constants from structs that have been flexibly-matched. |
| 2439 | if (src_inst->NumInOperandWords() != dst_inst->NumInOperandWords()) { |
| 2440 | return false; |
| 2441 | } |
| 2442 | return DoesOperandMatch(src_inst->GetOperand(0), |
| 2443 | dst_inst->GetOperand(0)) && |
| 2444 | DoOperandsMatch(src_inst, dst_inst, 0, |
| 2445 | src_inst->NumInOperandWords()); |
| 2446 | case spv::Op::OpConstantSampler: |
| 2447 | // Match sampler constants exactly. |
| 2448 | // TODO: Allow flexibility in parameters to better diff shaders where |
| 2449 | // the sampler param has changed. |
| 2450 | assert(src_inst->NumInOperandWords() == |
| 2451 | dst_inst->NumInOperandWords()); |
| 2452 | return DoOperandsMatch(src_inst, dst_inst, 0, |
no test coverage detected