void fps_intersperse(unsigned char *q, unsigned char *p, unsigned long n,
                     unsigned char c) {
  while (n > 1) {
    *q++ = *p++;
    *q++ = c;
    n--;
  }
  if (n == 1)
    *q = *p;
}


x86 assembly (clang, -O0):
<fps_intersperse>:
push   %rbp
mov    %rsp,%rbp
mov    %cl,%al
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %rdx,-0x18(%rbp)
mov    %al,-0x19(%rbp)
cmpq   $0x1,-0x18(%rbp)
jbe    1167 <fps_intersperse+0x67>
mov    -0x10(%rbp),%rax
mov    %rax,%rcx
add    $0x1,%rcx
mov    %rcx,-0x10(%rbp)
mov    (%rax),%cl
mov    -0x8(%rbp),%rax
mov    %rax,%rdx
add    $0x1,%rdx
mov    %rdx,-0x8(%rbp)
mov    %cl,(%rax)
mov    -0x19(%rbp),%cl
mov    -0x8(%rbp),%rax
mov    %rax,%rdx
add    $0x1,%rdx
mov    %rdx,-0x8(%rbp)
mov    %cl,(%rax)
mov    -0x18(%rbp),%rax
add    $0xffffffffffffffff,%rax
mov    %rax,-0x18(%rbp)
jmp    1115 <fps_intersperse+0x15>
cmpq   $0x1,-0x18(%rbp)
jne    117e <fps_intersperse+0x7e>
mov    -0x10(%rbp),%rax
mov    (%rax),%cl
mov    -0x8(%rbp),%rax
mov    %cl,(%rax)
pop    %rbp
ret

x86 assembly (clang, -O2):
<fps_intersperse>:
cmp    $0x2,%rdx
jb     121c <fps_intersperse+0x11c>
lea    -0x1(%rdx),%r9
cmp    $0x10,%r9
jb     1200 <fps_intersperse+0x100>
lea    (%rdx,%rsi,1),%rax
add    $0xffffffffffffffff,%rax
cmp    %rdi,%rax
jbe    1136 <fps_intersperse+0x36>
lea    (%rdi,%rdx,2),%rax
add    $0xfffffffffffffffe,%rax
cmp    %rsi,%rax
ja     1200 <fps_intersperse+0x100>
mov    %r9,%r8
and    $0xfffffffffffffff0,%r8
movzbl %cl,%eax
movd   %eax,%xmm0
punpcklbw %xmm0,%xmm0
pshuflw $0x0,%xmm0,%xmm0
lea    -0x10(%r8),%rax
mov    %rax,%r10
shr    $0x4,%r10
add    $0x1,%r10
test   %rax,%rax
je     1227 <fps_intersperse+0x127>
mov    %r10,%r11
and    $0xfffffffffffffffe,%r11
xor    %eax,%eax
xchg   %ax,%ax
movq   (%rsi,%rax,1),%xmm1
movq   0x8(%rsi,%rax,1),%xmm2
punpcklbw %xmm0,%xmm1
movdqu %xmm1,(%rdi,%rax,2)
punpcklbw %xmm0,%xmm2
movdqu %xmm2,0x10(%rdi,%rax,2)
movq   0x10(%rsi,%rax,1),%xmm1
movq   0x18(%rsi,%rax,1),%xmm2
punpcklbw %xmm0,%xmm1
movdqu %xmm1,0x20(%rdi,%rax,2)
punpcklbw %xmm0,%xmm2
movdqu %xmm2,0x30(%rdi,%rax,2)
add    $0x20,%rax
add    $0xfffffffffffffffe,%r11
jne    1170 <fps_intersperse+0x70>
test   $0x1,%r10b
je     11e4 <fps_intersperse+0xe4>
lea    (%rax,%rax,1),%r10
or     $0x10,%r10
movq   (%rsi,%rax,1),%xmm1
movq   0x8(%rsi,%rax,1),%xmm2
punpcklbw %xmm0,%xmm1
movdqu %xmm1,(%rdi,%rax,2)
punpcklbw %xmm0,%xmm2
movdqu %xmm2,(%rdi,%r10,1)
lea    (%rdi,%r8,2),%rdi
add    %r8,%rsi
cmp    %r8,%r9
je     1222 <fps_intersperse+0x122>
sub    %r8,%rdx
cs nopw 0x0(%rax,%rax,1)
nopl   (%rax)
movzbl (%rsi),%eax
add    $0x1,%rsi
mov    %al,(%rdi)
mov    %cl,0x1(%rdi)
add    $0x2,%rdi
add    $0xffffffffffffffff,%rdx
cmp    $0x1,%rdx
ja     1200 <fps_intersperse+0x100>
jmp    1222 <fps_intersperse+0x122>
cmp    $0x1,%rdx
jne    1226 <fps_intersperse+0x126>
mov    (%rsi),%al
mov    %al,(%rdi)
ret
xor    %eax,%eax
test   $0x1,%r10b
jne    11be <fps_intersperse+0xbe>
jmp    11e4 <fps_intersperse+0xe4>

LLVM IR (-O0):
define void @fps_intersperse(i8* %0, i8* %1, i64 %2, i8 zeroext %3) {
%5 = alloca i8*
%6 = alloca i8*
%7 = alloca i64
%8 = alloca i8
store i8* %0, i8** %5
store i8* %1, i8** %6
store i64 %2, i64* %7
store i8 %3, i8* %8
br label %9
9: ; preds = %12, %4
%10 = load i64, i64* %7
%11 = icmp ugt i64 %10, 1
br i1 %11, label %12, label %23
12: ; preds = %9
%13 = load i8*, i8** %6
%14 = getelementptr inbounds i8, i8* %13, i32 1
store i8* %14, i8** %6
%15 = load i8, i8* %13
%16 = load i8*, i8** %5
%17 = getelementptr inbounds i8, i8* %16, i32 1
store i8* %17, i8** %5
store i8 %15, i8* %16
%18 = load i8, i8* %8
%19 = load i8*, i8** %5
%20 = getelementptr inbounds i8, i8* %19, i32 1
store i8* %20, i8** %5
store i8 %18, i8* %19
%21 = load i64, i64* %7
%22 = add i64 %21, -1
store i64 %22, i64* %7
br label %9
23: ; preds = %9
%24 = load i64, i64* %7
%25 = icmp eq i64 %24, 1
br i1 %25, label %26, label %30
26: ; preds = %23
%27 = load i8*, i8** %6
%28 = load i8, i8* %27
%29 = load i8*, i8** %5
store i8 %28, i8* %29
br label %30
30: ; preds = %26, %23
ret void
}

LLVM IR (-O2):
define void @fps_intersperse(i8* nocapture writeonly %0, i8* nocapture %1, i64 %2, i8 zeroext %3) {
%5 = icmp ugt i64 %2, 1
br i1 %5, label %6, label %107
6: ; preds = %4
%7 = add i64 %2, -1
%8 = icmp ult i64 %7, 16
br i1 %8, label %93, label %9
9: ; preds = %6
%10 = shl i64 %2, 1
%11 = add i64 %10, -2
%12 = getelementptr i8, i8* %0, i64 %11
%13 = add i64 %2, -1
%14 = getelementptr i8, i8* %1, i64 %13
%15 = icmp ugt i8* %14, %0
%16 = icmp ugt i8* %12, %1
%17 = and i1 %15, %16
br i1 %17, label %93, label %18
18: ; preds = %9
%19 = and i64 %7, -16
%20 = shl i64 %19, 1
%21 = getelementptr i8, i8* %0, i64 %20
%22 = sub i64 %2, %19
%23 = getelementptr i8, i8* %1, i64 %19
%24 = insertelement <8 x i8> poison, i8 %3, i64 0
%25 = shufflevector <8 x i8> %24, <8 x i8> poison, <8 x i32> zeroinitializer
%26 = insertelement <8 x i8> poison, i8 %3, i64 0
%27 = shufflevector <8 x i8> %26, <8 x i8> poison, <8 x i32> zeroinitializer
%28 = add i64 %19, -16
%29 = lshr exact i64 %28, 4
%30 = add nuw nsw i64 %29, 1
%31 = and i64 %30, 1
%32 = icmp eq i64 %28, 0
br i1 %32, label %72, label %33
33: ; preds = %18
%34 = and i64 %30, 2305843009213693950
br label %35
35: ; preds = %35, %33
%36 = phi i64 [ 0, %33 ], [ %69, %35 ]
%37 = phi i64 [ 0, %33 ], [ %70, %35 ]
%38 = shl i64 %36, 1
%39 = shl i64 %36, 1
%40 = or i64 %39, 16
%41 = getelementptr i8, i8* %1, i64 %36
%42 = bitcast i8* %41 to <8 x i8>*
%43 = load <8 x i8>, <8 x i8>* %42
%44 = getelementptr i8, i8* %41, i64 8
%45 = bitcast i8* %44 to <8 x i8>*
%46 = load <8 x i8>, <8 x i8>* %45
%47 = getelementptr inbounds i8, i8* %0, i64 %38
%48 = bitcast i8* %47 to <16 x i8>*
%49 = getelementptr inbounds i8, i8* %0, i64 %40
%50 = bitcast i8* %49 to <16 x i8>*
%51 = shufflevector <8 x i8> %43, <8 x i8> %25, <16 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11, i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
store <16 x i8> %51, <16 x i8>* %48
%52 = shufflevector <8 x i8> %46, <8 x i8> %27, <16 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11, i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
store <16 x i8> %52, <16 x i8>* %50
%53 = or i64 %36, 16
%54 = shl i64 %53, 1
%55 = shl i64 %53, 1
%56 = or i64 %55, 16
%57 = getelementptr i8, i8* %1, i64 %53
%58 = bitcast i8* %57 to <8 x i8>*
%59 = load <8 x i8>, <8 x i8>* %58
%60 = getelementptr i8, i8* %57, i64 8
%61 = bitcast i8* %60 to <8 x i8>*
%62 = load <8 x i8>, <8 x i8>* %61
%63 = getelementptr inbounds i8, i8* %0, i64 %54
%64 = bitcast i8* %63 to <16 x i8>*
%65 = getelementptr inbounds i8, i8* %0, i64 %56
%66 = bitcast i8* %65 to <16 x i8>*
%67 = shufflevector <8 x i8> %59, <8 x i8> %25, <16 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11, i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
store <16 x i8> %67, <16 x i8>* %64
%68 = shufflevector <8 x i8> %62, <8 x i8> %27, <16 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11, i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
store <16 x i8> %68, <16 x i8>* %66
%69 = add nuw i64 %36, 32
%70 = add i64 %37, 2
%71 = icmp eq i64 %70, %34
br i1 %71, label %72, label %35
72: ; preds = %35, %18
%73 = phi i64 [ 0, %18 ], [ %69, %35 ]
%74 = icmp eq i64 %31, 0
br i1 %74, label %91, label %75
75: ; preds = %72
%76 = shl i64 %73, 1
%77 = shl i64 %73, 1
%78 = or i64 %77, 16
%79 = getelementptr i8, i8* %1, i64 %73
%80 = bitcast i8* %79 to <8 x i8>*
%81 = load <8 x i8>, <8 x i8>* %80
%82 = getelementptr i8, i8* %79, i64 8
%83 = bitcast i8* %82 to <8 x i8>*
%84 = load <8 x i8>, <8 x i8>* %83
%85 = getelementptr inbounds i8, i8* %0, i64 %76
%86 = bitcast i8* %85 to <16 x i8>*
%87 = getelementptr inbounds i8, i8* %0, i64 %78
%88 = bitcast i8* %87 to <16 x i8>*
%89 = shufflevector <8 x i8> %81, <8 x i8> %25, <16 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11, i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
store <16 x i8> %89, <16 x i8>* %86
%90 = shufflevector <8 x i8> %84, <8 x i8> %27, <16 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11, i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
store <16 x i8> %90, <16 x i8>* %88
br label %91
91: ; preds = %72, %75
%92 = icmp eq i64 %7, %19
br i1 %92, label %109, label %93
93: ; preds = %9, %6, %91
%94 = phi i8* [ %0, %9 ], [ %0, %6 ], [ %21, %91 ]
%95 = phi i64 [ %2, %9 ], [ %2, %6 ], [ %22, %91 ]
%96 = phi i8* [ %1, %9 ], [ %1, %6 ], [ %23, %91 ]
br label %97
97: ; preds = %93, %97
%98 = phi i8* [ %104, %97 ], [ %94, %93 ]
%99 = phi i64 [ %105, %97 ], [ %95, %93 ]
%100 = phi i8* [ %101, %97 ], [ %96, %93 ]
%101 = getelementptr inbounds i8, i8* %100, i64 1
%102 = load i8, i8* %100
%103 = getelementptr inbounds i8, i8* %98, i64 1
store i8 %102, i8* %98
%104 = getelementptr inbounds i8, i8* %98, i64 2
store i8 %3, i8* %103
%105 = add i64 %99, -1
%106 = icmp ugt i64 %105, 1
br i1 %106, label %97, label %109
107: ; preds = %4
%108 = icmp eq i64 %2, 1
br i1 %108, label %109, label %113
109: ; preds = %97, %91, %107
%110 = phi i8* [ %0, %107 ], [ %21, %91 ], [ %104, %97 ]
%111 = phi i8* [ %1, %107 ], [ %23, %91 ], [ %101, %97 ]
%112 = load i8, i8* %111
store i8 %112, i8* %110
br label %113
113: ; preds = %109, %107
ret void
}