Avoid unrolling large loops while fuzzing (#4835)

Uses a preprocessor macro to bail out of unrolling loops with large
iteration counts during fuzzing, to reduce the number of
timeouts/memouts that arise.

Related issue: #4728.
diff --git a/source/opt/loop_unroller.cpp b/source/opt/loop_unroller.cpp
index f36f0af..6f4e6f4 100644
--- a/source/opt/loop_unroller.cpp
+++ b/source/opt/loop_unroller.cpp
@@ -997,6 +997,20 @@
   if (!loop_->FindNumberOfIterations(induction, &*condition->ctail(), nullptr))
     return false;
 
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+  // ClusterFuzz/OSS-Fuzz is likely to yield examples with very high loop
+  // iteration counts. This can cause timeouts and memouts during fuzzing that
+  // are not classed as bugs. To avoid this noise, loop unrolling is not applied
+  // to loops with large iteration counts when fuzzing.
+  const size_t kFuzzerIterationLimit = 100;
+  size_t num_iterations;
+  loop_->FindNumberOfIterations(induction, &*condition->ctail(),
+                                &num_iterations);
+  if (num_iterations > kFuzzerIterationLimit) {
+    return false;
+  }
+#endif
+
   // Make sure the latch block is a unconditional branch to the header
   // block.
   const Instruction& branch = *loop_->GetLatchBlock()->ctail();