spirv-fuzz: Skip early terminator wrappers when merging returns (#3968)
Fixes #3955.
diff --git a/source/fuzz/fuzzer_pass_merge_function_returns.cpp b/source/fuzz/fuzzer_pass_merge_function_returns.cpp
index 4bcedb8..fc9c74d 100644
--- a/source/fuzz/fuzzer_pass_merge_function_returns.cpp
+++ b/source/fuzz/fuzzer_pass_merge_function_returns.cpp
@@ -48,6 +48,12 @@
continue;
}
+ // We skip wrappers for early terminators, since this fuzzer pass introduces
+ // such wrappers to eliminate early terminators.
+ if (IsEarlyTerminatorWrapper(*function)) {
+ continue;
+ }
+
// Only consider functions that have early returns.
if (!function->HasEarlyReturn()) {
continue;
@@ -316,5 +322,16 @@
return result;
}
+bool FuzzerPassMergeFunctionReturns::IsEarlyTerminatorWrapper(
+ const opt::Function& function) const {
+ for (SpvOp opcode : {SpvOpKill, SpvOpUnreachable, SpvOpTerminateInvocation}) {
+ if (TransformationWrapEarlyTerminatorInFunction::MaybeGetWrapperFunction(
+ GetIRContext(), opcode) == &function) {
+ return true;
+ }
+ }
+ return false;
+}
+
} // namespace fuzz
} // namespace spvtools
diff --git a/source/fuzz/fuzzer_pass_merge_function_returns.h b/source/fuzz/fuzzer_pass_merge_function_returns.h
index 2d79905..3b5a668 100644
--- a/source/fuzz/fuzzer_pass_merge_function_returns.h
+++ b/source/fuzz/fuzzer_pass_merge_function_returns.h
@@ -58,6 +58,10 @@
const std::vector<uint32_t>& merge_blocks,
std::map<uint32_t, std::vector<uint32_t>>*
ids_available_after_entry_block);
+
+ // Returns true if and only if |function| is a wrapper for an early terminator
+ // instruction such as OpKill.
+ bool IsEarlyTerminatorWrapper(const opt::Function& function) const;
};
} // namespace fuzz
} // namespace spvtools