spirv-fuzz: Restrict fuzzer pass to reachable blocks (#3970)
diff --git a/source/fuzz/fuzzer_pass_replace_opphi_ids_from_dead_predecessors.cpp b/source/fuzz/fuzzer_pass_replace_opphi_ids_from_dead_predecessors.cpp
index 080ace8..433cf74 100644
--- a/source/fuzz/fuzzer_pass_replace_opphi_ids_from_dead_predecessors.cpp
+++ b/source/fuzz/fuzzer_pass_replace_opphi_ids_from_dead_predecessors.cpp
@@ -35,76 +35,80 @@
// Keep a vector of the transformations to apply.
std::vector<TransformationReplaceOpPhiIdFromDeadPredecessor> transformations;
- // Loop through the blocks in the module.
+ // Loop through the reachable blocks in the module.
for (auto& function : *GetIRContext()->module()) {
- for (auto& block : function) {
- // Only consider dead blocks.
- if (!GetTransformationContext()->GetFactManager()->BlockIsDead(
- block.id())) {
- continue;
- }
+ GetIRContext()->cfg()->ForEachBlockInPostOrder(
+ &*function.begin(),
+ [this, &function, &transformations](opt::BasicBlock* block) {
+ // Only consider dead blocks.
+ if (!GetTransformationContext()->GetFactManager()->BlockIsDead(
+ block->id())) {
+ return;
+ }
- // Find all the uses of the label id of the block inside OpPhi
- // instructions.
- GetIRContext()->get_def_use_mgr()->ForEachUse(
- block.id(), [this, &function, &block, &transformations](
- opt::Instruction* instruction, uint32_t) {
- // Only consider OpPhi instructions.
- if (instruction->opcode() != SpvOpPhi) {
- return;
- }
+ // Find all the uses of the label id of the block inside OpPhi
+ // instructions.
+ GetIRContext()->get_def_use_mgr()->ForEachUse(
+ block->id(), [this, &function, block, &transformations](
+ opt::Instruction* instruction, uint32_t) {
+ // Only consider OpPhi instructions.
+ if (instruction->opcode() != SpvOpPhi) {
+ return;
+ }
- // Randomly decide whether to consider this use.
- if (!GetFuzzerContext()->ChoosePercentage(
- GetFuzzerContext()
- ->GetChanceOfReplacingOpPhiIdFromDeadPredecessor())) {
- return;
- }
+ // Randomly decide whether to consider this use.
+ if (!GetFuzzerContext()->ChoosePercentage(
+ GetFuzzerContext()
+ ->GetChanceOfReplacingOpPhiIdFromDeadPredecessor())) {
+ return;
+ }
- // Get the current id corresponding to the predecessor.
- uint32_t current_id = 0;
- for (uint32_t i = 1; i < instruction->NumInOperands(); i += 2) {
- if (instruction->GetSingleWordInOperand(i) == block.id()) {
- // The corresponding id is at the index of the block - 1.
- current_id = instruction->GetSingleWordInOperand(i - 1);
- break;
- }
- }
- assert(current_id != 0 &&
- "The predecessor - and corresponding id - should always be "
- "found.");
+ // Get the current id corresponding to the predecessor.
+ uint32_t current_id = 0;
+ for (uint32_t i = 1; i < instruction->NumInOperands(); i += 2) {
+ if (instruction->GetSingleWordInOperand(i) == block->id()) {
+ // The corresponding id is at the index of the block - 1.
+ current_id = instruction->GetSingleWordInOperand(i - 1);
+ break;
+ }
+ }
+ assert(
+ current_id != 0 &&
+ "The predecessor - and corresponding id - should always be "
+ "found.");
- uint32_t type_id = instruction->type_id();
+ uint32_t type_id = instruction->type_id();
- // Find all the suitable instructions to replace the id.
- const auto& candidates = FindAvailableInstructions(
- &function, &block, block.end(),
- [type_id, current_id](opt::IRContext* /* unused */,
- opt::Instruction* candidate) -> bool {
- // Only consider instructions with a result id different from
- // the currently-used one, and with the right type.
- return candidate->HasResultId() &&
- candidate->type_id() == type_id &&
- candidate->result_id() != current_id;
- });
+ // Find all the suitable instructions to replace the id.
+ const auto& candidates = FindAvailableInstructions(
+ &function, block, block->end(),
+ [type_id, current_id](opt::IRContext* /* unused */,
+ opt::Instruction* candidate) -> bool {
+ // Only consider instructions with a result id different
+ // from the currently-used one, and with the right type.
+ return candidate->HasResultId() &&
+ candidate->type_id() == type_id &&
+ candidate->result_id() != current_id;
+ });
- // If there is no possible replacement, we cannot apply any
- // transformation.
- if (candidates.empty()) {
- return;
- }
+ // If there is no possible replacement, we cannot apply any
+ // transformation.
+ if (candidates.empty()) {
+ return;
+ }
- // Choose one of the candidates.
- uint32_t replacement_id =
- candidates[GetFuzzerContext()->RandomIndex(candidates)]
- ->result_id();
+ // Choose one of the candidates.
+ uint32_t replacement_id =
+ candidates[GetFuzzerContext()->RandomIndex(candidates)]
+ ->result_id();
- // Add a new transformation to the list of transformations to apply.
- transformations.emplace_back(
- TransformationReplaceOpPhiIdFromDeadPredecessor(
- instruction->result_id(), block.id(), replacement_id));
- });
- }
+ // Add a new transformation to the list of transformations to
+ // apply.
+ transformations.emplace_back(
+ TransformationReplaceOpPhiIdFromDeadPredecessor(
+ instruction->result_id(), block->id(), replacement_id));
+ });
+ });
}
// Apply all the transformations.