int unrle(unsigned char *output, const unsigned char *input) {
  signed char count;
  unsigned char *out;
  unsigned char value;
  out = output;
  for (;;) {
    count = (signed char)*input++;
    if (count > 0) {
      value = *input++;
      while (count--)
        *out++ = value;
    } else if (count < 0) {
      while (count++)
        *out++ = *input++;
    } else
      break;
  }
  return (out - output);
}


x86 assembly (clang, -O0):
<unrle>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    -0x8(%rbp),%rax
mov    %rax,-0x20(%rbp)
mov    -0x10(%rbp),%rax
mov    %rax,%rcx
add    $0x1,%rcx
mov    %rcx,-0x10(%rbp)
mov    (%rax),%al
mov    %al,-0x11(%rbp)
movsbl -0x11(%rbp),%eax
cmp    $0x0,%eax
jle    117a <unrle+0x7a>
mov    -0x10(%rbp),%rax
mov    %rax,%rcx
add    $0x1,%rcx
mov    %rcx,-0x10(%rbp)
mov    (%rax),%al
mov    %al,-0x21(%rbp)
mov    -0x11(%rbp),%al
mov    %al,%cl
add    $0xff,%cl
mov    %cl,-0x11(%rbp)
cmp    $0x0,%al
je     1175 <unrle+0x75>
mov    -0x21(%rbp),%cl
mov    -0x20(%rbp),%rax
mov    %rax,%rdx
add    $0x1,%rdx
mov    %rdx,-0x20(%rbp)
mov    %cl,(%rax)
jmp    1149 <unrle+0x49>
jmp    11d5 <unrle+0xd5>
movsbl -0x11(%rbp),%eax
cmp    $0x0,%eax
jge    11cb <unrle+0xcb>
jmp    118c <unrle+0x8c>
mov    -0x11(%rbp),%al
mov    %al,%cl
add    $0x1,%cl
mov    %cl,-0x11(%rbp)
cmp    $0x0,%al
je     11c6 <unrle+0xc6>
mov    -0x10(%rbp),%rax
mov    %rax,%rcx
add    $0x1,%rcx
mov    %rcx,-0x10(%rbp)
mov    (%rax),%cl
mov    -0x20(%rbp),%rax
mov    %rax,%rdx
add    $0x1,%rdx
mov    %rdx,-0x20(%rbp)
mov    %cl,(%rax)
jmp    118c <unrle+0x8c>
jmp    11d0 <unrle+0xd0>
jmp    11da <unrle+0xda>
jmp    11d5 <unrle+0xd5>
jmp    1114 <unrle+0x14>
mov    -0x20(%rbp),%rax
mov    -0x8(%rbp),%rcx
sub    %rcx,%rax
pop    %rbp
ret

x86 assembly (clang, -O2):
<unrle>:
push   %rbp
push   %r15
push   %r14
push   %rbx
push   %rax
mov    %rsi,%r15
mov    %rdi,%r14
mov    %rdi,%rbx
jmp    1154 <unrle+0x44>
cs nopw 0x0(%rax,%rax,1)
nopl   0x0(%rax)
movzbl %bpl,%edx
movzbl 0x1(%r15),%esi
mov    %rbx,%rdi
call   1030 <memset@plt>
add    $0xff,%bpl
movzbl %bpl,%eax
add    $0x2,%r15
add    %rax,%rbx
add    $0x1,%rbx
lea    0x1(%r15),%rax
mov    (%r15),%bpl
test   %bpl,%bpl
jg     1130 <unrle+0x20>
jns    129b <unrle+0x18b>
cmp    $0xe0,%bpl
ja     1210 <unrle+0x100>
mov    %ebp,%ecx
not    %cl
movzbl %cl,%ecx
lea    (%r15,%rcx,1),%rdx
add    $0x2,%rdx
cmp    %rdx,%rbx
jae    1191 <unrle+0x81>
lea    (%rbx,%rcx,1),%rdx
add    $0x1,%rdx
cmp    %rdx,%rax
jb     1210 <unrle+0x100>
add    $0x1,%rcx
mov    %ecx,%edx
and    $0xffffffe0,%edx
movups 0x1(%r15),%xmm0
movups 0x11(%r15),%xmm1
movups %xmm0,(%rbx)
movups %xmm1,0x10(%rbx)
cmp    $0x20,%rdx
je     11f1 <unrle+0xe1>
movups 0x21(%r15),%xmm0
movups 0x31(%r15),%xmm1
movups %xmm0,0x20(%rbx)
movups %xmm1,0x30(%rbx)
cmp    $0x40,%edx
je     11f1 <unrle+0xe1>
movups 0x41(%r15),%xmm0
movups 0x51(%r15),%xmm1
movups %xmm0,0x40(%rbx)
movups %xmm1,0x50(%rbx)
cmp    $0x60,%edx
je     11f1 <unrle+0xe1>
movups 0x61(%r15),%xmm0
movups 0x71(%r15),%xmm1
movups %xmm0,0x60(%rbx)
movups %xmm1,0x70(%rbx)
add    %rdx,%rax
add    %rdx,%rbx
mov    %rax,%r15
cmp    %rdx,%rcx
je     1154 <unrle+0x44>
add    %dl,%bpl
cs nopw 0x0(%rax,%rax,1)
mov    %ebp,%ecx
neg    %cl
and    $0x7,%cl
je     123e <unrle+0x12e>
neg    %cl
movzbl %cl,%esi
xor    %edx,%edx
movzbl (%rax),%ecx
add    $0x1,%rax
mov    %cl,(%rbx)
add    $0x1,%rbx
add    $0xffffffffffffffff,%rdx
cmp    %dl,%sil
jne    1220 <unrle+0x110>
movzbl %bpl,%ecx
sub    %edx,%ecx
jmp    1240 <unrle+0x130>
mov    %ebp,%ecx
mov    %rax,%r15
cmp    $0xf8,%bpl
ja     1154 <unrle+0x44>
nopl   (%rax)
movzbl (%rax),%edx
mov    %dl,(%rbx)
movzbl 0x1(%rax),%edx
mov    %dl,0x1(%rbx)
movzbl 0x2(%rax),%edx
mov    %dl,0x2(%rbx)
movzbl 0x3(%rax),%edx
mov    %dl,0x3(%rbx)
movzbl 0x4(%rax),%edx
mov    %dl,0x4(%rbx)
movzbl 0x5(%rax),%edx
mov    %dl,0x5(%rbx)
movzbl 0x6(%rax),%edx
mov    %dl,0x6(%rbx)
movzbl 0x7(%rax),%edx
add    $0x8,%rax
mov    %dl,0x7(%rbx)
add    $0x8,%rbx
add    $0x8,%cl
jne    1250 <unrle+0x140>
mov    %rax,%r15
jmp    1154 <unrle+0x44>
sub    %r14d,%ebx
mov    %ebx,%eax
add    $0x8,%rsp
pop    %rbx
pop    %r14
pop    %r15
pop    %rbp
ret

LLVM IR (-O0):
define i32 @unrle(i8* %0, i8* %1) {
%3 = alloca i8*
%4 = alloca i8*
%5 = alloca i8
%6 = alloca i8*
%7 = alloca i8
store i8* %0, i8** %3
store i8* %1, i8** %4
%8 = load i8*, i8** %3
store i8* %8, i8** %6
br label %9
9: ; preds = %47, %2
%10 = load i8*, i8** %4
%11 = getelementptr inbounds i8, i8* %10, i32 1
store i8* %11, i8** %4
%12 = load i8, i8* %10
store i8 %12, i8* %5
%13 = load i8, i8* %5
%14 = sext i8 %13 to i32
%15 = icmp sgt i32 %14, 0
br i1 %15, label %16, label %29
16: ; preds = %9
%17 = load i8*, i8** %4
%18 = getelementptr inbounds i8, i8* %17, i32 1
store i8* %18, i8** %4
%19 = load i8, i8* %17
store i8 %19, i8* %7
br label %20
20: ; preds = %24, %16
%21 = load i8, i8* %5
%22 = add i8 %21, -1
store i8 %22, i8* %5
%23 = icmp ne i8 %21, 0
br i1 %23, label %24, label %28
24: ; preds = %20
%25 = load i8, i8* %7
%26 = load i8*, i8** %6
%27 = getelementptr inbounds i8, i8* %26, i32 1
store i8* %27, i8** %6
store i8 %25, i8* %26
br label %20
28: ; preds = %20
br label %47
29: ; preds = %9
%30 = load i8, i8* %5
%31 = sext i8 %30 to i32
%32 = icmp slt i32 %31, 0
br i1 %32, label %33, label %45
33: ; preds = %29
br label %34
34: ; preds = %38, %33
%35 = load i8, i8* %5
%36 = add i8 %35, 1
store i8 %36, i8* %5
%37 = icmp ne i8 %35, 0
br i1 %37, label %38, label %44
38: ; preds = %34
%39 = load i8*, i8** %4
%40 = getelementptr inbounds i8, i8* %39, i32 1
store i8* %40, i8** %4
%41 = load i8, i8* %39
%42 = load i8*, i8** %6
%43 = getelementptr inbounds i8, i8* %42, i32 1
store i8* %43, i8** %6
store i8 %41, i8* %42
br label %34
44: ; preds = %34
br label %46
45: ; preds = %29
br label %48
46: ; preds = %44
br label %47
47: ; preds = %46, %28
br label %9
48: ; preds = %45
%49 = load i8*, i8** %6
%50 = load i8*, i8** %3
%51 = ptrtoint i8* %49 to i64
%52 = ptrtoint i8* %50 to i64
%53 = sub i64 %51, %52
%54 = trunc i64 %53 to i32
ret i32 %54
}

LLVM IR (-O2):
define i32 @unrle(i8* %0, i8* nocapture %1) {
br label %3
3: ; preds = %86, %2
%4 = phi i8* [ %0, %2 ], [ %87, %86 ]
%5 = phi i8* [ %1, %2 ], [ %88, %86 ]
%6 = getelementptr i8, i8* %5, i64 1
%7 = load i8, i8* %5
%8 = icmp sgt i8 %7, 0
br i1 %8, label %9, label %17
9: ; preds = %3
%10 = load i8, i8* %6
%11 = zext i8 %7 to i64
%12 = add nsw i8 %7, -1
%13 = zext i8 %12 to i64
%14 = getelementptr inbounds i8, i8* %5, i64 2
%15 = getelementptr i8, i8* %4, i64 1
%16 = getelementptr i8, i8* %15, i64 %13
br label %86
17: ; preds = %3
%18 = icmp slt i8 %7, 0
br i1 %18, label %19, label %144
19: ; preds = %17
%20 = xor i8 %7, -1
%21 = zext i8 %20 to i64
%22 = add nuw nsw i64 %21, 1
%23 = icmp ugt i8 %7, -32
br i1 %23, label %89, label %24
24: ; preds = %19
%25 = getelementptr i8, i8* %4, i64 1
%26 = xor i8 %7, -1
%27 = zext i8 %26 to i64
%28 = getelementptr i8, i8* %25, i64 %27
%29 = getelementptr i8, i8* %5, i64 2
%30 = getelementptr i8, i8* %29, i64 %27
%31 = icmp ult i8* %4, %30
%32 = icmp ult i8* %6, %28
%33 = and i1 %31, %32
br i1 %33, label %89, label %34
34: ; preds = %24
%35 = and i64 %22, 480
%36 = getelementptr i8, i8* %6, i64 %35
%37 = getelementptr i8, i8* %4, i64 %35
%38 = trunc i64 %35 to i8
%39 = add i8 %7, %38
%40 = bitcast i8* %6 to <16 x i8>*
%41 = load <16 x i8>, <16 x i8>* %40
%42 = getelementptr i8, i8* %5, i64 17
%43 = bitcast i8* %42 to <16 x i8>*
%44 = load <16 x i8>, <16 x i8>* %43
%45 = bitcast i8* %4 to <16 x i8>*
store <16 x i8> %41, <16 x i8>* %45
%46 = getelementptr i8, i8* %4, i64 16
%47 = bitcast i8* %46 to <16 x i8>*
store <16 x i8> %44, <16 x i8>* %47
%48 = icmp eq i64 %35, 32
br i1 %48, label %84, label %49
49: ; preds = %34
%50 = getelementptr i8, i8* %5, i64 33
%51 = getelementptr i8, i8* %4, i64 32
%52 = bitcast i8* %50 to <16 x i8>*
%53 = load <16 x i8>, <16 x i8>* %52
%54 = getelementptr i8, i8* %5, i64 49
%55 = bitcast i8* %54 to <16 x i8>*
%56 = load <16 x i8>, <16 x i8>* %55
%57 = bitcast i8* %51 to <16 x i8>*
store <16 x i8> %53, <16 x i8>* %57
%58 = getelementptr i8, i8* %4, i64 48
%59 = bitcast i8* %58 to <16 x i8>*
store <16 x i8> %56, <16 x i8>* %59
%60 = icmp eq i64 %35, 64
br i1 %60, label %84, label %61
61: ; preds = %49
%62 = getelementptr i8, i8* %5, i64 65
%63 = getelementptr i8, i8* %4, i64 64
%64 = bitcast i8* %62 to <16 x i8>*
%65 = load <16 x i8>, <16 x i8>* %64
%66 = getelementptr i8, i8* %5, i64 81
%67 = bitcast i8* %66 to <16 x i8>*
%68 = load <16 x i8>, <16 x i8>* %67
%69 = bitcast i8* %63 to <16 x i8>*
store <16 x i8> %65, <16 x i8>* %69
%70 = getelementptr i8, i8* %4, i64 80
%71 = bitcast i8* %70 to <16 x i8>*
store <16 x i8> %68, <16 x i8>* %71
%72 = icmp eq i64 %35, 96
br i1 %72, label %84, label %73
73: ; preds = %61
%74 = getelementptr i8, i8* %5, i64 97
%75 = getelementptr i8, i8* %4, i64 96
%76 = bitcast i8* %74 to <16 x i8>*
%77 = load <16 x i8>, <16 x i8>* %76
%78 = getelementptr i8, i8* %5, i64 113
%79 = bitcast i8* %78 to <16 x i8>*
%80 = load <16 x i8>, <16 x i8>* %79
%81 = bitcast i8* %75 to <16 x i8>*
store <16 x i8> %77, <16 x i8>* %81
%82 = getelementptr i8, i8* %4, i64 112
%83 = bitcast i8* %82 to <16 x i8>*
store <16 x i8> %80, <16 x i8>* %83
br label %84
84: ; preds = %73, %61, %49, %34
%85 = icmp eq i64 %22, %35
br i1 %85, label %86, label %89
86: ; preds = %107, %114, %84, %9
%87 = phi i8* [ %16, %9 ], [ %37, %84 ], [ %109, %107 ], [ %142, %114 ]
%88 = phi i8* [ %14, %9 ], [ %36, %84 ], [ %108, %107 ], [ %140, %114 ]
br label %3
89: ; preds = %24, %19, %84
%90 = phi i8* [ %6, %24 ], [ %6, %19 ], [ %36, %84 ]
%91 = phi i8* [ %4, %24 ], [ %4, %19 ], [ %37, %84 ]
%92 = phi i8 [ %7, %24 ], [ %7, %19 ], [ %39, %84 ]
%93 = sub i8 0, %92
%94 = and i8 %93, 7
%95 = icmp eq i8 %94, 0
br i1 %95, label %107, label %96
96: ; preds = %89, %96
%97 = phi i8* [ %102, %96 ], [ %90, %89 ]
%98 = phi i8* [ %104, %96 ], [ %91, %89 ]
%99 = phi i8 [ %101, %96 ], [ %92, %89 ]
%100 = phi i8 [ %105, %96 ], [ 0, %89 ]
%101 = add i8 %99, 1
%102 = getelementptr inbounds i8, i8* %97, i64 1
%103 = load i8, i8* %97
%104 = getelementptr inbounds i8, i8* %98, i64 1
store i8 %103, i8* %98
%105 = add i8 %100, 1
%106 = icmp eq i8 %105, %94
br i1 %106, label %107, label %96
107: ; preds = %96, %89
%108 = phi i8* [ undef, %89 ], [ %102, %96 ]
%109 = phi i8* [ undef, %89 ], [ %104, %96 ]
%110 = phi i8* [ %90, %89 ], [ %102, %96 ]
%111 = phi i8* [ %91, %89 ], [ %104, %96 ]
%112 = phi i8 [ %92, %89 ], [ %101, %96 ]
%113 = icmp ugt i8 %92, -8
br i1 %113, label %86, label %114
114: ; preds = %107, %114
%115 = phi i8* [ %140, %114 ], [ %110, %107 ]
%116 = phi i8* [ %142, %114 ], [ %111, %107 ]
%117 = phi i8 [ %139, %114 ], [ %112, %107 ]
%118 = getelementptr inbounds i8, i8* %115, i64 1
%119 = load i8, i8* %115
%120 = getelementptr inbounds i8, i8* %116, i64 1
store i8 %119, i8* %116
%121 = getelementptr inbounds i8, i8* %115, i64 2
%122 = load i8, i8* %118
%123 = getelementptr inbounds i8, i8* %116, i64 2
store i8 %122, i8* %120
%124 = getelementptr inbounds i8, i8* %115, i64 3
%125 = load i8, i8* %121
%126 = getelementptr inbounds i8, i8* %116, i64 3
store i8 %125, i8* %123
%127 = getelementptr inbounds i8, i8* %115, i64 4
%128 = load i8, i8* %124
%129 = getelementptr inbounds i8, i8* %116, i64 4
store i8 %128, i8* %126
%130 = getelementptr inbounds i8, i8* %115, i64 5
%131 = load i8, i8* %127
%132 = getelementptr inbounds i8, i8* %116, i64 5
store i8 %131, i8* %129
%133 = getelementptr inbounds i8, i8* %115, i64 6
%134 = load i8, i8* %130
%135 = getelementptr inbounds i8, i8* %116, i64 6
store i8 %134, i8* %132
%136 = getelementptr inbounds i8, i8* %115, i64 7
%137 = load i8, i8* %133
%138 = getelementptr inbounds i8, i8* %116, i64 7
store i8 %137, i8* %135
%139 = add i8 %117, 8
%140 = getelementptr inbounds i8, i8* %115, i64 8
%141 = load i8, i8* %136
%142 = getelementptr inbounds i8, i8* %116, i64 8
store i8 %141, i8* %138
%143 = icmp eq i8 %139, 0
br i1 %143, label %86, label %114
144: ; preds = %17
%145 = ptrtoint i8* %4 to i64
%146 = ptrtoint i8* %0 to i64
%147 = sub i64 %145, %146
%148 = trunc i64 %147 to i32
ret i32 %148
}