about summary refs log tree commit diff
path: root/instrumentation
diff options
context:
space:
mode:
Diffstat (limited to 'instrumentation')
-rw-r--r--instrumentation/README.llvm.md4
-rw-r--r--instrumentation/README.lto.md126
-rw-r--r--instrumentation/SanitizerCoverageLTO.so.cc30
-rw-r--r--instrumentation/SanitizerCoveragePCGUARD.so.cc10
-rw-r--r--instrumentation/afl-compiler-rt.o.c126
-rw-r--r--instrumentation/afl-gcc-cmplog-pass.so.cc2
-rw-r--r--instrumentation/afl-gcc-cmptrs-pass.so.cc2
-rw-r--r--instrumentation/afl-gcc-common.h2
-rw-r--r--instrumentation/afl-gcc-pass.so.cc2
-rw-r--r--instrumentation/afl-llvm-common.cc2
-rw-r--r--instrumentation/afl-llvm-common.h9
-rw-r--r--instrumentation/afl-llvm-dict2file.so.cc23
-rw-r--r--instrumentation/afl-llvm-lto-instrumentlist.so.cc2
-rw-r--r--instrumentation/afl-llvm-pass.so.cc12
-rw-r--r--instrumentation/cmplog-instructions-pass.cc2
-rw-r--r--instrumentation/cmplog-routines-pass.cc6
-rw-r--r--instrumentation/cmplog-switches-pass.cc6
-rw-r--r--instrumentation/compare-transform-pass.so.cc4
-rw-r--r--instrumentation/split-compares-pass.so.cc270
-rw-r--r--instrumentation/split-switches-pass.so.cc20
20 files changed, 448 insertions, 212 deletions
diff --git a/instrumentation/README.llvm.md b/instrumentation/README.llvm.md
index 9da1b0f6..c0677474 100644
--- a/instrumentation/README.llvm.md
+++ b/instrumentation/README.llvm.md
@@ -167,6 +167,10 @@ Just specify `AFL_LLVM_DICT2FILE=/absolute/path/file.txt` and during compilation
 all constant string compare parameters will be written to this file to be used
 with afl-fuzz' `-x` option.
 
+Adding `AFL_LLVM_DICT2FILE_NO_MAIN=1` will skip parsing `main()` which often
+does command line parsing which has string comparisons that are not helpful
+for fuzzing.
+
 ## 6) AFL++ Context Sensitive Branch Coverage
 
 ### What is this?
diff --git a/instrumentation/README.lto.md b/instrumentation/README.lto.md
index a1c2f44a..df59cc2a 100644
--- a/instrumentation/README.lto.md
+++ b/instrumentation/README.lto.md
@@ -2,36 +2,37 @@
 
 ## TL;DR:
 
-This version requires a current llvm 11+ compiled from the GitHub master.
+This version requires a LLVM 11 or newer.
 
-1. Use afl-clang-lto/afl-clang-lto++ because it is faster and gives better
-   coverage than anything else that is out there in the AFL world.
+1. Use afl-clang-lto/afl-clang-lto++ because the resulting binaries run
+   slightly faster and give better coverage.
 
-2. You can use it together with llvm_mode: laf-intel and the instrument file
-   listing features and can be combined with cmplog/Redqueen.
+2. You can use it together with COMPCOV, COMPLOG and the instrument file
+   listing features.
 
-3. It only works with llvm 11+.
+3. It only works with LLVM 11 or newer.
 
-4. AUTODICTIONARY feature (see below)!
+4. AUTODICTIONARY feature (see below)
 
-5. If any problems arise, be sure to set `AR=llvm-ar RANLIB=llvm-ranlib`. Some
-   targets might need `LD=afl-clang-lto` and others `LD=afl-ld-lto`.
+5. If any problems arise, be sure to set `AR=llvm-ar RANLIB=llvm-ranlib AS=llvm-as`.
+   Some targets might need `LD=afl-clang-lto` and others `LD=afl-ld-lto`.
 
 ## Introduction and problem description
 
-A big issue with how AFL++ works is that the basic block IDs that are set during
-compilation are random - and hence naturally the larger the number of
-instrumented locations, the higher the number of edge collisions are in the map.
-This can result in not discovering new paths and therefore degrade the
+A big issue with how vanilla AFL worked was that the basic block IDs that are
+set during compilation are random - and hence naturally the larger the number
+of instrumented locations, the higher the number of edge collisions are in the
+map. This can result in not discovering new paths and therefore degrade the
 efficiency of the fuzzing process.
 
-*This issue is underestimated in the fuzzing community!* With a 2^16 = 64kb
+*This issue is underestimated in the fuzzing community* With a 2^16 = 64kb
 standard map at already 256 instrumented blocks, there is on average one
 collision. On average, a target has 10.000 to 50.000 instrumented blocks, hence
 the real collisions are between 750-18.000!
 
-To reach a solution that prevents any collisions took several approaches and
-many dead ends until we got to this:
+Note that PCGUARD (our own modified implementation and the SANCOV PCGUARD
+implementation from libfuzzer) also provides collision free coverage.
+It is a bit slower though and can a few targets with very early constructors.
 
 * We instrument at link time when we have all files pre-compiled.
 * To instrument at link time, we compile in LTO (link time optimization) mode.
@@ -45,9 +46,9 @@ many dead ends until we got to this:
 The result:
 
 * 10-25% speed gain compared to llvm_mode
-* guaranteed non-colliding edge coverage :-)
+* guaranteed non-colliding edge coverage 
 * The compile time, especially for binaries to an instrumented library, can be
-  much longer.
+  much (and sometimes much much) longer.
 
 Example build output from a libtiff build:
 
@@ -59,71 +60,30 @@ AUTODICTIONARY: 11 strings found
 [+] Instrumented 12071 locations with no collisions (on average 1046 collisions would be in afl-gcc/afl-clang-fast) (non-hardened mode).
 ```
 
-## Getting llvm 11+
+## Getting LLVM 11+
 
-### Installing llvm version 11 or 12
+### Installing llvm
 
-llvm 11 or even 12 should be available in all current Linux repositories. If you
-use an outdated Linux distribution, read the next section.
-
-### Installing llvm from the llvm repository (version 12+)
-
-Installing the llvm snapshot builds is easy and mostly painless:
-
-In the following line, change `NAME` for your Debian or Ubuntu release name
-(e.g., buster, focal, eon, etc.):
+The best way to install LLVM is to follow [https://apt.llvm.org/](https://apt.llvm.org/)
 
+e.g. for LLVM 15:
 ```
-echo deb http://apt.llvm.org/NAME/ llvm-toolchain-NAME NAME >> /etc/apt/sources.list
+wget https://apt.llvm.org/llvm.sh
+chmod +x llvm.sh
+sudo ./llvm.sh 15 all
 ```
 
-Then add the pgp key of llvm and install the packages:
+LLVM 11 to 16 should be available in all current Linux repositories.
 
-```
-wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add -
-apt-get update && apt-get upgrade -y
-apt-get install -y clang-12 clang-tools-12 libc++1-12 libc++-12-dev \
-    libc++abi1-12 libc++abi-12-dev libclang1-12 libclang-12-dev \
-    libclang-common-12-dev libclang-cpp12 libclang-cpp12-dev liblld-12 \
-    liblld-12-dev liblldb-12 liblldb-12-dev libllvm12 libomp-12-dev \
-    libomp5-12 lld-12 lldb-12 llvm-12 llvm-12-dev llvm-12-runtime llvm-12-tools
-```
+## How to build afl-clang-lto
+
+That part is easy.
+Just set `LLVM_CONFIG` to the llvm-config-VERSION and build AFL++, e.g. for
+LLVM 15:
 
-### Building llvm yourself (version 12+)
-
-Building llvm from GitHub takes quite some time and is not painless:
-
-```sh
-sudo apt install binutils-dev  # this is *essential*!
-git clone --depth=1 https://github.com/llvm/llvm-project
-cd llvm-project
-mkdir build
-cd build
-
-# Add -G Ninja if ninja-build installed
-# "Building with ninja significantly improves your build time, especially with
-# incremental builds, and improves your memory usage."
-cmake \
-    -DCLANG_INCLUDE_DOCS="OFF" \
-    -DCMAKE_BUILD_TYPE=Release \
-    -DLLVM_BINUTILS_INCDIR=/usr/include/ \
-    -DLLVM_BUILD_LLVM_DYLIB="ON" \
-    -DLLVM_ENABLE_BINDINGS="OFF" \
-    -DLLVM_ENABLE_PROJECTS='clang;compiler-rt;libcxx;libcxxabi;libunwind;lld' \
-    -DLLVM_ENABLE_WARNINGS="OFF" \
-    -DLLVM_INCLUDE_BENCHMARKS="OFF" \
-    -DLLVM_INCLUDE_DOCS="OFF" \
-    -DLLVM_INCLUDE_EXAMPLES="OFF" \
-    -DLLVM_INCLUDE_TESTS="OFF" \
-    -DLLVM_LINK_LLVM_DYLIB="ON" \
-    -DLLVM_TARGETS_TO_BUILD="host" \
-    ../llvm/
-# NOTE: for llvm 16 this needs to be changed to:
-#    -DLLVM_ENABLE_PROJECTS='clang;compiler-rt;lld' \
-#    -DLLVM_ENABLE_RUNTIMES='libcxx;libcxxabi' \
-cmake --build . -j4
-export LLVM_CONFIG="$(pwd)/bin/llvm-config"
-cd /path/to/AFLplusplus/
+```
+cd ~/AFLplusplus
+export LLVM_CONFIG=llvm-config-15
 make
 sudo make install
 ```
@@ -136,10 +96,10 @@ Also, the instrument file listing (AFL_LLVM_ALLOWLIST/AFL_LLVM_DENYLIST ->
 [README.instrument_list.md](README.instrument_list.md)) and laf-intel/compcov
 (AFL_LLVM_LAF_* -> [README.laf-intel.md](README.laf-intel.md)) work.
 
-Example:
+Example (note that you might need to add the version, e.g. `llvm-ar-15`:
 
 ```
-CC=afl-clang-lto CXX=afl-clang-lto++ RANLIB=llvm-ranlib AR=llvm-ar ./configure
+CC=afl-clang-lto CXX=afl-clang-lto++ RANLIB=llvm-ranlib AR=llvm-ar AS=llvm-as ./configure
 make
 ```
 
@@ -317,13 +277,13 @@ AS=llvm-as  ...
 afl-clang-lto is still work in progress.
 
 Known issues:
-* Anything that llvm 11+ cannot compile, afl-clang-lto cannot compile either -
+* Anything that LLVM 11+ cannot compile, afl-clang-lto cannot compile either -
   obviously.
 * Anything that does not compile with LTO, afl-clang-lto cannot compile either -
   obviously.
 
 Hence, if building a target with afl-clang-lto fails, try to build it with
-llvm12 and LTO enabled (`CC=clang-12`, `CXX=clang++-12`, `CFLAGS=-flto=full`,
+LLVM 12 and LTO enabled (`CC=clang-12`, `CXX=clang++-12`, `CFLAGS=-flto=full`,
 and `CXXFLAGS=-flto=full`).
 
 If this succeeds, then there is an issue with afl-clang-lto. Please report at
@@ -341,7 +301,7 @@ knows what this is doing. And the developer who implemented this didn't respond
 to emails.)
 
 In December then came the idea to implement this as a pass that is run via the
-llvm "opt" program, which is performed via an own linker that afterwards calls
+LLVM "opt" program, which is performed via an own linker that afterwards calls
 the real linker. This was first implemented in January and work ... kinda. The
 LTO time instrumentation worked, however, "how" the basic blocks were
 instrumented was a problem, as reducing duplicates turned out to be very, very
@@ -353,13 +313,13 @@ dead-end too.
 The final idea to solve this came from domenukk who proposed to insert a block
 into an edge and then just use incremental counters ... and this worked! After
 some trials and errors to implement this vanhauser-thc found out that there is
-actually an llvm function for this: SplitEdge() :-)
+actually an LLVM function for this: SplitEdge() :-)
 
-Still more problems came up though as this only works without bugs from llvm 9
+Still more problems came up though as this only works without bugs from LLVM 9
 onwards, and with high optimization the link optimization ruins the instrumented
 control flow graph.
 
-This is all now fixed with llvm 11+. The llvm's own linker is now able to load
+This is all now fixed with LLVM 11+. The llvm's own linker is now able to load
 passes and this bypasses all problems we had.
 
 Happy end :)
diff --git a/instrumentation/SanitizerCoverageLTO.so.cc b/instrumentation/SanitizerCoverageLTO.so.cc
index 231151f5..e779bb79 100644
--- a/instrumentation/SanitizerCoverageLTO.so.cc
+++ b/instrumentation/SanitizerCoverageLTO.so.cc
@@ -17,8 +17,10 @@
 #include "llvm/Transforms/Instrumentation/SanitizerCoverage.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/Triple.h"
-#include "llvm/Analysis/EHPersonalities.h"
+#if LLVM_VERSION_MAJOR < 17
+  #include "llvm/ADT/Triple.h"
+  #include "llvm/Analysis/EHPersonalities.h"
+#endif
 #include "llvm/Analysis/PostDominators.h"
 #include "llvm/Analysis/ValueTracking.h"
 #include "llvm/IR/BasicBlock.h"
@@ -47,7 +49,9 @@
 #include "llvm/Support/VirtualFileSystem.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Transforms/Instrumentation.h"
-#include "llvm/Transforms/IPO/PassManagerBuilder.h"
+#if LLVM_VERSION_MAJOR < 17
+  #include "llvm/Transforms/IPO/PassManagerBuilder.h"
+#endif
 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
 #include "llvm/Transforms/Utils/ModuleUtils.h"
@@ -236,6 +240,7 @@ class ModuleSanitizerCoverageLTO
   // const SpecialCaseList *          Allowlist;
   // const SpecialCaseList *          Blocklist;
   uint32_t                         autodictionary = 1;
+  uint32_t                         autodictionary_no_main = 0;
   uint32_t                         inst = 0;
   uint32_t                         afl_global_id = 0;
   uint32_t                         unhandled = 0;
@@ -411,7 +416,8 @@ bool ModuleSanitizerCoverageLTO::instrumentModule(
 
   /* Show a banner */
   setvbuf(stdout, NULL, _IONBF, 0);
-  if (getenv("AFL_DEBUG")) debug = 1;
+  if (getenv("AFL_DEBUG")) { debug = 1; }
+  if (getenv("AFL_LLVM_DICT2FILE_NO_MAIN")) { autodictionary_no_main = 1; }
 
   if ((isatty(2) && !getenv("AFL_QUIET")) || debug) {
 
@@ -429,6 +435,8 @@ bool ModuleSanitizerCoverageLTO::instrumentModule(
     if ((afl_global_id = atoi(ptr)) < 0)
       FATAL("AFL_LLVM_LTO_STARTID value of \"%s\" is negative\n", ptr);
 
+  if (afl_global_id < 4) { afl_global_id = 4; }
+
   if ((ptr = getenv("AFL_LLVM_DOCUMENT_IDS")) != NULL) {
 
     dFile.open(ptr, std::ofstream::out | std::ofstream::app);
@@ -503,6 +511,13 @@ bool ModuleSanitizerCoverageLTO::instrumentModule(
 
       if (!isInInstrumentList(&F, MNAME) || !F.size()) { continue; }
 
+      if (autodictionary_no_main &&
+          (!F.getName().compare("main") || !F.getName().compare("_main"))) {
+
+        continue;
+
+      }
+
       for (auto &BB : F) {
 
         for (auto &IN : BB) {
@@ -992,7 +1007,8 @@ bool ModuleSanitizerCoverageLTO::instrumentModule(
   // afl++ START
   if (dFile.is_open()) dFile.close();
 
-  if (!getenv("AFL_LLVM_LTO_DONTWRITEID") || dictionary.size() || map_addr) {
+  if (!getenv("AFL_LLVM_LTO_SKIPINIT") &&
+      (!getenv("AFL_LLVM_LTO_DONTWRITEID") || dictionary.size() || map_addr)) {
 
     // yes we could create our own function, insert it into ctors ...
     // but this would be a pain in the butt ... so we use afl-llvm-rt-lto.o
@@ -1770,6 +1786,7 @@ INITIALIZE_PASS_END(ModuleSanitizerCoverageLTOLegacyPass, "sancov-lto",
                     "Pass for instrumenting coverage on functions", false,
                     false)
 
+#if LLVM_VERSION_MAJOR < 16
 static void registerLTOPass(const PassManagerBuilder &,
                             legacy::PassManagerBase &PM) {
 
@@ -1784,8 +1801,9 @@ static RegisterStandardPasses RegisterCompTransPass(
 static RegisterStandardPasses RegisterCompTransPass0(
     PassManagerBuilder::EP_EnabledOnOptLevel0, registerLTOPass);
 
-#if LLVM_VERSION_MAJOR >= 11
+  #if LLVM_VERSION_MAJOR >= 11
 static RegisterStandardPasses RegisterCompTransPassLTO(
     PassManagerBuilder::EP_FullLinkTimeOptimizationLast, registerLTOPass);
+  #endif
 #endif
 
diff --git a/instrumentation/SanitizerCoveragePCGUARD.so.cc b/instrumentation/SanitizerCoveragePCGUARD.so.cc
index ef2d3b9c..8be9e329 100644
--- a/instrumentation/SanitizerCoveragePCGUARD.so.cc
+++ b/instrumentation/SanitizerCoveragePCGUARD.so.cc
@@ -13,8 +13,10 @@
 #include "llvm/Transforms/Instrumentation/SanitizerCoverage.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/Triple.h"
-#include "llvm/Analysis/EHPersonalities.h"
+#if LLVM_VERSION_MAJOR < 17
+  #include "llvm/ADT/Triple.h"
+  #include "llvm/Analysis/EHPersonalities.h"
+#endif
 #include "llvm/Analysis/PostDominators.h"
 #include "llvm/IR/CFG.h"
 #include "llvm/IR/Constant.h"
@@ -728,7 +730,11 @@ GlobalVariable *ModuleSanitizerCoverageAFL::CreateFunctionLocalArrayInSection(
   Array->setSection(getSectionName(Section));
 #if (LLVM_VERSION_MAJOR >= 11) || \
     (LLVM_VERSION_MAJOR == 10 && LLVM_VERSION_MINOR >= 1)
+  #if LLVM_VERSION_MAJOR >= 16
+  Array->setAlignment(Align(DL->getTypeStoreSize(Ty).getFixedValue()));
+  #else
   Array->setAlignment(Align(DL->getTypeStoreSize(Ty).getFixedSize()));
+  #endif
 #else
   Array->setAlignment(Align(4));  // cheating
 #endif
diff --git a/instrumentation/afl-compiler-rt.o.c b/instrumentation/afl-compiler-rt.o.c
index fd5f2d4c..0912e52b 100644
--- a/instrumentation/afl-compiler-rt.o.c
+++ b/instrumentation/afl-compiler-rt.o.c
@@ -3,7 +3,7 @@
    ------------------------------------------------
 
    Copyright 2015, 2016 Google Inc. All rights reserved.
-   Copyright 2019-2022 AFLplusplus Project. All rights reserved.
+   Copyright 2019-2023 AFLplusplus Project. All rights reserved.
 
    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
@@ -113,7 +113,7 @@ int        __afl_selective_coverage __attribute__((weak));
 int        __afl_selective_coverage_start_off __attribute__((weak));
 static int __afl_selective_coverage_temp = 1;
 
-#if defined(__ANDROID__) || defined(__HAIKU__)
+#if defined(__ANDROID__) || defined(__HAIKU__) || defined(NO_TLS)
 PREV_LOC_T __afl_prev_loc[NGRAM_SIZE_MAX];
 PREV_LOC_T __afl_prev_caller[CTX_MAX_K];
 u32        __afl_prev_ctx;
@@ -149,6 +149,7 @@ u32 __afl_already_initialized_shm;
 u32 __afl_already_initialized_forkserver;
 u32 __afl_already_initialized_first;
 u32 __afl_already_initialized_second;
+u32 __afl_already_initialized_early;
 u32 __afl_already_initialized_init;
 
 /* Dummy pipe for area_is_valid() */
@@ -1373,6 +1374,9 @@ __attribute__((constructor(EARLY_FS_PRIO))) void __early_forkserver(void) {
 
 __attribute__((constructor(CTOR_PRIO))) void __afl_auto_early(void) {
 
+  if (__afl_already_initialized_early) return;
+  __afl_already_initialized_early = 1;
+
   is_persistent = !!getenv(PERSIST_ENV_VAR);
 
   if (getenv("AFL_DISABLE_LLVM_INSTRUMENTATION")) return;
@@ -1514,6 +1518,14 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) {
 
   _is_sancov = 1;
 
+  if (!getenv("AFL_DUMP_MAP_SIZE")) {
+
+    __afl_auto_first();
+    __afl_auto_second();
+    __afl_auto_early();
+
+  }
+
   if (__afl_debug) {
 
     fprintf(stderr,
@@ -1524,7 +1536,21 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) {
 
   }
 
-  if (start == stop || *start) return;
+  if (start == stop || *start) { return; }
+
+  x = getenv("AFL_INST_RATIO");
+  if (x) {
+
+    inst_ratio = (u32)atoi(x);
+
+    if (!inst_ratio || inst_ratio > 100) {
+
+      fprintf(stderr, "[-] ERROR: Invalid AFL_INST_RATIO (must be 1-100).\n");
+      abort();
+
+    }
+
+  }
 
   // If a dlopen of an instrumented library happens after the forkserver then
   // we have a problem as we cannot increase the coverage map anymore.
@@ -1537,85 +1563,65 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) {
           "[-] FATAL: forkserver is already up, but an instrumented dlopen() "
           "library loaded afterwards. You must AFL_PRELOAD such libraries to "
           "be able to fuzz them or LD_PRELOAD to run outside of afl-fuzz.\n"
-          "To ignore this set AFL_IGNORE_PROBLEMS=1.\n");
+          "To ignore this set AFL_IGNORE_PROBLEMS=1 but this will lead to "
+          "ambiguous coverage data.\n"
+          "In addition, you can set AFL_IGNORE_PROBLEMS_COVERAGE=1 to "
+          "ignore the additional coverage instead (use with caution!).\n");
       abort();
 
     } else {
 
-      static u32 offset = 4;
-
-      while (start < stop) {
+      u8 ignore_dso_after_fs = !!getenv("AFL_IGNORE_PROBLEMS_COVERAGE");
+      if (__afl_debug && ignore_dso_after_fs) {
 
-        *(start++) = offset;
-        if (unlikely(++offset >= __afl_final_loc)) { offset = 4; }
+        fprintf(stderr, "Ignoring coverage from dynamically loaded code\n");
 
       }
 
-    }
-
-  }
-
-  x = getenv("AFL_INST_RATIO");
-  if (x) { inst_ratio = (u32)atoi(x); }
-
-  if (!inst_ratio || inst_ratio > 100) {
-
-    fprintf(stderr, "[-] ERROR: Invalid AFL_INST_RATIO (must be 1-100).\n");
-    abort();
-
-  }
-
-  /* instrumented code is loaded *after* our forkserver is up. this is a
-     problem. We cannot prevent collisions then :( */
-  /*
-  if (__afl_already_initialized_forkserver &&
-      __afl_final_loc + 1 + stop - start > __afl_map_size) {
-
-    if (__afl_debug) {
-
-      fprintf(stderr, "Warning: new instrumented code after the forkserver!\n");
+      static u32 offset = 5;
 
-    }
+      while (start < stop) {
 
-    __afl_final_loc = 2;
+        if (!ignore_dso_after_fs &&
+            (likely(inst_ratio == 100) || R(100) < inst_ratio)) {
 
-    if (1 + stop - start > __afl_map_size) {
+          *(start++) = offset;
 
-      *(start++) = ++__afl_final_loc;
+        } else {
 
-      while (start < stop) {
+          *(start++) = 0;  // write to map[0]
 
-        if (R(100) < inst_ratio)
-          *start = ++__afl_final_loc % __afl_map_size;
-        else
-          *start = 4;
+        }
 
-        start++;
+        if (unlikely(++offset >= __afl_final_loc)) { offset = 5; }
 
       }
 
-      return;
-
     }
 
-  }
+    return;  // we are done for this special case
 
-  */
+  }
 
   /* Make sure that the first element in the range is always set - we use that
      to avoid duplicate calls (which can happen as an artifact of the underlying
      implementation in LLVM). */
 
+  if (__afl_final_loc < 5) __afl_final_loc = 5;  // we skip the first 5 entries
+
   *(start++) = ++__afl_final_loc;
 
   while (start < stop) {
 
-    if (R(100) < inst_ratio)
-      *start = ++__afl_final_loc;
-    else
-      *start = 4;
+    if (likely(inst_ratio == 100) || R(100) < inst_ratio) {
 
-    start++;
+      *(start++) = ++__afl_final_loc;
+
+    } else {
+
+      *(start++) = 0;  // write to map[0]
+
+    }
 
   }
 
@@ -1627,17 +1633,23 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) {
 
   }
 
-  if (__afl_already_initialized_shm && __afl_final_loc > __afl_map_size) {
+  if (__afl_already_initialized_shm) {
 
-    if (__afl_debug) {
+    if (__afl_final_loc > __afl_map_size) {
+
+      if (__afl_debug) {
+
+        fprintf(stderr, "Reinit shm necessary (+%u)\n",
+                __afl_final_loc - __afl_map_size);
+
+      }
 
-      fprintf(stderr, "Reinit shm necessary (+%u)\n",
-              __afl_final_loc - __afl_map_size);
+      __afl_unmap_shm();
+      __afl_map_shm();
 
     }
 
-    __afl_unmap_shm();
-    __afl_map_shm();
+    __afl_map_size = __afl_final_loc + 1;
 
   }
 
diff --git a/instrumentation/afl-gcc-cmplog-pass.so.cc b/instrumentation/afl-gcc-cmplog-pass.so.cc
index 3c781fd7..b4e6fda9 100644
--- a/instrumentation/afl-gcc-cmplog-pass.so.cc
+++ b/instrumentation/afl-gcc-cmplog-pass.so.cc
@@ -3,7 +3,7 @@
    Copyright 2014-2019 Free Software Foundation, Inc
    Copyright 2015, 2016 Google Inc. All rights reserved.
    Copyright 2019-2020 AFLplusplus Project. All rights reserved.
-   Copyright 2019-2022 AdaCore
+   Copyright 2019-2023 AdaCore
 
    Written by Alexandre Oliva <oliva@adacore.com>, based on the AFL++
    LLVM CmpLog pass by Andrea Fioraldi <andreafioraldi@gmail.com>, and
diff --git a/instrumentation/afl-gcc-cmptrs-pass.so.cc b/instrumentation/afl-gcc-cmptrs-pass.so.cc
index 0ddbac15..dbb408b0 100644
--- a/instrumentation/afl-gcc-cmptrs-pass.so.cc
+++ b/instrumentation/afl-gcc-cmptrs-pass.so.cc
@@ -3,7 +3,7 @@
    Copyright 2014-2019 Free Software Foundation, Inc
    Copyright 2015, 2016 Google Inc. All rights reserved.
    Copyright 2019-2020 AFLplusplus Project. All rights reserved.
-   Copyright 2019-2022 AdaCore
+   Copyright 2019-2023 AdaCore
 
    Written by Alexandre Oliva <oliva@adacore.com>, based on the AFL++
    LLVM CmpLog Routines pass by Andrea Fioraldi
diff --git a/instrumentation/afl-gcc-common.h b/instrumentation/afl-gcc-common.h
index cda3f9d8..1d5eb466 100644
--- a/instrumentation/afl-gcc-common.h
+++ b/instrumentation/afl-gcc-common.h
@@ -2,7 +2,7 @@
 
    Copyright 2014-2019 Free Software Foundation, Inc
    Copyright 2015, 2016 Google Inc. All rights reserved.
-   Copyright 2019-2022 AdaCore
+   Copyright 2019-2023 AdaCore
 
    Written by Alexandre Oliva <oliva@adacore.com>, based on the AFL++
    GCC plugin.
diff --git a/instrumentation/afl-gcc-pass.so.cc b/instrumentation/afl-gcc-pass.so.cc
index ea938a7f..4d7fd0ef 100644
--- a/instrumentation/afl-gcc-pass.so.cc
+++ b/instrumentation/afl-gcc-pass.so.cc
@@ -2,7 +2,7 @@
 
    Copyright 2014-2019 Free Software Foundation, Inc
    Copyright 2015, 2016 Google Inc. All rights reserved.
-   Copyright 2019-2022 AdaCore
+   Copyright 2019-2023 AdaCore
 
    Written by Alexandre Oliva <oliva@adacore.com>, based on the AFL
    LLVM pass by Laszlo Szekeres <lszekeres@google.com> and Michal
diff --git a/instrumentation/afl-llvm-common.cc b/instrumentation/afl-llvm-common.cc
index 5fcf27fb..5d82aa25 100644
--- a/instrumentation/afl-llvm-common.cc
+++ b/instrumentation/afl-llvm-common.cc
@@ -12,6 +12,7 @@
 #include <list>
 #include <string>
 #include <fstream>
+#include <cmath>
 
 #include <llvm/Support/raw_ostream.h>
 
@@ -288,6 +289,7 @@ void scanForDangerousFunctions(llvm::Module *M) {
 
     StringRef ifunc_name = IF.getName();
     Constant *r = IF.getResolver();
+    if (r->getNumOperands() == 0) { continue; }
     StringRef r_name = cast<Function>(r->getOperand(0))->getName();
     if (!be_quiet)
       fprintf(stderr,
diff --git a/instrumentation/afl-llvm-common.h b/instrumentation/afl-llvm-common.h
index dee5f9fc..c9324460 100644
--- a/instrumentation/afl-llvm-common.h
+++ b/instrumentation/afl-llvm-common.h
@@ -8,6 +8,7 @@
 #include <list>
 #include <string>
 #include <fstream>
+#include <optional>
 #include <sys/time.h>
 
 #include "llvm/Config/llvm-config.h"
@@ -21,7 +22,9 @@ typedef long double max_align_t;
 #include "llvm/IR/Module.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/MathExtras.h"
+#if LLVM_VERSION_MAJOR < 17
 #include "llvm/Transforms/IPO/PassManagerBuilder.h"
+#endif
 
 #if LLVM_VERSION_MAJOR > 3 || \
     (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR > 4)
@@ -35,6 +38,12 @@ typedef long double max_align_t;
 #if LLVM_VERSION_MAJOR >= 11
   #define MNAME M.getSourceFileName()
   #define FMNAME F.getParent()->getSourceFileName()
+  #if LLVM_VERSION_MAJOR >= 16
+// None becomes deprecated
+// the standard std::nullopt_t is recommended instead
+// from C++17 and onwards.
+constexpr std::nullopt_t None = std::nullopt;
+  #endif
 #else
   #define MNAME std::string("")
   #define FMNAME std::string("")
diff --git a/instrumentation/afl-llvm-dict2file.so.cc b/instrumentation/afl-llvm-dict2file.so.cc
index fd8baea2..97155cd6 100644
--- a/instrumentation/afl-llvm-dict2file.so.cc
+++ b/instrumentation/afl-llvm-dict2file.so.cc
@@ -4,7 +4,7 @@
 
    Written by Marc Heuse <mh@mh-sec.de>
 
-   Copyright 2019-2022 AFLplusplus Project. All rights reserved.
+   Copyright 2019-2023 AFLplusplus Project. All rights reserved.
 
    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
@@ -53,7 +53,9 @@
 #include "llvm/IR/Verifier.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/raw_ostream.h"
-#include "llvm/Transforms/IPO/PassManagerBuilder.h"
+#if LLVM_VERSION_MAJOR < 17
+  #include "llvm/Transforms/IPO/PassManagerBuilder.h"
+#endif
 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
 #include "llvm/Analysis/LoopInfo.h"
 #include "llvm/Analysis/ValueTracking.h"
@@ -182,7 +184,7 @@ bool AFLdict2filePass::runOnModule(Module &M) {
 
   DenseMap<Value *, std::string *> valueMap;
   char                            *ptr;
-  int                              found = 0;
+  int                              found = 0, handle_main = 1;
 
   /* Show a banner */
   setvbuf(stdout, NULL, _IONBF, 0);
@@ -192,10 +194,14 @@ bool AFLdict2filePass::runOnModule(Module &M) {
     SAYF(cCYA "afl-llvm-dict2file" VERSION cRST
               " by Marc \"vanHauser\" Heuse <mh@mh-sec.de>\n");
 
-  } else
+  } else {
 
     be_quiet = 1;
 
+  }
+
+  if (getenv("AFL_LLVM_DICT2FILE_NO_MAIN")) { handle_main = 0; }
+
   scanForDangerousFunctions(&M);
 
   ptr = getenv("AFL_LLVM_DICT2FILE");
@@ -210,7 +216,14 @@ bool AFLdict2filePass::runOnModule(Module &M) {
 
   for (auto &F : M) {
 
-    if (isIgnoreFunction(&F)) continue;
+    if (!handle_main &&
+        (!F.getName().compare("main") || !F.getName().compare("_main"))) {
+
+      continue;
+
+    }
+
+    if (isIgnoreFunction(&F)) { continue; }
     if (!isInInstrumentList(&F, MNAME) || !F.size()) { continue; }
 
     /*  Some implementation notes.
diff --git a/instrumentation/afl-llvm-lto-instrumentlist.so.cc b/instrumentation/afl-llvm-lto-instrumentlist.so.cc
index 32b1798a..db5bd55e 100644
--- a/instrumentation/afl-llvm-lto-instrumentlist.so.cc
+++ b/instrumentation/afl-llvm-lto-instrumentlist.so.cc
@@ -9,7 +9,7 @@
    from afl-as.c are Michal's fault.
 
    Copyright 2015, 2016 Google Inc. All rights reserved.
-   Copyright 2019-2022 AFLplusplus Project. All rights reserved.
+   Copyright 2019-2023 AFLplusplus Project. All rights reserved.
 
    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
diff --git a/instrumentation/afl-llvm-pass.so.cc b/instrumentation/afl-llvm-pass.so.cc
index df1ccc4f..c59324fd 100644
--- a/instrumentation/afl-llvm-pass.so.cc
+++ b/instrumentation/afl-llvm-pass.so.cc
@@ -12,7 +12,7 @@
    NGRAM previous location coverage comes from Adrian Herrera.
 
    Copyright 2015, 2016 Google Inc. All rights reserved.
-   Copyright 2019-2022 AFLplusplus Project. All rights reserved.
+   Copyright 2019-2023 AFLplusplus Project. All rights reserved.
 
    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
@@ -413,7 +413,7 @@ bool AFLCoverage::runOnModule(Module &M) {
   GlobalVariable *AFLContext = NULL;
 
   if (ctx_str || caller_str)
-#if defined(__ANDROID__) || defined(__HAIKU__)
+#if defined(__ANDROID__) || defined(__HAIKU__) || defined(NO_TLS)
     AFLContext = new GlobalVariable(
         M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_prev_ctx");
 #else
@@ -424,7 +424,7 @@ bool AFLCoverage::runOnModule(Module &M) {
 
 #ifdef AFL_HAVE_VECTOR_INTRINSICS
   if (ngram_size)
-  #if defined(__ANDROID__) || defined(__HAIKU__)
+  #if defined(__ANDROID__) || defined(__HAIKU__) || defined(NO_TLS)
     AFLPrevLoc = new GlobalVariable(
         M, PrevLocTy, /* isConstant */ false, GlobalValue::ExternalLinkage,
         /* Initializer */ nullptr, "__afl_prev_loc");
@@ -437,7 +437,7 @@ bool AFLCoverage::runOnModule(Module &M) {
   #endif
   else
 #endif
-#if defined(__ANDROID__) || defined(__HAIKU__)
+#if defined(__ANDROID__) || defined(__HAIKU__) || defined(NO_TLS)
     AFLPrevLoc = new GlobalVariable(
         M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_prev_loc");
 #else
@@ -448,7 +448,7 @@ bool AFLCoverage::runOnModule(Module &M) {
 
 #ifdef AFL_HAVE_VECTOR_INTRINSICS
   if (ctx_k)
-  #if defined(__ANDROID__) || defined(__HAIKU__)
+  #if defined(__ANDROID__) || defined(__HAIKU__) || defined(NO_TLS)
     AFLPrevCaller = new GlobalVariable(
         M, PrevCallerTy, /* isConstant */ false, GlobalValue::ExternalLinkage,
         /* Initializer */ nullptr, "__afl_prev_caller");
@@ -461,7 +461,7 @@ bool AFLCoverage::runOnModule(Module &M) {
   #endif
   else
 #endif
-#if defined(__ANDROID__) || defined(__HAIKU__)
+#if defined(__ANDROID__) || defined(__HAIKU__) || defined(NO_TLS)
     AFLPrevCaller =
         new GlobalVariable(M, Int32Ty, false, GlobalValue::ExternalLinkage, 0,
                            "__afl_prev_caller");
diff --git a/instrumentation/cmplog-instructions-pass.cc b/instrumentation/cmplog-instructions-pass.cc
index 084ad8c9..bca1f927 100644
--- a/instrumentation/cmplog-instructions-pass.cc
+++ b/instrumentation/cmplog-instructions-pass.cc
@@ -5,7 +5,7 @@
    Written by Andrea Fioraldi <andreafioraldi@gmail.com>
 
    Copyright 2015, 2016 Google Inc. All rights reserved.
-   Copyright 2019-2022 AFLplusplus Project. All rights reserved.
+   Copyright 2019-2023 AFLplusplus Project. All rights reserved.
 
    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
diff --git a/instrumentation/cmplog-routines-pass.cc b/instrumentation/cmplog-routines-pass.cc
index 9733f86e..39db5aa4 100644
--- a/instrumentation/cmplog-routines-pass.cc
+++ b/instrumentation/cmplog-routines-pass.cc
@@ -5,7 +5,7 @@
    Written by Andrea Fioraldi <andreafioraldi@gmail.com>
 
    Copyright 2015, 2016 Google Inc. All rights reserved.
-   Copyright 2019-2022 AFLplusplus Project. All rights reserved.
+   Copyright 2019-2023 AFLplusplus Project. All rights reserved.
 
    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
@@ -38,7 +38,9 @@
 #include "llvm/IR/Module.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/raw_ostream.h"
-#include "llvm/Transforms/IPO/PassManagerBuilder.h"
+#if LLVM_VERSION_MAJOR < 17
+  #include "llvm/Transforms/IPO/PassManagerBuilder.h"
+#endif
 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
 #include "llvm/Pass.h"
 #include "llvm/Analysis/ValueTracking.h"
diff --git a/instrumentation/cmplog-switches-pass.cc b/instrumentation/cmplog-switches-pass.cc
index 563a4481..38de669d 100644
--- a/instrumentation/cmplog-switches-pass.cc
+++ b/instrumentation/cmplog-switches-pass.cc
@@ -5,7 +5,7 @@
    Written by Andrea Fioraldi <andreafioraldi@gmail.com>
 
    Copyright 2015, 2016 Google Inc. All rights reserved.
-   Copyright 2019-2022 AFLplusplus Project. All rights reserved.
+   Copyright 2019-2023 AFLplusplus Project. All rights reserved.
 
    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
@@ -39,7 +39,9 @@
 #include "llvm/IR/Module.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/raw_ostream.h"
-#include "llvm/Transforms/IPO/PassManagerBuilder.h"
+#if LLVM_VERSION_MAJOR < 17
+  #include "llvm/Transforms/IPO/PassManagerBuilder.h"
+#endif
 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
 #include "llvm/Pass.h"
 #include "llvm/Analysis/ValueTracking.h"
diff --git a/instrumentation/compare-transform-pass.so.cc b/instrumentation/compare-transform-pass.so.cc
index 39bff510..efc99d20 100644
--- a/instrumentation/compare-transform-pass.so.cc
+++ b/instrumentation/compare-transform-pass.so.cc
@@ -708,7 +708,11 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp,
     /* since the call is the first instruction of the bb it is safe to
      * replace it with a phi instruction */
     BasicBlock::iterator ii(callInst);
+#if LLVM_MAJOR >= 16
+    ReplaceInstWithInst(callInst->getParent(), ii, PN);
+#else
     ReplaceInstWithInst(callInst->getParent()->getInstList(), ii, PN);
+#endif
 
   }
 
diff --git a/instrumentation/split-compares-pass.so.cc b/instrumentation/split-compares-pass.so.cc
index 95eca0cb..8a07610c 100644
--- a/instrumentation/split-compares-pass.so.cc
+++ b/instrumentation/split-compares-pass.so.cc
@@ -322,8 +322,12 @@ bool SplitComparesTransform::simplifyFPCompares(Module &M) {
      * block bb it is now at the position where the old FcmpInst was */
     Instruction *fcmp_np;
     fcmp_np = CmpInst::Create(Instruction::FCmp, new_pred, op0, op1);
+#if LLVM_MAJOR >= 16
+    fcmp_np->insertInto(bb, BasicBlock::iterator(bb->getTerminator()));
+#else
     bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()),
                              fcmp_np);
+#endif
 
     /* create a new basic block which holds the new EQ fcmp */
     Instruction *fcmp_eq;
@@ -331,7 +335,11 @@ bool SplitComparesTransform::simplifyFPCompares(Module &M) {
     BasicBlock *middle_bb =
         BasicBlock::Create(C, "injected", end_bb->getParent(), end_bb);
     fcmp_eq = CmpInst::Create(Instruction::FCmp, CmpInst::FCMP_OEQ, op0, op1);
+#if LLVM_MAJOR >= 16
+    fcmp_eq->insertInto(middle_bb, middle_bb->end());
+#else
     middle_bb->getInstList().push_back(fcmp_eq);
+#endif
     /* add an unconditional branch to the end of middle_bb with destination
      * end_bb */
     BranchInst::Create(end_bb, middle_bb);
@@ -352,7 +360,11 @@ bool SplitComparesTransform::simplifyFPCompares(Module &M) {
     PN->addIncoming(ConstantInt::get(Int1Ty, 1), bb);
     /* replace the old FcmpInst with our new and shiny PHI inst */
     BasicBlock::iterator ii(FcmpInst);
+#if LLVM_MAJOR >= 16
+    ReplaceInstWithInst(FcmpInst->getParent(), ii, PN);
+#else
     ReplaceInstWithInst(FcmpInst->getParent()->getInstList(), ii, PN);
+#endif
 
   }
 
@@ -409,7 +421,11 @@ bool SplitComparesTransform::simplifyOrEqualsCompare(CmpInst     *IcmpInst,
   /* create the ICMP instruction with new_pred and add it to the old basic
    * block bb it is now at the position where the old IcmpInst was */
   CmpInst *icmp_np = CmpInst::Create(Instruction::ICmp, new_pred, op0, op1);
+#if LLVM_MAJOR >= 16
+  icmp_np->insertInto(bb, BasicBlock::iterator(bb->getTerminator()));
+#else
   bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()), icmp_np);
+#endif
 
   /* create a new basic block which holds the new EQ icmp */
   CmpInst *icmp_eq;
@@ -417,7 +433,11 @@ bool SplitComparesTransform::simplifyOrEqualsCompare(CmpInst     *IcmpInst,
   BasicBlock *middle_bb =
       BasicBlock::Create(C, "injected", end_bb->getParent(), end_bb);
   icmp_eq = CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ, op0, op1);
+#if LLVM_MAJOR >= 16
+  icmp_eq->insertInto(middle_bb, middle_bb->end());
+#else
   middle_bb->getInstList().push_back(icmp_eq);
+#endif
   /* add an unconditional branch to the end of middle_bb with destination
    * end_bb */
   BranchInst::Create(end_bb, middle_bb);
@@ -438,7 +458,11 @@ bool SplitComparesTransform::simplifyOrEqualsCompare(CmpInst     *IcmpInst,
   PN->addIncoming(ConstantInt::get(Int1Ty, 1), bb);
   /* replace the old IcmpInst with our new and shiny PHI inst */
   BasicBlock::iterator ii(IcmpInst);
+#if LLVM_MAJOR >= 16
+  ReplaceInstWithInst(IcmpInst->getParent(), ii, PN);
+#else
   ReplaceInstWithInst(IcmpInst->getParent()->getInstList(), ii, PN);
+#endif
 
   worklist.push_back(icmp_np);
   worklist.push_back(icmp_eq);
@@ -518,7 +542,11 @@ bool SplitComparesTransform::simplifySignedCompare(CmpInst *IcmpInst, Module &M,
 
   }
 
+#if LLVM_MAJOR >= 16
+  icmp_inv_sig_cmp->insertInto(sign_bb, sign_bb->end());
+#else
   sign_bb->getInstList().push_back(icmp_inv_sig_cmp);
+#endif
   BranchInst::Create(end_bb, sign_bb);
 
   /* create a new bb which is executed if signedness is equal */
@@ -528,7 +556,11 @@ bool SplitComparesTransform::simplifySignedCompare(CmpInst *IcmpInst, Module &M,
   /* we can do a normal unsigned compare now */
   icmp_usign_cmp = CmpInst::Create(Instruction::ICmp, new_pred, op0, op1);
 
+#if LLVM_MAJOR >= 16
+  icmp_usign_cmp->insertInto(middle_bb, middle_bb->end());
+#else
   middle_bb->getInstList().push_back(icmp_usign_cmp);
+#endif
   BranchInst::Create(end_bb, middle_bb);
 
   auto term = bb->getTerminator();
@@ -543,7 +575,11 @@ bool SplitComparesTransform::simplifySignedCompare(CmpInst *IcmpInst, Module &M,
   PN->addIncoming(icmp_inv_sig_cmp, sign_bb);
 
   BasicBlock::iterator ii(IcmpInst);
+#if LLVM_MAJOR >= 16
+  ReplaceInstWithInst(IcmpInst->getParent(), ii, PN);
+#else
   ReplaceInstWithInst(IcmpInst->getParent()->getInstList(), ii, PN);
+#endif
 
   // save for later
   worklist.push_back(icmp_usign_cmp);
@@ -717,7 +753,11 @@ bool SplitComparesTransform::splitCompare(CmpInst *cmp_inst, Module &M,
 
       }
 
+#if LLVM_MAJOR >= 16
+      icmp_inv_cmp->insertInto(inv_cmp_bb, inv_cmp_bb->end());
+#else
       inv_cmp_bb->getInstList().push_back(icmp_inv_cmp);
+#endif
       worklist.push_back(icmp_inv_cmp);
 
       auto term = bb->getTerminator();
@@ -728,12 +768,18 @@ bool SplitComparesTransform::splitCompare(CmpInst *cmp_inst, Module &M,
       BasicBlock *cmp_low_bb =
           BasicBlock::Create(C, "" /*"injected"*/, end_bb->getParent(), end_bb);
       op0_low = new TruncInst(op0, NewIntType);
-      cmp_low_bb->getInstList().push_back(op0_low);
       op1_low = new TruncInst(op1, NewIntType);
-      cmp_low_bb->getInstList().push_back(op1_low);
-
       icmp_low = CmpInst::Create(Instruction::ICmp, pred, op0_low, op1_low);
+
+#if LLVM_MAJOR >= 16
+      op0_low->insertInto(cmp_low_bb, cmp_low_bb->end());
+      op1_low->insertInto(cmp_low_bb, cmp_low_bb->end());
+      icmp_low->insertInto(cmp_low_bb, cmp_low_bb->end());
+#else
+      cmp_low_bb->getInstList().push_back(op0_low);
+      cmp_low_bb->getInstList().push_back(op1_low);
       cmp_low_bb->getInstList().push_back(icmp_low);
+#endif
       BranchInst::Create(end_bb, cmp_low_bb);
 
       BranchInst::Create(end_bb, cmp_low_bb, icmp_inv_cmp, inv_cmp_bb);
@@ -754,7 +800,11 @@ bool SplitComparesTransform::splitCompare(CmpInst *cmp_inst, Module &M,
   }
 
   BasicBlock::iterator ii(cmp_inst);
+#if LLVM_MAJOR >= 16
+  ReplaceInstWithInst(cmp_inst->getParent(), ii, PN);
+#else
   ReplaceInstWithInst(cmp_inst->getParent()->getInstList(), ii, PN);
+#endif
 
   // We split the comparison into low and high. If this isn't our target
   // bitwidth we recursively split the low and high parts again until we have
@@ -999,13 +1049,21 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
     Instruction *bpre_op0, *bpre_op1;
     bpre_op0 = CastInst::Create(Instruction::BitCast, op0,
                                 IntegerType::get(C, op_size));
+#if LLVM_MAJOR >= 16
+    bpre_op0->insertInto(bb, BasicBlock::iterator(bb->getTerminator()));
+#else
     bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()),
                              bpre_op0);
+#endif
 
     bpre_op1 = CastInst::Create(Instruction::BitCast, op1,
                                 IntegerType::get(C, op_size));
+#if LLVM_MAJOR >= 16
+    bpre_op1->insertInto(bb, BasicBlock::iterator(bb->getTerminator()));
+#else
     bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()),
                              bpre_op1);
+#endif
 
     /* Check if any operand is NaN.
      * If so, all comparisons except unequal (which yields true) yield false */
@@ -1025,34 +1083,42 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
     Instruction *nan_op0, *nan_op1;
     nan_op0 = BinaryOperator::Create(Instruction::Shl, bpre_op0,
                                      ConstantInt::get(bpre_op0->getType(), 1));
-    bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()),
-                             nan_op0);
-
+    /* Check op1 for NaN */
+    /* Shift right 1 Bit, ignore sign bit */
+    nan_op1 = BinaryOperator::Create(Instruction::Shl, bpre_op1,
+                                     ConstantInt::get(bpre_op1->getType(), 1));
     /* compare to NaN interval */
     Instruction *is_op0_nan =
         CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_UGT, nan_op0,
                         ConstantInt::get(intType, NaN_lowend));
+    /* compare to NaN interval */
+    Instruction *is_op1_nan =
+        CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_UGT, nan_op1,
+                        ConstantInt::get(intType, NaN_lowend));
+    /* combine checks */
+    Instruction *is_nan =
+        BinaryOperator::Create(Instruction::Or, is_op0_nan, is_op1_nan);
+#if LLVM_MAJOR >= 16
+    nan_op0->insertInto(bb, BasicBlock::iterator(bb->getTerminator()));
+    is_op0_nan->insertInto(bb, BasicBlock::iterator(bb->getTerminator()));
+    nan_op1->insertInto(bb, BasicBlock::iterator(bb->getTerminator()));
+    is_op1_nan->insertInto(bb, BasicBlock::iterator(bb->getTerminator()));
+    is_nan->insertInto(bb, BasicBlock::iterator(bb->getTerminator()));
+#else
+    bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()),
+                             nan_op0);
+
     bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()),
                              is_op0_nan);
 
-    /* Check op1 for NaN */
-    /* Shift right 1 Bit, ignore sign bit */
-    nan_op1 = BinaryOperator::Create(Instruction::Shl, bpre_op1,
-                                     ConstantInt::get(bpre_op1->getType(), 1));
     bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()),
                              nan_op1);
 
-    /* compare to NaN interval */
-    Instruction *is_op1_nan =
-        CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_UGT, nan_op1,
-                        ConstantInt::get(intType, NaN_lowend));
     bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()),
                              is_op1_nan);
 
-    /* combine checks */
-    Instruction *is_nan =
-        BinaryOperator::Create(Instruction::Or, is_op0_nan, is_op1_nan);
     bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()), is_nan);
+#endif
 
     /* the result of the comparison, when at least one op is NaN
        is true only for the "NOT EQUAL" predicates. */
@@ -1079,23 +1145,34 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
 
     isMzero_op0 = CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ, bpre_op0,
                                   ConstantInt::get(intType, MinusZero));
+    isMzero_op1 = CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ, bpre_op1,
+                                  ConstantInt::get(intType, MinusZero));
+    b_op0 = SelectInst::Create(isMzero_op0, ConstantInt::get(intType, PlusZero),
+                               bpre_op0);
+    b_op1 = SelectInst::Create(isMzero_op1, ConstantInt::get(intType, PlusZero),
+                               bpre_op1);
+#if LLVM_MAJOR >= 16
+    isMzero_op0->insertInto(nonan_bb,
+                            BasicBlock::iterator(nonan_bb->getTerminator()));
+    isMzero_op1->insertInto(nonan_bb,
+                            BasicBlock::iterator(nonan_bb->getTerminator()));
+    b_op0->insertInto(nonan_bb,
+                      BasicBlock::iterator(nonan_bb->getTerminator()));
+    b_op1->insertInto(nonan_bb,
+                      BasicBlock::iterator(nonan_bb->getTerminator()));
+#else
     nonan_bb->getInstList().insert(
         BasicBlock::iterator(nonan_bb->getTerminator()), isMzero_op0);
 
-    isMzero_op1 = CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ, bpre_op1,
-                                  ConstantInt::get(intType, MinusZero));
     nonan_bb->getInstList().insert(
         BasicBlock::iterator(nonan_bb->getTerminator()), isMzero_op1);
 
-    b_op0 = SelectInst::Create(isMzero_op0, ConstantInt::get(intType, PlusZero),
-                               bpre_op0);
     nonan_bb->getInstList().insert(
         BasicBlock::iterator(nonan_bb->getTerminator()), b_op0);
 
-    b_op1 = SelectInst::Create(isMzero_op1, ConstantInt::get(intType, PlusZero),
-                               bpre_op1);
     nonan_bb->getInstList().insert(
         BasicBlock::iterator(nonan_bb->getTerminator()), b_op1);
+#endif
 
     /* isolate signs of value of floating point type */
 
@@ -1106,26 +1183,35 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
     s_s0 =
         BinaryOperator::Create(Instruction::LShr, b_op0,
                                ConstantInt::get(b_op0->getType(), op_size - 1));
+    s_s1 =
+        BinaryOperator::Create(Instruction::LShr, b_op1,
+                               ConstantInt::get(b_op1->getType(), op_size - 1));
+    t_s0 = new TruncInst(s_s0, Int1Ty);
+    t_s1 = new TruncInst(s_s1, Int1Ty);
+    /* compare of the sign bits */
+    icmp_sign_bit =
+        CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ, t_s0, t_s1);
+#if LLVM_MAJOR >= 16
+    s_s0->insertInto(nonan_bb, BasicBlock::iterator(nonan_bb->getTerminator()));
+    t_s0->insertInto(nonan_bb, BasicBlock::iterator(nonan_bb->getTerminator()));
+    s_s1->insertInto(nonan_bb, BasicBlock::iterator(nonan_bb->getTerminator()));
+    t_s1->insertInto(nonan_bb, BasicBlock::iterator(nonan_bb->getTerminator()));
+    icmp_sign_bit->insertInto(nonan_bb,
+                              BasicBlock::iterator(nonan_bb->getTerminator()));
+#else
     nonan_bb->getInstList().insert(
         BasicBlock::iterator(nonan_bb->getTerminator()), s_s0);
-    t_s0 = new TruncInst(s_s0, Int1Ty);
     nonan_bb->getInstList().insert(
         BasicBlock::iterator(nonan_bb->getTerminator()), t_s0);
 
-    s_s1 =
-        BinaryOperator::Create(Instruction::LShr, b_op1,
-                               ConstantInt::get(b_op1->getType(), op_size - 1));
     nonan_bb->getInstList().insert(
         BasicBlock::iterator(nonan_bb->getTerminator()), s_s1);
-    t_s1 = new TruncInst(s_s1, Int1Ty);
     nonan_bb->getInstList().insert(
         BasicBlock::iterator(nonan_bb->getTerminator()), t_s1);
 
-    /* compare of the sign bits */
-    icmp_sign_bit =
-        CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ, t_s0, t_s1);
     nonan_bb->getInstList().insert(
         BasicBlock::iterator(nonan_bb->getTerminator()), icmp_sign_bit);
+#endif
 
     /* create a new basic block which is executed if the signedness bits are
      * equal */
@@ -1157,17 +1243,31 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
     s_e1 = BinaryOperator::Create(
         Instruction::LShr, b_op1,
         ConstantInt::get(b_op1->getType(), shiftR_exponent));
+#if LLVM_MAJOR >= 16
+    s_e0->insertInto(signequal_bb,
+                     BasicBlock::iterator(signequal_bb->getTerminator()));
+    s_e1->insertInto(signequal_bb,
+                     BasicBlock::iterator(signequal_bb->getTerminator()));
+#else
     signequal_bb->getInstList().insert(
         BasicBlock::iterator(signequal_bb->getTerminator()), s_e0);
     signequal_bb->getInstList().insert(
         BasicBlock::iterator(signequal_bb->getTerminator()), s_e1);
+#endif
 
     t_e0 = new TruncInst(s_e0, IntExponentTy);
     t_e1 = new TruncInst(s_e1, IntExponentTy);
+#if LLVM_MAJOR >= 16
+    t_e0->insertInto(signequal_bb,
+                     BasicBlock::iterator(signequal_bb->getTerminator()));
+    t_e1->insertInto(signequal_bb,
+                     BasicBlock::iterator(signequal_bb->getTerminator()));
+#else
     signequal_bb->getInstList().insert(
         BasicBlock::iterator(signequal_bb->getTerminator()), t_e0);
     signequal_bb->getInstList().insert(
         BasicBlock::iterator(signequal_bb->getTerminator()), t_e1);
+#endif
 
     if (sizeInBits - precision < exTySizeBytes * 8) {
 
@@ -1177,10 +1277,17 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
       m_e1 = BinaryOperator::Create(
           Instruction::And, t_e1,
           ConstantInt::get(t_e1->getType(), mask_exponent));
+#if LLVM_MAJOR >= 16
+      m_e0->insertInto(signequal_bb,
+                       BasicBlock::iterator(signequal_bb->getTerminator()));
+      m_e1->insertInto(signequal_bb,
+                       BasicBlock::iterator(signequal_bb->getTerminator()));
+#else
       signequal_bb->getInstList().insert(
           BasicBlock::iterator(signequal_bb->getTerminator()), m_e0);
       signequal_bb->getInstList().insert(
           BasicBlock::iterator(signequal_bb->getTerminator()), m_e1);
+#endif
 
     } else {
 
@@ -1214,9 +1321,14 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
         Instruction *icmp_exponent;
         icmp_exponents_equal =
             CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ, m_e0, m_e1);
+#if LLVM_MAJOR >= 16
+        icmp_exponents_equal->insertInto(
+            signequal_bb, BasicBlock::iterator(signequal_bb->getTerminator()));
+#else
         signequal_bb->getInstList().insert(
             BasicBlock::iterator(signequal_bb->getTerminator()),
             icmp_exponents_equal);
+#endif
 
         // shortcut for unequal exponents
         signequal2_bb = signequal_bb->splitBasicBlock(
@@ -1230,9 +1342,15 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
 
         icmp_exponent =
             CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_UGT, m_e0, m_e1);
+#if LLVM_MAJOR >= 16
+        icmp_exponent->insertInto(
+            signequal2_bb,
+            BasicBlock::iterator(signequal2_bb->getTerminator()));
+#else
         signequal2_bb->getInstList().insert(
             BasicBlock::iterator(signequal2_bb->getTerminator()),
             icmp_exponent);
+#endif
         icmp_exponent_result =
             BinaryOperator::Create(Instruction::Xor, icmp_exponent, t_s0);
         break;
@@ -1240,9 +1358,14 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
       case CmpInst::FCMP_ULT:
         icmp_exponents_equal =
             CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ, m_e0, m_e1);
+#if LLVM_MAJOR >= 16
+        icmp_exponents_equal->insertInto(
+            signequal_bb, BasicBlock::iterator(signequal_bb->getTerminator()));
+#else
         signequal_bb->getInstList().insert(
             BasicBlock::iterator(signequal_bb->getTerminator()),
             icmp_exponents_equal);
+#endif
 
         // shortcut for unequal exponents
         signequal2_bb = signequal_bb->splitBasicBlock(
@@ -1256,9 +1379,15 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
 
         icmp_exponent =
             CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_ULT, m_e0, m_e1);
+#if LLVM_MAJOR >= 16
+        icmp_exponent->insertInto(
+            signequal2_bb,
+            BasicBlock::iterator(signequal2_bb->getTerminator()));
+#else
         signequal2_bb->getInstList().insert(
             BasicBlock::iterator(signequal2_bb->getTerminator()),
             icmp_exponent);
+#endif
         icmp_exponent_result =
             BinaryOperator::Create(Instruction::Xor, icmp_exponent, t_s0);
         break;
@@ -1267,9 +1396,14 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
 
     }
 
+#if LLVM_MAJOR >= 16
+    icmp_exponent_result->insertInto(
+        signequal2_bb, BasicBlock::iterator(signequal2_bb->getTerminator()));
+#else
     signequal2_bb->getInstList().insert(
         BasicBlock::iterator(signequal2_bb->getTerminator()),
         icmp_exponent_result);
+#endif
 
     {
 
@@ -1319,19 +1453,33 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
       m_f1 = BinaryOperator::Create(
           Instruction::And, b_op1,
           ConstantInt::get(b_op1->getType(), mask_fraction));
+#if LLVM_MAJOR >= 16
+      m_f0->insertInto(middle_bb,
+                       BasicBlock::iterator(middle_bb->getTerminator()));
+      m_f1->insertInto(middle_bb,
+                       BasicBlock::iterator(middle_bb->getTerminator()));
+#else
       middle_bb->getInstList().insert(
           BasicBlock::iterator(middle_bb->getTerminator()), m_f0);
       middle_bb->getInstList().insert(
           BasicBlock::iterator(middle_bb->getTerminator()), m_f1);
+#endif
 
       if (needTrunc) {
 
         t_f0 = new TruncInst(m_f0, IntFractionTy);
         t_f1 = new TruncInst(m_f1, IntFractionTy);
+#if LLVM_MAJOR >= 16
+        t_f0->insertInto(middle_bb,
+                         BasicBlock::iterator(middle_bb->getTerminator()));
+        t_f1->insertInto(middle_bb,
+                         BasicBlock::iterator(middle_bb->getTerminator()));
+#else
         middle_bb->getInstList().insert(
             BasicBlock::iterator(middle_bb->getTerminator()), t_f0);
         middle_bb->getInstList().insert(
             BasicBlock::iterator(middle_bb->getTerminator()), t_f1);
+#endif
 
       } else {
 
@@ -1346,10 +1494,17 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
 
         t_f0 = new TruncInst(b_op0, IntFractionTy);
         t_f1 = new TruncInst(b_op1, IntFractionTy);
+#if LLVM_MAJOR >= 16
+        t_f0->insertInto(middle_bb,
+                         BasicBlock::iterator(middle_bb->getTerminator()));
+        t_f1->insertInto(middle_bb,
+                         BasicBlock::iterator(middle_bb->getTerminator()));
+#else
         middle_bb->getInstList().insert(
             BasicBlock::iterator(middle_bb->getTerminator()), t_f0);
         middle_bb->getInstList().insert(
             BasicBlock::iterator(middle_bb->getTerminator()), t_f1);
+#endif
 
       } else {
 
@@ -1370,18 +1525,28 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
       case CmpInst::FCMP_OEQ:
         icmp_fraction_result =
             CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ, t_f0, t_f1);
+#if LLVM_MAJOR >= 16
+        icmp_fraction_result->insertInto(
+            middle2_bb, BasicBlock::iterator(middle2_bb->getTerminator()));
+#else
         middle2_bb->getInstList().insert(
             BasicBlock::iterator(middle2_bb->getTerminator()),
             icmp_fraction_result);
+#endif
 
         break;
       case CmpInst::FCMP_UNE:
       case CmpInst::FCMP_ONE:
         icmp_fraction_result =
             CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_NE, t_f0, t_f1);
+#if LLVM_MAJOR >= 16
+        icmp_fraction_result->insertInto(
+            middle2_bb, BasicBlock::iterator(middle2_bb->getTerminator()));
+#else
         middle2_bb->getInstList().insert(
             BasicBlock::iterator(middle2_bb->getTerminator()),
             icmp_fraction_result);
+#endif
 
         break;
       case CmpInst::FCMP_OGT:
@@ -1402,21 +1567,31 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
         if (FcmpInst->getPredicate() == CmpInst::FCMP_OGT ||
             FcmpInst->getPredicate() == CmpInst::FCMP_UGT) {
 
-          negative_bb->getInstList().push_back(
-              icmp_fraction_result = CmpInst::Create(
-                  Instruction::ICmp, CmpInst::ICMP_ULT, t_f0, t_f1));
-          positive_bb->getInstList().push_back(
-              icmp_fraction_result2 = CmpInst::Create(
-                  Instruction::ICmp, CmpInst::ICMP_UGT, t_f0, t_f1));
+          icmp_fraction_result =
+              CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_ULT, t_f0, t_f1);
+          icmp_fraction_result2 =
+              CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_UGT, t_f0, t_f1);
+#if LLVM_MAJOR >= 16
+          icmp_fraction_result->insertInto(negative_bb, negative_bb->end());
+          icmp_fraction_result2->insertInto(positive_bb, negative_bb->end());
+#else
+          negative_bb->getInstList().push_back(icmp_fraction_result);
+          positive_bb->getInstList().push_back(icmp_fraction_result2);
+#endif
 
         } else {
 
-          negative_bb->getInstList().push_back(
-              icmp_fraction_result = CmpInst::Create(
-                  Instruction::ICmp, CmpInst::ICMP_UGT, t_f0, t_f1));
-          positive_bb->getInstList().push_back(
-              icmp_fraction_result2 = CmpInst::Create(
-                  Instruction::ICmp, CmpInst::ICMP_ULT, t_f0, t_f1));
+          icmp_fraction_result =
+              CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_UGT, t_f0, t_f1);
+          icmp_fraction_result2 =
+              CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_ULT, t_f0, t_f1);
+#if LLVM_MAJOR >= 16
+          icmp_fraction_result->insertInto(negative_bb, negative_bb->end());
+          icmp_fraction_result2->insertInto(positive_bb, negative_bb->end());
+#else
+          negative_bb->getInstList().push_back(icmp_fraction_result);
+          positive_bb->getInstList().push_back(icmp_fraction_result2);
+#endif
 
         }
 
@@ -1430,8 +1605,13 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
         PN2 = PHINode::Create(Int1Ty, 2, "");
         PN2->addIncoming(icmp_fraction_result, negative_bb);
         PN2->addIncoming(icmp_fraction_result2, positive_bb);
+#if LLVM_MAJOR >= 16
+        PN2->insertInto(middle2_bb,
+                        BasicBlock::iterator(middle2_bb->getTerminator()));
+#else
         middle2_bb->getInstList().insert(
             BasicBlock::iterator(middle2_bb->getTerminator()), PN2);
+#endif
 
       } break;
 
@@ -1494,7 +1674,11 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
     }
 
     BasicBlock::iterator ii(FcmpInst);
+#if LLVM_MAJOR >= 16
+    ReplaceInstWithInst(FcmpInst->getParent(), ii, PN);
+#else
     ReplaceInstWithInst(FcmpInst->getParent()->getInstList(), ii, PN);
+#endif
     ++count;
 
   }
diff --git a/instrumentation/split-switches-pass.so.cc b/instrumentation/split-switches-pass.so.cc
index 79ba12d2..dcd89652 100644
--- a/instrumentation/split-switches-pass.so.cc
+++ b/instrumentation/split-switches-pass.so.cc
@@ -225,12 +225,20 @@ BasicBlock *SplitSwitchesTransform::switchConvert(
   BasicBlock  *NewNode = BasicBlock::Create(Val->getContext(), "NodeBlock", F);
   Shift = BinaryOperator::Create(Instruction::LShr, Val,
                                  ConstantInt::get(ValType, smallestIndex * 8));
+#if LLVM_VERSION_MAJOR >= 16
+  Shift->insertInto(NewNode, NewNode->end());
+#else
   NewNode->getInstList().push_back(Shift);
+#endif
 
   if (ValTypeBitWidth > 8) {
 
     Trunc = new TruncInst(Shift, ByteType);
+#if LLVM_VERSION_MAJOR >= 16
+    Trunc->insertInto(NewNode, NewNode->end());
+#else
     NewNode->getInstList().push_back(Trunc);
+#endif
 
   } else {
 
@@ -253,7 +261,11 @@ BasicBlock *SplitSwitchesTransform::switchConvert(
     ICmpInst *Comp =
         new ICmpInst(ICmpInst::ICMP_EQ, Trunc, ConstantInt::get(ByteType, byte),
                      "byteMatch");
+#if LLVM_VERSION_MAJOR >= 16
+    Comp->insertInto(NewNode, NewNode->end());
+#else
     NewNode->getInstList().push_back(Comp);
+#endif
 
     bytesChecked[smallestIndex] = true;
     bool allBytesAreChecked = true;
@@ -355,7 +367,11 @@ BasicBlock *SplitSwitchesTransform::switchConvert(
     ICmpInst *Comp =
         new ICmpInst(ICmpInst::ICMP_ULT, Trunc,
                      ConstantInt::get(ByteType, pivot), "byteMatch");
+#if LLVM_VERSION_MAJOR >= 16
+    Comp->insertInto(NewNode, NewNode->end());
+#else
     NewNode->getInstList().push_back(Comp);
+#endif
     BranchInst::Create(LBB, RBB, Comp, NewNode);
 
   }
@@ -452,7 +468,11 @@ bool SplitSwitchesTransform::splitSwitches(Module &M) {
     BranchInst::Create(SwitchBlock, OrigBlock);
 
     /* We are now done with the switch instruction, delete it. */
+#if LLVM_VERSION_MAJOR >= 16
+    SI->eraseFromParent();
+#else
     CurBlock->getInstList().erase(SI);
+#endif
 
     /* we have to update the phi nodes! */
     for (BasicBlock::iterator I = Default->begin(); I != Default->end(); ++I) {