[compiler-rt] c5d7251 - Revert "Refactor mutation strategies into a standalone library"

Marco Vanotti via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 2 09:45:22 PDT 2021


Author: Marco Vanotti
Date: 2021-07-02T09:45:11-07:00
New Revision: c5d725172d4d919dcdc5a64a21699b6309a7b872

URL: https://github.com/llvm/llvm-project/commit/c5d725172d4d919dcdc5a64a21699b6309a7b872
DIFF: https://github.com/llvm/llvm-project/commit/c5d725172d4d919dcdc5a64a21699b6309a7b872.diff

LOG: Revert "Refactor mutation strategies into a standalone library"

This reverts commit 361f742f168de0f0f256802a329c19d081615d0d.

Added: 
    compiler-rt/lib/fuzzer/FuzzerCrossOver.cpp
    compiler-rt/lib/fuzzer/FuzzerDictionary.h

Modified: 
    compiler-rt/lib/fuzzer/CMakeLists.txt
    compiler-rt/lib/fuzzer/FuzzerDefs.h
    compiler-rt/lib/fuzzer/FuzzerDriver.cpp
    compiler-rt/lib/fuzzer/FuzzerInternal.h
    compiler-rt/lib/fuzzer/FuzzerLoop.cpp
    compiler-rt/lib/fuzzer/FuzzerMutate.cpp
    compiler-rt/lib/fuzzer/FuzzerMutate.h
    compiler-rt/lib/fuzzer/FuzzerRandom.h
    compiler-rt/lib/fuzzer/FuzzerTracePC.cpp
    compiler-rt/lib/fuzzer/FuzzerTracePC.h
    compiler-rt/lib/fuzzer/FuzzerUtil.h
    compiler-rt/lib/fuzzer/FuzzerUtilFuchsia.cpp
    compiler-rt/lib/fuzzer/FuzzerUtilPosix.cpp
    compiler-rt/lib/fuzzer/FuzzerUtilWindows.cpp
    compiler-rt/lib/fuzzer/build.sh
    compiler-rt/lib/fuzzer/tests/CMakeLists.txt
    compiler-rt/lib/fuzzer/tests/FuzzerUnittest.cpp
    compiler-rt/test/fuzzer/CMakeLists.txt

Removed: 
    compiler-rt/lib/fuzzer/mutagen/CMakeLists.txt
    compiler-rt/lib/fuzzer/mutagen/Mutagen.cpp
    compiler-rt/lib/fuzzer/mutagen/Mutagen.h
    compiler-rt/lib/fuzzer/mutagen/MutagenCrossOver.cpp
    compiler-rt/lib/fuzzer/mutagen/MutagenDictionary.h
    compiler-rt/lib/fuzzer/mutagen/MutagenDispatcher.cpp
    compiler-rt/lib/fuzzer/mutagen/MutagenDispatcher.h
    compiler-rt/lib/fuzzer/mutagen/MutagenSequence.h
    compiler-rt/lib/fuzzer/mutagen/MutagenUtil.h
    compiler-rt/lib/fuzzer/mutagen/MutagenUtilPosix.cpp
    compiler-rt/lib/fuzzer/mutagen/MutagenUtilWindows.cpp
    compiler-rt/lib/fuzzer/mutagen/build.sh
    compiler-rt/lib/fuzzer/tests/MutagenUnittest.cpp


################################################################################
diff  --git a/compiler-rt/lib/fuzzer/CMakeLists.txt b/compiler-rt/lib/fuzzer/CMakeLists.txt
index e27cf8d5e6fe8..3201ed279a621 100644
--- a/compiler-rt/lib/fuzzer/CMakeLists.txt
+++ b/compiler-rt/lib/fuzzer/CMakeLists.txt
@@ -1,4 +1,5 @@
 set(LIBFUZZER_SOURCES
+  FuzzerCrossOver.cpp
   FuzzerDataFlowTrace.cpp
   FuzzerDriver.cpp
   FuzzerExtFunctionsDlsym.cpp
@@ -28,6 +29,7 @@ set(LIBFUZZER_HEADERS
   FuzzerCorpus.h
   FuzzerDataFlowTrace.h
   FuzzerDefs.h
+  FuzzerDictionary.h
   FuzzerExtFunctions.def
   FuzzerExtFunctions.h
   FuzzerFlags.def
@@ -82,32 +84,6 @@ else()
   endif()
 endif()
 
-macro(partially_link_libcxx name dir arch)
-  if(${arch} MATCHES "i386")
-    set(EMULATION_ARGUMENT "-m" "elf_i386")
-  else()
-    set(EMULATION_ARGUMENT "")
-  endif()
-  set(cxx_${arch}_merge_dir "${CMAKE_CURRENT_BINARY_DIR}/cxx_${arch}_merge.dir")
-  file(MAKE_DIRECTORY ${cxx_${arch}_merge_dir})
-  add_custom_command(TARGET clang_rt.${name}-${arch} POST_BUILD
-    COMMAND ${CMAKE_LINKER} ${EMULATION_ARGUMENT} --whole-archive "$<TARGET_LINKER_FILE:clang_rt.${name}-${arch}>" --no-whole-archive ${dir}/lib/libc++.a -r -o ${name}.o
-    COMMAND ${CMAKE_OBJCOPY} --localize-hidden ${name}.o
-    COMMAND ${CMAKE_COMMAND} -E remove "$<TARGET_LINKER_FILE:clang_rt.${name}-${arch}>"
-    COMMAND ${CMAKE_AR} qcs "$<TARGET_LINKER_FILE:clang_rt.${name}-${arch}>" ${name}.o
-    WORKING_DIRECTORY ${cxx_${arch}_merge_dir}
-  )
-endmacro()
-
-add_subdirectory(mutagen)
-foreach(X IN LISTS LIBFUZZER_MUTAGEN_SOURCES)
-    list(APPEND LIBFUZZER_SOURCES "mutagen/${X}")
-endforeach()
-foreach(X IN LISTS LIBFUZZER_MUTAGEN_HEADERS)
-    list(APPEND LIBFUZZER_HEADERS "mutagen/${X}")
-endforeach()
-include_directories(.)
-
 add_compiler_rt_component(fuzzer)
 
 add_compiler_rt_object_libraries(RTfuzzer
@@ -159,6 +135,23 @@ add_compiler_rt_runtime(clang_rt.fuzzer_interceptors
 if(OS_NAME MATCHES "Linux|Fuchsia" AND
    COMPILER_RT_LIBCXX_PATH AND
    COMPILER_RT_LIBCXXABI_PATH)
+  macro(partially_link_libcxx name dir arch)
+    if(${arch} MATCHES "i386")
+      set(EMULATION_ARGUMENT "-m" "elf_i386")
+    else()
+      set(EMULATION_ARGUMENT "")
+    endif()
+    set(cxx_${arch}_merge_dir "${CMAKE_CURRENT_BINARY_DIR}/cxx_${arch}_merge.dir")
+    file(MAKE_DIRECTORY ${cxx_${arch}_merge_dir})
+    add_custom_command(TARGET clang_rt.${name}-${arch} POST_BUILD
+      COMMAND ${CMAKE_LINKER} ${EMULATION_ARGUMENT} --whole-archive "$<TARGET_LINKER_FILE:clang_rt.${name}-${arch}>" --no-whole-archive ${dir}/lib/libc++.a -r -o ${name}.o
+      COMMAND ${CMAKE_OBJCOPY} --localize-hidden ${name}.o
+      COMMAND ${CMAKE_COMMAND} -E remove "$<TARGET_LINKER_FILE:clang_rt.${name}-${arch}>"
+      COMMAND ${CMAKE_AR} qcs "$<TARGET_LINKER_FILE:clang_rt.${name}-${arch}>" ${name}.o
+      WORKING_DIRECTORY ${cxx_${arch}_merge_dir}
+    )
+  endmacro()
+
   foreach(arch ${FUZZER_SUPPORTED_ARCH})
     get_target_flags_for_arch(${arch} TARGET_CFLAGS)
     set(LIBCXX_${arch}_PREFIX ${CMAKE_CURRENT_BINARY_DIR}/libcxx_fuzzer_${arch})

diff  --git a/compiler-rt/lib/fuzzer/mutagen/MutagenCrossOver.cpp b/compiler-rt/lib/fuzzer/FuzzerCrossOver.cpp
similarity index 86%
rename from compiler-rt/lib/fuzzer/mutagen/MutagenCrossOver.cpp
rename to compiler-rt/lib/fuzzer/FuzzerCrossOver.cpp
index 0fcffaf68ddf4..83d9f8d47cb18 100644
--- a/compiler-rt/lib/fuzzer/mutagen/MutagenCrossOver.cpp
+++ b/compiler-rt/lib/fuzzer/FuzzerCrossOver.cpp
@@ -1,4 +1,4 @@
-//===- MutagenCrossOver.cpp - Cross over two test inputs ------------------===//
+//===- FuzzerCrossOver.cpp - Cross over two test inputs -------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -8,11 +8,12 @@
 // Cross over test inputs.
 //===----------------------------------------------------------------------===//
 
+#include "FuzzerDefs.h"
+#include "FuzzerMutate.h"
 #include "FuzzerRandom.h"
-#include "MutagenDispatcher.h"
 #include <cstring>
 
-namespace mutagen {
+namespace fuzzer {
 
 // Cross Data1 and Data2, store the result (up to MaxOutSize bytes) in Out.
 size_t MutationDispatcher::CrossOver(const uint8_t *Data1, size_t Size1,
@@ -39,12 +40,12 @@ size_t MutationDispatcher::CrossOver(const uint8_t *Data1, size_t Size1,
       (*InPos) += ExtraSize;
     }
     // Use the other input data on the next iteration.
-    InPos = CurrentlyUsingFirstData ? &Pos2 : &Pos1;
+    InPos  = CurrentlyUsingFirstData ? &Pos2 : &Pos1;
     InSize = CurrentlyUsingFirstData ? Size2 : Size1;
-    Data = CurrentlyUsingFirstData ? Data2 : Data1;
+    Data   = CurrentlyUsingFirstData ? Data2 : Data1;
     CurrentlyUsingFirstData = !CurrentlyUsingFirstData;
   }
   return OutPos;
 }
 
-} // namespace mutagen
+}  // namespace fuzzer

diff  --git a/compiler-rt/lib/fuzzer/FuzzerDefs.h b/compiler-rt/lib/fuzzer/FuzzerDefs.h
index 36820b61c2aa5..1a2752af2f4d5 100644
--- a/compiler-rt/lib/fuzzer/FuzzerDefs.h
+++ b/compiler-rt/lib/fuzzer/FuzzerDefs.h
@@ -15,18 +15,21 @@
 #include <cstddef>
 #include <cstdint>
 #include <cstring>
-#include <limits>
 #include <memory>
 #include <set>
 #include <string>
 #include <vector>
 
+
 namespace fuzzer {
 
 template <class T> T Min(T a, T b) { return a < b ? a : b; }
 template <class T> T Max(T a, T b) { return a > b ? a : b; }
 
 class Random;
+class Dictionary;
+class DictionaryEntry;
+class MutationDispatcher;
 struct FuzzingOptions;
 class InputCorpus;
 struct InputInfo;
@@ -57,37 +60,6 @@ using Set = std::set<T, std::less<T>, fuzzer_allocator<T>>;
 
 typedef Vector<uint8_t> Unit;
 typedef Vector<Unit> UnitVector;
-
-// A simple POD sized array of bytes.
-template <size_t kMaxSizeT> class FixedWord {
-public:
-  static const size_t kMaxSize = kMaxSizeT;
-  FixedWord() { memset(Data, 0, kMaxSize); }
-  FixedWord(const uint8_t *B, size_t S) { Set(B, S); }
-
-  void Set(const uint8_t *B, size_t S) {
-    static_assert(kMaxSizeT <= std::numeric_limits<uint8_t>::max(),
-                  "FixedWord::kMaxSizeT cannot fit in a uint8_t.");
-    assert(S <= kMaxSize);
-    memcpy(Data, B, S);
-    Size = static_cast<uint8_t>(S);
-  }
-
-  bool operator==(const FixedWord<kMaxSize> &w) const {
-    return Size == w.Size && 0 == memcmp(Data, w.Data, Size);
-  }
-
-  static size_t GetMaxSize() { return kMaxSize; }
-  const uint8_t *data() const { return Data; }
-  uint8_t size() const { return Size; }
-
-private:
-  uint8_t Size = 0;
-  uint8_t Data[kMaxSize];
-};
-
-typedef FixedWord<64> Word;
-
 typedef int (*UserCallback)(const uint8_t *Data, size_t Size);
 
 int FuzzerDriver(int *argc, char ***argv, UserCallback Callback);

diff  --git a/compiler-rt/lib/fuzzer/FuzzerDictionary.h b/compiler-rt/lib/fuzzer/FuzzerDictionary.h
new file mode 100644
index 0000000000000..db55907d93631
--- /dev/null
+++ b/compiler-rt/lib/fuzzer/FuzzerDictionary.h
@@ -0,0 +1,120 @@
+//===- FuzzerDictionary.h - Internal header for the Fuzzer ------*- C++ -* ===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+// fuzzer::Dictionary
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_FUZZER_DICTIONARY_H
+#define LLVM_FUZZER_DICTIONARY_H
+
+#include "FuzzerDefs.h"
+#include "FuzzerIO.h"
+#include "FuzzerUtil.h"
+#include <algorithm>
+#include <limits>
+
+namespace fuzzer {
+// A simple POD sized array of bytes.
+template <size_t kMaxSizeT> class FixedWord {
+public:
+  static const size_t kMaxSize = kMaxSizeT;
+  FixedWord() {}
+  FixedWord(const uint8_t *B, size_t S) { Set(B, S); }
+
+  void Set(const uint8_t *B, size_t S) {
+    static_assert(kMaxSizeT <= std::numeric_limits<uint8_t>::max(),
+                  "FixedWord::kMaxSizeT cannot fit in a uint8_t.");
+    assert(S <= kMaxSize);
+    memcpy(Data, B, S);
+    Size = static_cast<uint8_t>(S);
+  }
+
+  bool operator==(const FixedWord<kMaxSize> &w) const {
+    return Size == w.Size && 0 == memcmp(Data, w.Data, Size);
+  }
+
+  static size_t GetMaxSize() { return kMaxSize; }
+  const uint8_t *data() const { return Data; }
+  uint8_t size() const { return Size; }
+
+private:
+  uint8_t Size = 0;
+  uint8_t Data[kMaxSize];
+};
+
+typedef FixedWord<64> Word;
+
+class DictionaryEntry {
+ public:
+  DictionaryEntry() {}
+  DictionaryEntry(Word W) : W(W) {}
+  DictionaryEntry(Word W, size_t PositionHint) : W(W), PositionHint(PositionHint) {}
+  const Word &GetW() const { return W; }
+
+  bool HasPositionHint() const { return PositionHint != std::numeric_limits<size_t>::max(); }
+  size_t GetPositionHint() const {
+    assert(HasPositionHint());
+    return PositionHint;
+  }
+  void IncUseCount() { UseCount++; }
+  void IncSuccessCount() { SuccessCount++; }
+  size_t GetUseCount() const { return UseCount; }
+  size_t GetSuccessCount() const {return SuccessCount; }
+
+  void Print(const char *PrintAfter = "\n") {
+    PrintASCII(W.data(), W.size());
+    if (HasPositionHint())
+      Printf("@%zd", GetPositionHint());
+    Printf("%s", PrintAfter);
+  }
+
+private:
+  Word W;
+  size_t PositionHint = std::numeric_limits<size_t>::max();
+  size_t UseCount = 0;
+  size_t SuccessCount = 0;
+};
+
+class Dictionary {
+ public:
+  static const size_t kMaxDictSize = 1 << 14;
+
+  bool ContainsWord(const Word &W) const {
+    return std::any_of(begin(), end(), [&](const DictionaryEntry &DE) {
+      return DE.GetW() == W;
+    });
+  }
+  const DictionaryEntry *begin() const { return &DE[0]; }
+  const DictionaryEntry *end() const { return begin() + Size; }
+  DictionaryEntry & operator[] (size_t Idx) {
+    assert(Idx < Size);
+    return DE[Idx];
+  }
+  void push_back(DictionaryEntry DE) {
+    if (Size < kMaxDictSize)
+      this->DE[Size++] = DE;
+  }
+  void clear() { Size = 0; }
+  bool empty() const { return Size == 0; }
+  size_t size() const { return Size; }
+
+private:
+  DictionaryEntry DE[kMaxDictSize];
+  size_t Size = 0;
+};
+
+// Parses one dictionary entry.
+// If successful, write the enty to Unit and returns true,
+// otherwise returns false.
+bool ParseOneDictionaryEntry(const std::string &Str, Unit *U);
+// Parses the dictionary file, fills Units, returns true iff all lines
+// were parsed successfully.
+bool ParseDictionaryFile(const std::string &Text, Vector<Unit> *Units);
+
+}  // namespace fuzzer
+
+#endif  // LLVM_FUZZER_DICTIONARY_H

diff  --git a/compiler-rt/lib/fuzzer/FuzzerDriver.cpp b/compiler-rt/lib/fuzzer/FuzzerDriver.cpp
index 38efc2e18863c..ceaa9070512f0 100644
--- a/compiler-rt/lib/fuzzer/FuzzerDriver.cpp
+++ b/compiler-rt/lib/fuzzer/FuzzerDriver.cpp
@@ -19,16 +19,15 @@
 #include "FuzzerPlatform.h"
 #include "FuzzerRandom.h"
 #include "FuzzerTracePC.h"
-#include "mutagen/MutagenDispatcher.h"
 #include <algorithm>
 #include <atomic>
 #include <chrono>
 #include <cstdlib>
 #include <cstring>
-#include <fstream>
 #include <mutex>
 #include <string>
 #include <thread>
+#include <fstream>
 
 // This function should be present in the libFuzzer so that the client
 // binary can test for its existence.
@@ -804,9 +803,8 @@ int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) {
                         ReadCorpora(*Inputs, {}));
   }
 
-  LLVMMutagenConfiguration Config;
-  ConfigureMutagen(Seed, Options, &Config);
-  auto *MD = new MutationDispatcher(&Config);
+  Random Rand(Seed);
+  auto *MD = new MutationDispatcher(Rand, Options);
   auto *Corpus = new InputCorpus(Options.OutputCorpus, Entropic);
   auto *F = new Fuzzer(Callback, *Corpus, *MD, Options);
 

diff  --git a/compiler-rt/lib/fuzzer/FuzzerInternal.h b/compiler-rt/lib/fuzzer/FuzzerInternal.h
index a629c3d02f774..37c8a01dc3c64 100644
--- a/compiler-rt/lib/fuzzer/FuzzerInternal.h
+++ b/compiler-rt/lib/fuzzer/FuzzerInternal.h
@@ -18,7 +18,6 @@
 #include "FuzzerOptions.h"
 #include "FuzzerSHA1.h"
 #include "FuzzerValueBitMap.h"
-#include "mutagen/MutagenDispatcher.h"
 #include <algorithm>
 #include <atomic>
 #include <chrono>
@@ -27,12 +26,8 @@
 #include <string.h>
 
 namespace fuzzer {
-namespace {
 
 using namespace std::chrono;
-using mutagen::MutationDispatcher;
-
-} // namespace
 
 class Fuzzer {
 public:

diff  --git a/compiler-rt/lib/fuzzer/FuzzerLoop.cpp b/compiler-rt/lib/fuzzer/FuzzerLoop.cpp
index d50277e9f2a0d..86a78ab751741 100644
--- a/compiler-rt/lib/fuzzer/FuzzerLoop.cpp
+++ b/compiler-rt/lib/fuzzer/FuzzerLoop.cpp
@@ -177,7 +177,7 @@ void Fuzzer::DumpCurrentUnit(const char *Prefix) {
   if (!CurrentUnitData)
     return; // Happens when running individual inputs.
   ScopedDisableMsanInterceptorChecks S;
-  PrintMutationSequence(MD);
+  MD.PrintMutationSequence();
   Printf("; base unit: %s\n", Sha1ToString(BaseSha1).c_str());
   size_t UnitSize = CurrentUnitSize;
   if (UnitSize <= kMaxUnitSizeToPrint) {
@@ -539,9 +539,8 @@ bool Fuzzer::RunOne(const uint8_t *Data, size_t Size, bool MayDeleteFile,
                            TimeOfUnit, UniqFeatureSetTmp, DFT, II);
     WriteFeatureSetToFile(Options.FeaturesDir, Sha1ToString(NewII->Sha1),
                           NewII->UniqFeatureSet);
-    const auto &MS = MD.MutationSequence();
     WriteEdgeToMutationGraphFile(Options.MutationGraphFile, NewII, II,
-                                 MS.GetString());
+                                 MD.MutationSequence());
     return true;
   }
   if (II && FoundUniqFeaturesOfII &&
@@ -653,7 +652,7 @@ void Fuzzer::PrintStatusForNewUnit(const Unit &U, const char *Text) {
   PrintStats(Text, "");
   if (Options.Verbosity) {
     Printf(" L: %zd/%zd ", U.size(), Corpus.MaxInputSize());
-    PrintMutationSequence(MD, Options.Verbosity >= 2);
+    MD.PrintMutationSequence(Options.Verbosity >= 2);
     Printf("\n");
   }
 }
@@ -899,7 +898,7 @@ void Fuzzer::Loop(Vector<SizedFile> &CorporaFiles) {
   }
 
   PrintStats("DONE  ", "\n");
-  PrintRecommendedDictionary(MD);
+  MD.PrintRecommendedDictionary();
 }
 
 void Fuzzer::MinimizeCrashLoop(const Unit &U) {

diff  --git a/compiler-rt/lib/fuzzer/FuzzerMutate.cpp b/compiler-rt/lib/fuzzer/FuzzerMutate.cpp
index bbce4aab58024..4650f1beceacd 100644
--- a/compiler-rt/lib/fuzzer/FuzzerMutate.cpp
+++ b/compiler-rt/lib/fuzzer/FuzzerMutate.cpp
@@ -1,77 +1,497 @@
-//===- FuzzerMutate.cpp - Mutation utilities -----------------------------===//
+//===- FuzzerMutate.cpp - Mutate a test input -----------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
-// Mutate utilities.
+// Mutate a test input.
 //===----------------------------------------------------------------------===//
 
-#include "FuzzerMutate.h"
+#include "FuzzerDefs.h"
 #include "FuzzerExtFunctions.h"
 #include "FuzzerIO.h"
+#include "FuzzerMutate.h"
+#include "FuzzerOptions.h"
 #include "FuzzerTracePC.h"
-#include "FuzzerUtil.h"
 
 namespace fuzzer {
-namespace {
 
-void FromTORC4(size_t Idx, uint32_t *A, uint32_t *B) {
-  const auto &X = TPC.TORC4.Get(Idx);
-  *A = X.A;
-  *B = X.B;
+const size_t Dictionary::kMaxDictSize;
+static const size_t kMaxMutationsToPrint = 10;
+
+static void PrintASCII(const Word &W, const char *PrintAfter) {
+  PrintASCII(W.data(), W.size(), PrintAfter);
+}
+
+MutationDispatcher::MutationDispatcher(Random &Rand,
+                                       const FuzzingOptions &Options)
+    : Rand(Rand), Options(Options) {
+  DefaultMutators.insert(
+      DefaultMutators.begin(),
+      {
+          {&MutationDispatcher::Mutate_EraseBytes, "EraseBytes"},
+          {&MutationDispatcher::Mutate_InsertByte, "InsertByte"},
+          {&MutationDispatcher::Mutate_InsertRepeatedBytes,
+           "InsertRepeatedBytes"},
+          {&MutationDispatcher::Mutate_ChangeByte, "ChangeByte"},
+          {&MutationDispatcher::Mutate_ChangeBit, "ChangeBit"},
+          {&MutationDispatcher::Mutate_ShuffleBytes, "ShuffleBytes"},
+          {&MutationDispatcher::Mutate_ChangeASCIIInteger, "ChangeASCIIInt"},
+          {&MutationDispatcher::Mutate_ChangeBinaryInteger, "ChangeBinInt"},
+          {&MutationDispatcher::Mutate_CopyPart, "CopyPart"},
+          {&MutationDispatcher::Mutate_CrossOver, "CrossOver"},
+          {&MutationDispatcher::Mutate_AddWordFromManualDictionary,
+           "ManualDict"},
+          {&MutationDispatcher::Mutate_AddWordFromPersistentAutoDictionary,
+           "PersAutoDict"},
+      });
+  if(Options.UseCmp)
+    DefaultMutators.push_back(
+        {&MutationDispatcher::Mutate_AddWordFromTORC, "CMP"});
+
+  if (EF->LLVMFuzzerCustomMutator)
+    Mutators.push_back({&MutationDispatcher::Mutate_Custom, "Custom"});
+  else
+    Mutators = DefaultMutators;
+
+  if (EF->LLVMFuzzerCustomCrossOver)
+    Mutators.push_back(
+        {&MutationDispatcher::Mutate_CustomCrossOver, "CustomCrossOver"});
+}
+
+static char RandCh(Random &Rand) {
+  if (Rand.RandBool())
+    return static_cast<char>(Rand(256));
+  const char Special[] = "!*'();:@&=+$,/?%#[]012Az-`~.\xff\x00";
+  return Special[Rand(sizeof(Special) - 1)];
+}
+
+size_t MutationDispatcher::Mutate_Custom(uint8_t *Data, size_t Size,
+                                         size_t MaxSize) {
+  if (EF->__msan_unpoison)
+    EF->__msan_unpoison(Data, Size);
+  if (EF->__msan_unpoison_param)
+    EF->__msan_unpoison_param(4);
+  return EF->LLVMFuzzerCustomMutator(Data, Size, MaxSize,
+                                     Rand.Rand<unsigned int>());
+}
+
+size_t MutationDispatcher::Mutate_CustomCrossOver(uint8_t *Data, size_t Size,
+                                                  size_t MaxSize) {
+  if (Size == 0)
+    return 0;
+  if (!CrossOverWith) return 0;
+  const Unit &Other = *CrossOverWith;
+  if (Other.empty())
+    return 0;
+  CustomCrossOverInPlaceHere.resize(MaxSize);
+  auto &U = CustomCrossOverInPlaceHere;
+
+  if (EF->__msan_unpoison) {
+    EF->__msan_unpoison(Data, Size);
+    EF->__msan_unpoison(Other.data(), Other.size());
+    EF->__msan_unpoison(U.data(), U.size());
+  }
+  if (EF->__msan_unpoison_param)
+    EF->__msan_unpoison_param(7);
+  size_t NewSize = EF->LLVMFuzzerCustomCrossOver(
+      Data, Size, Other.data(), Other.size(), U.data(), U.size(),
+      Rand.Rand<unsigned int>());
+
+  if (!NewSize)
+    return 0;
+  assert(NewSize <= MaxSize && "CustomCrossOver returned overisized unit");
+  memcpy(Data, U.data(), NewSize);
+  return NewSize;
+}
+
+size_t MutationDispatcher::Mutate_ShuffleBytes(uint8_t *Data, size_t Size,
+                                               size_t MaxSize) {
+  if (Size > MaxSize || Size == 0) return 0;
+  size_t ShuffleAmount =
+      Rand(std::min(Size, (size_t)8)) + 1; // [1,8] and <= Size.
+  size_t ShuffleStart = Rand(Size - ShuffleAmount);
+  assert(ShuffleStart + ShuffleAmount <= Size);
+  std::shuffle(Data + ShuffleStart, Data + ShuffleStart + ShuffleAmount, Rand);
+  return Size;
+}
+
+size_t MutationDispatcher::Mutate_EraseBytes(uint8_t *Data, size_t Size,
+                                             size_t MaxSize) {
+  if (Size <= 1) return 0;
+  size_t N = Rand(Size / 2) + 1;
+  assert(N < Size);
+  size_t Idx = Rand(Size - N + 1);
+  // Erase Data[Idx:Idx+N].
+  memmove(Data + Idx, Data + Idx + N, Size - Idx - N);
+  // Printf("Erase: %zd %zd => %zd; Idx %zd\n", N, Size, Size - N, Idx);
+  return Size - N;
 }
 
-void FromTORC8(size_t Idx, uint64_t *A, uint64_t *B) {
-  const auto &X = TPC.TORC8.Get(Idx);
-  *A = X.A;
-  *B = X.B;
+size_t MutationDispatcher::Mutate_InsertByte(uint8_t *Data, size_t Size,
+                                             size_t MaxSize) {
+  if (Size >= MaxSize) return 0;
+  size_t Idx = Rand(Size + 1);
+  // Insert new value at Data[Idx].
+  memmove(Data + Idx + 1, Data + Idx, Size - Idx);
+  Data[Idx] = RandCh(Rand);
+  return Size + 1;
 }
 
-void FromTORCW(size_t Idx, const uint8_t **DataA, size_t *SizeA,
-               const uint8_t **DataB, size_t *SizeB) {
-  const auto &X = TPC.TORCW.Get(Idx);
-  *DataA = X.A.data();
-  *SizeA = X.A.size();
-  *DataB = X.B.data();
-  *SizeB = X.B.size();
+size_t MutationDispatcher::Mutate_InsertRepeatedBytes(uint8_t *Data,
+                                                      size_t Size,
+                                                      size_t MaxSize) {
+  const size_t kMinBytesToInsert = 3;
+  if (Size + kMinBytesToInsert >= MaxSize) return 0;
+  size_t MaxBytesToInsert = std::min(MaxSize - Size, (size_t)128);
+  size_t N = Rand(MaxBytesToInsert - kMinBytesToInsert + 1) + kMinBytesToInsert;
+  assert(Size + N <= MaxSize && N);
+  size_t Idx = Rand(Size + 1);
+  // Insert new values at Data[Idx].
+  memmove(Data + Idx + N, Data + Idx, Size - Idx);
+  // Give preference to 0x00 and 0xff.
+  uint8_t Byte = static_cast<uint8_t>(
+      Rand.RandBool() ? Rand(256) : (Rand.RandBool() ? 0 : 255));
+  for (size_t i = 0; i < N; i++)
+    Data[Idx + i] = Byte;
+  return Size + N;
 }
 
-void FromMMT(size_t Idx, const uint8_t **Data, size_t *Size) {
-  const auto &W = TPC.MMT.Get(Idx);
-  *Data = W.data();
-  *Size = W.size();
+size_t MutationDispatcher::Mutate_ChangeByte(uint8_t *Data, size_t Size,
+                                             size_t MaxSize) {
+  if (Size > MaxSize) return 0;
+  size_t Idx = Rand(Size);
+  Data[Idx] = RandCh(Rand);
+  return Size;
 }
 
-void PrintASCII(const Word &W, const char *PrintAfter) {
-  fuzzer::PrintASCII(W.data(), W.size(), PrintAfter);
+size_t MutationDispatcher::Mutate_ChangeBit(uint8_t *Data, size_t Size,
+                                            size_t MaxSize) {
+  if (Size > MaxSize) return 0;
+  size_t Idx = Rand(Size);
+  Data[Idx] ^= 1 << Rand(8);
+  return Size;
 }
 
-} // namespace
+size_t MutationDispatcher::Mutate_AddWordFromManualDictionary(uint8_t *Data,
+                                                              size_t Size,
+                                                              size_t MaxSize) {
+  return AddWordFromDictionary(ManualDictionary, Data, Size, MaxSize);
+}
+
+size_t MutationDispatcher::ApplyDictionaryEntry(uint8_t *Data, size_t Size,
+                                                size_t MaxSize,
+                                                DictionaryEntry &DE) {
+  const Word &W = DE.GetW();
+  bool UsePositionHint = DE.HasPositionHint() &&
+                         DE.GetPositionHint() + W.size() < Size &&
+                         Rand.RandBool();
+  if (Rand.RandBool()) {  // Insert W.
+    if (Size + W.size() > MaxSize) return 0;
+    size_t Idx = UsePositionHint ? DE.GetPositionHint() : Rand(Size + 1);
+    memmove(Data + Idx + W.size(), Data + Idx, Size - Idx);
+    memcpy(Data + Idx, W.data(), W.size());
+    Size += W.size();
+  } else {  // Overwrite some bytes with W.
+    if (W.size() > Size) return 0;
+    size_t Idx =
+        UsePositionHint ? DE.GetPositionHint() : Rand(Size + 1 - W.size());
+    memcpy(Data + Idx, W.data(), W.size());
+  }
+  return Size;
+}
+
+// Somewhere in the past we have observed a comparison instructions
+// with arguments Arg1 Arg2. This function tries to guess a dictionary
+// entry that will satisfy that comparison.
+// It first tries to find one of the arguments (possibly swapped) in the
+// input and if it succeeds it creates a DE with a position hint.
+// Otherwise it creates a DE with one of the arguments w/o a position hint.
+DictionaryEntry MutationDispatcher::MakeDictionaryEntryFromCMP(
+    const void *Arg1, const void *Arg2,
+    const void *Arg1Mutation, const void *Arg2Mutation,
+    size_t ArgSize, const uint8_t *Data,
+    size_t Size) {
+  bool HandleFirst = Rand.RandBool();
+  const void *ExistingBytes, *DesiredBytes;
+  Word W;
+  const uint8_t *End = Data + Size;
+  for (int Arg = 0; Arg < 2; Arg++) {
+    ExistingBytes = HandleFirst ? Arg1 : Arg2;
+    DesiredBytes = HandleFirst ? Arg2Mutation : Arg1Mutation;
+    HandleFirst = !HandleFirst;
+    W.Set(reinterpret_cast<const uint8_t*>(DesiredBytes), ArgSize);
+    const size_t kMaxNumPositions = 8;
+    size_t Positions[kMaxNumPositions];
+    size_t NumPositions = 0;
+    for (const uint8_t *Cur = Data;
+         Cur < End && NumPositions < kMaxNumPositions; Cur++) {
+      Cur =
+          (const uint8_t *)SearchMemory(Cur, End - Cur, ExistingBytes, ArgSize);
+      if (!Cur) break;
+      Positions[NumPositions++] = Cur - Data;
+    }
+    if (!NumPositions) continue;
+    return DictionaryEntry(W, Positions[Rand(NumPositions)]);
+  }
+  DictionaryEntry DE(W);
+  return DE;
+}
+
+
+template <class T>
+DictionaryEntry MutationDispatcher::MakeDictionaryEntryFromCMP(
+    T Arg1, T Arg2, const uint8_t *Data, size_t Size) {
+  if (Rand.RandBool()) Arg1 = Bswap(Arg1);
+  if (Rand.RandBool()) Arg2 = Bswap(Arg2);
+  T Arg1Mutation = static_cast<T>(Arg1 + Rand(-1, 1));
+  T Arg2Mutation = static_cast<T>(Arg2 + Rand(-1, 1));
+  return MakeDictionaryEntryFromCMP(&Arg1, &Arg2, &Arg1Mutation, &Arg2Mutation,
+                                    sizeof(Arg1), Data, Size);
+}
 
-void ConfigureMutagen(unsigned int Seed, const FuzzingOptions &Options,
-                      LLVMMutagenConfiguration *OutConfig) {
-  memset(OutConfig, 0, sizeof(*OutConfig));
-  OutConfig->Seed = Seed;
-  OutConfig->UseCmp = Options.UseCmp;
-  OutConfig->FromTORC4 = FromTORC4;
-  OutConfig->FromTORC8 = FromTORC8;
-  OutConfig->FromTORCW = FromTORCW;
-  OutConfig->UseMemmem = Options.UseMemmem;
-  OutConfig->FromMMT = FromMMT;
-  OutConfig->CustomMutator = EF->LLVMFuzzerCustomMutator;
-  OutConfig->CustomCrossOver = EF->LLVMFuzzerCustomCrossOver;
-  OutConfig->MSanUnpoison = EF->__msan_unpoison;
-  OutConfig->MSanUnpoisonParam = EF->__msan_unpoison_param;
+DictionaryEntry MutationDispatcher::MakeDictionaryEntryFromCMP(
+    const Word &Arg1, const Word &Arg2, const uint8_t *Data, size_t Size) {
+  return MakeDictionaryEntryFromCMP(Arg1.data(), Arg2.data(), Arg1.data(),
+                                    Arg2.data(), Arg1.size(), Data, Size);
 }
 
-void PrintRecommendedDictionary(MutationDispatcher &MD) {
-  auto RecommendedDictionary = MD.RecommendDictionary();
-  if (RecommendedDictionary.empty())
-    return;
+size_t MutationDispatcher::Mutate_AddWordFromTORC(
+    uint8_t *Data, size_t Size, size_t MaxSize) {
+  Word W;
+  DictionaryEntry DE;
+  switch (Rand(4)) {
+  case 0: {
+    auto X = TPC.TORC8.Get(Rand.Rand<size_t>());
+    DE = MakeDictionaryEntryFromCMP(X.A, X.B, Data, Size);
+  } break;
+  case 1: {
+    auto X = TPC.TORC4.Get(Rand.Rand<size_t>());
+    if ((X.A >> 16) == 0 && (X.B >> 16) == 0 && Rand.RandBool())
+      DE = MakeDictionaryEntryFromCMP((uint16_t)X.A, (uint16_t)X.B, Data, Size);
+    else
+      DE = MakeDictionaryEntryFromCMP(X.A, X.B, Data, Size);
+  } break;
+  case 2: {
+    auto X = TPC.TORCW.Get(Rand.Rand<size_t>());
+    DE = MakeDictionaryEntryFromCMP(X.A, X.B, Data, Size);
+  } break;
+  case 3: if (Options.UseMemmem) {
+      auto X = TPC.MMT.Get(Rand.Rand<size_t>());
+      DE = DictionaryEntry(X);
+  } break;
+  default:
+    assert(0);
+  }
+  if (!DE.GetW().size()) return 0;
+  Size = ApplyDictionaryEntry(Data, Size, MaxSize, DE);
+  if (!Size) return 0;
+  DictionaryEntry &DERef =
+      CmpDictionaryEntriesDeque[CmpDictionaryEntriesDequeIdx++ %
+                                kCmpDictionaryEntriesDequeSize];
+  DERef = DE;
+  CurrentDictionaryEntrySequence.push_back(&DERef);
+  return Size;
+}
+
+size_t MutationDispatcher::Mutate_AddWordFromPersistentAutoDictionary(
+    uint8_t *Data, size_t Size, size_t MaxSize) {
+  return AddWordFromDictionary(PersistentAutoDictionary, Data, Size, MaxSize);
+}
+
+size_t MutationDispatcher::AddWordFromDictionary(Dictionary &D, uint8_t *Data,
+                                                 size_t Size, size_t MaxSize) {
+  if (Size > MaxSize) return 0;
+  if (D.empty()) return 0;
+  DictionaryEntry &DE = D[Rand(D.size())];
+  Size = ApplyDictionaryEntry(Data, Size, MaxSize, DE);
+  if (!Size) return 0;
+  DE.IncUseCount();
+  CurrentDictionaryEntrySequence.push_back(&DE);
+  return Size;
+}
+
+// Overwrites part of To[0,ToSize) with a part of From[0,FromSize).
+// Returns ToSize.
+size_t MutationDispatcher::CopyPartOf(const uint8_t *From, size_t FromSize,
+                                      uint8_t *To, size_t ToSize) {
+  // Copy From[FromBeg, FromBeg + CopySize) into To[ToBeg, ToBeg + CopySize).
+  size_t ToBeg = Rand(ToSize);
+  size_t CopySize = Rand(ToSize - ToBeg) + 1;
+  assert(ToBeg + CopySize <= ToSize);
+  CopySize = std::min(CopySize, FromSize);
+  size_t FromBeg = Rand(FromSize - CopySize + 1);
+  assert(FromBeg + CopySize <= FromSize);
+  memmove(To + ToBeg, From + FromBeg, CopySize);
+  return ToSize;
+}
+
+// Inserts part of From[0,ToSize) into To.
+// Returns new size of To on success or 0 on failure.
+size_t MutationDispatcher::InsertPartOf(const uint8_t *From, size_t FromSize,
+                                        uint8_t *To, size_t ToSize,
+                                        size_t MaxToSize) {
+  if (ToSize >= MaxToSize) return 0;
+  size_t AvailableSpace = MaxToSize - ToSize;
+  size_t MaxCopySize = std::min(AvailableSpace, FromSize);
+  size_t CopySize = Rand(MaxCopySize) + 1;
+  size_t FromBeg = Rand(FromSize - CopySize + 1);
+  assert(FromBeg + CopySize <= FromSize);
+  size_t ToInsertPos = Rand(ToSize + 1);
+  assert(ToInsertPos + CopySize <= MaxToSize);
+  size_t TailSize = ToSize - ToInsertPos;
+  if (To == From) {
+    MutateInPlaceHere.resize(MaxToSize);
+    memcpy(MutateInPlaceHere.data(), From + FromBeg, CopySize);
+    memmove(To + ToInsertPos + CopySize, To + ToInsertPos, TailSize);
+    memmove(To + ToInsertPos, MutateInPlaceHere.data(), CopySize);
+  } else {
+    memmove(To + ToInsertPos + CopySize, To + ToInsertPos, TailSize);
+    memmove(To + ToInsertPos, From + FromBeg, CopySize);
+  }
+  return ToSize + CopySize;
+}
+
+size_t MutationDispatcher::Mutate_CopyPart(uint8_t *Data, size_t Size,
+                                           size_t MaxSize) {
+  if (Size > MaxSize || Size == 0) return 0;
+  // If Size == MaxSize, `InsertPartOf(...)` will
+  // fail so there's no point using it in this case.
+  if (Size == MaxSize || Rand.RandBool())
+    return CopyPartOf(Data, Size, Data, Size);
+  else
+    return InsertPartOf(Data, Size, Data, Size, MaxSize);
+}
+
+size_t MutationDispatcher::Mutate_ChangeASCIIInteger(uint8_t *Data, size_t Size,
+                                                     size_t MaxSize) {
+  if (Size > MaxSize) return 0;
+  size_t B = Rand(Size);
+  while (B < Size && !isdigit(Data[B])) B++;
+  if (B == Size) return 0;
+  size_t E = B;
+  while (E < Size && isdigit(Data[E])) E++;
+  assert(B < E);
+  // now we have digits in [B, E).
+  // strtol and friends don't accept non-zero-teminated data, parse it manually.
+  uint64_t Val = Data[B] - '0';
+  for (size_t i = B + 1; i < E; i++)
+    Val = Val * 10 + Data[i] - '0';
+
+  // Mutate the integer value.
+  switch(Rand(5)) {
+    case 0: Val++; break;
+    case 1: Val--; break;
+    case 2: Val /= 2; break;
+    case 3: Val *= 2; break;
+    case 4: Val = Rand(Val * Val); break;
+    default: assert(0);
+  }
+  // Just replace the bytes with the new ones, don't bother moving bytes.
+  for (size_t i = B; i < E; i++) {
+    size_t Idx = E + B - i - 1;
+    assert(Idx >= B && Idx < E);
+    Data[Idx] = (Val % 10) + '0';
+    Val /= 10;
+  }
+  return Size;
+}
+
+template<class T>
+size_t ChangeBinaryInteger(uint8_t *Data, size_t Size, Random &Rand) {
+  if (Size < sizeof(T)) return 0;
+  size_t Off = Rand(Size - sizeof(T) + 1);
+  assert(Off + sizeof(T) <= Size);
+  T Val;
+  if (Off < 64 && !Rand(4)) {
+    Val = static_cast<T>(Size);
+    if (Rand.RandBool())
+      Val = Bswap(Val);
+  } else {
+    memcpy(&Val, Data + Off, sizeof(Val));
+    T Add = static_cast<T>(Rand(21));
+    Add -= 10;
+    if (Rand.RandBool())
+      Val = Bswap(T(Bswap(Val) + Add)); // Add assuming 
diff erent endiannes.
+    else
+      Val = Val + Add;               // Add assuming current endiannes.
+    if (Add == 0 || Rand.RandBool()) // Maybe negate.
+      Val = -Val;
+  }
+  memcpy(Data + Off, &Val, sizeof(Val));
+  return Size;
+}
+
+size_t MutationDispatcher::Mutate_ChangeBinaryInteger(uint8_t *Data,
+                                                      size_t Size,
+                                                      size_t MaxSize) {
+  if (Size > MaxSize) return 0;
+  switch (Rand(4)) {
+    case 3: return ChangeBinaryInteger<uint64_t>(Data, Size, Rand);
+    case 2: return ChangeBinaryInteger<uint32_t>(Data, Size, Rand);
+    case 1: return ChangeBinaryInteger<uint16_t>(Data, Size, Rand);
+    case 0: return ChangeBinaryInteger<uint8_t>(Data, Size, Rand);
+    default: assert(0);
+  }
+  return 0;
+}
+
+size_t MutationDispatcher::Mutate_CrossOver(uint8_t *Data, size_t Size,
+                                            size_t MaxSize) {
+  if (Size > MaxSize) return 0;
+  if (Size == 0) return 0;
+  if (!CrossOverWith) return 0;
+  const Unit &O = *CrossOverWith;
+  if (O.empty()) return 0;
+  size_t NewSize = 0;
+  switch(Rand(3)) {
+    case 0:
+      MutateInPlaceHere.resize(MaxSize);
+      NewSize = CrossOver(Data, Size, O.data(), O.size(),
+                          MutateInPlaceHere.data(), MaxSize);
+      memcpy(Data, MutateInPlaceHere.data(), NewSize);
+      break;
+    case 1:
+      NewSize = InsertPartOf(O.data(), O.size(), Data, Size, MaxSize);
+      if (!NewSize)
+        NewSize = CopyPartOf(O.data(), O.size(), Data, Size);
+      break;
+    case 2:
+      NewSize = CopyPartOf(O.data(), O.size(), Data, Size);
+      break;
+    default: assert(0);
+  }
+  assert(NewSize > 0 && "CrossOver returned empty unit");
+  assert(NewSize <= MaxSize && "CrossOver returned overisized unit");
+  return NewSize;
+}
+
+void MutationDispatcher::StartMutationSequence() {
+  CurrentMutatorSequence.clear();
+  CurrentDictionaryEntrySequence.clear();
+}
+
+// Copy successful dictionary entries to PersistentAutoDictionary.
+void MutationDispatcher::RecordSuccessfulMutationSequence() {
+  for (auto DE : CurrentDictionaryEntrySequence) {
+    // PersistentAutoDictionary.AddWithSuccessCountOne(DE);
+    DE->IncSuccessCount();
+    assert(DE->GetW().size());
+    // Linear search is fine here as this happens seldom.
+    if (!PersistentAutoDictionary.ContainsWord(DE->GetW()))
+      PersistentAutoDictionary.push_back(*DE);
+  }
+}
+
+void MutationDispatcher::PrintRecommendedDictionary() {
+  Vector<DictionaryEntry> V;
+  for (auto &DE : PersistentAutoDictionary)
+    if (!ManualDictionary.ContainsWord(DE.GetW()))
+      V.push_back(DE);
+  if (V.empty()) return;
   Printf("###### Recommended dictionary. ######\n");
-  for (auto &DE : RecommendedDictionary) {
+  for (auto &DE: V) {
     assert(DE.GetW().size());
     Printf("\"");
     PrintASCII(DE.GetW(), "\"");
@@ -80,12 +500,97 @@ void PrintRecommendedDictionary(MutationDispatcher &MD) {
   Printf("###### End of recommended dictionary. ######\n");
 }
 
-void PrintMutationSequence(MutationDispatcher &MD, bool Verbose) {
-  const auto &MS = MD.MutationSequence();
-  const auto &DS = MD.DictionaryEntrySequence();
-  Printf("MS: %zd %s", MS.size(), MS.GetString(Verbose).c_str());
-  if (!DS.empty())
-    Printf(" DE: %s", DS.GetString(Verbose).c_str());
+void MutationDispatcher::PrintMutationSequence(bool Verbose) {
+  Printf("MS: %zd ", CurrentMutatorSequence.size());
+  size_t EntriesToPrint =
+      Verbose ? CurrentMutatorSequence.size()
+              : std::min(kMaxMutationsToPrint, CurrentMutatorSequence.size());
+  for (size_t i = 0; i < EntriesToPrint; i++)
+    Printf("%s-", CurrentMutatorSequence[i].Name);
+  if (!CurrentDictionaryEntrySequence.empty()) {
+    Printf(" DE: ");
+    EntriesToPrint = Verbose ? CurrentDictionaryEntrySequence.size()
+                             : std::min(kMaxMutationsToPrint,
+                                        CurrentDictionaryEntrySequence.size());
+    for (size_t i = 0; i < EntriesToPrint; i++) {
+      Printf("\"");
+      PrintASCII(CurrentDictionaryEntrySequence[i]->GetW(), "\"-");
+    }
+  }
+}
+
+std::string MutationDispatcher::MutationSequence() {
+  std::string MS;
+  for (auto M : CurrentMutatorSequence) {
+    MS += M.Name;
+    MS += "-";
+  }
+  return MS;
+}
+
+size_t MutationDispatcher::Mutate(uint8_t *Data, size_t Size, size_t MaxSize) {
+  return MutateImpl(Data, Size, MaxSize, Mutators);
+}
+
+size_t MutationDispatcher::DefaultMutate(uint8_t *Data, size_t Size,
+                                         size_t MaxSize) {
+  return MutateImpl(Data, Size, MaxSize, DefaultMutators);
+}
+
+// Mutates Data in place, returns new size.
+size_t MutationDispatcher::MutateImpl(uint8_t *Data, size_t Size,
+                                      size_t MaxSize,
+                                      Vector<Mutator> &Mutators) {
+  assert(MaxSize > 0);
+  // Some mutations may fail (e.g. can't insert more bytes if Size == MaxSize),
+  // in which case they will return 0.
+  // Try several times before returning un-mutated data.
+  for (int Iter = 0; Iter < 100; Iter++) {
+    auto M = Mutators[Rand(Mutators.size())];
+    size_t NewSize = (this->*(M.Fn))(Data, Size, MaxSize);
+    if (NewSize && NewSize <= MaxSize) {
+      if (Options.OnlyASCII)
+        ToASCII(Data, NewSize);
+      CurrentMutatorSequence.push_back(M);
+      return NewSize;
+    }
+  }
+  *Data = ' ';
+  return 1;   // Fallback, should not happen frequently.
+}
+
+// Mask represents the set of Data bytes that are worth mutating.
+size_t MutationDispatcher::MutateWithMask(uint8_t *Data, size_t Size,
+                                          size_t MaxSize,
+                                          const Vector<uint8_t> &Mask) {
+  size_t MaskedSize = std::min(Size, Mask.size());
+  // * Copy the worthy bytes into a temporary array T
+  // * Mutate T
+  // * Copy T back.
+  // This is totally unoptimized.
+  auto &T = MutateWithMaskTemp;
+  if (T.size() < Size)
+    T.resize(Size);
+  size_t OneBits = 0;
+  for (size_t I = 0; I < MaskedSize; I++)
+    if (Mask[I])
+      T[OneBits++] = Data[I];
+
+  if (!OneBits) return 0;
+  assert(!T.empty());
+  size_t NewSize = Mutate(T.data(), OneBits, OneBits);
+  assert(NewSize <= OneBits);
+  (void)NewSize;
+  // Even if NewSize < OneBits we still use all OneBits bytes.
+  for (size_t I = 0, J = 0; I < MaskedSize; I++)
+    if (Mask[I])
+      Data[I] = T[J++];
+  return Size;
+}
+
+void MutationDispatcher::AddWordToManualDictionary(const Word &W) {
+  ManualDictionary.push_back(
+      {W, std::numeric_limits<size_t>::max()});
 }
 
 }  // namespace fuzzer

diff  --git a/compiler-rt/lib/fuzzer/FuzzerMutate.h b/compiler-rt/lib/fuzzer/FuzzerMutate.h
index 85e284ef571c1..fd37191156d3f 100644
--- a/compiler-rt/lib/fuzzer/FuzzerMutate.h
+++ b/compiler-rt/lib/fuzzer/FuzzerMutate.h
@@ -11,23 +11,145 @@
 #ifndef LLVM_FUZZER_MUTATE_H
 #define LLVM_FUZZER_MUTATE_H
 
+#include "FuzzerDefs.h"
+#include "FuzzerDictionary.h"
 #include "FuzzerOptions.h"
-#include "mutagen/Mutagen.h"
-#include "mutagen/MutagenDispatcher.h"
+#include "FuzzerRandom.h"
 
 namespace fuzzer {
-namespace {
 
-using mutagen::MutationDispatcher;
+class MutationDispatcher {
+public:
+  MutationDispatcher(Random &Rand, const FuzzingOptions &Options);
+  ~MutationDispatcher() {}
+  /// Indicate that we are about to start a new sequence of mutations.
+  void StartMutationSequence();
+  /// Print the current sequence of mutations. Only prints the full sequence
+  /// when Verbose is true.
+  void PrintMutationSequence(bool Verbose = true);
+  /// Return the current sequence of mutations.
+  std::string MutationSequence();
+  /// Indicate that the current sequence of mutations was successful.
+  void RecordSuccessfulMutationSequence();
+  /// Mutates data by invoking user-provided mutator.
+  size_t Mutate_Custom(uint8_t *Data, size_t Size, size_t MaxSize);
+  /// Mutates data by invoking user-provided crossover.
+  size_t Mutate_CustomCrossOver(uint8_t *Data, size_t Size, size_t MaxSize);
+  /// Mutates data by shuffling bytes.
+  size_t Mutate_ShuffleBytes(uint8_t *Data, size_t Size, size_t MaxSize);
+  /// Mutates data by erasing bytes.
+  size_t Mutate_EraseBytes(uint8_t *Data, size_t Size, size_t MaxSize);
+  /// Mutates data by inserting a byte.
+  size_t Mutate_InsertByte(uint8_t *Data, size_t Size, size_t MaxSize);
+  /// Mutates data by inserting several repeated bytes.
+  size_t Mutate_InsertRepeatedBytes(uint8_t *Data, size_t Size, size_t MaxSize);
+  /// Mutates data by changing one byte.
+  size_t Mutate_ChangeByte(uint8_t *Data, size_t Size, size_t MaxSize);
+  /// Mutates data by changing one bit.
+  size_t Mutate_ChangeBit(uint8_t *Data, size_t Size, size_t MaxSize);
+  /// Mutates data by copying/inserting a part of data into a 
diff erent place.
+  size_t Mutate_CopyPart(uint8_t *Data, size_t Size, size_t MaxSize);
 
-} // namespace
+  /// Mutates data by adding a word from the manual dictionary.
+  size_t Mutate_AddWordFromManualDictionary(uint8_t *Data, size_t Size,
+                                            size_t MaxSize);
 
-void ConfigureMutagen(unsigned int Seed, const FuzzingOptions &Options,
-                      LLVMMutagenConfiguration *OutConfig);
+  /// Mutates data by adding a word from the TORC.
+  size_t Mutate_AddWordFromTORC(uint8_t *Data, size_t Size, size_t MaxSize);
 
-void PrintRecommendedDictionary(MutationDispatcher &MD);
+  /// Mutates data by adding a word from the persistent automatic dictionary.
+  size_t Mutate_AddWordFromPersistentAutoDictionary(uint8_t *Data, size_t Size,
+                                                    size_t MaxSize);
 
-void PrintMutationSequence(MutationDispatcher &MD, bool Verbose = true);
+  /// Tries to find an ASCII integer in Data, changes it to another ASCII int.
+  size_t Mutate_ChangeASCIIInteger(uint8_t *Data, size_t Size, size_t MaxSize);
+  /// Change a 1-, 2-, 4-, or 8-byte integer in interesting ways.
+  size_t Mutate_ChangeBinaryInteger(uint8_t *Data, size_t Size, size_t MaxSize);
+
+  /// CrossOver Data with CrossOverWith.
+  size_t Mutate_CrossOver(uint8_t *Data, size_t Size, size_t MaxSize);
+
+  /// Applies one of the configured mutations.
+  /// Returns the new size of data which could be up to MaxSize.
+  size_t Mutate(uint8_t *Data, size_t Size, size_t MaxSize);
+
+  /// Applies one of the configured mutations to the bytes of Data
+  /// that have '1' in Mask.
+  /// Mask.size() should be >= Size.
+  size_t MutateWithMask(uint8_t *Data, size_t Size, size_t MaxSize,
+                        const Vector<uint8_t> &Mask);
+
+  /// Applies one of the default mutations. Provided as a service
+  /// to mutation authors.
+  size_t DefaultMutate(uint8_t *Data, size_t Size, size_t MaxSize);
+
+  /// Creates a cross-over of two pieces of Data, returns its size.
+  size_t CrossOver(const uint8_t *Data1, size_t Size1, const uint8_t *Data2,
+                   size_t Size2, uint8_t *Out, size_t MaxOutSize);
+
+  void AddWordToManualDictionary(const Word &W);
+
+  void PrintRecommendedDictionary();
+
+  void SetCrossOverWith(const Unit *U) { CrossOverWith = U; }
+
+  Random &GetRand() { return Rand; }
+
+ private:
+  struct Mutator {
+    size_t (MutationDispatcher::*Fn)(uint8_t *Data, size_t Size, size_t Max);
+    const char *Name;
+  };
+
+  size_t AddWordFromDictionary(Dictionary &D, uint8_t *Data, size_t Size,
+                               size_t MaxSize);
+  size_t MutateImpl(uint8_t *Data, size_t Size, size_t MaxSize,
+                    Vector<Mutator> &Mutators);
+
+  size_t InsertPartOf(const uint8_t *From, size_t FromSize, uint8_t *To,
+                      size_t ToSize, size_t MaxToSize);
+  size_t CopyPartOf(const uint8_t *From, size_t FromSize, uint8_t *To,
+                    size_t ToSize);
+  size_t ApplyDictionaryEntry(uint8_t *Data, size_t Size, size_t MaxSize,
+                              DictionaryEntry &DE);
+
+  template <class T>
+  DictionaryEntry MakeDictionaryEntryFromCMP(T Arg1, T Arg2,
+                                             const uint8_t *Data, size_t Size);
+  DictionaryEntry MakeDictionaryEntryFromCMP(const Word &Arg1, const Word &Arg2,
+                                             const uint8_t *Data, size_t Size);
+  DictionaryEntry MakeDictionaryEntryFromCMP(const void *Arg1, const void *Arg2,
+                                             const void *Arg1Mutation,
+                                             const void *Arg2Mutation,
+                                             size_t ArgSize,
+                                             const uint8_t *Data, size_t Size);
+
+  Random &Rand;
+  const FuzzingOptions Options;
+
+  // Dictionary provided by the user via -dict=DICT_FILE.
+  Dictionary ManualDictionary;
+  // Persistent dictionary modified by the fuzzer, consists of
+  // entries that led to successful discoveries in the past mutations.
+  Dictionary PersistentAutoDictionary;
+
+  Vector<DictionaryEntry *> CurrentDictionaryEntrySequence;
+
+  static const size_t kCmpDictionaryEntriesDequeSize = 16;
+  DictionaryEntry CmpDictionaryEntriesDeque[kCmpDictionaryEntriesDequeSize];
+  size_t CmpDictionaryEntriesDequeIdx = 0;
+
+  const Unit *CrossOverWith = nullptr;
+  Vector<uint8_t> MutateInPlaceHere;
+  Vector<uint8_t> MutateWithMaskTemp;
+  // CustomCrossOver needs its own buffer as a custom implementation may call
+  // LLVMFuzzerMutate, which in turn may resize MutateInPlaceHere.
+  Vector<uint8_t> CustomCrossOverInPlaceHere;
+
+  Vector<Mutator> Mutators;
+  Vector<Mutator> DefaultMutators;
+  Vector<Mutator> CurrentMutatorSequence;
+};
 
 }  // namespace fuzzer
 

diff  --git a/compiler-rt/lib/fuzzer/FuzzerRandom.h b/compiler-rt/lib/fuzzer/FuzzerRandom.h
index 8256853a65bb5..ad6c07eb5ef56 100644
--- a/compiler-rt/lib/fuzzer/FuzzerRandom.h
+++ b/compiler-rt/lib/fuzzer/FuzzerRandom.h
@@ -11,7 +11,6 @@
 #ifndef LLVM_FUZZER_RANDOM_H
 #define LLVM_FUZZER_RANDOM_H
 
-#include <cassert>
 #include <random>
 
 namespace fuzzer {

diff  --git a/compiler-rt/lib/fuzzer/FuzzerTracePC.cpp b/compiler-rt/lib/fuzzer/FuzzerTracePC.cpp
index b613aef7b59f5..d808b9b00fa35 100644
--- a/compiler-rt/lib/fuzzer/FuzzerTracePC.cpp
+++ b/compiler-rt/lib/fuzzer/FuzzerTracePC.cpp
@@ -16,6 +16,7 @@
 #include "FuzzerBuiltinsMsvc.h"
 #include "FuzzerCorpus.h"
 #include "FuzzerDefs.h"
+#include "FuzzerDictionary.h"
 #include "FuzzerExtFunctions.h"
 #include "FuzzerIO.h"
 #include "FuzzerPlatform.h"

diff  --git a/compiler-rt/lib/fuzzer/FuzzerTracePC.h b/compiler-rt/lib/fuzzer/FuzzerTracePC.h
index 921a13f082ae3..a93732972f7d7 100644
--- a/compiler-rt/lib/fuzzer/FuzzerTracePC.h
+++ b/compiler-rt/lib/fuzzer/FuzzerTracePC.h
@@ -12,7 +12,7 @@
 #define LLVM_FUZZER_TRACE_PC
 
 #include "FuzzerDefs.h"
-#include "FuzzerUtil.h"
+#include "FuzzerDictionary.h"
 #include "FuzzerValueBitMap.h"
 
 #include <set>
@@ -40,7 +40,7 @@ struct TableOfRecentCompares {
     Table[Idx].B = Arg2;
   }
 
-  const Pair &Get(size_t I) { return Table[I % kSize]; }
+  Pair Get(size_t I) { return Table[I % kSize]; }
 
   Pair Table[kSize];
 };

diff  --git a/compiler-rt/lib/fuzzer/FuzzerUtil.h b/compiler-rt/lib/fuzzer/FuzzerUtil.h
index 285f56be8a767..a188a7be32a53 100644
--- a/compiler-rt/lib/fuzzer/FuzzerUtil.h
+++ b/compiler-rt/lib/fuzzer/FuzzerUtil.h
@@ -47,15 +47,6 @@ void PrintMemoryProfile();
 
 unsigned NumberOfCpuCores();
 
-// Parses one dictionary entry.
-// If successful, write the enty to Unit and returns true,
-// otherwise returns false.
-bool ParseOneDictionaryEntry(const std::string &Str, Unit *U);
-
-// Parses the dictionary file, fills Units, returns true iff all lines
-// were parsed successfully.
-bool ParseDictionaryFile(const std::string &Text, Vector<Unit> *Units);
-
 // Platform specific functions.
 void SetSignalHandler(const FuzzingOptions& Options);
 
@@ -72,6 +63,9 @@ bool ExecuteCommand(const Command &Cmd, std::string *CmdOutput);
 FILE *OpenProcessPipe(const char *Command, const char *Mode);
 int CloseProcessPipe(FILE *F);
 
+const void *SearchMemory(const void *haystack, size_t haystacklen,
+                         const void *needle, size_t needlelen);
+
 std::string CloneArgsWithoutX(const Vector<std::string> &Args,
                               const char *X1, const char *X2);
 

diff  --git a/compiler-rt/lib/fuzzer/FuzzerUtilFuchsia.cpp b/compiler-rt/lib/fuzzer/FuzzerUtilFuchsia.cpp
index e83baa62886c0..5034b4a28d3f5 100644
--- a/compiler-rt/lib/fuzzer/FuzzerUtilFuchsia.cpp
+++ b/compiler-rt/lib/fuzzer/FuzzerUtilFuchsia.cpp
@@ -528,6 +528,11 @@ bool ExecuteCommand(const Command &BaseCmd, std::string *CmdOutput) {
   return Ret == 0;
 }
 
+const void *SearchMemory(const void *Data, size_t DataLen, const void *Patt,
+                         size_t PattLen) {
+  return memmem(Data, DataLen, Patt, PattLen);
+}
+
 // In fuchsia, accessing /dev/null is not supported. There's nothing
 // similar to a file that discards everything that is written to it.
 // The way of doing something similar in fuchsia is by using

diff  --git a/compiler-rt/lib/fuzzer/FuzzerUtilPosix.cpp b/compiler-rt/lib/fuzzer/FuzzerUtilPosix.cpp
index 5f0aa0190dd66..0446d732a9ec8 100644
--- a/compiler-rt/lib/fuzzer/FuzzerUtilPosix.cpp
+++ b/compiler-rt/lib/fuzzer/FuzzerUtilPosix.cpp
@@ -170,6 +170,11 @@ int CloseProcessPipe(FILE *F) {
   return pclose(F);
 }
 
+const void *SearchMemory(const void *Data, size_t DataLen, const void *Patt,
+                         size_t PattLen) {
+  return memmem(Data, DataLen, Patt, PattLen);
+}
+
 std::string DisassembleCmd(const std::string &FileName) {
   return "objdump -d " + FileName;
 }

diff  --git a/compiler-rt/lib/fuzzer/FuzzerUtilWindows.cpp b/compiler-rt/lib/fuzzer/FuzzerUtilWindows.cpp
index 5deb5998fccb4..1a54bb569eca4 100644
--- a/compiler-rt/lib/fuzzer/FuzzerUtilWindows.cpp
+++ b/compiler-rt/lib/fuzzer/FuzzerUtilWindows.cpp
@@ -182,6 +182,27 @@ bool ExecuteCommand(const Command &Cmd, std::string *CmdOutput) {
   return _pclose(Pipe) == 0;
 }
 
+const void *SearchMemory(const void *Data, size_t DataLen, const void *Patt,
+                         size_t PattLen) {
+  // TODO: make this implementation more efficient.
+  const char *Cdata = (const char *)Data;
+  const char *Cpatt = (const char *)Patt;
+
+  if (!Data || !Patt || DataLen == 0 || PattLen == 0 || DataLen < PattLen)
+    return NULL;
+
+  if (PattLen == 1)
+    return memchr(Data, *Cpatt, DataLen);
+
+  const char *End = Cdata + DataLen - PattLen + 1;
+
+  for (const char *It = Cdata; It < End; ++It)
+    if (It[0] == Cpatt[0] && memcmp(It, Cpatt, PattLen) == 0)
+      return It;
+
+  return NULL;
+}
+
 std::string DisassembleCmd(const std::string &FileName) {
   Vector<std::string> command_vector;
   command_vector.push_back("dumpbin /summary > nul");

diff  --git a/compiler-rt/lib/fuzzer/build.sh b/compiler-rt/lib/fuzzer/build.sh
index 822b606041278..504e54e3a819e 100755
--- a/compiler-rt/lib/fuzzer/build.sh
+++ b/compiler-rt/lib/fuzzer/build.sh
@@ -1,11 +1,11 @@
 #!/bin/sh
 LIBFUZZER_SRC_DIR=$(dirname $0)
-LIBMUTAGEN_SRC_DIR=$LIBFUZZER_SRC_DIR/mutagen
 CXX="${CXX:-clang}"
-for f in $LIBFUZZER_SRC_DIR/*.cpp $LIBMUTAGEN_SRC_DIR/*.cpp; do
-  $CXX -g -O2 -fno-omit-frame-pointer -std=c++11 $f -c -I$LIBFUZZER_SRC_DIR &
+for f in $LIBFUZZER_SRC_DIR/*.cpp; do
+  $CXX -g -O2 -fno-omit-frame-pointer -std=c++11 $f -c &
 done
 wait
 rm -f libFuzzer.a
-ar ru libFuzzer.a Fuzzer*.o Mutagen*.o
-rm -f Fuzzer*.o Mutagen*.o
+ar ru libFuzzer.a Fuzzer*.o
+rm -f Fuzzer*.o
+

diff  --git a/compiler-rt/lib/fuzzer/mutagen/CMakeLists.txt b/compiler-rt/lib/fuzzer/mutagen/CMakeLists.txt
deleted file mode 100644
index 1a8175ce6e6ec..0000000000000
--- a/compiler-rt/lib/fuzzer/mutagen/CMakeLists.txt
+++ /dev/null
@@ -1,59 +0,0 @@
-set(MUTAGEN_SOURCES
-  Mutagen.cpp
-  MutagenCrossOver.cpp
-  MutagenDispatcher.cpp
-  MutagenUtilPosix.cpp
-  MutagenUtilWindows.cpp)
-
-set(MUTAGEN_HEADERS
-  Mutagen.h
-  MutagenDictionary.h
-  MutagenDispatcher.h
-  MutagenUtil.h)
-
-# Expose the files in this library to libFuzzer for optimized, direct inclusion.
-set(LIBFUZZER_MUTAGEN_SOURCES ${MUTAGEN_SOURCES} PARENT_SCOPE)
-set(LIBFUZZER_MUTAGEN_HEADERS ${MUTAGEN_HEADERS} PARENT_SCOPE)
-
-# Reuse the following variables from libFuzzer:
-#   FUZZER_SUPPORTED_ARCH
-#   FUZZER_SUPPORTED_OS
-#   LIBFUZZER_CFLAGS
-#   LIBFUZZER_DEPS
-include_directories(..)
-
-add_compiler_rt_component(mutagen)
-
-add_compiler_rt_object_libraries(RTmutagen
-  OS ${FUZZER_SUPPORTED_OS}
-  ARCHS ${FUZZER_SUPPORTED_ARCH}
-  SOURCES ${MUTAGEN_SOURCES}
-  ADDITIONAL_HEADERS ${MUTAGEN_HEADERS}
-  CFLAGS ${LIBFUZZER_CFLAGS}
-  DEPS ${LIBFUZZER_DEPS})
-
-add_compiler_rt_runtime(clang_rt.mutagen
-  STATIC
-  OS ${FUZZER_SUPPORTED_OS}
-  ARCHS ${FUZZER_SUPPORTED_ARCH}
-  OBJECT_LIBS RTmutagen
-  CFLAGS ${LIBFUZZER_CFLAGS}
-  PARENT_TARGET mutagen)
-
-if(OS_NAME MATCHES "Linux|Fuchsia" AND
-   COMPILER_RT_LIBCXX_PATH AND
-   COMPILER_RT_LIBCXXABI_PATH)
-  foreach(arch ${FUZZER_SUPPORTED_ARCH})
-    get_target_flags_for_arch(${arch} TARGET_CFLAGS)
-    set(LIBCXX_${arch}_PREFIX ${CMAKE_CURRENT_BINARY_DIR}/libcxx_mutagen_${arch})
-    add_custom_libcxx(libcxx_mutagen_${arch} ${LIBCXX_${arch}_PREFIX}
-      CFLAGS ${TARGET_CFLAGS}
-      CMAKE_ARGS -DCMAKE_CXX_COMPILER_WORKS=ON
-                 -DCMAKE_POSITION_INDEPENDENT_CODE=ON
-                 -DLIBCXXABI_ENABLE_EXCEPTIONS=OFF
-                 -DLIBCXX_ABI_NAMESPACE=__Fuzzer)
-    target_compile_options(RTmutagen.${arch} PRIVATE -isystem ${LIBCXX_${arch}_PREFIX}/include/c++/v1)
-    add_dependencies(RTmutagen.${arch} libcxx_mutagen_${arch}-build)
-    partially_link_libcxx(mutagen ${LIBCXX_${arch}_PREFIX} ${arch})
-  endforeach()
-endif()

diff  --git a/compiler-rt/lib/fuzzer/mutagen/Mutagen.cpp b/compiler-rt/lib/fuzzer/mutagen/Mutagen.cpp
deleted file mode 100644
index 8d5858191afeb..0000000000000
--- a/compiler-rt/lib/fuzzer/mutagen/Mutagen.cpp
+++ /dev/null
@@ -1,100 +0,0 @@
-//===- Mutagen.cpp - Interface header for the mutagen -----------*- C++ -* ===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-// Define the interface between libMutagen and its consumers.
-//===----------------------------------------------------------------------===//
-
-#include "Mutagen.h"
-#include "FuzzerDefs.h"
-#include "MutagenDispatcher.h"
-#include <algorithm>
-#include <cstdio>
-#include <string>
-
-namespace mutagen {
-namespace {
-
-MutationDispatcher *MD = nullptr;
-
-} // namespace
-
-MutationDispatcher *GetMutationDispatcherForTest() { return MD; }
-
-} // namespace mutagen
-
-using fuzzer::Unit;
-using mutagen::MD;
-using mutagen::MutationDispatcher;
-using mutagen::Word;
-
-extern "C" {
-
-ATTRIBUTE_INTERFACE void
-LLVMMutagenConfigure(const LLVMMutagenConfiguration *Config) {
-  if (MD)
-    delete MD;
-  MD = new MutationDispatcher(Config);
-}
-
-ATTRIBUTE_INTERFACE void LLVMMutagenResetSequence() {
-  MD->StartMutationSequence();
-}
-
-ATTRIBUTE_INTERFACE void LLVMMutagenSetCrossOverWith(const uint8_t *Data,
-                                                     size_t Size) {
-  static Unit CrossOverWith;
-  Unit U(Data, Data + Size);
-  CrossOverWith = std::move(U);
-  MD->SetCrossOverWith(&CrossOverWith);
-}
-
-ATTRIBUTE_INTERFACE size_t LLVMMutagenMutate(uint8_t *Data, size_t Size,
-                                             size_t Max) {
-  return MD->Mutate(Data, Size, Max);
-}
-
-ATTRIBUTE_INTERFACE size_t LLVMMutagenDefaultMutate(uint8_t *Data, size_t Size,
-                                                    size_t Max) {
-  return MD->DefaultMutate(Data, Size, Max);
-}
-
-ATTRIBUTE_INTERFACE void LLVMMutagenRecordSequence() {
-  MD->RecordSuccessfulMutationSequence();
-}
-
-ATTRIBUTE_INTERFACE size_t LLVMMutagenGetMutationSequence(int Verbose,
-                                                          char *Out, size_t Max,
-                                                          size_t *OutNumItems) {
-  const auto &Seq = MD->MutationSequence();
-  if (OutNumItems)
-    *OutNumItems = Seq.size();
-  return snprintf(Out, Max, "%s", Seq.GetString(Verbose).c_str());
-}
-
-ATTRIBUTE_INTERFACE void LLVMMutagenAddWordToDictionary(const uint8_t *Data,
-                                                        size_t Size) {
-  MD->AddWordToManualDictionary(Word(Data, std::min(Size, Word::GetMaxSize())));
-}
-
-ATTRIBUTE_INTERFACE size_t LLVMMutagenGetDictionaryEntrySequence(
-    int Verbose, char *Out, size_t Max, size_t *OutNumItems) {
-  const auto &Seq = MD->DictionaryEntrySequence();
-  if (OutNumItems)
-    *OutNumItems = Seq.size();
-  return snprintf(Out, Max, "%s", Seq.GetString(Verbose).c_str());
-}
-
-ATTRIBUTE_INTERFACE size_t LLVMMutagenRecommendDictionary() {
-  return MD->RecommendDictionary().size();
-}
-
-ATTRIBUTE_INTERFACE const char *
-LLVMMutagenRecommendDictionaryEntry(size_t *OutUseCount) {
-  return MD->RecommendDictionaryEntry(OutUseCount);
-}
-
-} // extern "C"

diff  --git a/compiler-rt/lib/fuzzer/mutagen/Mutagen.h b/compiler-rt/lib/fuzzer/mutagen/Mutagen.h
deleted file mode 100644
index 757ee3e07d2cd..0000000000000
--- a/compiler-rt/lib/fuzzer/mutagen/Mutagen.h
+++ /dev/null
@@ -1,119 +0,0 @@
-//===- Mutagen.h - Interface header for the mutagen -------------*- C++ -* ===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-// Define the interface between libMutagen and its consumers.
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_FUZZER_MUTAGEN_H
-#define LLVM_FUZZER_MUTAGEN_H
-
-#include "FuzzerPlatform.h"
-#include <stddef.h>
-#include <stdint.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif // __cplusplus
-
-#define MAX_WORD_SIZE 64
-
-typedef struct {
-  // PRNG seed.
-  unsigned int Seed;
-
-  // If non-zero, use CMP traces to guide mutations. Ignored if any of
-  // |FromTORC4|, |FromTORC8|, or |FromTORCW| are null.
-  int UseCmp;
-  void (*FromTORC4)(size_t Idx, uint32_t *Arg1, uint32_t *Arg2);
-  void (*FromTORC8)(size_t Idx, uint64_t *Arg1, uint64_t *Arg2);
-  void (*FromTORCW)(size_t Idx, const uint8_t **Data1, size_t *Size1,
-                    const uint8_t **Data2, size_t *Size2);
-
-  // If non-zero, use hints from intercepting memmem, strstr, etc. Ignored if
-  // |UseCmp| is zero or if |FromMMT| is null.
-  int UseMemmem;
-  void (*FromMMT)(size_t Idx, const uint8_t **Data, size_t *Size);
-
-  // If non-zero, generate only ASCII (isprint+isspace) inputs.
-  int OnlyASCII;
-
-  // Optional user-provided custom mutator.
-  size_t (*CustomMutator)(uint8_t *Data, size_t Size, size_t MaxSize,
-                          unsigned int Seed);
-
-  // Optional user-provided custom cross-over function.
-  size_t (*CustomCrossOver)(const uint8_t *Data1, size_t Size1,
-                            const uint8_t *Data2, size_t Size2, uint8_t *Out,
-                            size_t MaxOutSize, unsigned int Seed);
-
-  // Optional MemorySanitizer callbacks.
-  void (*MSanUnpoison)(const volatile void *, size_t size);
-  void (*MSanUnpoisonParam)(size_t n);
-} LLVMMutagenConfiguration;
-
-// Re-seeds the PRNG and sets mutator-related options.
-ATTRIBUTE_INTERFACE void
-LLVMMutagenConfigure(const LLVMMutagenConfiguration *config);
-
-// Writes the mutation sequence to |Out|, and returns the number of
-// characters it wrote, or would have written given a large enough buffer,
-// excluding the null terminator. Thus, a return value of |Max| or greater
-// indicates the sequence was truncated (like snprintf). May truncate the
-// sequence unless |Verbose| is non-zero. Sets |OutNumItems| to the number of
-// items in the untruncated sequence.
-ATTRIBUTE_INTERFACE size_t LLVMMutagenGetMutationSequence(int Verbose,
-                                                          char *Out, size_t Max,
-                                                          size_t *OutNumItems);
-
-// Writes the dictionary entry sequence to |Out|, and returns the number of
-// characters it wrote, or would have written given a large enough buffer,
-// excluding a null terminator. Thus, a return value of |Max| or greater
-// indicates the sequence was truncated (like snprintf). May truncate the
-// sequence unless |Verbose| is non-zero. Sets |OutNumItems| to the number of
-// items in the untruncated sequence.
-ATTRIBUTE_INTERFACE size_t LLVMMutagenGetDictionaryEntrySequence(
-    int Verbose, char *Out, size_t Max, size_t *OutNumItems);
-
-// Instructs the library to record the current mutation sequence as successful
-// at increasing coverage.
-ATTRIBUTE_INTERFACE void LLVMMutagenRecordSequence();
-
-// Clears the mutation and dictionary entry sequences.
-ATTRIBUTE_INTERFACE void LLVMMutagenResetSequence();
-
-// Adds data used by various mutators to produce new inputs.
-ATTRIBUTE_INTERFACE void LLVMMutagenSetCrossOverWith(const uint8_t *Data,
-                                                     size_t Size);
-ATTRIBUTE_INTERFACE void LLVMMutagenAddWordToDictionary(const uint8_t *Word,
-                                                        size_t Size);
-
-// Mutates the contents of |Data| and returns the new size.
-ATTRIBUTE_INTERFACE size_t LLVMMutagenMutate(uint8_t *Data, size_t Size,
-                                             size_t Max);
-
-// Like |LLVMMutagenMutate|, but never selects the custom mutators and is
-// therefore suitable to be called from them.
-ATTRIBUTE_INTERFACE size_t LLVMMutagenDefaultMutate(uint8_t *Data, size_t Size,
-                                                    size_t Max);
-
-// Creates a recommended dictionary and returns its number of entries. The
-// entries can be retrieved by subsequent calls to
-// |LLVMMutagenRecommendDictionaryEntry|.
-ATTRIBUTE_INTERFACE size_t LLVMMutagenRecommendDictionary();
-
-// Returns the ASCII representation of the next recommended dictionary entry,
-// or null if no entries remain (or |LLVMMutagenRecommendDictionary| wasn't
-// called). If non-null, the return pointer is valid until the next call to this
-// method, and if provided, |OutUseCount| is set to the entry's use count.
-ATTRIBUTE_INTERFACE const char *
-LLVMMutagenRecommendDictionaryEntry(size_t *OutUseCount);
-
-#ifdef __cplusplus
-} // extern "C"
-#endif // __cplusplus
-
-#endif // LLVM_FUZZER_MUTAGEN_H

diff  --git a/compiler-rt/lib/fuzzer/mutagen/MutagenDictionary.h b/compiler-rt/lib/fuzzer/mutagen/MutagenDictionary.h
deleted file mode 100644
index a665cabc316e7..0000000000000
--- a/compiler-rt/lib/fuzzer/mutagen/MutagenDictionary.h
+++ /dev/null
@@ -1,85 +0,0 @@
-//===- MutagenDictionary.h - Internal header for the mutagen ----*- C++ -* ===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-// mutagen::Dictionary
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_FUZZER_MUTAGEN_DICTIONARY_H
-#define LLVM_FUZZER_MUTAGEN_DICTIONARY_H
-
-#include "FuzzerDefs.h"
-#include <algorithm>
-#include <cassert>
-#include <cstddef>
-#include <cstdint>
-#include <limits>
-
-namespace mutagen {
-namespace {
-
-using fuzzer::Word;
-
-} // namespace
-
-class DictionaryEntry {
-public:
-  DictionaryEntry() {}
-  DictionaryEntry(Word W) : W(W) {}
-  DictionaryEntry(Word W, size_t PositionHint)
-      : W(W), PositionHint(PositionHint) {}
-  const Word &GetW() const { return W; }
-
-  bool HasPositionHint() const {
-    return PositionHint != std::numeric_limits<size_t>::max();
-  }
-  size_t GetPositionHint() const {
-    assert(HasPositionHint());
-    return PositionHint;
-  }
-  void IncUseCount() { UseCount++; }
-  void IncSuccessCount() { SuccessCount++; }
-  size_t GetUseCount() const { return UseCount; }
-  size_t GetSuccessCount() const { return SuccessCount; }
-
-private:
-  Word W;
-  size_t PositionHint = std::numeric_limits<size_t>::max();
-  size_t UseCount = 0;
-  size_t SuccessCount = 0;
-};
-
-class Dictionary {
-public:
-  static const size_t kMaxDictSize = 1 << 14;
-
-  bool ContainsWord(const Word &W) const {
-    return std::any_of(begin(), end(), [&](const DictionaryEntry &DE) {
-      return DE.GetW() == W;
-    });
-  }
-  const DictionaryEntry *begin() const { return &DE[0]; }
-  const DictionaryEntry *end() const { return begin() + Size; }
-  DictionaryEntry &operator[](size_t Idx) {
-    assert(Idx < Size);
-    return DE[Idx];
-  }
-  void push_back(DictionaryEntry DE) {
-    if (Size < kMaxDictSize)
-      this->DE[Size++] = DE;
-  }
-  void clear() { Size = 0; }
-  bool empty() const { return Size == 0; }
-  size_t size() const { return Size; }
-
-private:
-  DictionaryEntry DE[kMaxDictSize];
-  size_t Size = 0;
-};
-
-} // namespace mutagen
-
-#endif // LLVM_FUZZER_MUTAGEN_DICTIONARY_H

diff  --git a/compiler-rt/lib/fuzzer/mutagen/MutagenDispatcher.cpp b/compiler-rt/lib/fuzzer/mutagen/MutagenDispatcher.cpp
deleted file mode 100644
index 32b5694cc6862..0000000000000
--- a/compiler-rt/lib/fuzzer/mutagen/MutagenDispatcher.cpp
+++ /dev/null
@@ -1,659 +0,0 @@
-//===- MutagenDispatcher.cpp - Mutate a test input ------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-// Mutate a test input.
-//===----------------------------------------------------------------------===//
-
-#include "MutagenDispatcher.h"
-#include "FuzzerBuiltins.h"
-#include "FuzzerBuiltinsMsvc.h"
-#include "FuzzerPlatform.h"
-#include "MutagenUtil.h"
-#include <iomanip>
-#include <sstream>
-
-namespace mutagen {
-namespace {
-
-using fuzzer::Bswap;
-
-std::string ToASCII(const uint8_t *Data, size_t Size) {
-  std::ostringstream OSS;
-  for (size_t i = 0; i < Size; i++) {
-    uint16_t Byte = Data[i];
-    if (Byte == '\\')
-      OSS << "\\\\";
-    else if (Byte == '"')
-      OSS << "\\\"";
-    else if (Byte >= 32 && Byte < 127)
-      OSS << static_cast<char>(Byte);
-    else
-      OSS << "\\x" << std::hex << std::setw(2) << std::setfill('0') << Byte
-          << std::dec;
-  }
-  return OSS.str();
-}
-
-std::string ToASCII(const Word &W) { return ToASCII(W.data(), W.size()); }
-
-} // namespace
-
-void MutationDispatcher::SetConfig(const LLVMMutagenConfiguration *C) {
-  memcpy(&Config, C, sizeof(Config));
-  if (!Config.FromTORC4 || !Config.FromTORC8 || !Config.FromTORCW)
-    Config.UseCmp = 0;
-  if (!Config.FromMMT)
-    Config.UseMemmem = 0;
-}
-
-MutationDispatcher::MutationDispatcher(const LLVMMutagenConfiguration *config)
-    : Rand(config->Seed) {
-  SetConfig(config);
-  DefaultMutators.insert(
-      DefaultMutators.begin(),
-      {
-          {&MutationDispatcher::Mutate_EraseBytes, "EraseBytes"},
-          {&MutationDispatcher::Mutate_InsertByte, "InsertByte"},
-          {&MutationDispatcher::Mutate_InsertRepeatedBytes,
-           "InsertRepeatedBytes"},
-          {&MutationDispatcher::Mutate_ChangeByte, "ChangeByte"},
-          {&MutationDispatcher::Mutate_ChangeBit, "ChangeBit"},
-          {&MutationDispatcher::Mutate_ShuffleBytes, "ShuffleBytes"},
-          {&MutationDispatcher::Mutate_ChangeASCIIInteger, "ChangeASCIIInt"},
-          {&MutationDispatcher::Mutate_ChangeBinaryInteger, "ChangeBinInt"},
-          {&MutationDispatcher::Mutate_CopyPart, "CopyPart"},
-          {&MutationDispatcher::Mutate_CrossOver, "CrossOver"},
-          {&MutationDispatcher::Mutate_AddWordFromManualDictionary,
-           "ManualDict"},
-          {&MutationDispatcher::Mutate_AddWordFromPersistentAutoDictionary,
-           "PersAutoDict"},
-      });
-  if (Config.UseCmp)
-    DefaultMutators.push_back(
-        {&MutationDispatcher::Mutate_AddWordFromTORC, "CMP"});
-
-  if (Config.CustomMutator)
-    Mutators.push_back({&MutationDispatcher::Mutate_Custom, "Custom"});
-  else
-    Mutators = DefaultMutators;
-
-  if (Config.CustomCrossOver)
-    Mutators.push_back(
-        {&MutationDispatcher::Mutate_CustomCrossOver, "CustomCrossOver"});
-}
-
-static char RandCh(Random &Rand) {
-  if (Rand.RandBool())
-    return static_cast<char>(Rand(256));
-  const char Special[] = "!*'();:@&=+$,/?%#[]012Az-`~.\xff\x00";
-  return Special[Rand(sizeof(Special) - 1)];
-}
-
-size_t MutationDispatcher::Mutate_Custom(uint8_t *Data, size_t Size,
-                                         size_t MaxSize) {
-  if (Config.MSanUnpoison)
-    Config.MSanUnpoison(Data, Size);
-  if (Config.MSanUnpoisonParam)
-    Config.MSanUnpoisonParam(4);
-  return Config.CustomMutator(Data, Size, MaxSize, Rand.Rand<unsigned int>());
-}
-
-size_t MutationDispatcher::Mutate_CustomCrossOver(uint8_t *Data, size_t Size,
-                                                  size_t MaxSize) {
-  if (Size == 0)
-    return 0;
-  if (!CrossOverWith)
-    return 0;
-  const Unit &Other = *CrossOverWith;
-  if (Other.empty())
-    return 0;
-  CustomCrossOverInPlaceHere.resize(MaxSize);
-  auto &U = CustomCrossOverInPlaceHere;
-
-  if (Config.MSanUnpoison) {
-    Config.MSanUnpoison(Data, Size);
-    Config.MSanUnpoison(Other.data(), Other.size());
-    Config.MSanUnpoison(U.data(), U.size());
-  }
-  if (Config.MSanUnpoisonParam)
-    Config.MSanUnpoisonParam(7);
-  size_t NewSize =
-      Config.CustomCrossOver(Data, Size, Other.data(), Other.size(), U.data(),
-                             U.size(), Rand.Rand<unsigned int>());
-
-  if (!NewSize)
-    return 0;
-  assert(NewSize <= MaxSize && "CustomCrossOver returned overisized unit");
-  memcpy(Data, U.data(), NewSize);
-  return NewSize;
-}
-
-size_t MutationDispatcher::Mutate_ShuffleBytes(uint8_t *Data, size_t Size,
-                                               size_t MaxSize) {
-  if (Size > MaxSize || Size == 0)
-    return 0;
-  size_t ShuffleAmount =
-      Rand(std::min(Size, (size_t)8)) + 1; // [1,8] and <= Size.
-  size_t ShuffleStart = Rand(Size - ShuffleAmount);
-  assert(ShuffleStart + ShuffleAmount <= Size);
-  std::shuffle(Data + ShuffleStart, Data + ShuffleStart + ShuffleAmount, Rand);
-  return Size;
-}
-
-size_t MutationDispatcher::Mutate_EraseBytes(uint8_t *Data, size_t Size,
-                                             size_t MaxSize) {
-  if (Size <= 1)
-    return 0;
-  size_t N = Rand(Size / 2) + 1;
-  assert(N < Size);
-  size_t Idx = Rand(Size - N + 1);
-  // Erase Data[Idx:Idx+N].
-  memmove(Data + Idx, Data + Idx + N, Size - Idx - N);
-  // Printf("Erase: %zd %zd => %zd; Idx %zd\n", N, Size, Size - N, Idx);
-  return Size - N;
-}
-
-size_t MutationDispatcher::Mutate_InsertByte(uint8_t *Data, size_t Size,
-                                             size_t MaxSize) {
-  if (Size >= MaxSize)
-    return 0;
-  size_t Idx = Rand(Size + 1);
-  // Insert new value at Data[Idx].
-  memmove(Data + Idx + 1, Data + Idx, Size - Idx);
-  Data[Idx] = RandCh(Rand);
-  return Size + 1;
-}
-
-size_t MutationDispatcher::Mutate_InsertRepeatedBytes(uint8_t *Data,
-                                                      size_t Size,
-                                                      size_t MaxSize) {
-  const size_t kMinBytesToInsert = 3;
-  if (Size + kMinBytesToInsert >= MaxSize)
-    return 0;
-  size_t MaxBytesToInsert = std::min(MaxSize - Size, (size_t)128);
-  size_t N = Rand(MaxBytesToInsert - kMinBytesToInsert + 1) + kMinBytesToInsert;
-  assert(Size + N <= MaxSize && N);
-  size_t Idx = Rand(Size + 1);
-  // Insert new values at Data[Idx].
-  memmove(Data + Idx + N, Data + Idx, Size - Idx);
-  // Give preference to 0x00 and 0xff.
-  uint8_t Byte = static_cast<uint8_t>(
-      Rand.RandBool() ? Rand(256) : (Rand.RandBool() ? 0 : 255));
-  for (size_t i = 0; i < N; i++)
-    Data[Idx + i] = Byte;
-  return Size + N;
-}
-
-size_t MutationDispatcher::Mutate_ChangeByte(uint8_t *Data, size_t Size,
-                                             size_t MaxSize) {
-  if (Size > MaxSize)
-    return 0;
-  size_t Idx = Rand(Size);
-  Data[Idx] = RandCh(Rand);
-  return Size;
-}
-
-size_t MutationDispatcher::Mutate_ChangeBit(uint8_t *Data, size_t Size,
-                                            size_t MaxSize) {
-  if (Size > MaxSize)
-    return 0;
-  size_t Idx = Rand(Size);
-  Data[Idx] ^= 1 << Rand(8);
-  return Size;
-}
-
-size_t MutationDispatcher::Mutate_AddWordFromManualDictionary(uint8_t *Data,
-                                                              size_t Size,
-                                                              size_t MaxSize) {
-  return AddWordFromDictionary(ManualDictionary, Data, Size, MaxSize);
-}
-
-size_t MutationDispatcher::ApplyDictionaryEntry(uint8_t *Data, size_t Size,
-                                                size_t MaxSize,
-                                                DictionaryEntry &DE) {
-  const Word &W = DE.GetW();
-  bool UsePositionHint = DE.HasPositionHint() &&
-                         DE.GetPositionHint() + W.size() < Size &&
-                         Rand.RandBool();
-  if (Rand.RandBool()) { // Insert W.
-    if (Size + W.size() > MaxSize)
-      return 0;
-    size_t Idx = UsePositionHint ? DE.GetPositionHint() : Rand(Size + 1);
-    memmove(Data + Idx + W.size(), Data + Idx, Size - Idx);
-    memcpy(Data + Idx, W.data(), W.size());
-    Size += W.size();
-  } else { // Overwrite some bytes with W.
-    if (W.size() > Size)
-      return 0;
-    size_t Idx =
-        UsePositionHint ? DE.GetPositionHint() : Rand(Size + 1 - W.size());
-    memcpy(Data + Idx, W.data(), W.size());
-  }
-  return Size;
-}
-
-// Somewhere in the past we have observed a comparison instructions
-// with arguments Arg1 Arg2. This function tries to guess a dictionary
-// entry that will satisfy that comparison.
-// It first tries to find one of the arguments (possibly swapped) in the
-// input and if it succeeds it creates a DE with a position hint.
-// Otherwise it creates a DE with one of the arguments w/o a position hint.
-DictionaryEntry MutationDispatcher::MakeDictionaryEntryFromCMP(
-    const void *Arg1, const void *Arg2, const void *Arg1Mutation,
-    const void *Arg2Mutation, size_t ArgSize, const uint8_t *Data,
-    size_t Size) {
-  bool HandleFirst = Rand.RandBool();
-  const void *ExistingBytes, *DesiredBytes;
-  Word W;
-  const uint8_t *End = Data + Size;
-  for (int Arg = 0; Arg < 2; Arg++) {
-    ExistingBytes = HandleFirst ? Arg1 : Arg2;
-    DesiredBytes = HandleFirst ? Arg2Mutation : Arg1Mutation;
-    HandleFirst = !HandleFirst;
-    W.Set(reinterpret_cast<const uint8_t *>(DesiredBytes), ArgSize);
-    const size_t kMaxNumPositions = 8;
-    size_t Positions[kMaxNumPositions];
-    size_t NumPositions = 0;
-    for (const uint8_t *Cur = Data;
-         Cur < End && NumPositions < kMaxNumPositions; Cur++) {
-      Cur =
-          (const uint8_t *)SearchMemory(Cur, End - Cur, ExistingBytes, ArgSize);
-      if (!Cur)
-        break;
-      Positions[NumPositions++] = Cur - Data;
-    }
-    if (!NumPositions)
-      continue;
-    return DictionaryEntry(W, Positions[Rand(NumPositions)]);
-  }
-  DictionaryEntry DE(W);
-  return DE;
-}
-
-template <class T>
-DictionaryEntry MutationDispatcher::MakeDictionaryEntryFromCMP(
-    T Arg1, T Arg2, const uint8_t *Data, size_t Size) {
-  if (Rand.RandBool())
-    Arg1 = Bswap(Arg1);
-  if (Rand.RandBool())
-    Arg2 = Bswap(Arg2);
-  T Arg1Mutation = static_cast<T>(Arg1 + Rand(-1, 1));
-  T Arg2Mutation = static_cast<T>(Arg2 + Rand(-1, 1));
-  return MakeDictionaryEntryFromCMP(&Arg1, &Arg2, &Arg1Mutation, &Arg2Mutation,
-                                    sizeof(Arg1), Data, Size);
-}
-
-size_t MutationDispatcher::Mutate_AddWordFromTORC(uint8_t *Data, size_t Size,
-                                                  size_t MaxSize) {
-  Word W;
-  DictionaryEntry DE;
-  switch (Rand(4)) {
-  case 0: {
-    uint64_t A, B;
-    Config.FromTORC8(Rand.Rand<size_t>(), &A, &B);
-    DE = MakeDictionaryEntryFromCMP(A, B, Data, Size);
-  } break;
-  case 1: {
-    uint32_t A, B;
-    Config.FromTORC4(Rand.Rand<size_t>(), &A, &B);
-    if ((A >> 16) == 0 && (B >> 16) == 0 && Rand.RandBool())
-      DE = MakeDictionaryEntryFromCMP((uint16_t)A, (uint16_t)B, Data, Size);
-    else
-      DE = MakeDictionaryEntryFromCMP(A, B, Data, Size);
-  } break;
-  case 2: {
-    const uint8_t *DataA, *DataB;
-    size_t SizeA, SizeB;
-    Config.FromTORCW(Rand.Rand<size_t>(), &DataA, &SizeA, &DataB, &SizeB);
-    DE = MakeDictionaryEntryFromCMP(DataA, DataB, DataA, DataB, SizeA, Data,
-                                    Size);
-  } break;
-  case 3:
-    if (Config.UseMemmem) {
-      const uint8_t *DataW;
-      size_t SizeW;
-      Config.FromMMT(Rand.Rand<size_t>(), &DataW, &SizeW);
-      DE = DictionaryEntry(Word(DataW, SizeW));
-    }
-    break;
-  default:
-    assert(0);
-  }
-  if (!DE.GetW().size())
-    return 0;
-  Size = ApplyDictionaryEntry(Data, Size, MaxSize, DE);
-  if (!Size)
-    return 0;
-  DictionaryEntry &DERef =
-      CmpDictionaryEntriesDeque[CmpDictionaryEntriesDequeIdx++ %
-                                kCmpDictionaryEntriesDequeSize];
-  DERef = DE;
-  CurrentDictionaryEntrySequence.push_back(&DERef);
-  return Size;
-}
-
-size_t MutationDispatcher::Mutate_AddWordFromPersistentAutoDictionary(
-    uint8_t *Data, size_t Size, size_t MaxSize) {
-  return AddWordFromDictionary(PersistentAutoDictionary, Data, Size, MaxSize);
-}
-
-size_t MutationDispatcher::AddWordFromDictionary(Dictionary &D, uint8_t *Data,
-                                                 size_t Size, size_t MaxSize) {
-  if (Size > MaxSize)
-    return 0;
-  if (D.empty())
-    return 0;
-  DictionaryEntry &DE = D[Rand(D.size())];
-  Size = ApplyDictionaryEntry(Data, Size, MaxSize, DE);
-  if (!Size)
-    return 0;
-  DE.IncUseCount();
-  CurrentDictionaryEntrySequence.push_back(&DE);
-  return Size;
-}
-
-// Overwrites part of To[0,ToSize) with a part of From[0,FromSize).
-// Returns ToSize.
-size_t MutationDispatcher::CopyPartOf(const uint8_t *From, size_t FromSize,
-                                      uint8_t *To, size_t ToSize) {
-  // Copy From[FromBeg, FromBeg + CopySize) into To[ToBeg, ToBeg + CopySize).
-  size_t ToBeg = Rand(ToSize);
-  size_t CopySize = Rand(ToSize - ToBeg) + 1;
-  assert(ToBeg + CopySize <= ToSize);
-  CopySize = std::min(CopySize, FromSize);
-  size_t FromBeg = Rand(FromSize - CopySize + 1);
-  assert(FromBeg + CopySize <= FromSize);
-  memmove(To + ToBeg, From + FromBeg, CopySize);
-  return ToSize;
-}
-
-// Inserts part of From[0,ToSize) into To.
-// Returns new size of To on success or 0 on failure.
-size_t MutationDispatcher::InsertPartOf(const uint8_t *From, size_t FromSize,
-                                        uint8_t *To, size_t ToSize,
-                                        size_t MaxToSize) {
-  if (ToSize >= MaxToSize)
-    return 0;
-  size_t AvailableSpace = MaxToSize - ToSize;
-  size_t MaxCopySize = std::min(AvailableSpace, FromSize);
-  size_t CopySize = Rand(MaxCopySize) + 1;
-  size_t FromBeg = Rand(FromSize - CopySize + 1);
-  assert(FromBeg + CopySize <= FromSize);
-  size_t ToInsertPos = Rand(ToSize + 1);
-  assert(ToInsertPos + CopySize <= MaxToSize);
-  size_t TailSize = ToSize - ToInsertPos;
-  if (To == From) {
-    MutateInPlaceHere.resize(MaxToSize);
-    memcpy(MutateInPlaceHere.data(), From + FromBeg, CopySize);
-    memmove(To + ToInsertPos + CopySize, To + ToInsertPos, TailSize);
-    memmove(To + ToInsertPos, MutateInPlaceHere.data(), CopySize);
-  } else {
-    memmove(To + ToInsertPos + CopySize, To + ToInsertPos, TailSize);
-    memmove(To + ToInsertPos, From + FromBeg, CopySize);
-  }
-  return ToSize + CopySize;
-}
-
-size_t MutationDispatcher::Mutate_CopyPart(uint8_t *Data, size_t Size,
-                                           size_t MaxSize) {
-  if (Size > MaxSize || Size == 0)
-    return 0;
-  // If Size == MaxSize, `InsertPartOf(...)` will
-  // fail so there's no point using it in this case.
-  if (Size == MaxSize || Rand.RandBool())
-    return CopyPartOf(Data, Size, Data, Size);
-  else
-    return InsertPartOf(Data, Size, Data, Size, MaxSize);
-}
-
-size_t MutationDispatcher::Mutate_ChangeASCIIInteger(uint8_t *Data, size_t Size,
-                                                     size_t MaxSize) {
-  if (Size > MaxSize)
-    return 0;
-  size_t B = Rand(Size);
-  while (B < Size && !isdigit(Data[B]))
-    B++;
-  if (B == Size)
-    return 0;
-  size_t E = B;
-  while (E < Size && isdigit(Data[E]))
-    E++;
-  assert(B < E);
-  // now we have digits in [B, E).
-  // strtol and friends don't accept non-zero-teminated data, parse it manually.
-  uint64_t Val = Data[B] - '0';
-  for (size_t i = B + 1; i < E; i++)
-    Val = Val * 10 + Data[i] - '0';
-
-  // Mutate the integer value.
-  switch (Rand(5)) {
-  case 0:
-    Val++;
-    break;
-  case 1:
-    Val--;
-    break;
-  case 2:
-    Val /= 2;
-    break;
-  case 3:
-    Val *= 2;
-    break;
-  case 4:
-    Val = Rand(Val * Val);
-    break;
-  default:
-    assert(0);
-  }
-  // Just replace the bytes with the new ones, don't bother moving bytes.
-  for (size_t i = B; i < E; i++) {
-    size_t Idx = E + B - i - 1;
-    assert(Idx >= B && Idx < E);
-    Data[Idx] = (Val % 10) + '0';
-    Val /= 10;
-  }
-  return Size;
-}
-
-template <class T>
-size_t ChangeBinaryInteger(uint8_t *Data, size_t Size, Random &Rand) {
-  if (Size < sizeof(T))
-    return 0;
-  size_t Off = Rand(Size - sizeof(T) + 1);
-  assert(Off + sizeof(T) <= Size);
-  T Val;
-  if (Off < 64 && !Rand(4)) {
-    Val = static_cast<T>(Size);
-    if (Rand.RandBool())
-      Val = Bswap(Val);
-  } else {
-    memcpy(&Val, Data + Off, sizeof(Val));
-    T Add = static_cast<T>(Rand(21));
-    Add -= 10;
-    if (Rand.RandBool())
-      Val = Bswap(T(Bswap(Val) + Add)); // Add assuming 
diff erent endiannes.
-    else
-      Val = Val + Add;               // Add assuming current endiannes.
-    if (Add == 0 || Rand.RandBool()) // Maybe negate.
-      Val = -Val;
-  }
-  memcpy(Data + Off, &Val, sizeof(Val));
-  return Size;
-}
-
-size_t MutationDispatcher::Mutate_ChangeBinaryInteger(uint8_t *Data,
-                                                      size_t Size,
-                                                      size_t MaxSize) {
-  if (Size > MaxSize)
-    return 0;
-  switch (Rand(4)) {
-  case 3:
-    return ChangeBinaryInteger<uint64_t>(Data, Size, Rand);
-  case 2:
-    return ChangeBinaryInteger<uint32_t>(Data, Size, Rand);
-  case 1:
-    return ChangeBinaryInteger<uint16_t>(Data, Size, Rand);
-  case 0:
-    return ChangeBinaryInteger<uint8_t>(Data, Size, Rand);
-  default:
-    assert(0);
-  }
-  return 0;
-}
-
-size_t MutationDispatcher::Mutate_CrossOver(uint8_t *Data, size_t Size,
-                                            size_t MaxSize) {
-  if (Size > MaxSize)
-    return 0;
-  if (Size == 0)
-    return 0;
-  if (!CrossOverWith)
-    return 0;
-  const Unit &O = *CrossOverWith;
-  if (O.empty())
-    return 0;
-  size_t NewSize = 0;
-  switch (Rand(3)) {
-  case 0:
-    MutateInPlaceHere.resize(MaxSize);
-    NewSize = CrossOver(Data, Size, O.data(), O.size(),
-                        MutateInPlaceHere.data(), MaxSize);
-    memcpy(Data, MutateInPlaceHere.data(), NewSize);
-    break;
-  case 1:
-    NewSize = InsertPartOf(O.data(), O.size(), Data, Size, MaxSize);
-    if (!NewSize)
-      NewSize = CopyPartOf(O.data(), O.size(), Data, Size);
-    break;
-  case 2:
-    NewSize = CopyPartOf(O.data(), O.size(), Data, Size);
-    break;
-  default:
-    assert(0);
-  }
-  assert(NewSize > 0 && "CrossOver returned empty unit");
-  assert(NewSize <= MaxSize && "CrossOver returned overisized unit");
-  return NewSize;
-}
-
-void MutationDispatcher::StartMutationSequence() {
-  CurrentMutatorSequence.clear();
-  CurrentDictionaryEntrySequence.clear();
-}
-
-// Copy successful dictionary entries to PersistentAutoDictionary.
-void MutationDispatcher::RecordSuccessfulMutationSequence() {
-  for (auto *DE : CurrentDictionaryEntrySequence) {
-    // PersistentAutoDictionary.AddWithSuccessCountOne(DE);
-    DE->IncSuccessCount();
-    assert(DE->GetW().size());
-    // Linear search is fine here as this happens seldom.
-    if (!PersistentAutoDictionary.ContainsWord(DE->GetW()))
-      PersistentAutoDictionary.push_back(*DE);
-  }
-}
-
-const Dictionary &MutationDispatcher::RecommendDictionary() {
-  RecommendedDictionary.clear();
-  for (auto &DE : PersistentAutoDictionary)
-    if (!ManualDictionary.ContainsWord(DE.GetW()))
-      RecommendedDictionary.push_back(DE);
-  NextRecommendedDictionaryEntry = 0;
-  return RecommendedDictionary;
-}
-
-const char *MutationDispatcher::RecommendDictionaryEntry(size_t *UseCount) {
-  if (NextRecommendedDictionaryEntry >= RecommendedDictionary.size())
-    return nullptr;
-  auto &DE = RecommendedDictionary[NextRecommendedDictionaryEntry++];
-  assert(DE.GetW().size());
-  DictionaryEntryWord = ToASCII(DE.GetW());
-  if (UseCount)
-    *UseCount = DE.GetUseCount();
-  return DictionaryEntryWord.c_str();
-}
-
-const Sequence<MutationDispatcher::Mutator> &
-MutationDispatcher::MutationSequence() {
-  CurrentMutatorSequence.SetString([](Mutator M) { return M.Name; });
-  return CurrentMutatorSequence;
-}
-
-const Sequence<DictionaryEntry *> &
-MutationDispatcher::DictionaryEntrySequence() {
-  CurrentDictionaryEntrySequence.SetString([](DictionaryEntry *DE) {
-    return std::string("\"") + ToASCII(DE->GetW()) + std::string("\"");
-  });
-  return CurrentDictionaryEntrySequence;
-}
-
-size_t MutationDispatcher::Mutate(uint8_t *Data, size_t Size, size_t MaxSize) {
-  return MutateImpl(Data, Size, MaxSize, Mutators);
-}
-
-size_t MutationDispatcher::DefaultMutate(uint8_t *Data, size_t Size,
-                                         size_t MaxSize) {
-  return MutateImpl(Data, Size, MaxSize, DefaultMutators);
-}
-
-// Mutates Data in place, returns new size.
-size_t MutationDispatcher::MutateImpl(uint8_t *Data, size_t Size,
-                                      size_t MaxSize,
-                                      Vector<Mutator> &Mutators) {
-  assert(MaxSize > 0);
-  // Some mutations may fail (e.g. can't insert more bytes if Size == MaxSize),
-  // in which case they will return 0.
-  // Try several times before returning un-mutated data.
-  for (int Iter = 0; Iter < 100; Iter++) {
-    auto M = Mutators[Rand(Mutators.size())];
-    size_t NewSize = (this->*(M.Fn))(Data, Size, MaxSize);
-    if (NewSize && NewSize <= MaxSize) {
-      if (Config.OnlyASCII)
-        ToASCII(Data, NewSize);
-      CurrentMutatorSequence.push_back(M);
-      return NewSize;
-    }
-  }
-  *Data = ' ';
-  return 1; // Fallback, should not happen frequently.
-}
-
-// Mask represents the set of Data bytes that are worth mutating.
-size_t MutationDispatcher::MutateWithMask(uint8_t *Data, size_t Size,
-                                          size_t MaxSize,
-                                          const Vector<uint8_t> &Mask) {
-  size_t MaskedSize = std::min(Size, Mask.size());
-  // * Copy the worthy bytes into a temporary array T
-  // * Mutate T
-  // * Copy T back.
-  // This is totally unoptimized.
-  auto &T = MutateWithMaskTemp;
-  if (T.size() < Size)
-    T.resize(Size);
-  size_t OneBits = 0;
-  for (size_t I = 0; I < MaskedSize; I++)
-    if (Mask[I])
-      T[OneBits++] = Data[I];
-
-  if (!OneBits)
-    return 0;
-  assert(!T.empty());
-  size_t NewSize = Mutate(T.data(), OneBits, OneBits);
-  assert(NewSize <= OneBits);
-  (void)NewSize;
-  // Even if NewSize < OneBits we still use all OneBits bytes.
-  for (size_t I = 0, J = 0; I < MaskedSize; I++)
-    if (Mask[I])
-      Data[I] = T[J++];
-  return Size;
-}
-
-void MutationDispatcher::AddWordToManualDictionary(const Word &W) {
-  ManualDictionary.push_back({W, std::numeric_limits<size_t>::max()});
-}
-
-} // namespace mutagen

diff  --git a/compiler-rt/lib/fuzzer/mutagen/MutagenDispatcher.h b/compiler-rt/lib/fuzzer/mutagen/MutagenDispatcher.h
deleted file mode 100644
index c5c43d5c346fe..0000000000000
--- a/compiler-rt/lib/fuzzer/mutagen/MutagenDispatcher.h
+++ /dev/null
@@ -1,190 +0,0 @@
-//===- MutagenDispatcher.h - Internal header for the mutagen ----*- C++ -* ===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-// mutagen::MutationDispatcher
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_FUZZER_MUTAGEN_DISPATCHER_H
-#define LLVM_FUZZER_MUTAGEN_DISPATCHER_H
-
-#include "FuzzerRandom.h"
-#include "Mutagen.h"
-#include "MutagenDictionary.h"
-#include "MutagenSequence.h"
-#include <cstddef>
-#include <cstdint>
-#include <string>
-
-namespace mutagen {
-namespace {
-
-using fuzzer::Random;
-using fuzzer::Unit;
-using fuzzer::Vector;
-using fuzzer::Word;
-
-} // namespace
-
-class MutationDispatcher final {
-public:
-  struct Mutator {
-    size_t (MutationDispatcher::*Fn)(uint8_t *Data, size_t Size, size_t Max);
-    const char *Name;
-  };
-
-  explicit MutationDispatcher(const LLVMMutagenConfiguration *Config);
-  ~MutationDispatcher() = default;
-
-  /// Indicate that we are about to start a new sequence of mutations.
-  void StartMutationSequence();
-  /// Returns the current sequence of mutations. May truncate the sequence
-  /// unless Verbose is true. Sets |OutSize| to the length of the untrancated
-  /// sequence, if provided.
-  const Sequence<Mutator> &MutationSequence();
-  /// Returns the current sequence of dictionary entries. May truncate the
-  /// sequence unless Verbose is true. Sets |OutSize| to the length of the
-  /// untrancated sequence, if provided.
-  const Sequence<DictionaryEntry *> &DictionaryEntrySequence();
-  /// Indicate that the current sequence of mutations was successful.
-  void RecordSuccessfulMutationSequence();
-  /// Mutates data by invoking user-provided mutator.
-  size_t Mutate_Custom(uint8_t *Data, size_t Size, size_t MaxSize);
-  /// Mutates data by invoking user-provided crossover.
-  size_t Mutate_CustomCrossOver(uint8_t *Data, size_t Size, size_t MaxSize);
-  /// Mutates data by shuffling bytes.
-  size_t Mutate_ShuffleBytes(uint8_t *Data, size_t Size, size_t MaxSize);
-  /// Mutates data by erasing bytes.
-  size_t Mutate_EraseBytes(uint8_t *Data, size_t Size, size_t MaxSize);
-  /// Mutates data by inserting a byte.
-  size_t Mutate_InsertByte(uint8_t *Data, size_t Size, size_t MaxSize);
-  /// Mutates data by inserting several repeated bytes.
-  size_t Mutate_InsertRepeatedBytes(uint8_t *Data, size_t Size, size_t MaxSize);
-  /// Mutates data by changing one byte.
-  size_t Mutate_ChangeByte(uint8_t *Data, size_t Size, size_t MaxSize);
-  /// Mutates data by changing one bit.
-  size_t Mutate_ChangeBit(uint8_t *Data, size_t Size, size_t MaxSize);
-  /// Mutates data by copying/inserting a part of data into a 
diff erent place.
-  size_t Mutate_CopyPart(uint8_t *Data, size_t Size, size_t MaxSize);
-
-  /// Mutates data by adding a word from the manual dictionary.
-  size_t Mutate_AddWordFromManualDictionary(uint8_t *Data, size_t Size,
-                                            size_t MaxSize);
-
-  /// Mutates data by adding a word from the TORC.
-  size_t Mutate_AddWordFromTORC(uint8_t *Data, size_t Size, size_t MaxSize);
-
-  /// Mutates data by adding a word from the persistent automatic dictionary.
-  size_t Mutate_AddWordFromPersistentAutoDictionary(uint8_t *Data, size_t Size,
-                                                    size_t MaxSize);
-
-  /// Tries to find an ASCII integer in Data, changes it to another ASCII int.
-  size_t Mutate_ChangeASCIIInteger(uint8_t *Data, size_t Size, size_t MaxSize);
-  /// Change a 1-, 2-, 4-, or 8-byte integer in interesting ways.
-  size_t Mutate_ChangeBinaryInteger(uint8_t *Data, size_t Size, size_t MaxSize);
-
-  /// CrossOver Data with CrossOverWith.
-  size_t Mutate_CrossOver(uint8_t *Data, size_t Size, size_t MaxSize);
-
-  size_t AddWordFromDictionary(Dictionary &D, uint8_t *Data, size_t Size,
-                               size_t MaxSize);
-  size_t MutateImpl(uint8_t *Data, size_t Size, size_t MaxSize,
-                    Vector<Mutator> &Mutators);
-
-  size_t InsertPartOf(const uint8_t *From, size_t FromSize, uint8_t *To,
-                      size_t ToSize, size_t MaxToSize);
-  size_t CopyPartOf(const uint8_t *From, size_t FromSize, uint8_t *To,
-                    size_t ToSize);
-  size_t ApplyDictionaryEntry(uint8_t *Data, size_t Size, size_t MaxSize,
-                              DictionaryEntry &DE);
-
-  template <class T>
-  DictionaryEntry MakeDictionaryEntryFromCMP(T Arg1, T Arg2,
-                                             const uint8_t *Data, size_t Size);
-  DictionaryEntry MakeDictionaryEntryFromCMP(const Word &Arg1, const Word &Arg2,
-                                             const uint8_t *Data, size_t Size);
-  DictionaryEntry MakeDictionaryEntryFromCMP(const void *Arg1, const void *Arg2,
-                                             const void *Arg1Mutation,
-                                             const void *Arg2Mutation,
-                                             size_t ArgSize,
-                                             const uint8_t *Data, size_t Size);
-
-  /// Applies one of the configured mutations.
-  /// Returns the new size of data which could be up to MaxSize.
-  size_t Mutate(uint8_t *Data, size_t Size, size_t MaxSize);
-
-  /// Applies one of the configured mutations to the bytes of Data
-  /// that have '1' in Mask.
-  /// Mask.size() should be >= Size.
-  size_t MutateWithMask(uint8_t *Data, size_t Size, size_t MaxSize,
-                        const Vector<uint8_t> &Mask);
-
-  /// Applies one of the default mutations. Provided as a service
-  /// to mutation authors.
-  size_t DefaultMutate(uint8_t *Data, size_t Size, size_t MaxSize);
-
-  /// Creates a cross-over of two pieces of Data, returns its size.
-  size_t CrossOver(const uint8_t *Data1, size_t Size1, const uint8_t *Data2,
-                   size_t Size2, uint8_t *Out, size_t MaxOutSize);
-
-  void AddWordToManualDictionary(const Word &W);
-
-  // Creates a recommended dictionary and returns its number of entries. The
-  // entries can be retrieved by subsequent calls to
-  // |LLVMMutagenRecommendDictionaryEntry|.
-  const Dictionary &RecommendDictionary();
-
-  // Returns the ASCII representation of the next recommended dictionary entry,
-  // and sets |OutUseCount| to its use count. The return pointer is valid until
-  // the next call to this method.
-  const char *RecommendDictionaryEntry(size_t *OutUseCount);
-
-  void SetCrossOverWith(const Unit *U) { CrossOverWith = U; }
-
-  Random &GetRand() { return Rand; }
-
-private:
-  // Imports and validates the disptacher's configuration.
-  void SetConfig(const LLVMMutagenConfiguration *Config);
-
-  Random Rand;
-  LLVMMutagenConfiguration Config;
-
-  // Dictionary provided by the user via -dict=DICT_FILE.
-  Dictionary ManualDictionary;
-  // Persistent dictionary modified by the fuzzer, consists of
-  // entries that led to successful discoveries in the past mutations.
-  Dictionary PersistentAutoDictionary;
-  // Recommended dictionary buolt by |RecommendDictionary|.
-  Dictionary RecommendedDictionary;
-  size_t NextRecommendedDictionaryEntry = 0;
-  std::string DictionaryEntryWord;
-
-  Sequence<DictionaryEntry *> CurrentDictionaryEntrySequence;
-
-  static const size_t kCmpDictionaryEntriesDequeSize = 16;
-  DictionaryEntry CmpDictionaryEntriesDeque[kCmpDictionaryEntriesDequeSize];
-  size_t CmpDictionaryEntriesDequeIdx = 0;
-
-  const Unit *CrossOverWith = nullptr;
-  Vector<uint8_t> MutateInPlaceHere;
-  Vector<uint8_t> MutateWithMaskTemp;
-  // CustomCrossOver needs its own buffer as a custom implementation may call
-  // LLVMFuzzerMutate, which in turn may resize MutateInPlaceHere.
-  Vector<uint8_t> CustomCrossOverInPlaceHere;
-
-  Vector<Mutator> Mutators;
-  Vector<Mutator> DefaultMutators;
-  Sequence<Mutator> CurrentMutatorSequence;
-};
-
-// Returns a pointer to the MutationDispatcher is use by MutagenInterface.
-// This should only be used for testing.
-MutationDispatcher *GetMutationDispatcherForTest();
-
-} // namespace mutagen
-
-#endif // LLVM_FUZZER_MUTAGEN_DISPATCHER_H

diff  --git a/compiler-rt/lib/fuzzer/mutagen/MutagenSequence.h b/compiler-rt/lib/fuzzer/mutagen/MutagenSequence.h
deleted file mode 100644
index fd0ab2cb5f0f9..0000000000000
--- a/compiler-rt/lib/fuzzer/mutagen/MutagenSequence.h
+++ /dev/null
@@ -1,101 +0,0 @@
-//===- MutagenSequence.h - Internal header for the mutagen ------*- C++ -* ===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-// mutagen::Sequence
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_FUZZER_MUTAGEN_SEQUENCE_H
-#define LLVM_FUZZER_MUTAGEN_SEQUENCE_H
-
-#include "FuzzerDefs.h"
-#include <sstream>
-#include <string>
-
-namespace mutagen {
-namespace {
-
-using fuzzer::Vector;
-
-} // namespace
-
-// The Sequence type bundles together a list of items, a string representation,
-// and a position in that string suitable for truncating it when overly long,
-// e.g. after the tenth item.
-template <typename T> class Sequence {
-public:
-  constexpr static size_t kMaxBriefItems = 10;
-
-  void clear() {
-    Items.clear();
-    Size = 0;
-    Str.clear();
-    Brief = 0;
-  }
-
-  bool empty() const { return Size == 0; }
-
-  size_t size() const { return Size; }
-
-  void push_back(T t) { Items.push_back(t); }
-
-  typename Vector<T>::const_iterator begin() const { return Items.begin(); }
-  typename Vector<T>::iterator begin() { return Items.begin(); }
-
-  typename Vector<T>::const_iterator end() const { return Items.end(); }
-  typename Vector<T>::iterator end() { return Items.end(); }
-
-  std::string GetString(bool Verbose = true) const {
-    return Verbose ? Str : Str.substr(0, Brief);
-  }
-
-  // Constructs the string representation of the sequence, using a callback that
-  // converts items to strings.
-  template <typename ItemCallback>
-  // std::string ItemCallback(T Item);
-  void SetString(ItemCallback ConvertToASCII) {
-    // No change since last call.
-    if (Size == Items.size())
-      return;
-    Size = Items.size();
-    std::ostringstream OSS;
-    size_t i = 0;
-    for (; i < Size && i < kMaxBriefItems; i++)
-      OSS << ConvertToASCII(Items[i]) << "-";
-    Brief = static_cast<size_t>(OSS.tellp());
-    for (; i < Size; i++)
-      OSS << ConvertToASCII(Items[i]) << "-";
-    Str = OSS.str();
-  }
-
-private:
-  Vector<T> Items;
-  size_t Size = 0;
-  std::string Str;
-  size_t Brief = 0;
-};
-
-template <typename T>
-typename Vector<T>::const_iterator begin(const Sequence<T> &S) {
-  return S.begin();
-}
-
-template <typename T> typename Vector<T>::iterator begin(Sequence<T> &S) {
-  return S.begin();
-}
-
-template <typename T>
-typename Vector<T>::const_iterator end(const Sequence<T> &S) {
-  return S.end();
-}
-
-template <typename T> typename Vector<T>::iterator end(Sequence<T> &S) {
-  return S.end();
-}
-
-} // namespace mutagen
-
-#endif // LLVM_FUZZER_MUTAGEN_SEQUENCE_H

diff  --git a/compiler-rt/lib/fuzzer/mutagen/MutagenUtil.h b/compiler-rt/lib/fuzzer/mutagen/MutagenUtil.h
deleted file mode 100644
index cf3b78b9655af..0000000000000
--- a/compiler-rt/lib/fuzzer/mutagen/MutagenUtil.h
+++ /dev/null
@@ -1,24 +0,0 @@
-//===- MutagenUtil.h - Internal header for the mutagen Utils ----*- C++ -* ===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-// Util functions.
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_FUZZER_MUTAGEN_UTIL_H
-#define LLVM_FUZZER_MUTAGEN_UTIL_H
-
-#include <cstddef>
-#include <cstdint>
-
-namespace mutagen {
-
-const void *SearchMemory(const void *haystack, size_t haystacklen,
-                         const void *needle, size_t needlelen);
-
-} // namespace mutagen
-
-#endif // LLVM_FUZZER_MUTAGEN_UTIL_H

diff  --git a/compiler-rt/lib/fuzzer/mutagen/MutagenUtilPosix.cpp b/compiler-rt/lib/fuzzer/mutagen/MutagenUtilPosix.cpp
deleted file mode 100644
index c157c6190c5d7..0000000000000
--- a/compiler-rt/lib/fuzzer/mutagen/MutagenUtilPosix.cpp
+++ /dev/null
@@ -1,23 +0,0 @@
-//===- MutagenUtilPosix.cpp - Misc utils for Posix. -----------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-// Misc utils implementation using Posix API.
-//===----------------------------------------------------------------------===//
-#include "FuzzerPlatform.h"
-#if (LIBFUZZER_POSIX || LIBFUZZER_FUCHSIA)
-#include <cstring>
-
-namespace mutagen {
-
-const void *SearchMemory(const void *Data, size_t DataLen, const void *Patt,
-                         size_t PattLen) {
-  return memmem(Data, DataLen, Patt, PattLen);
-}
-
-} // namespace mutagen
-
-#endif // (LIBFUZZER_POSIX || LIBFUZZER_FUCHSIA)

diff  --git a/compiler-rt/lib/fuzzer/mutagen/MutagenUtilWindows.cpp b/compiler-rt/lib/fuzzer/mutagen/MutagenUtilWindows.cpp
deleted file mode 100644
index 93b86556b1393..0000000000000
--- a/compiler-rt/lib/fuzzer/mutagen/MutagenUtilWindows.cpp
+++ /dev/null
@@ -1,41 +0,0 @@
-//===- MutagenUtilWindows.cpp - Misc utils for Windows. -------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-// Misc utils implementation for Windows.
-//===----------------------------------------------------------------------===//
-#include "FuzzerPlatform.h"
-#if LIBFUZZER_WINDOWS
-#include <cstddef>
-#include <cstdio>
-#include <cstring>
-
-namespace mutagen {
-
-const void *SearchMemory(const void *Data, size_t DataLen, const void *Patt,
-                         size_t PattLen) {
-  // TODO: make this implementation more efficient.
-  const char *Cdata = (const char *)Data;
-  const char *Cpatt = (const char *)Patt;
-
-  if (!Data || !Patt || DataLen == 0 || PattLen == 0 || DataLen < PattLen)
-    return NULL;
-
-  if (PattLen == 1)
-    return memchr(Data, *Cpatt, DataLen);
-
-  const char *End = Cdata + DataLen - PattLen + 1;
-
-  for (const char *It = Cdata; It < End; ++It)
-    if (It[0] == Cpatt[0] && memcmp(It, Cpatt, PattLen) == 0)
-      return It;
-
-  return NULL;
-}
-
-} // namespace mutagen
-
-#endif // LIBFUZZER_WINDOWS

diff  --git a/compiler-rt/lib/fuzzer/mutagen/build.sh b/compiler-rt/lib/fuzzer/mutagen/build.sh
deleted file mode 100755
index 19c22b8fc5562..0000000000000
--- a/compiler-rt/lib/fuzzer/mutagen/build.sh
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/bin/sh
-LIBMUTAGEN_SRC_DIR=$(dirname $0)
-LIBFUZZER_SRC_DIR=$LIBMUTAGEN_SRC_DIR/..
-CXX="${CXX:-clang}"
-for f in $LIBMUTAGEN_SRC_DIR/*.cpp; do
-  $CXX -g -O2 -fno-omit-frame-pointer -std=c++11 $f -c -I$LIBFUZZER_SRC_DIR &
-done
-wait
-rm -f libMutagen.a
-ar ru libMutagen.a Mutagen*.o
-rm -f Mutagen*.o
-

diff  --git a/compiler-rt/lib/fuzzer/tests/CMakeLists.txt b/compiler-rt/lib/fuzzer/tests/CMakeLists.txt
index 974efc3c5b630..5b3e906419546 100644
--- a/compiler-rt/lib/fuzzer/tests/CMakeLists.txt
+++ b/compiler-rt/lib/fuzzer/tests/CMakeLists.txt
@@ -17,9 +17,6 @@ set_target_properties(FuzzerUnitTests PROPERTIES FOLDER "Compiler-RT Tests")
 add_custom_target(FuzzedDataProviderUnitTests)
 set_target_properties(FuzzedDataProviderUnitTests PROPERTIES FOLDER "Compiler-RT Tests")
 
-add_custom_target(MutagenUnitTests)
-set_target_properties(MutagenUnitTests PROPERTIES FOLDER "Compiler-RT Tests")
-
 set(LIBFUZZER_UNITTEST_LINK_FLAGS ${COMPILER_RT_UNITTEST_LINK_FLAGS})
 list(APPEND LIBFUZZER_UNITTEST_LINK_FLAGS --driver-mode=g++)
 
@@ -49,35 +46,23 @@ if(COMPILER_RT_DEFAULT_TARGET_ARCH IN_LIST FUZZER_SUPPORTED_ARCH)
   set(arch ${COMPILER_RT_DEFAULT_TARGET_ARCH})
 
   set(LIBFUZZER_TEST_RUNTIME RTFuzzerTest.${arch})
-  set(LIBMUTAGEN_TEST_RUNTIME RTMutagenTest.${arch})
   if(APPLE)
     set(LIBFUZZER_TEST_RUNTIME_OBJECTS
       $<TARGET_OBJECTS:RTfuzzer.osx>)
-    set(LIBMUTAGEN_TEST_RUNTIME_OBJECTS
-      $<TARGET_OBJECTS:RTmutagen.osx>)
   else()
     set(LIBFUZZER_TEST_RUNTIME_OBJECTS
       $<TARGET_OBJECTS:RTfuzzer.${arch}>)
-    set(LIBMUTAGEN_TEST_RUNTIME_OBJECTS
-      $<TARGET_OBJECTS:RTmutagen.${arch}>)
   endif()
   add_library(${LIBFUZZER_TEST_RUNTIME} STATIC
-    ${LIBFUZZER_TEST_RUNTIME_OBJECTS}
-    ${LIBMUTAGEN_TEST_RUNTIME_OBJECTS})
+    ${LIBFUZZER_TEST_RUNTIME_OBJECTS})
   set_target_properties(${LIBFUZZER_TEST_RUNTIME} PROPERTIES
     ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
     FOLDER "Compiler-RT Runtime tests")
 
-  add_library(${LIBMUTAGEN_TEST_RUNTIME} STATIC
-    ${LIBMUTAGEN_TEST_RUNTIME_OBJECTS})
-  set_target_properties(${LIBMUTAGEN_TEST_RUNTIME} PROPERTIES
-    ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
-    FOLDER "Compiler-RT Runtime tests")
-
   if(CMAKE_SYSTEM_NAME STREQUAL "Linux" AND
      COMPILER_RT_LIBCXX_PATH AND
      COMPILER_RT_LIBCXXABI_PATH)
-    file(GLOB libfuzzer_headers ../*.h ../mutagen/*.h)
+    file(GLOB libfuzzer_headers ../*.h)
     set(LIBFUZZER_TEST_RUNTIME_DEPS libcxx_fuzzer_${arch}-build ${libfuzzer_headers})
     set(LIBFUZZER_TEST_RUNTIME_CFLAGS -isystem ${LIBCXX_${arch}_PREFIX}/include/c++/v1)
     set(LIBFUZZER_TEST_RUNTIME_LINK_FLAGS ${LIBCXX_${arch}_PREFIX}/lib/libc++.a)
@@ -88,7 +73,7 @@ if(COMPILER_RT_DEFAULT_TARGET_ARCH IN_LIST FUZZER_SUPPORTED_ARCH)
     FuzzerUnitTests "Fuzzer-${arch}-Test" ${arch}
     SOURCES FuzzerUnittest.cpp ${COMPILER_RT_GTEST_SOURCE}
     RUNTIME ${LIBFUZZER_TEST_RUNTIME}
-    DEPS gtest ${LIBFUZZER_TEST_RUNTIME_DEPS}
+    DEPS gtest ${LIBFUZZER_TEST_RUNTIME_DEPS} 
     CFLAGS ${LIBFUZZER_UNITTEST_CFLAGS} ${LIBFUZZER_TEST_RUNTIME_CFLAGS}
     LINK_FLAGS ${LIBFUZZER_UNITTEST_LINK_FLAGS} ${LIBFUZZER_TEST_RUNTIME_LINK_FLAGS})
   set_target_properties(FuzzerUnitTests PROPERTIES
@@ -103,15 +88,4 @@ if(COMPILER_RT_DEFAULT_TARGET_ARCH IN_LIST FUZZER_SUPPORTED_ARCH)
     LINK_FLAGS ${LIBFUZZER_UNITTEST_LINK_FLAGS} ${LIBFUZZER_TEST_RUNTIME_LINK_FLAGS})
   set_target_properties(FuzzedDataProviderUnitTests PROPERTIES
     RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
-
-  set(MutagenTestObjects)
-  generate_compiler_rt_tests(MutagenTestObjects
-    MutagenUnitTests "Mutagen-${arch}-Test" ${arch}
-    SOURCES MutagenUnittest.cpp ${COMPILER_RT_GTEST_SOURCE}
-    RUNTIME ${LIBFUZZER_TEST_RUNTIME}
-    DEPS gtest ${LIBFUZZER_TEST_RUNTIME_DEPS} ${LIBMUTAGEN_TEST_RUNTIME_DEPS}
-    CFLAGS ${LIBFUZZER_UNITTEST_CFLAGS} ${LIBFUZZER_TEST_RUNTIME_CFLAGS}
-    LINK_FLAGS ${LIBFUZZER_UNITTEST_LINK_FLAGS} ${LIBFUZZER_TEST_RUNTIME_LINK_FLAGS})
-  set_target_properties(MutagenUnitTests PROPERTIES
-    RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
 endif()

diff  --git a/compiler-rt/lib/fuzzer/tests/FuzzerUnittest.cpp b/compiler-rt/lib/fuzzer/tests/FuzzerUnittest.cpp
index 277fa5e6183f8..974a01ff4ab6e 100644
--- a/compiler-rt/lib/fuzzer/tests/FuzzerUnittest.cpp
+++ b/compiler-rt/lib/fuzzer/tests/FuzzerUnittest.cpp
@@ -10,6 +10,7 @@
 #define GTEST_NO_LLVM_SUPPORT 1
 
 #include "FuzzerCorpus.h"
+#include "FuzzerDictionary.h"
 #include "FuzzerInternal.h"
 #include "FuzzerMerge.h"
 #include "FuzzerMutate.h"
@@ -43,6 +44,65 @@ TEST(Fuzzer, Basename) {
 #endif
 }
 
+TEST(Fuzzer, CrossOver) {
+  std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
+  fuzzer::EF = t.get();
+  Random Rand(0);
+  std::unique_ptr<MutationDispatcher> MD(new MutationDispatcher(Rand, {}));
+  Unit A({0, 1, 2}), B({5, 6, 7});
+  Unit C;
+  Unit Expected[] = {
+       { 0 },
+       { 0, 1 },
+       { 0, 5 },
+       { 0, 1, 2 },
+       { 0, 1, 5 },
+       { 0, 5, 1 },
+       { 0, 5, 6 },
+       { 0, 1, 2, 5 },
+       { 0, 1, 5, 2 },
+       { 0, 1, 5, 6 },
+       { 0, 5, 1, 2 },
+       { 0, 5, 1, 6 },
+       { 0, 5, 6, 1 },
+       { 0, 5, 6, 7 },
+       { 0, 1, 2, 5, 6 },
+       { 0, 1, 5, 2, 6 },
+       { 0, 1, 5, 6, 2 },
+       { 0, 1, 5, 6, 7 },
+       { 0, 5, 1, 2, 6 },
+       { 0, 5, 1, 6, 2 },
+       { 0, 5, 1, 6, 7 },
+       { 0, 5, 6, 1, 2 },
+       { 0, 5, 6, 1, 7 },
+       { 0, 5, 6, 7, 1 },
+       { 0, 1, 2, 5, 6, 7 },
+       { 0, 1, 5, 2, 6, 7 },
+       { 0, 1, 5, 6, 2, 7 },
+       { 0, 1, 5, 6, 7, 2 },
+       { 0, 5, 1, 2, 6, 7 },
+       { 0, 5, 1, 6, 2, 7 },
+       { 0, 5, 1, 6, 7, 2 },
+       { 0, 5, 6, 1, 2, 7 },
+       { 0, 5, 6, 1, 7, 2 },
+       { 0, 5, 6, 7, 1, 2 }
+  };
+  for (size_t Len = 1; Len < 8; Len++) {
+    Set<Unit> FoundUnits, ExpectedUnitsWitThisLength;
+    for (int Iter = 0; Iter < 3000; Iter++) {
+      C.resize(Len);
+      size_t NewSize = MD->CrossOver(A.data(), A.size(), B.data(), B.size(),
+                                     C.data(), C.size());
+      C.resize(NewSize);
+      FoundUnits.insert(C);
+    }
+    for (const Unit &U : Expected)
+      if (U.size() <= Len)
+        ExpectedUnitsWitThisLength.insert(U);
+    EXPECT_EQ(ExpectedUnitsWitThisLength, FoundUnits);
+  }
+}
+
 TEST(Fuzzer, Hash) {
   uint8_t A[] = {'a', 'b', 'c'};
   fuzzer::Unit U(A, A + sizeof(A));
@@ -51,6 +111,423 @@ TEST(Fuzzer, Hash) {
   EXPECT_EQ("81fe8bfe87576c3ecb22426f8e57847382917acf", fuzzer::Hash(U));
 }
 
+typedef size_t (MutationDispatcher::*Mutator)(uint8_t *Data, size_t Size,
+                                              size_t MaxSize);
+
+void TestEraseBytes(Mutator M, int NumIter) {
+  std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
+  fuzzer::EF = t.get();
+  uint8_t REM0[8] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
+  uint8_t REM1[8] = {0x00, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
+  uint8_t REM2[8] = {0x00, 0x11, 0x33, 0x44, 0x55, 0x66, 0x77};
+  uint8_t REM3[8] = {0x00, 0x11, 0x22, 0x44, 0x55, 0x66, 0x77};
+  uint8_t REM4[8] = {0x00, 0x11, 0x22, 0x33, 0x55, 0x66, 0x77};
+  uint8_t REM5[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x66, 0x77};
+  uint8_t REM6[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x77};
+  uint8_t REM7[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
+
+  uint8_t REM8[6] = {0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
+  uint8_t REM9[6] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55};
+  uint8_t REM10[6] = {0x00, 0x11, 0x22, 0x55, 0x66, 0x77};
+
+  uint8_t REM11[5] = {0x33, 0x44, 0x55, 0x66, 0x77};
+  uint8_t REM12[5] = {0x00, 0x11, 0x22, 0x33, 0x44};
+  uint8_t REM13[5] = {0x00, 0x44, 0x55, 0x66, 0x77};
+
+
+  Random Rand(0);
+  std::unique_ptr<MutationDispatcher> MD(new MutationDispatcher(Rand, {}));
+  int FoundMask = 0;
+  for (int i = 0; i < NumIter; i++) {
+    uint8_t T[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
+    size_t NewSize = (*MD.*M)(T, sizeof(T), sizeof(T));
+    if (NewSize == 7 && !memcmp(REM0, T, 7)) FoundMask |= 1 << 0;
+    if (NewSize == 7 && !memcmp(REM1, T, 7)) FoundMask |= 1 << 1;
+    if (NewSize == 7 && !memcmp(REM2, T, 7)) FoundMask |= 1 << 2;
+    if (NewSize == 7 && !memcmp(REM3, T, 7)) FoundMask |= 1 << 3;
+    if (NewSize == 7 && !memcmp(REM4, T, 7)) FoundMask |= 1 << 4;
+    if (NewSize == 7 && !memcmp(REM5, T, 7)) FoundMask |= 1 << 5;
+    if (NewSize == 7 && !memcmp(REM6, T, 7)) FoundMask |= 1 << 6;
+    if (NewSize == 7 && !memcmp(REM7, T, 7)) FoundMask |= 1 << 7;
+
+    if (NewSize == 6 && !memcmp(REM8, T, 6)) FoundMask |= 1 << 8;
+    if (NewSize == 6 && !memcmp(REM9, T, 6)) FoundMask |= 1 << 9;
+    if (NewSize == 6 && !memcmp(REM10, T, 6)) FoundMask |= 1 << 10;
+
+    if (NewSize == 5 && !memcmp(REM11, T, 5)) FoundMask |= 1 << 11;
+    if (NewSize == 5 && !memcmp(REM12, T, 5)) FoundMask |= 1 << 12;
+    if (NewSize == 5 && !memcmp(REM13, T, 5)) FoundMask |= 1 << 13;
+  }
+  EXPECT_EQ(FoundMask, (1 << 14) - 1);
+}
+
+TEST(FuzzerMutate, EraseBytes1) {
+  TestEraseBytes(&MutationDispatcher::Mutate_EraseBytes, 200);
+}
+TEST(FuzzerMutate, EraseBytes2) {
+  TestEraseBytes(&MutationDispatcher::Mutate, 2000);
+}
+
+void TestInsertByte(Mutator M, int NumIter) {
+  std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
+  fuzzer::EF = t.get();
+  Random Rand(0);
+  std::unique_ptr<MutationDispatcher> MD(new MutationDispatcher(Rand, {}));
+  int FoundMask = 0;
+  uint8_t INS0[8] = {0xF1, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
+  uint8_t INS1[8] = {0x00, 0xF2, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
+  uint8_t INS2[8] = {0x00, 0x11, 0xF3, 0x22, 0x33, 0x44, 0x55, 0x66};
+  uint8_t INS3[8] = {0x00, 0x11, 0x22, 0xF4, 0x33, 0x44, 0x55, 0x66};
+  uint8_t INS4[8] = {0x00, 0x11, 0x22, 0x33, 0xF5, 0x44, 0x55, 0x66};
+  uint8_t INS5[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0xF6, 0x55, 0x66};
+  uint8_t INS6[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0xF7, 0x66};
+  uint8_t INS7[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0xF8};
+  for (int i = 0; i < NumIter; i++) {
+    uint8_t T[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
+    size_t NewSize = (*MD.*M)(T, 7, 8);
+    if (NewSize == 8 && !memcmp(INS0, T, 8)) FoundMask |= 1 << 0;
+    if (NewSize == 8 && !memcmp(INS1, T, 8)) FoundMask |= 1 << 1;
+    if (NewSize == 8 && !memcmp(INS2, T, 8)) FoundMask |= 1 << 2;
+    if (NewSize == 8 && !memcmp(INS3, T, 8)) FoundMask |= 1 << 3;
+    if (NewSize == 8 && !memcmp(INS4, T, 8)) FoundMask |= 1 << 4;
+    if (NewSize == 8 && !memcmp(INS5, T, 8)) FoundMask |= 1 << 5;
+    if (NewSize == 8 && !memcmp(INS6, T, 8)) FoundMask |= 1 << 6;
+    if (NewSize == 8 && !memcmp(INS7, T, 8)) FoundMask |= 1 << 7;
+  }
+  EXPECT_EQ(FoundMask, 255);
+}
+
+TEST(FuzzerMutate, InsertByte1) {
+  TestInsertByte(&MutationDispatcher::Mutate_InsertByte, 1 << 15);
+}
+TEST(FuzzerMutate, InsertByte2) {
+  TestInsertByte(&MutationDispatcher::Mutate, 1 << 17);
+}
+
+void TestInsertRepeatedBytes(Mutator M, int NumIter) {
+  std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
+  fuzzer::EF = t.get();
+  Random Rand(0);
+  std::unique_ptr<MutationDispatcher> MD(new MutationDispatcher(Rand, {}));
+  int FoundMask = 0;
+  uint8_t INS0[7] = {0x00, 0x11, 0x22, 0x33, 'a', 'a', 'a'};
+  uint8_t INS1[7] = {0x00, 0x11, 0x22, 'a', 'a', 'a', 0x33};
+  uint8_t INS2[7] = {0x00, 0x11, 'a', 'a', 'a', 0x22, 0x33};
+  uint8_t INS3[7] = {0x00, 'a', 'a', 'a', 0x11, 0x22, 0x33};
+  uint8_t INS4[7] = {'a', 'a', 'a', 0x00, 0x11, 0x22, 0x33};
+
+  uint8_t INS5[8] = {0x00, 0x11, 0x22, 0x33, 'b', 'b', 'b', 'b'};
+  uint8_t INS6[8] = {0x00, 0x11, 0x22, 'b', 'b', 'b', 'b', 0x33};
+  uint8_t INS7[8] = {0x00, 0x11, 'b', 'b', 'b', 'b', 0x22, 0x33};
+  uint8_t INS8[8] = {0x00, 'b', 'b', 'b', 'b', 0x11, 0x22, 0x33};
+  uint8_t INS9[8] = {'b', 'b', 'b', 'b', 0x00, 0x11, 0x22, 0x33};
+
+  for (int i = 0; i < NumIter; i++) {
+    uint8_t T[8] = {0x00, 0x11, 0x22, 0x33};
+    size_t NewSize = (*MD.*M)(T, 4, 8);
+    if (NewSize == 7 && !memcmp(INS0, T, 7)) FoundMask |= 1 << 0;
+    if (NewSize == 7 && !memcmp(INS1, T, 7)) FoundMask |= 1 << 1;
+    if (NewSize == 7 && !memcmp(INS2, T, 7)) FoundMask |= 1 << 2;
+    if (NewSize == 7 && !memcmp(INS3, T, 7)) FoundMask |= 1 << 3;
+    if (NewSize == 7 && !memcmp(INS4, T, 7)) FoundMask |= 1 << 4;
+
+    if (NewSize == 8 && !memcmp(INS5, T, 8)) FoundMask |= 1 << 5;
+    if (NewSize == 8 && !memcmp(INS6, T, 8)) FoundMask |= 1 << 6;
+    if (NewSize == 8 && !memcmp(INS7, T, 8)) FoundMask |= 1 << 7;
+    if (NewSize == 8 && !memcmp(INS8, T, 8)) FoundMask |= 1 << 8;
+    if (NewSize == 8 && !memcmp(INS9, T, 8)) FoundMask |= 1 << 9;
+
+  }
+  EXPECT_EQ(FoundMask, (1 << 10) - 1);
+}
+
+TEST(FuzzerMutate, InsertRepeatedBytes1) {
+  TestInsertRepeatedBytes(&MutationDispatcher::Mutate_InsertRepeatedBytes, 10000);
+}
+TEST(FuzzerMutate, InsertRepeatedBytes2) {
+  TestInsertRepeatedBytes(&MutationDispatcher::Mutate, 300000);
+}
+
+void TestChangeByte(Mutator M, int NumIter) {
+  std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
+  fuzzer::EF = t.get();
+  Random Rand(0);
+  std::unique_ptr<MutationDispatcher> MD(new MutationDispatcher(Rand, {}));
+  int FoundMask = 0;
+  uint8_t CH0[8] = {0xF0, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
+  uint8_t CH1[8] = {0x00, 0xF1, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
+  uint8_t CH2[8] = {0x00, 0x11, 0xF2, 0x33, 0x44, 0x55, 0x66, 0x77};
+  uint8_t CH3[8] = {0x00, 0x11, 0x22, 0xF3, 0x44, 0x55, 0x66, 0x77};
+  uint8_t CH4[8] = {0x00, 0x11, 0x22, 0x33, 0xF4, 0x55, 0x66, 0x77};
+  uint8_t CH5[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0xF5, 0x66, 0x77};
+  uint8_t CH6[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0xF5, 0x77};
+  uint8_t CH7[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0xF7};
+  for (int i = 0; i < NumIter; i++) {
+    uint8_t T[9] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
+    size_t NewSize = (*MD.*M)(T, 8, 9);
+    if (NewSize == 8 && !memcmp(CH0, T, 8)) FoundMask |= 1 << 0;
+    if (NewSize == 8 && !memcmp(CH1, T, 8)) FoundMask |= 1 << 1;
+    if (NewSize == 8 && !memcmp(CH2, T, 8)) FoundMask |= 1 << 2;
+    if (NewSize == 8 && !memcmp(CH3, T, 8)) FoundMask |= 1 << 3;
+    if (NewSize == 8 && !memcmp(CH4, T, 8)) FoundMask |= 1 << 4;
+    if (NewSize == 8 && !memcmp(CH5, T, 8)) FoundMask |= 1 << 5;
+    if (NewSize == 8 && !memcmp(CH6, T, 8)) FoundMask |= 1 << 6;
+    if (NewSize == 8 && !memcmp(CH7, T, 8)) FoundMask |= 1 << 7;
+  }
+  EXPECT_EQ(FoundMask, 255);
+}
+
+TEST(FuzzerMutate, ChangeByte1) {
+  TestChangeByte(&MutationDispatcher::Mutate_ChangeByte, 1 << 15);
+}
+TEST(FuzzerMutate, ChangeByte2) {
+  TestChangeByte(&MutationDispatcher::Mutate, 1 << 17);
+}
+
+void TestChangeBit(Mutator M, int NumIter) {
+  std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
+  fuzzer::EF = t.get();
+  Random Rand(0);
+  std::unique_ptr<MutationDispatcher> MD(new MutationDispatcher(Rand, {}));
+  int FoundMask = 0;
+  uint8_t CH0[8] = {0x01, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
+  uint8_t CH1[8] = {0x00, 0x13, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
+  uint8_t CH2[8] = {0x00, 0x11, 0x02, 0x33, 0x44, 0x55, 0x66, 0x77};
+  uint8_t CH3[8] = {0x00, 0x11, 0x22, 0x37, 0x44, 0x55, 0x66, 0x77};
+  uint8_t CH4[8] = {0x00, 0x11, 0x22, 0x33, 0x54, 0x55, 0x66, 0x77};
+  uint8_t CH5[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x54, 0x66, 0x77};
+  uint8_t CH6[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x76, 0x77};
+  uint8_t CH7[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0xF7};
+  for (int i = 0; i < NumIter; i++) {
+    uint8_t T[9] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
+    size_t NewSize = (*MD.*M)(T, 8, 9);
+    if (NewSize == 8 && !memcmp(CH0, T, 8)) FoundMask |= 1 << 0;
+    if (NewSize == 8 && !memcmp(CH1, T, 8)) FoundMask |= 1 << 1;
+    if (NewSize == 8 && !memcmp(CH2, T, 8)) FoundMask |= 1 << 2;
+    if (NewSize == 8 && !memcmp(CH3, T, 8)) FoundMask |= 1 << 3;
+    if (NewSize == 8 && !memcmp(CH4, T, 8)) FoundMask |= 1 << 4;
+    if (NewSize == 8 && !memcmp(CH5, T, 8)) FoundMask |= 1 << 5;
+    if (NewSize == 8 && !memcmp(CH6, T, 8)) FoundMask |= 1 << 6;
+    if (NewSize == 8 && !memcmp(CH7, T, 8)) FoundMask |= 1 << 7;
+  }
+  EXPECT_EQ(FoundMask, 255);
+}
+
+TEST(FuzzerMutate, ChangeBit1) {
+  TestChangeBit(&MutationDispatcher::Mutate_ChangeBit, 1 << 16);
+}
+TEST(FuzzerMutate, ChangeBit2) {
+  TestChangeBit(&MutationDispatcher::Mutate, 1 << 18);
+}
+
+void TestShuffleBytes(Mutator M, int NumIter) {
+  std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
+  fuzzer::EF = t.get();
+  Random Rand(0);
+  std::unique_ptr<MutationDispatcher> MD(new MutationDispatcher(Rand, {}));
+  int FoundMask = 0;
+  uint8_t CH0[7] = {0x00, 0x22, 0x11, 0x33, 0x44, 0x55, 0x66};
+  uint8_t CH1[7] = {0x11, 0x00, 0x33, 0x22, 0x44, 0x55, 0x66};
+  uint8_t CH2[7] = {0x00, 0x33, 0x11, 0x22, 0x44, 0x55, 0x66};
+  uint8_t CH3[7] = {0x00, 0x11, 0x22, 0x44, 0x55, 0x66, 0x33};
+  uint8_t CH4[7] = {0x00, 0x11, 0x22, 0x33, 0x55, 0x44, 0x66};
+  for (int i = 0; i < NumIter; i++) {
+    uint8_t T[7] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
+    size_t NewSize = (*MD.*M)(T, 7, 7);
+    if (NewSize == 7 && !memcmp(CH0, T, 7)) FoundMask |= 1 << 0;
+    if (NewSize == 7 && !memcmp(CH1, T, 7)) FoundMask |= 1 << 1;
+    if (NewSize == 7 && !memcmp(CH2, T, 7)) FoundMask |= 1 << 2;
+    if (NewSize == 7 && !memcmp(CH3, T, 7)) FoundMask |= 1 << 3;
+    if (NewSize == 7 && !memcmp(CH4, T, 7)) FoundMask |= 1 << 4;
+  }
+  EXPECT_EQ(FoundMask, 31);
+}
+
+TEST(FuzzerMutate, ShuffleBytes1) {
+  TestShuffleBytes(&MutationDispatcher::Mutate_ShuffleBytes, 1 << 17);
+}
+TEST(FuzzerMutate, ShuffleBytes2) {
+  TestShuffleBytes(&MutationDispatcher::Mutate, 1 << 20);
+}
+
+void TestCopyPart(Mutator M, int NumIter) {
+  std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
+  fuzzer::EF = t.get();
+  Random Rand(0);
+  std::unique_ptr<MutationDispatcher> MD(new MutationDispatcher(Rand, {}));
+  int FoundMask = 0;
+  uint8_t CH0[7] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x00, 0x11};
+  uint8_t CH1[7] = {0x55, 0x66, 0x22, 0x33, 0x44, 0x55, 0x66};
+  uint8_t CH2[7] = {0x00, 0x55, 0x66, 0x33, 0x44, 0x55, 0x66};
+  uint8_t CH3[7] = {0x00, 0x11, 0x22, 0x00, 0x11, 0x22, 0x66};
+  uint8_t CH4[7] = {0x00, 0x11, 0x11, 0x22, 0x33, 0x55, 0x66};
+
+  for (int i = 0; i < NumIter; i++) {
+    uint8_t T[7] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
+    size_t NewSize = (*MD.*M)(T, 7, 7);
+    if (NewSize == 7 && !memcmp(CH0, T, 7)) FoundMask |= 1 << 0;
+    if (NewSize == 7 && !memcmp(CH1, T, 7)) FoundMask |= 1 << 1;
+    if (NewSize == 7 && !memcmp(CH2, T, 7)) FoundMask |= 1 << 2;
+    if (NewSize == 7 && !memcmp(CH3, T, 7)) FoundMask |= 1 << 3;
+    if (NewSize == 7 && !memcmp(CH4, T, 7)) FoundMask |= 1 << 4;
+  }
+
+  uint8_t CH5[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x00, 0x11, 0x22};
+  uint8_t CH6[8] = {0x22, 0x33, 0x44, 0x00, 0x11, 0x22, 0x33, 0x44};
+  uint8_t CH7[8] = {0x00, 0x11, 0x22, 0x00, 0x11, 0x22, 0x33, 0x44};
+  uint8_t CH8[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x22, 0x33, 0x44};
+  uint8_t CH9[8] = {0x00, 0x11, 0x22, 0x22, 0x33, 0x44, 0x33, 0x44};
+
+  for (int i = 0; i < NumIter; i++) {
+    uint8_t T[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
+    size_t NewSize = (*MD.*M)(T, 5, 8);
+    if (NewSize == 8 && !memcmp(CH5, T, 8)) FoundMask |= 1 << 5;
+    if (NewSize == 8 && !memcmp(CH6, T, 8)) FoundMask |= 1 << 6;
+    if (NewSize == 8 && !memcmp(CH7, T, 8)) FoundMask |= 1 << 7;
+    if (NewSize == 8 && !memcmp(CH8, T, 8)) FoundMask |= 1 << 8;
+    if (NewSize == 8 && !memcmp(CH9, T, 8)) FoundMask |= 1 << 9;
+  }
+
+  EXPECT_EQ(FoundMask, 1023);
+}
+
+TEST(FuzzerMutate, CopyPart1) {
+  TestCopyPart(&MutationDispatcher::Mutate_CopyPart, 1 << 10);
+}
+TEST(FuzzerMutate, CopyPart2) {
+  TestCopyPart(&MutationDispatcher::Mutate, 1 << 13);
+}
+TEST(FuzzerMutate, CopyPartNoInsertAtMaxSize) {
+  // This (non exhaustively) tests if `Mutate_CopyPart` tries to perform an
+  // insert on an input of size `MaxSize`.  Performing an insert in this case
+  // will lead to the mutation failing.
+  std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
+  fuzzer::EF = t.get();
+  Random Rand(0);
+  std::unique_ptr<MutationDispatcher> MD(new MutationDispatcher(Rand, {}));
+  uint8_t Data[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x00, 0x11, 0x22};
+  size_t MaxSize = sizeof(Data);
+  for (int count = 0; count < (1 << 18); ++count) {
+    size_t NewSize = MD->Mutate_CopyPart(Data, MaxSize, MaxSize);
+    ASSERT_EQ(NewSize, MaxSize);
+  }
+}
+
+void TestAddWordFromDictionary(Mutator M, int NumIter) {
+  std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
+  fuzzer::EF = t.get();
+  Random Rand(0);
+  std::unique_ptr<MutationDispatcher> MD(new MutationDispatcher(Rand, {}));
+  uint8_t Word1[4] = {0xAA, 0xBB, 0xCC, 0xDD};
+  uint8_t Word2[3] = {0xFF, 0xEE, 0xEF};
+  MD->AddWordToManualDictionary(Word(Word1, sizeof(Word1)));
+  MD->AddWordToManualDictionary(Word(Word2, sizeof(Word2)));
+  int FoundMask = 0;
+  uint8_t CH0[7] = {0x00, 0x11, 0x22, 0xAA, 0xBB, 0xCC, 0xDD};
+  uint8_t CH1[7] = {0x00, 0x11, 0xAA, 0xBB, 0xCC, 0xDD, 0x22};
+  uint8_t CH2[7] = {0x00, 0xAA, 0xBB, 0xCC, 0xDD, 0x11, 0x22};
+  uint8_t CH3[7] = {0xAA, 0xBB, 0xCC, 0xDD, 0x00, 0x11, 0x22};
+  uint8_t CH4[6] = {0x00, 0x11, 0x22, 0xFF, 0xEE, 0xEF};
+  uint8_t CH5[6] = {0x00, 0x11, 0xFF, 0xEE, 0xEF, 0x22};
+  uint8_t CH6[6] = {0x00, 0xFF, 0xEE, 0xEF, 0x11, 0x22};
+  uint8_t CH7[6] = {0xFF, 0xEE, 0xEF, 0x00, 0x11, 0x22};
+  for (int i = 0; i < NumIter; i++) {
+    uint8_t T[7] = {0x00, 0x11, 0x22};
+    size_t NewSize = (*MD.*M)(T, 3, 7);
+    if (NewSize == 7 && !memcmp(CH0, T, 7)) FoundMask |= 1 << 0;
+    if (NewSize == 7 && !memcmp(CH1, T, 7)) FoundMask |= 1 << 1;
+    if (NewSize == 7 && !memcmp(CH2, T, 7)) FoundMask |= 1 << 2;
+    if (NewSize == 7 && !memcmp(CH3, T, 7)) FoundMask |= 1 << 3;
+    if (NewSize == 6 && !memcmp(CH4, T, 6)) FoundMask |= 1 << 4;
+    if (NewSize == 6 && !memcmp(CH5, T, 6)) FoundMask |= 1 << 5;
+    if (NewSize == 6 && !memcmp(CH6, T, 6)) FoundMask |= 1 << 6;
+    if (NewSize == 6 && !memcmp(CH7, T, 6)) FoundMask |= 1 << 7;
+  }
+  EXPECT_EQ(FoundMask, 255);
+}
+
+TEST(FuzzerMutate, AddWordFromDictionary1) {
+  TestAddWordFromDictionary(
+      &MutationDispatcher::Mutate_AddWordFromManualDictionary, 1 << 15);
+}
+
+TEST(FuzzerMutate, AddWordFromDictionary2) {
+  TestAddWordFromDictionary(&MutationDispatcher::Mutate, 1 << 15);
+}
+
+void TestChangeASCIIInteger(Mutator M, int NumIter) {
+  std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
+  fuzzer::EF = t.get();
+  Random Rand(0);
+  std::unique_ptr<MutationDispatcher> MD(new MutationDispatcher(Rand, {}));
+
+  uint8_t CH0[8] = {'1', '2', '3', '4', '5', '6', '7', '7'};
+  uint8_t CH1[8] = {'1', '2', '3', '4', '5', '6', '7', '9'};
+  uint8_t CH2[8] = {'2', '4', '6', '9', '1', '3', '5', '6'};
+  uint8_t CH3[8] = {'0', '6', '1', '7', '2', '8', '3', '9'};
+  int FoundMask = 0;
+  for (int i = 0; i < NumIter; i++) {
+    uint8_t T[8] = {'1', '2', '3', '4', '5', '6', '7', '8'};
+    size_t NewSize = (*MD.*M)(T, 8, 8);
+    /**/ if (NewSize == 8 && !memcmp(CH0, T, 8)) FoundMask |= 1 << 0;
+    else if (NewSize == 8 && !memcmp(CH1, T, 8)) FoundMask |= 1 << 1;
+    else if (NewSize == 8 && !memcmp(CH2, T, 8)) FoundMask |= 1 << 2;
+    else if (NewSize == 8 && !memcmp(CH3, T, 8)) FoundMask |= 1 << 3;
+    else if (NewSize == 8)                       FoundMask |= 1 << 4;
+  }
+  EXPECT_EQ(FoundMask, 31);
+}
+
+TEST(FuzzerMutate, ChangeASCIIInteger1) {
+  TestChangeASCIIInteger(&MutationDispatcher::Mutate_ChangeASCIIInteger,
+                         1 << 15);
+}
+
+TEST(FuzzerMutate, ChangeASCIIInteger2) {
+  TestChangeASCIIInteger(&MutationDispatcher::Mutate, 1 << 15);
+}
+
+void TestChangeBinaryInteger(Mutator M, int NumIter) {
+  std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
+  fuzzer::EF = t.get();
+  Random Rand(0);
+  std::unique_ptr<MutationDispatcher> MD(new MutationDispatcher(Rand, {}));
+
+  uint8_t CH0[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x79};
+  uint8_t CH1[8] = {0x00, 0x11, 0x22, 0x31, 0x44, 0x55, 0x66, 0x77};
+  uint8_t CH2[8] = {0xff, 0x10, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
+  uint8_t CH3[8] = {0x00, 0x11, 0x2a, 0x33, 0x44, 0x55, 0x66, 0x77};
+  uint8_t CH4[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x4f, 0x66, 0x77};
+  uint8_t CH5[8] = {0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88};
+  uint8_t CH6[8] = {0x00, 0x11, 0x22, 0x00, 0x00, 0x00, 0x08, 0x77}; // Size
+  uint8_t CH7[8] = {0x00, 0x08, 0x00, 0x33, 0x44, 0x55, 0x66, 0x77}; // Sw(Size)
+
+  int FoundMask = 0;
+  for (int i = 0; i < NumIter; i++) {
+    uint8_t T[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
+    size_t NewSize = (*MD.*M)(T, 8, 8);
+    /**/ if (NewSize == 8 && !memcmp(CH0, T, 8)) FoundMask |= 1 << 0;
+    else if (NewSize == 8 && !memcmp(CH1, T, 8)) FoundMask |= 1 << 1;
+    else if (NewSize == 8 && !memcmp(CH2, T, 8)) FoundMask |= 1 << 2;
+    else if (NewSize == 8 && !memcmp(CH3, T, 8)) FoundMask |= 1 << 3;
+    else if (NewSize == 8 && !memcmp(CH4, T, 8)) FoundMask |= 1 << 4;
+    else if (NewSize == 8 && !memcmp(CH5, T, 8)) FoundMask |= 1 << 5;
+    else if (NewSize == 8 && !memcmp(CH6, T, 8)) FoundMask |= 1 << 6;
+    else if (NewSize == 8 && !memcmp(CH7, T, 8)) FoundMask |= 1 << 7;
+  }
+  EXPECT_EQ(FoundMask, 255);
+}
+
+TEST(FuzzerMutate, ChangeBinaryInteger1) {
+  TestChangeBinaryInteger(&MutationDispatcher::Mutate_ChangeBinaryInteger,
+                         1 << 12);
+}
+
+TEST(FuzzerMutate, ChangeBinaryInteger2) {
+  TestChangeBinaryInteger(&MutationDispatcher::Mutate, 1 << 15);
+}
+
+
 TEST(FuzzerDictionary, ParseOneDictionaryEntry) {
   Unit U;
   EXPECT_FALSE(ParseOneDictionaryEntry("", &U));

diff  --git a/compiler-rt/lib/fuzzer/tests/MutagenUnittest.cpp b/compiler-rt/lib/fuzzer/tests/MutagenUnittest.cpp
deleted file mode 100644
index 287eecf5fe2c8..0000000000000
--- a/compiler-rt/lib/fuzzer/tests/MutagenUnittest.cpp
+++ /dev/null
@@ -1,971 +0,0 @@
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-
-#include "mutagen/Mutagen.h"
-#include "mutagen/MutagenDispatcher.h"
-#include "mutagen/MutagenSequence.h"
-#include "mutagen/MutagenUtil.h"
-#include "gtest/gtest.h"
-#include <chrono>
-
-// This test doesn't set Config.MsanUnpoison*, so ensure MSan isn't present.
-// Avoid using fuzzer::ExternalFunctions, since it may not be linked against
-// the test binary.
-#if defined(__has_feature)
-#if __has_feature(memory_sanitizer)
-#error MemorySanitizer is not supported for the mutagen unit tests.
-#endif // __has_feature(memory_sanitizer)
-#endif // defined(__has_feature)
-
-namespace mutagen {
-namespace {
-
-using fuzzer::Set;
-
-std::unique_ptr<MutationDispatcher> CreateMutationDispatcher() {
-  LLVMMutagenConfiguration Config;
-  memset(&Config, 0, sizeof(Config));
-  return std::unique_ptr<MutationDispatcher>(new MutationDispatcher(&Config));
-}
-
-typedef size_t (MutationDispatcher::*Mutator)(uint8_t *Data, size_t Size,
-                                              size_t MaxSize);
-
-TEST(MutationDispatcher, CrossOver) {
-  auto MD = CreateMutationDispatcher();
-  Unit A({0, 1, 2}), B({5, 6, 7});
-  Unit C;
-  Unit Expected[] = {{0},
-                     {0, 1},
-                     {0, 5},
-                     {0, 1, 2},
-                     {0, 1, 5},
-                     {0, 5, 1},
-                     {0, 5, 6},
-                     {0, 1, 2, 5},
-                     {0, 1, 5, 2},
-                     {0, 1, 5, 6},
-                     {0, 5, 1, 2},
-                     {0, 5, 1, 6},
-                     {0, 5, 6, 1},
-                     {0, 5, 6, 7},
-                     {0, 1, 2, 5, 6},
-                     {0, 1, 5, 2, 6},
-                     {0, 1, 5, 6, 2},
-                     {0, 1, 5, 6, 7},
-                     {0, 5, 1, 2, 6},
-                     {0, 5, 1, 6, 2},
-                     {0, 5, 1, 6, 7},
-                     {0, 5, 6, 1, 2},
-                     {0, 5, 6, 1, 7},
-                     {0, 5, 6, 7, 1},
-                     {0, 1, 2, 5, 6, 7},
-                     {0, 1, 5, 2, 6, 7},
-                     {0, 1, 5, 6, 2, 7},
-                     {0, 1, 5, 6, 7, 2},
-                     {0, 5, 1, 2, 6, 7},
-                     {0, 5, 1, 6, 2, 7},
-                     {0, 5, 1, 6, 7, 2},
-                     {0, 5, 6, 1, 2, 7},
-                     {0, 5, 6, 1, 7, 2},
-                     {0, 5, 6, 7, 1, 2}};
-  for (size_t Len = 1; Len < 8; Len++) {
-    Set<Unit> FoundUnits, ExpectedUnitsWitThisLength;
-    for (int Iter = 0; Iter < 3000; Iter++) {
-      C.resize(Len);
-      size_t NewSize = MD->CrossOver(A.data(), A.size(), B.data(), B.size(),
-                                     C.data(), C.size());
-      C.resize(NewSize);
-      FoundUnits.insert(C);
-    }
-    for (const Unit &U : Expected)
-      if (U.size() <= Len)
-        ExpectedUnitsWitThisLength.insert(U);
-    EXPECT_EQ(ExpectedUnitsWitThisLength, FoundUnits);
-  }
-}
-
-void TestEraseBytes(Mutator M, int NumIter) {
-  uint8_t REM0[8] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
-  uint8_t REM1[8] = {0x00, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
-  uint8_t REM2[8] = {0x00, 0x11, 0x33, 0x44, 0x55, 0x66, 0x77};
-  uint8_t REM3[8] = {0x00, 0x11, 0x22, 0x44, 0x55, 0x66, 0x77};
-  uint8_t REM4[8] = {0x00, 0x11, 0x22, 0x33, 0x55, 0x66, 0x77};
-  uint8_t REM5[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x66, 0x77};
-  uint8_t REM6[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x77};
-  uint8_t REM7[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
-
-  uint8_t REM8[6] = {0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
-  uint8_t REM9[6] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55};
-  uint8_t REM10[6] = {0x00, 0x11, 0x22, 0x55, 0x66, 0x77};
-
-  uint8_t REM11[5] = {0x33, 0x44, 0x55, 0x66, 0x77};
-  uint8_t REM12[5] = {0x00, 0x11, 0x22, 0x33, 0x44};
-  uint8_t REM13[5] = {0x00, 0x44, 0x55, 0x66, 0x77};
-
-  auto MD = CreateMutationDispatcher();
-  int FoundMask = 0;
-  for (int i = 0; i < NumIter; i++) {
-    uint8_t T[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
-    size_t NewSize = (*MD.*M)(T, sizeof(T), sizeof(T));
-    if (NewSize == 7 && !memcmp(REM0, T, 7))
-      FoundMask |= 1 << 0;
-    if (NewSize == 7 && !memcmp(REM1, T, 7))
-      FoundMask |= 1 << 1;
-    if (NewSize == 7 && !memcmp(REM2, T, 7))
-      FoundMask |= 1 << 2;
-    if (NewSize == 7 && !memcmp(REM3, T, 7))
-      FoundMask |= 1 << 3;
-    if (NewSize == 7 && !memcmp(REM4, T, 7))
-      FoundMask |= 1 << 4;
-    if (NewSize == 7 && !memcmp(REM5, T, 7))
-      FoundMask |= 1 << 5;
-    if (NewSize == 7 && !memcmp(REM6, T, 7))
-      FoundMask |= 1 << 6;
-    if (NewSize == 7 && !memcmp(REM7, T, 7))
-      FoundMask |= 1 << 7;
-
-    if (NewSize == 6 && !memcmp(REM8, T, 6))
-      FoundMask |= 1 << 8;
-    if (NewSize == 6 && !memcmp(REM9, T, 6))
-      FoundMask |= 1 << 9;
-    if (NewSize == 6 && !memcmp(REM10, T, 6))
-      FoundMask |= 1 << 10;
-
-    if (NewSize == 5 && !memcmp(REM11, T, 5))
-      FoundMask |= 1 << 11;
-    if (NewSize == 5 && !memcmp(REM12, T, 5))
-      FoundMask |= 1 << 12;
-    if (NewSize == 5 && !memcmp(REM13, T, 5))
-      FoundMask |= 1 << 13;
-  }
-  EXPECT_EQ(FoundMask, (1 << 14) - 1);
-}
-
-TEST(MutationDispatcher, EraseBytes1) {
-  TestEraseBytes(&MutationDispatcher::Mutate_EraseBytes, 200);
-}
-TEST(MutationDispatcher, EraseBytes2) {
-  TestEraseBytes(&MutationDispatcher::Mutate, 2000);
-}
-
-void TestInsertByte(Mutator M, int NumIter) {
-  auto MD = CreateMutationDispatcher();
-  int FoundMask = 0;
-  uint8_t INS0[8] = {0xF1, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
-  uint8_t INS1[8] = {0x00, 0xF2, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
-  uint8_t INS2[8] = {0x00, 0x11, 0xF3, 0x22, 0x33, 0x44, 0x55, 0x66};
-  uint8_t INS3[8] = {0x00, 0x11, 0x22, 0xF4, 0x33, 0x44, 0x55, 0x66};
-  uint8_t INS4[8] = {0x00, 0x11, 0x22, 0x33, 0xF5, 0x44, 0x55, 0x66};
-  uint8_t INS5[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0xF6, 0x55, 0x66};
-  uint8_t INS6[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0xF7, 0x66};
-  uint8_t INS7[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0xF8};
-  for (int i = 0; i < NumIter; i++) {
-    uint8_t T[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
-    size_t NewSize = (*MD.*M)(T, 7, 8);
-    if (NewSize == 8 && !memcmp(INS0, T, 8))
-      FoundMask |= 1 << 0;
-    if (NewSize == 8 && !memcmp(INS1, T, 8))
-      FoundMask |= 1 << 1;
-    if (NewSize == 8 && !memcmp(INS2, T, 8))
-      FoundMask |= 1 << 2;
-    if (NewSize == 8 && !memcmp(INS3, T, 8))
-      FoundMask |= 1 << 3;
-    if (NewSize == 8 && !memcmp(INS4, T, 8))
-      FoundMask |= 1 << 4;
-    if (NewSize == 8 && !memcmp(INS5, T, 8))
-      FoundMask |= 1 << 5;
-    if (NewSize == 8 && !memcmp(INS6, T, 8))
-      FoundMask |= 1 << 6;
-    if (NewSize == 8 && !memcmp(INS7, T, 8))
-      FoundMask |= 1 << 7;
-  }
-  EXPECT_EQ(FoundMask, 255);
-}
-
-TEST(MutationDispatcher, InsertByte1) {
-  TestInsertByte(&MutationDispatcher::Mutate_InsertByte, 1 << 15);
-}
-TEST(MutationDispatcher, InsertByte2) {
-  TestInsertByte(&MutationDispatcher::Mutate, 1 << 17);
-}
-
-void TestInsertRepeatedBytes(Mutator M, int NumIter) {
-  auto MD = CreateMutationDispatcher();
-  int FoundMask = 0;
-  uint8_t INS0[7] = {0x00, 0x11, 0x22, 0x33, 'a', 'a', 'a'};
-  uint8_t INS1[7] = {0x00, 0x11, 0x22, 'a', 'a', 'a', 0x33};
-  uint8_t INS2[7] = {0x00, 0x11, 'a', 'a', 'a', 0x22, 0x33};
-  uint8_t INS3[7] = {0x00, 'a', 'a', 'a', 0x11, 0x22, 0x33};
-  uint8_t INS4[7] = {'a', 'a', 'a', 0x00, 0x11, 0x22, 0x33};
-
-  uint8_t INS5[8] = {0x00, 0x11, 0x22, 0x33, 'b', 'b', 'b', 'b'};
-  uint8_t INS6[8] = {0x00, 0x11, 0x22, 'b', 'b', 'b', 'b', 0x33};
-  uint8_t INS7[8] = {0x00, 0x11, 'b', 'b', 'b', 'b', 0x22, 0x33};
-  uint8_t INS8[8] = {0x00, 'b', 'b', 'b', 'b', 0x11, 0x22, 0x33};
-  uint8_t INS9[8] = {'b', 'b', 'b', 'b', 0x00, 0x11, 0x22, 0x33};
-
-  for (int i = 0; i < NumIter; i++) {
-    uint8_t T[8] = {0x00, 0x11, 0x22, 0x33};
-    size_t NewSize = (*MD.*M)(T, 4, 8);
-    if (NewSize == 7 && !memcmp(INS0, T, 7))
-      FoundMask |= 1 << 0;
-    if (NewSize == 7 && !memcmp(INS1, T, 7))
-      FoundMask |= 1 << 1;
-    if (NewSize == 7 && !memcmp(INS2, T, 7))
-      FoundMask |= 1 << 2;
-    if (NewSize == 7 && !memcmp(INS3, T, 7))
-      FoundMask |= 1 << 3;
-    if (NewSize == 7 && !memcmp(INS4, T, 7))
-      FoundMask |= 1 << 4;
-
-    if (NewSize == 8 && !memcmp(INS5, T, 8))
-      FoundMask |= 1 << 5;
-    if (NewSize == 8 && !memcmp(INS6, T, 8))
-      FoundMask |= 1 << 6;
-    if (NewSize == 8 && !memcmp(INS7, T, 8))
-      FoundMask |= 1 << 7;
-    if (NewSize == 8 && !memcmp(INS8, T, 8))
-      FoundMask |= 1 << 8;
-    if (NewSize == 8 && !memcmp(INS9, T, 8))
-      FoundMask |= 1 << 9;
-  }
-  EXPECT_EQ(FoundMask, (1 << 10) - 1);
-}
-
-TEST(MutationDispatcher, InsertRepeatedBytes1) {
-  TestInsertRepeatedBytes(&MutationDispatcher::Mutate_InsertRepeatedBytes,
-                          10000);
-}
-TEST(MutationDispatcher, InsertRepeatedBytes2) {
-  TestInsertRepeatedBytes(&MutationDispatcher::Mutate, 300000);
-}
-
-void TestChangeByte(Mutator M, int NumIter) {
-  auto MD = CreateMutationDispatcher();
-  int FoundMask = 0;
-  uint8_t CH0[8] = {0xF0, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
-  uint8_t CH1[8] = {0x00, 0xF1, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
-  uint8_t CH2[8] = {0x00, 0x11, 0xF2, 0x33, 0x44, 0x55, 0x66, 0x77};
-  uint8_t CH3[8] = {0x00, 0x11, 0x22, 0xF3, 0x44, 0x55, 0x66, 0x77};
-  uint8_t CH4[8] = {0x00, 0x11, 0x22, 0x33, 0xF4, 0x55, 0x66, 0x77};
-  uint8_t CH5[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0xF5, 0x66, 0x77};
-  uint8_t CH6[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0xF5, 0x77};
-  uint8_t CH7[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0xF7};
-  for (int i = 0; i < NumIter; i++) {
-    uint8_t T[9] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
-    size_t NewSize = (*MD.*M)(T, 8, 9);
-    if (NewSize == 8 && !memcmp(CH0, T, 8))
-      FoundMask |= 1 << 0;
-    if (NewSize == 8 && !memcmp(CH1, T, 8))
-      FoundMask |= 1 << 1;
-    if (NewSize == 8 && !memcmp(CH2, T, 8))
-      FoundMask |= 1 << 2;
-    if (NewSize == 8 && !memcmp(CH3, T, 8))
-      FoundMask |= 1 << 3;
-    if (NewSize == 8 && !memcmp(CH4, T, 8))
-      FoundMask |= 1 << 4;
-    if (NewSize == 8 && !memcmp(CH5, T, 8))
-      FoundMask |= 1 << 5;
-    if (NewSize == 8 && !memcmp(CH6, T, 8))
-      FoundMask |= 1 << 6;
-    if (NewSize == 8 && !memcmp(CH7, T, 8))
-      FoundMask |= 1 << 7;
-  }
-  EXPECT_EQ(FoundMask, 255);
-}
-
-TEST(MutationDispatcher, ChangeByte1) {
-  TestChangeByte(&MutationDispatcher::Mutate_ChangeByte, 1 << 15);
-}
-TEST(MutationDispatcher, ChangeByte2) {
-  TestChangeByte(&MutationDispatcher::Mutate, 1 << 17);
-}
-
-void TestChangeBit(Mutator M, int NumIter) {
-  auto MD = CreateMutationDispatcher();
-  int FoundMask = 0;
-  uint8_t CH0[8] = {0x01, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
-  uint8_t CH1[8] = {0x00, 0x13, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
-  uint8_t CH2[8] = {0x00, 0x11, 0x02, 0x33, 0x44, 0x55, 0x66, 0x77};
-  uint8_t CH3[8] = {0x00, 0x11, 0x22, 0x37, 0x44, 0x55, 0x66, 0x77};
-  uint8_t CH4[8] = {0x00, 0x11, 0x22, 0x33, 0x54, 0x55, 0x66, 0x77};
-  uint8_t CH5[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x54, 0x66, 0x77};
-  uint8_t CH6[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x76, 0x77};
-  uint8_t CH7[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0xF7};
-  for (int i = 0; i < NumIter; i++) {
-    uint8_t T[9] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
-    size_t NewSize = (*MD.*M)(T, 8, 9);
-    if (NewSize == 8 && !memcmp(CH0, T, 8))
-      FoundMask |= 1 << 0;
-    if (NewSize == 8 && !memcmp(CH1, T, 8))
-      FoundMask |= 1 << 1;
-    if (NewSize == 8 && !memcmp(CH2, T, 8))
-      FoundMask |= 1 << 2;
-    if (NewSize == 8 && !memcmp(CH3, T, 8))
-      FoundMask |= 1 << 3;
-    if (NewSize == 8 && !memcmp(CH4, T, 8))
-      FoundMask |= 1 << 4;
-    if (NewSize == 8 && !memcmp(CH5, T, 8))
-      FoundMask |= 1 << 5;
-    if (NewSize == 8 && !memcmp(CH6, T, 8))
-      FoundMask |= 1 << 6;
-    if (NewSize == 8 && !memcmp(CH7, T, 8))
-      FoundMask |= 1 << 7;
-  }
-  EXPECT_EQ(FoundMask, 255);
-}
-
-TEST(MutationDispatcher, ChangeBit1) {
-  TestChangeBit(&MutationDispatcher::Mutate_ChangeBit, 1 << 16);
-}
-TEST(MutationDispatcher, ChangeBit2) {
-  TestChangeBit(&MutationDispatcher::Mutate, 1 << 18);
-}
-
-void TestShuffleBytes(Mutator M, int NumIter) {
-  auto MD = CreateMutationDispatcher();
-  int FoundMask = 0;
-  uint8_t CH0[7] = {0x00, 0x22, 0x11, 0x33, 0x44, 0x55, 0x66};
-  uint8_t CH1[7] = {0x11, 0x00, 0x33, 0x22, 0x44, 0x55, 0x66};
-  uint8_t CH2[7] = {0x00, 0x33, 0x11, 0x22, 0x44, 0x55, 0x66};
-  uint8_t CH3[7] = {0x00, 0x11, 0x22, 0x44, 0x55, 0x66, 0x33};
-  uint8_t CH4[7] = {0x00, 0x11, 0x22, 0x33, 0x55, 0x44, 0x66};
-  for (int i = 0; i < NumIter; i++) {
-    uint8_t T[7] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
-    size_t NewSize = (*MD.*M)(T, 7, 7);
-    if (NewSize == 7 && !memcmp(CH0, T, 7))
-      FoundMask |= 1 << 0;
-    if (NewSize == 7 && !memcmp(CH1, T, 7))
-      FoundMask |= 1 << 1;
-    if (NewSize == 7 && !memcmp(CH2, T, 7))
-      FoundMask |= 1 << 2;
-    if (NewSize == 7 && !memcmp(CH3, T, 7))
-      FoundMask |= 1 << 3;
-    if (NewSize == 7 && !memcmp(CH4, T, 7))
-      FoundMask |= 1 << 4;
-  }
-  EXPECT_EQ(FoundMask, 31);
-}
-
-TEST(MutationDispatcher, ShuffleBytes1) {
-  TestShuffleBytes(&MutationDispatcher::Mutate_ShuffleBytes, 1 << 17);
-}
-TEST(MutationDispatcher, ShuffleBytes2) {
-  TestShuffleBytes(&MutationDispatcher::Mutate, 1 << 20);
-}
-
-void TestCopyPart(Mutator M, int NumIter) {
-  auto MD = CreateMutationDispatcher();
-  int FoundMask = 0;
-  uint8_t CH0[7] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x00, 0x11};
-  uint8_t CH1[7] = {0x55, 0x66, 0x22, 0x33, 0x44, 0x55, 0x66};
-  uint8_t CH2[7] = {0x00, 0x55, 0x66, 0x33, 0x44, 0x55, 0x66};
-  uint8_t CH3[7] = {0x00, 0x11, 0x22, 0x00, 0x11, 0x22, 0x66};
-  uint8_t CH4[7] = {0x00, 0x11, 0x11, 0x22, 0x33, 0x55, 0x66};
-
-  for (int i = 0; i < NumIter; i++) {
-    uint8_t T[7] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
-    size_t NewSize = (*MD.*M)(T, 7, 7);
-    if (NewSize == 7 && !memcmp(CH0, T, 7))
-      FoundMask |= 1 << 0;
-    if (NewSize == 7 && !memcmp(CH1, T, 7))
-      FoundMask |= 1 << 1;
-    if (NewSize == 7 && !memcmp(CH2, T, 7))
-      FoundMask |= 1 << 2;
-    if (NewSize == 7 && !memcmp(CH3, T, 7))
-      FoundMask |= 1 << 3;
-    if (NewSize == 7 && !memcmp(CH4, T, 7))
-      FoundMask |= 1 << 4;
-  }
-
-  uint8_t CH5[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x00, 0x11, 0x22};
-  uint8_t CH6[8] = {0x22, 0x33, 0x44, 0x00, 0x11, 0x22, 0x33, 0x44};
-  uint8_t CH7[8] = {0x00, 0x11, 0x22, 0x00, 0x11, 0x22, 0x33, 0x44};
-  uint8_t CH8[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x22, 0x33, 0x44};
-  uint8_t CH9[8] = {0x00, 0x11, 0x22, 0x22, 0x33, 0x44, 0x33, 0x44};
-
-  for (int i = 0; i < NumIter; i++) {
-    uint8_t T[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
-    size_t NewSize = (*MD.*M)(T, 5, 8);
-    if (NewSize == 8 && !memcmp(CH5, T, 8))
-      FoundMask |= 1 << 5;
-    if (NewSize == 8 && !memcmp(CH6, T, 8))
-      FoundMask |= 1 << 6;
-    if (NewSize == 8 && !memcmp(CH7, T, 8))
-      FoundMask |= 1 << 7;
-    if (NewSize == 8 && !memcmp(CH8, T, 8))
-      FoundMask |= 1 << 8;
-    if (NewSize == 8 && !memcmp(CH9, T, 8))
-      FoundMask |= 1 << 9;
-  }
-
-  EXPECT_EQ(FoundMask, 1023);
-}
-
-TEST(MutationDispatcher, CopyPart1) {
-  TestCopyPart(&MutationDispatcher::Mutate_CopyPart, 1 << 10);
-}
-TEST(MutationDispatcher, CopyPart2) {
-  TestCopyPart(&MutationDispatcher::Mutate, 1 << 13);
-}
-TEST(MutationDispatcher, CopyPartNoInsertAtMaxSize) {
-  // This (non exhaustively) tests if `Mutate_CopyPart` tries to perform an
-  // insert on an input of size `MaxSize`.  Performing an insert in this case
-  // will lead to the mutation failing.
-  auto MD = CreateMutationDispatcher();
-  uint8_t Data[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x00, 0x11, 0x22};
-  size_t MaxSize = sizeof(Data);
-  for (int count = 0; count < (1 << 18); ++count) {
-    size_t NewSize = MD->Mutate_CopyPart(Data, MaxSize, MaxSize);
-    ASSERT_EQ(NewSize, MaxSize);
-  }
-}
-
-void TestAddWordFromDictionary(Mutator M, int NumIter) {
-  auto MD = CreateMutationDispatcher();
-  uint8_t Word1[4] = {0xAA, 0xBB, 0xCC, 0xDD};
-  uint8_t Word2[3] = {0xFF, 0xEE, 0xEF};
-  MD->AddWordToManualDictionary(Word(Word1, sizeof(Word1)));
-  MD->AddWordToManualDictionary(Word(Word2, sizeof(Word2)));
-  int FoundMask = 0;
-  uint8_t CH0[7] = {0x00, 0x11, 0x22, 0xAA, 0xBB, 0xCC, 0xDD};
-  uint8_t CH1[7] = {0x00, 0x11, 0xAA, 0xBB, 0xCC, 0xDD, 0x22};
-  uint8_t CH2[7] = {0x00, 0xAA, 0xBB, 0xCC, 0xDD, 0x11, 0x22};
-  uint8_t CH3[7] = {0xAA, 0xBB, 0xCC, 0xDD, 0x00, 0x11, 0x22};
-  uint8_t CH4[6] = {0x00, 0x11, 0x22, 0xFF, 0xEE, 0xEF};
-  uint8_t CH5[6] = {0x00, 0x11, 0xFF, 0xEE, 0xEF, 0x22};
-  uint8_t CH6[6] = {0x00, 0xFF, 0xEE, 0xEF, 0x11, 0x22};
-  uint8_t CH7[6] = {0xFF, 0xEE, 0xEF, 0x00, 0x11, 0x22};
-  for (int i = 0; i < NumIter; i++) {
-    uint8_t T[7] = {0x00, 0x11, 0x22};
-    size_t NewSize = (*MD.*M)(T, 3, 7);
-    if (NewSize == 7 && !memcmp(CH0, T, 7))
-      FoundMask |= 1 << 0;
-    if (NewSize == 7 && !memcmp(CH1, T, 7))
-      FoundMask |= 1 << 1;
-    if (NewSize == 7 && !memcmp(CH2, T, 7))
-      FoundMask |= 1 << 2;
-    if (NewSize == 7 && !memcmp(CH3, T, 7))
-      FoundMask |= 1 << 3;
-    if (NewSize == 6 && !memcmp(CH4, T, 6))
-      FoundMask |= 1 << 4;
-    if (NewSize == 6 && !memcmp(CH5, T, 6))
-      FoundMask |= 1 << 5;
-    if (NewSize == 6 && !memcmp(CH6, T, 6))
-      FoundMask |= 1 << 6;
-    if (NewSize == 6 && !memcmp(CH7, T, 6))
-      FoundMask |= 1 << 7;
-  }
-  EXPECT_EQ(FoundMask, 255);
-}
-
-TEST(MutationDispatcher, AddWordFromDictionary1) {
-  TestAddWordFromDictionary(
-      &MutationDispatcher::Mutate_AddWordFromManualDictionary, 1 << 15);
-}
-
-TEST(MutationDispatcher, AddWordFromDictionary2) {
-  TestAddWordFromDictionary(&MutationDispatcher::Mutate, 1 << 15);
-}
-
-void TestChangeASCIIInteger(Mutator M, int NumIter) {
-  auto MD = CreateMutationDispatcher();
-
-  uint8_t CH0[8] = {'1', '2', '3', '4', '5', '6', '7', '7'};
-  uint8_t CH1[8] = {'1', '2', '3', '4', '5', '6', '7', '9'};
-  uint8_t CH2[8] = {'2', '4', '6', '9', '1', '3', '5', '6'};
-  uint8_t CH3[8] = {'0', '6', '1', '7', '2', '8', '3', '9'};
-  int FoundMask = 0;
-  for (int i = 0; i < NumIter; i++) {
-    uint8_t T[8] = {'1', '2', '3', '4', '5', '6', '7', '8'};
-    size_t NewSize = (*MD.*M)(T, 8, 8);
-    /**/ if (NewSize == 8 && !memcmp(CH0, T, 8))
-      FoundMask |= 1 << 0;
-    else if (NewSize == 8 && !memcmp(CH1, T, 8))
-      FoundMask |= 1 << 1;
-    else if (NewSize == 8 && !memcmp(CH2, T, 8))
-      FoundMask |= 1 << 2;
-    else if (NewSize == 8 && !memcmp(CH3, T, 8))
-      FoundMask |= 1 << 3;
-    else if (NewSize == 8)
-      FoundMask |= 1 << 4;
-  }
-  EXPECT_EQ(FoundMask, 31);
-}
-
-TEST(MutationDispatcher, ChangeASCIIInteger1) {
-  TestChangeASCIIInteger(&MutationDispatcher::Mutate_ChangeASCIIInteger,
-                         1 << 15);
-}
-
-TEST(MutationDispatcher, ChangeASCIIInteger2) {
-  TestChangeASCIIInteger(&MutationDispatcher::Mutate, 1 << 15);
-}
-
-void TestChangeBinaryInteger(Mutator M, int NumIter) {
-  auto MD = CreateMutationDispatcher();
-
-  uint8_t CH0[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x79};
-  uint8_t CH1[8] = {0x00, 0x11, 0x22, 0x31, 0x44, 0x55, 0x66, 0x77};
-  uint8_t CH2[8] = {0xff, 0x10, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
-  uint8_t CH3[8] = {0x00, 0x11, 0x2a, 0x33, 0x44, 0x55, 0x66, 0x77};
-  uint8_t CH4[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x4f, 0x66, 0x77};
-  uint8_t CH5[8] = {0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88};
-  uint8_t CH6[8] = {0x00, 0x11, 0x22, 0x00, 0x00, 0x00, 0x08, 0x77}; // Size
-  uint8_t CH7[8] = {0x00, 0x08, 0x00, 0x33, 0x44, 0x55, 0x66, 0x77}; // Sw(Size)
-
-  int FoundMask = 0;
-  for (int i = 0; i < NumIter; i++) {
-    uint8_t T[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
-    size_t NewSize = (*MD.*M)(T, 8, 8);
-    /**/ if (NewSize == 8 && !memcmp(CH0, T, 8))
-      FoundMask |= 1 << 0;
-    else if (NewSize == 8 && !memcmp(CH1, T, 8))
-      FoundMask |= 1 << 1;
-    else if (NewSize == 8 && !memcmp(CH2, T, 8))
-      FoundMask |= 1 << 2;
-    else if (NewSize == 8 && !memcmp(CH3, T, 8))
-      FoundMask |= 1 << 3;
-    else if (NewSize == 8 && !memcmp(CH4, T, 8))
-      FoundMask |= 1 << 4;
-    else if (NewSize == 8 && !memcmp(CH5, T, 8))
-      FoundMask |= 1 << 5;
-    else if (NewSize == 8 && !memcmp(CH6, T, 8))
-      FoundMask |= 1 << 6;
-    else if (NewSize == 8 && !memcmp(CH7, T, 8))
-      FoundMask |= 1 << 7;
-  }
-  EXPECT_EQ(FoundMask, 255);
-}
-
-TEST(MutationDispatcher, ChangeBinaryInteger1) {
-  TestChangeBinaryInteger(&MutationDispatcher::Mutate_ChangeBinaryInteger,
-                          1 << 12);
-}
-
-TEST(MutationDispatcher, ChangeBinaryInteger2) {
-  TestChangeBinaryInteger(&MutationDispatcher::Mutate, 1 << 15);
-}
-
-// Test fixture for MutagenInterface unit tests.
-static const char *kWord1 = "word1";
-static const char *kWord2 = "word2";
-
-class MutagenInterface : public ::testing::Test {
-protected:
-  void SetUp() override {
-    Current = this;
-    memset(&Config, 0, sizeof(Config));
-
-    Config.Seed = 1;
-
-    Config.UseCmp = 1;
-    Config.FromTORC4 = [](size_t Idx, uint32_t *Arg1, uint32_t *Arg2) {
-      ++(Current->FromTORC4Calls);
-      *Arg1 = 0x0401;
-      *Arg2 = 0x0402;
-    };
-    Config.FromTORC8 = [](size_t Idx, uint64_t *Arg1, uint64_t *Arg2) {
-      ++(Current->FromTORC8Calls);
-      *Arg1 = 0x0801;
-      *Arg2 = 0x0802;
-    };
-    Config.FromTORCW = [](size_t Idx, const uint8_t **Data1, size_t *Size1,
-                          const uint8_t **Data2, size_t *Size2) {
-      ++(Current->FromTORCWCalls);
-      *Data1 = reinterpret_cast<const uint8_t *>(kWord1);
-      *Size1 = strlen(kWord1);
-      *Data2 = reinterpret_cast<const uint8_t *>(kWord2);
-      *Size2 = strlen(kWord2);
-    };
-
-    Config.UseMemmem = 0;
-    Config.FromMMT = [](size_t Idx, const uint8_t **Data, size_t *Size) {
-      ++(Current->FromMMTCalls);
-      *Data = reinterpret_cast<const uint8_t *>(kWord1);
-      *Size = strlen(kWord1);
-    };
-
-    Config.OnlyASCII = 0;
-
-    Config.CustomMutator = [](uint8_t *Data, size_t Size, size_t MaxSize,
-                              unsigned int Seed) {
-      ++(Current->CustomMutatorCalls);
-      return LLVMMutagenDefaultMutate(Data, Size, MaxSize);
-    };
-
-    Config.CustomCrossOver =
-        [](const uint8_t *Data1, size_t Size1, const uint8_t *Data2,
-           size_t Size2, uint8_t *Out, size_t MaxOutSize, unsigned int Seed) {
-          ++(Current->CustomCrossOverCalls);
-          auto *MD = GetMutationDispatcherForTest();
-          return MD->CrossOver(Data1, Size1, Data2, Size2, Out, MaxOutSize);
-        };
-
-    U = Unit({1, 2, 3, 4});
-    U.reserve(8);
-  }
-
-  void TearDown() override {
-    Current = nullptr;
-    memset(&Config, 0, sizeof(Config));
-    LLVMMutagenConfigure(&Config);
-  }
-
-  LLVMMutagenConfiguration Config;
-  Unit U;
-
-  size_t FromTORC4Calls = 0;
-  size_t FromTORC8Calls = 0;
-  size_t FromTORCWCalls = 0;
-  size_t FromMMTCalls = 0;
-  size_t CustomMutatorCalls = 0;
-  size_t CustomCrossOverCalls = 0;
-
-private:
-  static MutagenInterface *Current;
-};
-
-MutagenInterface *MutagenInterface::Current = nullptr;
-
-// Unit tests for MutagenInterface.
-
-TEST_F(MutagenInterface, Configure) {
-  Config.OnlyASCII = 1;
-  LLVMMutagenConfigure(&Config);
-  auto *MD = GetMutationDispatcherForTest();
-  ASSERT_NE(MD, nullptr);
-
-  Random Rand1(Config.Seed);
-  Random &Rand2 = MD->GetRand();
-  for (size_t i = 0; i < 10; ++i)
-    EXPECT_EQ(Rand1(), Rand2());
-
-  Config.Seed = static_cast<unsigned>(
-      std::chrono::system_clock::now().time_since_epoch().count());
-  Config.OnlyASCII = 0;
-  LLVMMutagenConfigure(&Config);
-  MD = GetMutationDispatcherForTest();
-  ASSERT_NE(MD, nullptr);
-
-  Random Rand3(Config.Seed);
-  Random &Rand4 = MD->GetRand();
-  for (size_t i = 0; i < 10; ++i)
-    EXPECT_EQ(Rand3(), Rand4());
-}
-
-TEST_F(MutagenInterface, UseTORCs) {
-  // If !UseCmp, none of the TORC/MMT callbacks are called, regardless of
-  // UseMemmem.
-  Config.UseCmp = 0;
-  Config.UseMemmem = 1;
-  LLVMMutagenConfigure(&Config);
-  for (size_t i = 0; i < 200; ++i)
-    LLVMMutagenMutate(U.data(), U.size(), U.capacity());
-  EXPECT_EQ(FromTORC4Calls, 0U);
-  EXPECT_EQ(FromTORC8Calls, 0U);
-  EXPECT_EQ(FromTORCWCalls, 0U);
-  EXPECT_EQ(FromMMTCalls, 0U);
-
-  // If UseCmp, but !UseMemmem, only the TORC callbacks are invoked.
-  Config.UseCmp = 1;
-  Config.UseMemmem = 0;
-  LLVMMutagenConfigure(&Config);
-  for (size_t i = 0; i < 200; ++i)
-    LLVMMutagenMutate(U.data(), U.size(), U.capacity());
-  EXPECT_NE(FromTORC4Calls, 0U);
-  EXPECT_NE(FromTORC8Calls, 0U);
-  EXPECT_NE(FromTORCWCalls, 0U);
-  EXPECT_EQ(FromMMTCalls, 0U);
-
-  // If UseCmp and UseMemmem, all the TORC/MMT callbacks are invoked.
-  Config.UseCmp = 1;
-  Config.UseMemmem = 1;
-  LLVMMutagenConfigure(&Config);
-  for (size_t i = 0; i < 200; ++i)
-    LLVMMutagenMutate(U.data(), U.size(), U.capacity());
-  EXPECT_NE(FromTORC4Calls, 0U);
-  EXPECT_NE(FromTORC8Calls, 0U);
-  EXPECT_NE(FromTORCWCalls, 0U);
-  EXPECT_NE(FromMMTCalls, 0U);
-}
-
-TEST_F(MutagenInterface, CustomCallbacks) {
-  // DefaultMutate never selects custom callbacks.
-  LLVMMutagenConfigure(&Config);
-  for (size_t i = 0; i < 200; ++i)
-    LLVMMutagenDefaultMutate(U.data(), U.size(), U.capacity());
-
-  // Valid.
-  auto *MD = GetMutationDispatcherForTest();
-  EXPECT_EQ(CustomMutatorCalls, 0U);
-  MD->Mutate_Custom(U.data(), U.size(), U.capacity());
-  EXPECT_EQ(CustomMutatorCalls, 1U);
-
-  // Null cross-over input disables CustomCrossOver.
-  LLVMMutagenSetCrossOverWith(nullptr, 0);
-  MD->Mutate_CustomCrossOver(U.data(), U.size(), U.capacity());
-  EXPECT_EQ(CustomCrossOverCalls, 0U);
-
-  // Zero-length cross-over input disables CustomCrossOver.
-  Unit CrossOverWith = {4, 3, 2, 1};
-  LLVMMutagenSetCrossOverWith(CrossOverWith.data(), 0);
-  MD->Mutate_CustomCrossOver(U.data(), U.size(), U.capacity());
-  EXPECT_EQ(CustomCrossOverCalls, 0U);
-
-  // Valid.
-  LLVMMutagenSetCrossOverWith(CrossOverWith.data(), CrossOverWith.size());
-  MD->Mutate_CustomCrossOver(U.data(), U.size(), U.capacity());
-  EXPECT_EQ(CustomCrossOverCalls, 1U);
-
-  // Can mutate without custom callbacks.
-  Config.CustomMutator = nullptr;
-  Config.CustomCrossOver = nullptr;
-  LLVMMutagenConfigure(&Config);
-  for (size_t i = 0; i < 200; ++i)
-    LLVMMutagenMutate(U.data(), U.size(), U.capacity());
-}
-
-TEST_F(MutagenInterface, MutationSequence) {
-  LLVMMutagenConfigure(&Config);
-  char Buf[1024];
-  size_t NumItems;
-
-  Set<std::string> Names = {
-      "ShuffleBytes", "EraseBytes", "InsertBytes", "InsertRepeatedBytes",
-      "ChangeByte",   "ChangeBit",  "CopyPart",    "ChangeASCIIInt",
-      "ChangeBinInt",
-  };
-  std::string Name;
-  std::istringstream ISS;
-
-  // Empty sequences
-  auto Size = LLVMMutagenGetMutationSequence(true, Buf, sizeof(Buf), &NumItems);
-  EXPECT_STREQ(Buf, "");
-  EXPECT_EQ(Size, 0U);
-  EXPECT_EQ(NumItems, 0U);
-
-  while (true) {
-    // Can get size without output parameters.
-    Size = LLVMMutagenGetMutationSequence(true, nullptr, 0, &NumItems);
-    if (NumItems > Sequence<Mutator>::kMaxBriefItems)
-      break;
-    // !Verbose has no effect for <= 10 items.
-    EXPECT_EQ(LLVMMutagenGetMutationSequence(false, nullptr, 0, nullptr), Size);
-    EXPECT_GT(LLVMMutagenDefaultMutate(U.data(), U.size(), U.capacity()), 0U);
-  }
-
-  // All items are valid.
-  LLVMMutagenGetMutationSequence(true, Buf, sizeof(Buf), nullptr);
-  ISS.str(Buf);
-  size_t N = 0;
-  while (std::getline(ISS, Name, '-')) {
-    EXPECT_GT(Names.count(Name), 0U);
-    ++N;
-  }
-  EXPECT_EQ(N, NumItems);
-
-  // !Verbose truncates, but items are still valid.
-  EXPECT_LT(LLVMMutagenGetMutationSequence(false, Buf, sizeof(Buf), nullptr),
-            Size);
-  ISS.str(Buf);
-  N = 0;
-  while (std::getline(ISS, Name, '-')) {
-    EXPECT_GT(Names.count(Name), 0U);
-    ++N;
-  }
-  EXPECT_LT(N, NumItems);
-
-  // Truncated sequence is a prefix of its untruncated equivalent.
-  std::string Truncated(Buf);
-  LLVMMutagenGetMutationSequence(true, Buf, sizeof(Buf), &NumItems);
-  Buf[Truncated.size()] = '\0';
-  EXPECT_STREQ(Truncated.c_str(), Buf);
-
-  // Stops at the end of |Buf|, and null terminates.
-  EXPECT_EQ(LLVMMutagenGetMutationSequence(true, Buf, Size - 1, nullptr), Size);
-  EXPECT_EQ(strlen(Buf), Size - 2);
-
-  // Clear the sequence.
-  LLVMMutagenResetSequence();
-  EXPECT_EQ(LLVMMutagenGetMutationSequence(true, nullptr, 0, nullptr), 0U);
-}
-
-static uint8_t FromASCIINybble(char C) {
-  if ('0' <= C && C <= '9')
-    return static_cast<uint8_t>(C - '0');
-  if ('A' <= C && C <= 'F')
-    return static_cast<uint8_t>(C - 'A' + 10);
-  assert('a' <= C && C <= 'f');
-  return static_cast<uint8_t>(C - 'a' + 10);
-}
-
-static Word FromASCII(const char *DE) {
-  Unit Tmp;
-  bool Escape = false;
-  size_t Hex = 0;
-  uint8_t Nybble = 0;
-  for (char C = *DE++; C; C = *DE++) {
-    if (Hex == 2) {
-      Nybble = FromASCIINybble(C);
-      --Hex;
-    } else if (Hex == 1) {
-      Tmp.push_back(static_cast<uint8_t>(Nybble << 4) | FromASCIINybble(C));
-      --Hex;
-    } else if (Escape) {
-      switch (C) {
-      case '\\':
-      case '"':
-        Tmp.push_back(static_cast<uint8_t>(C));
-        break;
-      case 'x':
-        Hex = 2;
-        break;
-      default:
-        assert(false && "FromASCII failure.");
-      }
-      Escape = false;
-    } else if (C == '\\') {
-      Escape = true;
-    } else {
-      Tmp.push_back(static_cast<uint8_t>(C));
-    }
-  }
-  return Word(Tmp.data(), Tmp.size());
-}
-
-TEST_F(MutagenInterface, Dictionaries) {
-  LLVMMutagenConfigure(&Config);
-  size_t NumItems;
-  char Buf[1024];
-  std::istringstream ISS;
-  std::string Str;
-
-  // Empty sequences
-  auto Size =
-      LLVMMutagenGetDictionaryEntrySequence(true, Buf, sizeof(Buf), &NumItems);
-  EXPECT_STREQ(Buf, "");
-  EXPECT_EQ(Size, 0U);
-  EXPECT_EQ(NumItems, 0U);
-
-  auto *MD = GetMutationDispatcherForTest();
-  while (true) {
-    // Can get size without output parameters.
-    Size = LLVMMutagenGetDictionaryEntrySequence(true, nullptr, 0, &NumItems);
-    if (NumItems > Sequence<DictionaryEntry *>::kMaxBriefItems)
-      break;
-    // !Verbose has no effect for <= 10 items.
-    EXPECT_EQ(LLVMMutagenGetDictionaryEntrySequence(false, nullptr, 0, nullptr),
-              Size);
-    MD->Mutate_AddWordFromTORC(U.data(), U.size(), U.capacity());
-  }
-
-  // All items are valid.
-  LLVMMutagenGetDictionaryEntrySequence(true, Buf, sizeof(Buf), nullptr);
-  ISS.str(Buf);
-  size_t N = 0;
-  while (std::getline(ISS, Str, '-')) {
-    ASSERT_FALSE(Str.empty());
-    EXPECT_EQ(Str[0], '"');
-    EXPECT_EQ(Str[Str.size() - 1], '"');
-    ++N;
-  }
-  EXPECT_EQ(N, NumItems);
-
-  // !Verbose truncates, but items are still valid.
-  EXPECT_LT(
-      LLVMMutagenGetDictionaryEntrySequence(false, Buf, sizeof(Buf), nullptr),
-      Size);
-  ISS.str(Buf);
-  N = 0;
-  while (std::getline(ISS, Str, '-')) {
-    ASSERT_FALSE(Str.empty());
-    EXPECT_EQ(Str[0], '"');
-    EXPECT_EQ(Str[Str.size() - 1], '"');
-    ++N;
-  }
-  EXPECT_LT(N, NumItems);
-
-  // Truncated sequence is a prefix of its untruncated equivalent.
-  std::string Truncated(Buf);
-  LLVMMutagenGetDictionaryEntrySequence(true, Buf, sizeof(Buf), &NumItems);
-  Buf[Truncated.size()] = '\0';
-  EXPECT_STREQ(Truncated.c_str(), Buf);
-
-  // Stops at the end of |Buf|, and null terminates.
-  EXPECT_EQ(LLVMMutagenGetDictionaryEntrySequence(true, Buf, Size - 1, nullptr),
-            Size);
-  EXPECT_EQ(strlen(Buf), Size - 2);
-
-  // Clear the sequence.
-  LLVMMutagenResetSequence();
-  EXPECT_EQ(LLVMMutagenGetDictionaryEntrySequence(true, nullptr, 0, nullptr),
-            0U);
-
-  // Retuns null if no recommendations.
-  size_t UseCount = 0;
-  EXPECT_EQ(LLVMMutagenRecommendDictionaryEntry(&UseCount), nullptr);
-  EXPECT_EQ(LLVMMutagenRecommendDictionary(), 0U);
-  EXPECT_EQ(LLVMMutagenRecommendDictionaryEntry(&UseCount), nullptr);
-
-  // Record sequences.
-  for (size_t i = 0; i < 5; ++i) {
-    for (size_t i = 0; i < 5; ++i) {
-      MD->Mutate_AddWordFromTORC(U.data(), U.size(), U.capacity());
-    }
-    LLVMMutagenRecordSequence();
-  }
-
-  size_t NumDEs = LLVMMutagenRecommendDictionary();
-  EXPECT_NE(NumDEs, 0U);
-  for (size_t i = 0; i < NumDEs; ++i) {
-    auto *DE = LLVMMutagenRecommendDictionaryEntry(&UseCount);
-    EXPECT_NE(DE, nullptr);
-    EXPECT_EQ(UseCount, 0U);
-  }
-
-  // Increment the use counts of entries.
-  for (size_t i = 0; i < 100; ++i)
-    MD->Mutate_AddWordFromPersistentAutoDictionary(U.data(), U.size(),
-                                                   U.capacity());
-  NumDEs = LLVMMutagenRecommendDictionary();
-  EXPECT_NE(NumDEs, 0U);
-  for (size_t i = 0; i < NumDEs; ++i) {
-    auto *DE = LLVMMutagenRecommendDictionaryEntry(&UseCount);
-    EXPECT_NE(DE, nullptr);
-    EXPECT_NE(UseCount, 0U);
-  }
-
-  // Add the first few words manually to exclude them from recommendations.
-  Vector<Word> ManualAdditions;
-  NumDEs = LLVMMutagenRecommendDictionary();
-  ASSERT_GT(NumDEs, 3U);
-  for (size_t i = 0; i < 3; ++i) {
-    auto *DE = LLVMMutagenRecommendDictionaryEntry(nullptr);
-    auto W = FromASCII(DE);
-    LLVMMutagenAddWordToDictionary(W.data(), W.size());
-    ManualAdditions.push_back(W);
-  }
-  N = NumDEs;
-
-  // Get the recommended dictionary without the manual additions.
-  NumDEs = LLVMMutagenRecommendDictionary();
-  EXPECT_EQ(NumDEs, N - 3);
-  for (size_t i = 0; i < NumDEs; ++i) {
-    auto *DE = LLVMMutagenRecommendDictionaryEntry(nullptr);
-    ASSERT_NE(DE, nullptr);
-    Word W1(reinterpret_cast<const uint8_t *>(DE), strlen(DE));
-    for (const auto &W2 : ManualAdditions)
-      EXPECT_FALSE(W1 == W2);
-  }
-}
-
-} // namespace
-} // namespace mutagen
-
-int main(int argc, char **argv) {
-  testing::InitGoogleTest(&argc, argv);
-  return RUN_ALL_TESTS();
-}

diff  --git a/compiler-rt/test/fuzzer/CMakeLists.txt b/compiler-rt/test/fuzzer/CMakeLists.txt
index acfcd437f0287..c12a04b6f2702 100644
--- a/compiler-rt/test/fuzzer/CMakeLists.txt
+++ b/compiler-rt/test/fuzzer/CMakeLists.txt
@@ -20,7 +20,6 @@ endif()
 if(COMPILER_RT_INCLUDE_TESTS)
   list(APPEND LIBFUZZER_TEST_DEPS FuzzerUnitTests)
   list(APPEND LIBFUZZER_TEST_DEPS FuzzedDataProviderUnitTests)
-  list(APPEND LIBFUZZER_TEST_DEPS MutagenUnitTests)
 endif()
 
 add_custom_target(check-fuzzer)


        


More information about the llvm-commits mailing list