diff --git a/gcc/testsuite/g++.dg/torture/pr111465.C b/gcc/testsuite/g++.dg/torture/pr111465.C
new file mode 100644
index 0000000000000000000000000000000000000000..8f2577adf4ce4389d1b101aac78fea11f049a9fe
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr111465.C
@@ -0,0 +1,55 @@
+// { dg-do compile }
+// { dg-additional-options "-fno-exceptions --param=logical-op-non-short-circuit=0" }
+
+typedef unsigned int location_t;
+const location_t MAX_LOCATION_T = 0x7FFFFFFF;
+struct line_maps {
+  unsigned int  info_ordinary;
+  location_t *maps;
+  unsigned int used;
+  location_t *data;
+};
+inline location_t LINEMAPS_MACRO_LOWEST_LOCATION(const line_maps *set) {
+  return set->used
+             ? set->maps[set->used - 1]
+             : MAX_LOCATION_T + 1;
+}
+const location_t *linemap_lookup(const line_maps *set, location_t line) {
+  int mn = set->info_ordinary;
+  if (mn >= 0)
+  if ((unsigned int)mn < set->used)
+  return &set->maps[0];
+  __builtin_unreachable();
+}
+bool linemap_location_from_macro_expansion_p(const class line_maps *set,
+                                             location_t location) {
+  if (location > MAX_LOCATION_T)
+    location = set->data[location & MAX_LOCATION_T];
+  return location >= LINEMAPS_MACRO_LOWEST_LOCATION(set);
+}
+void first_map_in_common_1(line_maps *set, location_t *loc0,
+                                             location_t *loc1) {
+  linemap_lookup(set, 0);
+  __builtin_unreachable();
+}
+int linemap_compare_locations(line_maps *set, location_t pre, location_t post) {
+  bool pre_virtual_p;
+  location_t l0 = pre, l1 = post;
+  if (l0 > MAX_LOCATION_T)
+    l0 = set->data[l0 & MAX_LOCATION_T];
+  if (l1 > MAX_LOCATION_T)
+    l1 = set->data[l1 & MAX_LOCATION_T];;
+  if (l0 == l1)
+    return 0;
+  if ((pre_virtual_p = linemap_location_from_macro_expansion_p(set, l0)))
+    l0 = set->data[l0 & MAX_LOCATION_T];
+  if (linemap_location_from_macro_expansion_p(set, l1))
+    l1 = set->data[l1 & MAX_LOCATION_T];
+  if (l0 == l1)
+     if (pre_virtual_p)
+	first_map_in_common_1(set, &l0, &l1);
+  if (l0 > MAX_LOCATION_T)
+    if (l1 > MAX_LOCATION_T)
+      l1 = set->data[l1 & MAX_LOCATION_T];
+  return l1 - l0;
+}
diff --git a/gcc/tree-ssa-threadupdate.cc b/gcc/tree-ssa-threadupdate.cc
index a5b9a002a8ab6cf2d1657f1359ede6980acbce42..86fe8aac67798913a06f2d9752a7d43409c09855 100644
--- a/gcc/tree-ssa-threadupdate.cc
+++ b/gcc/tree-ssa-threadupdate.cc
@@ -1454,6 +1454,19 @@ fwd_jt_path_registry::thread_block_1 (basic_block bb,
 	  || ((*path)[1]->type == EDGE_COPY_SRC_BLOCK && joiners))
 	continue;
 
+      /* When a NO_COPY_SRC block became non-empty cancel the path.  */
+      if (path->last ()->type == EDGE_NO_COPY_SRC_BLOCK)
+	{
+	  auto gsi = gsi_start_nondebug_bb (path->last ()->e->src);
+	  if (!gsi_end_p (gsi)
+	      && !is_ctrl_stmt (gsi_stmt (gsi)))
+	    {
+	      cancel_thread (path, "Non-empty EDGE_NO_COPY_SRC_BLOCK");
+	      e->aux = NULL;
+	      continue;
+	    }
+	}
+
       e2 = path->last ()->e;
       if (!e2 || noloop_only)
 	{