char *ata_get_string(const unsigned char *buf, int word_start, int word_end,
                     char *str) {
  int word;
  int i;
  for (i = 0, word = word_start; word <= word_end; word++) {
    str[i++] = buf[word * 2 + 1];
    str[i++] = buf[word * 2];
  }
  str[i] = 0;
  return str;
}


x86 assembly (clang, -O0):
<ata_get_string>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    %esi,-0xc(%rbp)
mov    %edx,-0x10(%rbp)
mov    %rcx,-0x18(%rbp)
movl   $0x0,-0x20(%rbp)
mov    -0xc(%rbp),%eax
mov    %eax,-0x1c(%rbp)
mov    -0x1c(%rbp),%eax
cmp    -0x10(%rbp),%eax
jg     1186 <ata_get_string+0x86>
mov    -0x8(%rbp),%rax
mov    -0x1c(%rbp),%ecx
shl    $0x1,%ecx
add    $0x1,%ecx
movslq %ecx,%rcx
mov    (%rax,%rcx,1),%dl
mov    -0x18(%rbp),%rax
mov    -0x20(%rbp),%ecx
mov    %ecx,%esi
add    $0x1,%esi
mov    %esi,-0x20(%rbp)
movslq %ecx,%rcx
mov    %dl,(%rax,%rcx,1)
mov    -0x8(%rbp),%rax
mov    -0x1c(%rbp),%ecx
shl    $0x1,%ecx
movslq %ecx,%rcx
mov    (%rax,%rcx,1),%dl
mov    -0x18(%rbp),%rax
mov    -0x20(%rbp),%ecx
mov    %ecx,%esi
add    $0x1,%esi
mov    %esi,-0x20(%rbp)
movslq %ecx,%rcx
mov    %dl,(%rax,%rcx,1)
mov    -0x1c(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x1c(%rbp)
jmp    111f <ata_get_string+0x1f>
mov    -0x18(%rbp),%rax
movslq -0x20(%rbp),%rcx
movb   $0x0,(%rax,%rcx,1)
mov    -0x18(%rbp),%rax
pop    %rbp
ret

x86 assembly (clang, -O2):
<ata_get_string>:
push   %rbp
push   %r14
push   %rbx
mov    %rcx,%rax
mov    %edx,%r9d
sub    %esi,%r9d
jge    1117 <ata_get_string+0x17>
xor    %r11d,%r11d
jmp    130c <ata_get_string+0x20c>
mov    %esi,%r8d
cmp    $0x7,%r9d
jae    1145 <ata_get_string+0x45>
xor    %r11d,%r11d
mov    %edx,%ecx
sub    %r8d,%ecx
add    $0x1,%ecx
test   $0x1,%cl
jne    1263 <ata_get_string+0x163>
mov    %r8,%r9
cmp    %edx,%r8d
jne    1292 <ata_get_string+0x192>
jmp    1308 <ata_get_string+0x208>
lea    (%rsi,%rsi,1),%ecx
add    $0x1,%ecx
mov    %r9d,%ebx
add    %ebx,%ebx
setb   %r10b
lea    (%rbx,%rsi,2),%ebp
add    $0x1,%ebp
xor    %r11d,%r11d
cmp    %ecx,%ebp
jl     1123 <ata_get_string+0x23>
test   %r10b,%r10b
jne    1123 <ata_get_string+0x23>
lea    (%rsi,%rsi,1),%ecx
lea    (%rbx,%rsi,2),%ebx
cmp    %ecx,%ebx
jl     1123 <ata_get_string+0x23>
test   %r10b,%r10b
jne    1123 <ata_get_string+0x23>
movslq %ecx,%rbx
lea    (%rbx,%r9,2),%rbp
add    %rdi,%rbp
add    $0x2,%rbp
cmp    %rax,%rbp
jbe    1198 <ata_get_string+0x98>
lea    (%rax,%r9,2),%rbp
add    $0x2,%rbp
add    %rdi,%rbx
cmp    %rbp,%rbx
jb     1120 <ata_get_string+0x20>
add    $0x1,%r9
mov    %r9,%r10
and    $0xfffffffffffffff8,%r10
lea    -0x8(%r10),%rbp
mov    %rbp,%r14
shr    $0x3,%r14
add    $0x1,%r14
test   %rbp,%rbp
je     1316 <ata_get_string+0x216>
mov    %r14,%rbx
and    $0xfffffffffffffffe,%rbx
add    $0x11,%ecx
xor    %r11d,%r11d
nopl   0x0(%rax,%rax,1)
lea    -0x10(%rcx),%ebp
movslq %ebp,%rbp
movdqu -0x1(%rdi,%rbp,1),%xmm0
movdqa %xmm0,%xmm1
psrlw  $0x8,%xmm1
psllw  $0x8,%xmm0
por    %xmm1,%xmm0
movdqu %xmm0,(%rax,%r11,2)
movslq %ecx,%rcx
movdqu -0x1(%rdi,%rcx,1),%xmm0
movdqa %xmm0,%xmm1
psrlw  $0x8,%xmm1
psllw  $0x8,%xmm0
por    %xmm1,%xmm0
movdqu %xmm0,0x10(%rax,%r11,2)
add    $0x10,%r11
add    $0x20,%ecx
add    $0xfffffffffffffffe,%rbx
jne    11d0 <ata_get_string+0xd0>
test   $0x1,%r14b
je     124e <ata_get_string+0x14e>
add    %r11d,%esi
add    %esi,%esi
movslq %esi,%rcx
movdqu (%rdi,%rcx,1),%xmm0
movdqa %xmm0,%xmm1
psrlw  $0x8,%xmm1
psllw  $0x8,%xmm0
por    %xmm1,%xmm0
movdqu %xmm0,(%rax,%r11,2)
lea    (%r10,%r10,1),%r11
cmp    %r10,%r9
je     1308 <ata_get_string+0x208>
add    %r10,%r8
jmp    1123 <ata_get_string+0x23>
movslq %r8d,%rcx
lea    (%rcx,%rcx,1),%rsi
movslq %esi,%rsi
mov    0x1(%rdi,%rsi,1),%bl
mov    %r11,%rsi
or     $0x1,%rsi
mov    %bl,(%rax,%r11,1)
mov    (%rdi,%rcx,2),%cl
add    $0x2,%r11
mov    %cl,(%rax,%rsi,1)
mov    %r8,%r9
add    $0x1,%r9
cmp    %edx,%r8d
je     1308 <ata_get_string+0x208>
sub    %r9d,%edx
and    $0x7fffffff,%r9d
add    %r9,%r9
add    $0x1,%edx
lea    (%r11,%rax,1),%r8
add    $0x2,%r8
xor    %esi,%esi
nopl   0x0(%rax)
lea    (%r11,%rsi,1),%rbp
lea    (%r9,%rsi,1),%rcx
lea    0x1(%rcx),%ebx
movslq %ebx,%rbx
movzbl (%rdi,%rbx,1),%ebx
or     $0x1,%rbp
mov    %bl,-0x2(%r8,%rsi,1)
movslq %ecx,%rcx
movzbl (%rdi,%rcx,1),%ebx
mov    %bl,(%rax,%rbp,1)
lea    0x2(%rcx),%ebp
add    $0x3,%ecx
movslq %ecx,%rcx
movzbl (%rdi,%rcx,1),%ecx
lea    (%r11,%rsi,1),%rbx
add    $0x2,%rbx
or     $0x1,%rbx
mov    %cl,(%r8,%rsi,1)
movslq %ebp,%rcx
movzbl (%rdi,%rcx,1),%ecx
mov    %cl,(%rax,%rbx,1)
add    $0x4,%rsi
add    $0xfffffffe,%edx
jne    12b0 <ata_get_string+0x1b0>
add    %rsi,%r11
and    $0xfffffffe,%r11d
movb   $0x0,(%rax,%r11,1)
pop    %rbx
pop    %r14
pop    %rbp
ret
xor    %r11d,%r11d
test   $0x1,%r14b
jne    1229 <ata_get_string+0x129>
jmp    124e <ata_get_string+0x14e>

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

LLVM IR (-O2):
define i8* @ata_get_string(i8* nocapture %0, i32 %1, i32 %2, i8* returned writeonly %3) {
%5 = icmp slt i32 %2, %1
br i1 %5, label %184, label %6
6: ; preds = %4
%7 = zext i32 %1 to i64
%8 = add i32 %2, 1
%9 = sub i32 %2, %1
%10 = zext i32 %9 to i64
%11 = add nuw nsw i64 %10, 1
%12 = icmp ult i32 %9, 7
br i1 %12, label %120, label %13
13: ; preds = %6
%14 = sub i32 %2, %1
%15 = shl i32 %1, 1
%16 = or i32 %15, 1
%17 = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 %14, i32 2)
%18 = extractvalue { i32, i1 } %17, 0
%19 = extractvalue { i32, i1 } %17, 1
%20 = add i32 %16, %18
%21 = icmp slt i32 %20, %16
%22 = or i1 %21, %19
%23 = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 %14, i32 2)
%24 = extractvalue { i32, i1 } %23, 0
%25 = extractvalue { i32, i1 } %23, 1
%26 = add i32 %15, %24
%27 = icmp slt i32 %26, %15
%28 = or i1 %27, %25
%29 = or i1 %22, %28
br i1 %29, label %120, label %30
30: ; preds = %13
%31 = sub i32 %2, %1
%32 = zext i32 %31 to i64
%33 = shl nuw nsw i64 %32, 1
%34 = add nuw nsw i64 %33, 2
%35 = getelementptr i8, i8* %3, i64 %34
%36 = shl i32 %1, 1
%37 = sext i32 %36 to i64
%38 = getelementptr i8, i8* %0, i64 %37
%39 = add nsw i64 %33, %37
%40 = add nsw i64 %39, 2
%41 = getelementptr i8, i8* %0, i64 %40
%42 = icmp ugt i8* %41, %3
%43 = icmp ult i8* %38, %35
%44 = and i1 %42, %43
br i1 %44, label %120, label %45
45: ; preds = %30
%46 = and i64 %11, 8589934584
%47 = add nuw nsw i64 %46, %7
%48 = shl nuw nsw i64 %46, 1
%49 = add nsw i64 %46, -8
%50 = lshr exact i64 %49, 3
%51 = add nuw nsw i64 %50, 1
%52 = and i64 %51, 1
%53 = icmp eq i64 %49, 0
br i1 %53, label %97, label %54
54: ; preds = %45
%55 = and i64 %51, 4611686018427387902
%56 = getelementptr inbounds i8, i8* %0, i64 -1
%57 = getelementptr inbounds i8, i8* %3, i64 -1
%58 = getelementptr inbounds i8, i8* %0, i64 -1
%59 = getelementptr inbounds i8, i8* %3, i64 -1
br label %60
60: ; preds = %60, %54
%61 = phi i64 [ 0, %54 ], [ %94, %60 ]
%62 = phi i64 [ 0, %54 ], [ %95, %60 ]
%63 = shl i64 %61, 1
%64 = trunc i64 %61 to i32
%65 = add i32 %64, %1
%66 = shl nsw i32 %65, 1
%67 = or i32 %66, 1
%68 = sext i32 %67 to i64
%69 = getelementptr inbounds i8, i8* %56, i64 %68
%70 = bitcast i8* %69 to <16 x i8>*
%71 = load <16 x i8>, <16 x i8>* %70
%72 = shufflevector <16 x i8> %71, <16 x i8> poison, <8 x i32> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 12, i32 14>
%73 = shufflevector <16 x i8> %71, <16 x i8> poison, <8 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15>
%74 = or i64 %63, 1
%75 = getelementptr inbounds i8, i8* %57, i64 %74
%76 = bitcast i8* %75 to <16 x i8>*
%77 = shufflevector <8 x i8> %73, <8 x i8> %72, <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> %77, <16 x i8>* %76
%78 = or i64 %61, 8
%79 = shl i64 %78, 1
%80 = trunc i64 %78 to i32
%81 = add i32 %80, %1
%82 = shl nsw i32 %81, 1
%83 = or i32 %82, 1
%84 = sext i32 %83 to i64
%85 = getelementptr inbounds i8, i8* %58, i64 %84
%86 = bitcast i8* %85 to <16 x i8>*
%87 = load <16 x i8>, <16 x i8>* %86
%88 = shufflevector <16 x i8> %87, <16 x i8> poison, <8 x i32> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 12, i32 14>
%89 = shufflevector <16 x i8> %87, <16 x i8> poison, <8 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15>
%90 = or i64 %79, 1
%91 = getelementptr inbounds i8, i8* %59, i64 %90
%92 = bitcast i8* %91 to <16 x i8>*
%93 = shufflevector <8 x i8> %89, <8 x i8> %88, <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> %93, <16 x i8>* %92
%94 = add nuw i64 %61, 16
%95 = add i64 %62, 2
%96 = icmp eq i64 %95, %55
br i1 %96, label %97, label %60
97: ; preds = %60, %45
%98 = phi i64 [ 0, %45 ], [ %94, %60 ]
%99 = icmp eq i64 %52, 0
br i1 %99, label %118, label %100
100: ; preds = %97
%101 = shl i64 %98, 1
%102 = trunc i64 %98 to i32
%103 = add i32 %102, %1
%104 = shl nsw i32 %103, 1
%105 = or i32 %104, 1
%106 = sext i32 %105 to i64
%107 = getelementptr inbounds i8, i8* %0, i64 -1
%108 = getelementptr inbounds i8, i8* %107, i64 %106
%109 = bitcast i8* %108 to <16 x i8>*
%110 = load <16 x i8>, <16 x i8>* %109
%111 = shufflevector <16 x i8> %110, <16 x i8> poison, <8 x i32> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 12, i32 14>
%112 = shufflevector <16 x i8> %110, <16 x i8> poison, <8 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15>
%113 = or i64 %101, 1
%114 = getelementptr inbounds i8, i8* %3, i64 -1
%115 = getelementptr inbounds i8, i8* %114, i64 %113
%116 = bitcast i8* %115 to <16 x i8>*
%117 = shufflevector <8 x i8> %112, <8 x i8> %111, <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> %117, <16 x i8>* %116
br label %118
118: ; preds = %97, %100
%119 = icmp eq i64 %11, %46
br i1 %119, label %181, label %120
120: ; preds = %30, %13, %6, %118
%121 = phi i64 [ %7, %30 ], [ %7, %13 ], [ %7, %6 ], [ %47, %118 ]
%122 = phi i64 [ 0, %30 ], [ 0, %13 ], [ 0, %6 ], [ %48, %118 ]
%123 = add i32 %2, 1
%124 = trunc i64 %121 to i32
%125 = sub i32 %123, %124
%126 = and i32 %125, 1
%127 = icmp eq i32 %126, 0
br i1 %127, label %143, label %128
128: ; preds = %120
%129 = trunc i64 %121 to i32
%130 = shl nsw i32 %129, 1
%131 = or i32 %130, 1
%132 = sext i32 %131 to i64
%133 = getelementptr inbounds i8, i8* %0, i64 %132
%134 = load i8, i8* %133
%135 = or i64 %122, 1
%136 = getelementptr inbounds i8, i8* %3, i64 %122
store i8 %134, i8* %136
%137 = sext i32 %130 to i64
%138 = getelementptr inbounds i8, i8* %0, i64 %137
%139 = load i8, i8* %138
%140 = add nuw nsw i64 %122, 2
%141 = getelementptr inbounds i8, i8* %3, i64 %135
store i8 %139, i8* %141
%142 = add nsw i64 %121, 1
br label %143
143: ; preds = %128, %120
%144 = phi i64 [ undef, %120 ], [ %140, %128 ]
%145 = phi i64 [ %121, %120 ], [ %142, %128 ]
%146 = phi i64 [ %122, %120 ], [ %140, %128 ]
%147 = icmp eq i32 %124, %2
br i1 %147, label %181, label %148
148: ; preds = %143, %148
%149 = phi i64 [ %178, %148 ], [ %145, %143 ]
%150 = phi i64 [ %176, %148 ], [ %146, %143 ]
%151 = trunc i64 %149 to i32
%152 = shl nsw i32 %151, 1
%153 = or i32 %152, 1
%154 = sext i32 %153 to i64
%155 = getelementptr inbounds i8, i8* %0, i64 %154
%156 = load i8, i8* %155
%157 = or i64 %150, 1
%158 = getelementptr inbounds i8, i8* %3, i64 %150
store i8 %156, i8* %158
%159 = sext i32 %152 to i64
%160 = getelementptr inbounds i8, i8* %0, i64 %159
%161 = load i8, i8* %160
%162 = add nuw nsw i64 %150, 2
%163 = getelementptr inbounds i8, i8* %3, i64 %157
store i8 %161, i8* %163
%164 = trunc i64 %149 to i32
%165 = shl i32 %164, 1
%166 = add i32 %165, 2
%167 = or i32 %166, 1
%168 = sext i32 %167 to i64
%169 = getelementptr inbounds i8, i8* %0, i64 %168
%170 = load i8, i8* %169
%171 = or i64 %162, 1
%172 = getelementptr inbounds i8, i8* %3, i64 %162
store i8 %170, i8* %172
%173 = sext i32 %166 to i64
%174 = getelementptr inbounds i8, i8* %0, i64 %173
%175 = load i8, i8* %174
%176 = add nuw nsw i64 %150, 4
%177 = getelementptr inbounds i8, i8* %3, i64 %171
store i8 %175, i8* %177
%178 = add nuw nsw i64 %149, 2
%179 = trunc i64 %178 to i32
%180 = icmp eq i32 %8, %179
br i1 %180, label %181, label %148
181: ; preds = %143, %148, %118
%182 = phi i64 [ %48, %118 ], [ %144, %143 ], [ %176, %148 ]
%183 = and i64 %182, 4294967294
br label %184
184: ; preds = %181, %4
%185 = phi i64 [ 0, %4 ], [ %183, %181 ]
%186 = getelementptr inbounds i8, i8* %3, i64 %185
store i8 0, i8* %186
ret i8* %3
}