unsigned unsigned_stats(unsigned *minout, unsigned *median, unsigned *maxout,
                        const unsigned char *data, const unsigned char *prev,
                        unsigned len) {
  unsigned char max = data[0] - prev[0], min = max;
  unsigned i;
  for (i = 1; i < len; ++i) {
    unsigned char ch = data[i] - prev[i];
    if (ch > max)
      max = ch;
    else if (ch < min)
      min = ch;
  }
  *minout = min;
  *median = (((unsigned int)max) + ((unsigned int)min)) / 2;
  *maxout = max;
  return ((unsigned int)max) - ((unsigned int)min) + 1;
}


x86 assembly (clang, -O0):
<unsigned_stats>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %rdx,-0x18(%rbp)
mov    %rcx,-0x20(%rbp)
mov    %r8,-0x28(%rbp)
mov    %r9d,-0x2c(%rbp)
mov    -0x20(%rbp),%rax
movzbl (%rax),%eax
mov    -0x28(%rbp),%rcx
movzbl (%rcx),%ecx
sub    %ecx,%eax
mov    %al,-0x2d(%rbp)
mov    -0x2d(%rbp),%al
mov    %al,-0x2e(%rbp)
movl   $0x1,-0x34(%rbp)
mov    -0x34(%rbp),%eax
cmp    -0x2c(%rbp),%eax
jae    11ac <unsigned_stats+0xac>
mov    -0x20(%rbp),%rax
mov    -0x34(%rbp),%ecx
movzbl (%rax,%rcx,1),%eax
mov    -0x28(%rbp),%rcx
mov    -0x34(%rbp),%edx
movzbl (%rcx,%rdx,1),%ecx
sub    %ecx,%eax
mov    %al,-0x35(%rbp)
movzbl -0x35(%rbp),%eax
movzbl -0x2d(%rbp),%ecx
cmp    %ecx,%eax
jle    117e <unsigned_stats+0x7e>
mov    -0x35(%rbp),%al
mov    %al,-0x2d(%rbp)
jmp    1199 <unsigned_stats+0x99>
movzbl -0x35(%rbp),%eax
movzbl -0x2e(%rbp),%ecx
cmp    %ecx,%eax
jge    1194 <unsigned_stats+0x94>
mov    -0x35(%rbp),%al
mov    %al,-0x2e(%rbp)
jmp    1199 <unsigned_stats+0x99>
jmp    119e <unsigned_stats+0x9e>
mov    -0x34(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x34(%rbp)
jmp    113c <unsigned_stats+0x3c>
movzbl -0x2e(%rbp),%ecx
mov    -0x8(%rbp),%rax
mov    %ecx,(%rax)
movzbl -0x2d(%rbp),%ecx
movzbl -0x2e(%rbp),%eax
add    %eax,%ecx
shr    $0x1,%ecx
mov    -0x10(%rbp),%rax
mov    %ecx,(%rax)
movzbl -0x2d(%rbp),%ecx
mov    -0x18(%rbp),%rax
mov    %ecx,(%rax)
movzbl -0x2d(%rbp),%eax
movzbl -0x2e(%rbp),%ecx
sub    %ecx,%eax
add    $0x1,%eax
pop    %rbp
ret

x86 assembly (clang, -O2):
<unsigned_stats>:
push   %rbp
push   %r14
push   %rbx
mov    (%rcx),%r11b
sub    (%r8),%r11b
cmp    $0x2,%r9d
jb     1128 <unsigned_stats+0x28>
mov    %r9d,%r10d
add    $0xffffffffffffffff,%r10
cmp    $0x2,%r9d
jne    1130 <unsigned_stats+0x30>
mov    $0x1,%r9d
mov    %r11d,%eax
jmp    11a6 <unsigned_stats+0xa6>
mov    %r11d,%eax
jmp    11cf <unsigned_stats+0xcf>
mov    %r10,%r14
and    $0xfffffffffffffffe,%r14
neg    %r14
mov    $0x1,%r9d
mov    %r11d,%eax
cs nopw 0x0(%rax,%rax,1)
nopl   (%rax)
movzbl (%rcx,%r9,1),%ebx
sub    (%r8,%r9,1),%bl
cmp    %al,%bl
movzbl %al,%eax
movzbl %bl,%ebx
mov    %eax,%ebp
cmovb  %ebx,%ebp
cmp    %r11b,%bl
cmova  %eax,%ebp
movzbl %r11b,%r11d
cmova  %ebx,%r11d
movzbl 0x1(%rcx,%r9,1),%eax
sub    0x1(%r8,%r9,1),%al
cmp    %bpl,%al
movzbl %al,%ebx
mov    %ebp,%eax
cmovb  %ebx,%eax
cmp    %r11b,%bl
cmova  %ebp,%eax
cmova  %ebx,%r11d
lea    (%r14,%r9,1),%rbx
add    $0x2,%rbx
add    $0x2,%r9
cmp    $0x1,%rbx
jne    1150 <unsigned_stats+0x50>
test   $0x1,%r10b
je     11cf <unsigned_stats+0xcf>
mov    (%rcx,%r9,1),%cl
sub    (%r8,%r9,1),%cl
cmp    %al,%cl
movzbl %al,%ebp
movzbl %cl,%ecx
mov    %ebp,%eax
cmovb  %ecx,%eax
cmp    %r11b,%cl
cmova  %ebp,%eax
movzbl %r11b,%r11d
cmova  %ecx,%r11d
movzbl %al,%ecx
mov    %ecx,(%rdi)
movzbl %r11b,%eax
lea    (%rax,%rcx,1),%edi
shr    %edi
mov    %edi,(%rsi)
mov    %eax,(%rdx)
sub    %ecx,%eax
add    $0x1,%eax
pop    %rbx
pop    %r14
pop    %rbp
ret

LLVM IR (-O0):
define i32 @unsigned_stats(i32* %0, i32* %1, i32* %2, i8* %3, i8* %4, i32 %5) {
%7 = alloca i32*
%8 = alloca i32*
%9 = alloca i32*
%10 = alloca i8*
%11 = alloca i8*
%12 = alloca i32
%13 = alloca i8
%14 = alloca i8
%15 = alloca i32
%16 = alloca i8
store i32* %0, i32** %7
store i32* %1, i32** %8
store i32* %2, i32** %9
store i8* %3, i8** %10
store i8* %4, i8** %11
store i32 %5, i32* %12
%17 = load i8*, i8** %10
%18 = getelementptr inbounds i8, i8* %17, i64 0
%19 = load i8, i8* %18
%20 = zext i8 %19 to i32
%21 = load i8*, i8** %11
%22 = getelementptr inbounds i8, i8* %21, i64 0
%23 = load i8, i8* %22
%24 = zext i8 %23 to i32
%25 = sub nsw i32 %20, %24
%26 = trunc i32 %25 to i8
store i8 %26, i8* %13
%27 = load i8, i8* %13
store i8 %27, i8* %14
store i32 1, i32* %15
br label %28
28: ; preds = %64, %6
%29 = load i32, i32* %15
%30 = load i32, i32* %12
%31 = icmp ult i32 %29, %30
br i1 %31, label %32, label %67
32: ; preds = %28
%33 = load i8*, i8** %10
%34 = load i32, i32* %15
%35 = zext i32 %34 to i64
%36 = getelementptr inbounds i8, i8* %33, i64 %35
%37 = load i8, i8* %36
%38 = zext i8 %37 to i32
%39 = load i8*, i8** %11
%40 = load i32, i32* %15
%41 = zext i32 %40 to i64
%42 = getelementptr inbounds i8, i8* %39, i64 %41
%43 = load i8, i8* %42
%44 = zext i8 %43 to i32
%45 = sub nsw i32 %38, %44
%46 = trunc i32 %45 to i8
store i8 %46, i8* %16
%47 = load i8, i8* %16
%48 = zext i8 %47 to i32
%49 = load i8, i8* %13
%50 = zext i8 %49 to i32
%51 = icmp sgt i32 %48, %50
br i1 %51, label %52, label %54
52: ; preds = %32
%53 = load i8, i8* %16
store i8 %53, i8* %13
br label %63
54: ; preds = %32
%55 = load i8, i8* %16
%56 = zext i8 %55 to i32
%57 = load i8, i8* %14
%58 = zext i8 %57 to i32
%59 = icmp slt i32 %56, %58
br i1 %59, label %60, label %62
60: ; preds = %54
%61 = load i8, i8* %16
store i8 %61, i8* %14
br label %62
62: ; preds = %60, %54
br label %63
63: ; preds = %62, %52
br label %64
64: ; preds = %63
%65 = load i32, i32* %15
%66 = add i32 %65, 1
store i32 %66, i32* %15
br label %28
67: ; preds = %28
%68 = load i8, i8* %14
%69 = zext i8 %68 to i32
%70 = load i32*, i32** %7
store i32 %69, i32* %70
%71 = load i8, i8* %13
%72 = zext i8 %71 to i32
%73 = load i8, i8* %14
%74 = zext i8 %73 to i32
%75 = add i32 %72, %74
%76 = udiv i32 %75, 2
%77 = load i32*, i32** %8
store i32 %76, i32* %77
%78 = load i8, i8* %13
%79 = zext i8 %78 to i32
%80 = load i32*, i32** %9
store i32 %79, i32* %80
%81 = load i8, i8* %13
%82 = zext i8 %81 to i32
%83 = load i8, i8* %14
%84 = zext i8 %83 to i32
%85 = sub i32 %82, %84
%86 = add i32 %85, 1
ret i32 %86
}

LLVM IR (-O2):
define i32 @unsigned_stats(i32* nocapture writeonly %0, i32* nocapture writeonly %1, i32* nocapture writeonly %2, i8* nocapture %3, i8* nocapture %4, i32 %5) {
%7 = load i8, i8* %3
%8 = load i8, i8* %4
%9 = sub i8 %7, %8
%10 = icmp ugt i32 %5, 1
br i1 %10, label %11, label %65
11: ; preds = %6
%12 = zext i32 %5 to i64
%13 = add nsw i64 %12, -1
%14 = and i64 %13, 1
%15 = icmp eq i32 %5, 2
br i1 %15, label %47, label %16
16: ; preds = %11
%17 = and i64 %13, -2
br label %18
18: ; preds = %18, %16
%19 = phi i64 [ 1, %16 ], [ %44, %18 ]
%20 = phi i8 [ %9, %16 ], [ %43, %18 ]
%21 = phi i8 [ %9, %16 ], [ %42, %18 ]
%22 = phi i64 [ 0, %16 ], [ %45, %18 ]
%23 = getelementptr inbounds i8, i8* %3, i64 %19
%24 = load i8, i8* %23
%25 = getelementptr inbounds i8, i8* %4, i64 %19
%26 = load i8, i8* %25
%27 = sub i8 %24, %26
%28 = icmp ugt i8 %27, %20
%29 = icmp ult i8 %27, %21
%30 = select i1 %29, i8 %27, i8 %21
%31 = select i1 %28, i8 %21, i8 %30
%32 = select i1 %28, i8 %27, i8 %20
%33 = add nuw nsw i64 %19, 1
%34 = getelementptr inbounds i8, i8* %3, i64 %33
%35 = load i8, i8* %34
%36 = getelementptr inbounds i8, i8* %4, i64 %33
%37 = load i8, i8* %36
%38 = sub i8 %35, %37
%39 = icmp ugt i8 %38, %32
%40 = icmp ult i8 %38, %31
%41 = select i1 %40, i8 %38, i8 %31
%42 = select i1 %39, i8 %31, i8 %41
%43 = select i1 %39, i8 %38, i8 %32
%44 = add nuw nsw i64 %19, 2
%45 = add i64 %22, 2
%46 = icmp eq i64 %45, %17
br i1 %46, label %47, label %18
47: ; preds = %18, %11
%48 = phi i8 [ undef, %11 ], [ %42, %18 ]
%49 = phi i8 [ undef, %11 ], [ %43, %18 ]
%50 = phi i64 [ 1, %11 ], [ %44, %18 ]
%51 = phi i8 [ %9, %11 ], [ %43, %18 ]
%52 = phi i8 [ %9, %11 ], [ %42, %18 ]
%53 = icmp eq i64 %14, 0
br i1 %53, label %65, label %54
54: ; preds = %47
%55 = getelementptr inbounds i8, i8* %3, i64 %50
%56 = load i8, i8* %55
%57 = getelementptr inbounds i8, i8* %4, i64 %50
%58 = load i8, i8* %57
%59 = sub i8 %56, %58
%60 = icmp ugt i8 %59, %51
%61 = icmp ult i8 %59, %52
%62 = select i1 %61, i8 %59, i8 %52
%63 = select i1 %60, i8 %52, i8 %62
%64 = select i1 %60, i8 %59, i8 %51
br label %65
65: ; preds = %54, %47, %6
%66 = phi i8 [ %9, %6 ], [ %48, %47 ], [ %63, %54 ]
%67 = phi i8 [ %9, %6 ], [ %49, %47 ], [ %64, %54 ]
%68 = zext i8 %66 to i32
store i32 %68, i32* %0
%69 = zext i8 %67 to i32
%70 = add nuw nsw i32 %69, %68
%71 = lshr i32 %70, 1
store i32 %71, i32* %1
store i32 %69, i32* %2
%72 = sub nsw i32 1, %68
%73 = add nsw i32 %72, %69
ret i32 %73
}