Reduce duplication
diff --git a/include/grpc/slice.h b/include/grpc/slice.h
index 4dce6da..fe6379c 100644
--- a/include/grpc/slice.h
+++ b/include/grpc/slice.h
@@ -124,8 +124,11 @@
    Requires s intialized, split <= s.length */
 GPRAPI grpc_slice grpc_slice_split_tail(grpc_slice *s, size_t split);
 
-/* The same as grpc_slice_split_tail, but without altering refcounts */
-GPRAPI grpc_slice grpc_slice_split_tail_no_ref(grpc_slice *s, size_t split);
+/* The same as grpc_slice_split_tail, but with an option to skip altering
+ * refcounts (grpc_slice_split_tail_maybe_ref(..., true) is equivalent to
+ * grpc_slice_split_tail(...)) */
+GPRAPI grpc_slice grpc_slice_split_tail_maybe_ref(grpc_slice *s, size_t split,
+                                                  bool inc_refs);
 
 /* Splits s into two: modifies s to be s[split:s.length], and returns a new
    slice, sharing a refcount with s, that contains s[0:split].
diff --git a/src/core/lib/slice/slice.c b/src/core/lib/slice/slice.c
index 8896f1d..2852188 100644
--- a/src/core/lib/slice/slice.c
+++ b/src/core/lib/slice/slice.c
@@ -312,7 +312,8 @@
   return subset;
 }
 
-grpc_slice grpc_slice_split_tail(grpc_slice *source, size_t split) {
+grpc_slice grpc_slice_split_tail_maybe_ref(grpc_slice *source, size_t split,
+                                           bool incref) {
   grpc_slice tail;
 
   if (source->refcount == NULL) {
@@ -334,9 +335,13 @@
              tail_length);
     } else {
       /* Build the result */
-      tail.refcount = source->refcount->sub_refcount;
-      /* Bump the refcount */
-      tail.refcount->vtable->ref(tail.refcount);
+      if (incref) {
+        tail.refcount = source->refcount->sub_refcount;
+        /* Bump the refcount */
+        tail.refcount->vtable->ref(tail.refcount);
+      } else {
+        tail.refcount = &noop_refcount;
+      }
       /* Point into the source array */
       tail.data.refcounted.bytes = source->data.refcounted.bytes + split;
       tail.data.refcounted.length = tail_length;
@@ -348,38 +353,8 @@
   return tail;
 }
 
-grpc_slice grpc_slice_split_tail_no_ref(grpc_slice *source, size_t split) {
-  grpc_slice tail;
-
-  if (source->refcount == NULL) {
-    /* inlined data, copy it out */
-    GPR_ASSERT(source->data.inlined.length >= split);
-    tail.refcount = NULL;
-    tail.data.inlined.length = (uint8_t)(source->data.inlined.length - split);
-    memcpy(tail.data.inlined.bytes, source->data.inlined.bytes + split,
-           tail.data.inlined.length);
-    source->data.inlined.length = (uint8_t)split;
-  } else {
-    size_t tail_length = source->data.refcounted.length - split;
-    GPR_ASSERT(source->data.refcounted.length >= split);
-    if (tail_length < sizeof(tail.data.inlined.bytes)) {
-      /* Copy out the bytes - it'll be cheaper than refcounting */
-      tail.refcount = NULL;
-      tail.data.inlined.length = (uint8_t)tail_length;
-      memcpy(tail.data.inlined.bytes, source->data.refcounted.bytes + split,
-             tail_length);
-    } else {
-      /* Build the result */
-      tail.refcount = &noop_refcount;
-      /* Point into the source array */
-      tail.data.refcounted.bytes = source->data.refcounted.bytes + split;
-      tail.data.refcounted.length = tail_length;
-    }
-    source->refcount = source->refcount->sub_refcount;
-    source->data.refcounted.length = split;
-  }
-
-  return tail;
+grpc_slice grpc_slice_split_tail(grpc_slice *source, size_t split) {
+  return grpc_slice_split_tail_maybe_ref(source, split, true);
 }
 
 grpc_slice grpc_slice_split_head(grpc_slice *source, size_t split) {
diff --git a/src/core/lib/slice/slice_buffer.c b/src/core/lib/slice/slice_buffer.c
index a13941e..5a4b434 100644
--- a/src/core/lib/slice/slice_buffer.c
+++ b/src/core/lib/slice/slice_buffer.c
@@ -253,40 +253,9 @@
   src->length = 0;
 }
 
-void grpc_slice_buffer_move_first(grpc_slice_buffer *src, size_t n,
-                                  grpc_slice_buffer *dst) {
-  GPR_ASSERT(src->length >= n);
-  if (src->length == n) {
-    grpc_slice_buffer_move_into(src, dst);
-    return;
-  }
-
-  size_t output_len = dst->length + n;
-  size_t new_input_len = src->length - n;
-
-  while (src->count > 0) {
-    grpc_slice slice = grpc_slice_buffer_take_first(src);
-    size_t slice_len = GRPC_SLICE_LENGTH(slice);
-    if (n > slice_len) {
-      grpc_slice_buffer_add(dst, slice);
-      n -= slice_len;
-    } else if (n == slice_len) {
-      grpc_slice_buffer_add(dst, slice);
-      break;
-    } else { /* n < slice_len */
-      grpc_slice_buffer_undo_take_first(src, grpc_slice_split_tail(&slice, n));
-      GPR_ASSERT(GRPC_SLICE_LENGTH(slice) == n);
-      grpc_slice_buffer_add(dst, slice);
-      break;
-    }
-  }
-  GPR_ASSERT(dst->length == output_len);
-  GPR_ASSERT(src->length == new_input_len);
-  GPR_ASSERT(src->count > 0);
-}
-
-void grpc_slice_buffer_move_first_no_ref(grpc_slice_buffer *src, size_t n,
-                                         grpc_slice_buffer *dst) {
+static void slice_buffer_move_first_maybe_ref(grpc_slice_buffer *src, size_t n,
+                                              grpc_slice_buffer *dst,
+                                              bool incref) {
   GPR_ASSERT(src->length >= n);
   if (src->length == n) {
     grpc_slice_buffer_move_into(src, dst);
@@ -307,7 +276,7 @@
       break;
     } else { /* n < slice_len */
       grpc_slice_buffer_undo_take_first(
-          src, grpc_slice_split_tail_no_ref(&slice, n));
+          src, grpc_slice_split_tail_maybe_ref(&slice, n, incref));
       GPR_ASSERT(GRPC_SLICE_LENGTH(slice) == n);
       grpc_slice_buffer_add(dst, slice);
       break;
@@ -318,6 +287,16 @@
   GPR_ASSERT(src->count > 0);
 }
 
+void grpc_slice_buffer_move_first(grpc_slice_buffer *src, size_t n,
+                                  grpc_slice_buffer *dst) {
+  slice_buffer_move_first_maybe_ref(src, n, dst, true);
+}
+
+void grpc_slice_buffer_move_first_no_ref(grpc_slice_buffer *src, size_t n,
+                                         grpc_slice_buffer *dst) {
+  slice_buffer_move_first_maybe_ref(src, n, dst, false);
+}
+
 void grpc_slice_buffer_move_first_into_buffer(grpc_exec_ctx *exec_ctx,
                                               grpc_slice_buffer *src, size_t n,
                                               void *dst) {