diff --git a/gcc/rtl-ssa/accesses.cc b/gcc/rtl-ssa/accesses.cc
index 3f1304fc5bf..5cc05cb4be7 100644
--- a/gcc/rtl-ssa/accesses.cc
+++ b/gcc/rtl-ssa/accesses.cc
@@ -792,11 +792,11 @@ function_info::merge_clobber_groups (clobber_info *clobber1,
 }
 
 // GROUP spans INSN, and INSN now sets the resource that GROUP clobbers.
-// Split GROUP around INSN and return the clobber that comes immediately
-// before INSN.
+// Split GROUP around INSN, to form two new groups, and return the clobber
+// that comes immediately before INSN.
 //
 // The resource that GROUP clobbers is known to have an associated
-// splay tree.
+// splay tree.  The caller must remove GROUP from the tree on return.
 clobber_info *
 function_info::split_clobber_group (clobber_group *group, insn_info *insn)
 {
@@ -827,27 +827,20 @@ function_info::split_clobber_group (clobber_group *group, insn_info *insn)
       prev = as_a<clobber_info *> (next->prev_def ());
     }
 
-  // Use GROUP to hold PREV and earlier clobbers.  Create a new group for
-  // NEXT onwards.
+  // Create a new group for each side of the split.  We need to invalidate
+  // the old group so that clobber_info::group can tell whether a lazy
+  // update is needed.
+  clobber_info *first_clobber = group->first_clobber ();
   clobber_info *last_clobber = group->last_clobber ();
-  clobber_group *group1 = group;
-  clobber_group *group2 = allocate<clobber_group> (next);
-
-  // Finish setting up GROUP1, making sure that the roots and extremities
-  // have a correct group pointer.  Leave the rest to be updated lazily.
-  group1->set_last_clobber (prev);
-  tree1->set_group (group1);
-  prev->set_group (group1);
-
-  // Finish setting up GROUP2, with the same approach as for GROUP1.
-  group2->set_first_clobber (next);
-  group2->set_last_clobber (last_clobber);
-  next->set_group (group2);
-  tree2->set_group (group2);
-  last_clobber->set_group (group2);
+  auto *group1 = allocate<clobber_group> (first_clobber, prev, tree1.root ());
+  auto *group2 = allocate<clobber_group> (next, last_clobber, tree2.root ());
 
   // Insert GROUP2 into the splay tree as an immediate successor of GROUP1.
-  def_splay_tree::insert_child (group1, 1, group2);
+  def_splay_tree::insert_child (group, 1, group2);
+  def_splay_tree::insert_child (group, 1, group1);
+
+  // Invalidate the old group.
+  group->set_last_clobber (nullptr);
 
   return prev;
 }
@@ -952,6 +945,8 @@ function_info::add_def (def_info *def)
 	    }
 	  prev = split_clobber_group (group, insn);
 	  next = prev->next_def ();
+	  tree.remove_root ();
+	  last->set_splay_root (tree.root ());
 	}
       // COMPARISON is < 0 if DEF comes before ROOT or > 0 if DEF comes
       // after ROOT.
diff --git a/gcc/rtl-ssa/accesses.h b/gcc/rtl-ssa/accesses.h
index 7d2916d00c2..27810a02063 100644
--- a/gcc/rtl-ssa/accesses.h
+++ b/gcc/rtl-ssa/accesses.h
@@ -937,7 +937,8 @@ public:
   void print (pretty_printer *pp) const;
 
 private:
-  clobber_group (clobber_info *clobber);
+  clobber_group (clobber_info *);
+  clobber_group (clobber_info *, clobber_info *, clobber_info *);
 
   // Set the values of first_clobber () and last_clobber ().
   void set_first_clobber (clobber_info *c) { m_clobber_or_set = c; }
diff --git a/gcc/rtl-ssa/internals.inl b/gcc/rtl-ssa/internals.inl
index c736877479e..9bc40bf35c5 100644
--- a/gcc/rtl-ssa/internals.inl
+++ b/gcc/rtl-ssa/internals.inl
@@ -380,6 +380,20 @@ inline clobber_group::clobber_group (clobber_info *clobber)
   clobber->m_group = this;
 }
 
+// Construct a new group of clobber_infos that spans [FIRST_CLOBBER,
+// LAST_CLOBBER].  Set the root of the splay tree to CLOBBER_TREE.
+inline clobber_group::clobber_group (clobber_info *first_clobber,
+				     clobber_info *last_clobber,
+				     clobber_info *clobber_tree)
+  : def_node (first_clobber),
+    m_last_clobber (last_clobber),
+    m_clobber_tree (clobber_tree)
+{
+  first_clobber->m_group = this;
+  last_clobber->m_group = this;
+  clobber_tree->m_group = this;
+}
+
 // Construct a node for the instruction with uid UID.
 inline insn_info::order_node::order_node (int uid)
   : insn_note (kind),
diff --git a/gcc/testsuite/gcc.dg/torture/pr115928.c b/gcc/testsuite/gcc.dg/torture/pr115928.c
new file mode 100644
index 00000000000..4379fa968ad
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr115928.c
@@ -0,0 +1,23 @@
+/* { dg-additional-options "-fgcse-sm" } */
+
+int a[1], b, c;
+struct {
+  int d;
+  int e;
+  int : 8;
+} f[1];
+static int g;
+char h, i, j;
+void k(int l) { b = 5 ^ a[b ^ (l & 5)]; }
+void m(long l) { k(c >> 6); }
+int main() {
+  g++;
+  if (b) {
+    h = 5 && j;
+    if (h)
+      h -= i;
+    m(f[g].d);
+    m(f[g].e);
+  }
+  return 0;
+}
