void reverse(char *const start, char *const end) {
  char *m = start + (end - start) / 2;
  char tmp, *s = start, *e = end - 1;
  while (s < m) {
    tmp = *s;
    *s++ = *e;
    *e-- = tmp;
  }
}


x86 assembly (clang, -O0):
<reverse>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    -0x8(%rbp),%rax
mov    %rax,-0x38(%rbp)
mov    -0x10(%rbp),%rax
mov    -0x8(%rbp),%rcx
sub    %rcx,%rax
mov    $0x2,%ecx
cqto
idiv   %rcx
mov    %rax,%rcx
mov    -0x38(%rbp),%rax
add    %rcx,%rax
mov    %rax,-0x18(%rbp)
mov    -0x8(%rbp),%rax
mov    %rax,-0x28(%rbp)
mov    -0x10(%rbp),%rax
add    $0xffffffffffffffff,%rax
mov    %rax,-0x30(%rbp)
mov    -0x28(%rbp),%rax
cmp    -0x18(%rbp),%rax
jae    1192 <reverse+0x92>
mov    -0x28(%rbp),%rax
mov    (%rax),%al
mov    %al,-0x19(%rbp)
mov    -0x30(%rbp),%rax
mov    (%rax),%cl
mov    -0x28(%rbp),%rax
mov    %rax,%rdx
add    $0x1,%rdx
mov    %rdx,-0x28(%rbp)
mov    %cl,(%rax)
mov    -0x19(%rbp),%cl
mov    -0x30(%rbp),%rax
mov    %rax,%rdx
add    $0xffffffffffffffff,%rdx
mov    %rdx,-0x30(%rbp)
mov    %cl,(%rax)
jmp    114b <reverse+0x4b>
pop    %rbp
ret

x86 assembly (clang, -O2):
<reverse>:
mov    %rsi,%rax
sub    %rdi,%rax
cmp    $0x2,%rax
jl     1178 <reverse+0x78>
mov    %rax,%r10
shr    $0x3f,%r10
add    %rax,%r10
sar    %r10
add    %rdi,%r10
lea    0x1(%rdi),%r8
cmp    %r8,%r10
mov    %r8,%r9
cmova  %r10,%r9
sub    %rdi,%r9
cmp    $0x4,%r9
jb     1150 <reverse+0x50>
cmp    %r8,%r10
mov    %r8,%rax
cmova  %r10,%rax
cmp    %rsi,%rdi
jae    1179 <reverse+0x79>
mov    %rdi,%rcx
sub    %rax,%rcx
add    %rsi,%rcx
cmp    %rax,%rcx
jae    1179 <reverse+0x79>
mov    %rsi,%rcx
mov    %rdi,%rax
add    $0xffffffffffffffff,%rcx
nopw   0x0(%rax,%rax,1)
movzbl (%rax),%esi
movzbl (%rcx),%edx
mov    %dl,(%rax)
add    $0x1,%rax
mov    %sil,(%rcx)
add    $0xffffffffffffffff,%rcx
cmp    %r10,%rax
jb     1160 <reverse+0x60>
ret
cmp    $0x10,%r9
jae    1186 <reverse+0x86>
xor    %edx,%edx
jmp    122c <reverse+0x12c>
mov    %r9,%rdx
and    $0xfffffffffffffff0,%rdx
mov    %rdx,%r11
neg    %r11
xor    %ecx,%ecx
pxor   %xmm0,%xmm0
mov    %rdi,%rax
nopl   0x0(%rax)
movdqu (%rax),%xmm1
movdqu -0x10(%rsi,%rcx,1),%xmm2
movdqa %xmm2,%xmm3
punpcklbw %xmm0,%xmm3
pshufd $0x4e,%xmm3,%xmm3
pshuflw $0x1b,%xmm3,%xmm3
pshufhw $0x1b,%xmm3,%xmm3
punpckhbw %xmm0,%xmm2
pshufd $0x4e,%xmm2,%xmm2
pshuflw $0x1b,%xmm2,%xmm2
pshufhw $0x1b,%xmm2,%xmm2
packuswb %xmm3,%xmm2
movdqu %xmm2,(%rax)
movdqa %xmm1,%xmm2
punpcklbw %xmm0,%xmm2
pshufd $0x4e,%xmm2,%xmm2
pshuflw $0x1b,%xmm2,%xmm2
pshufhw $0x1b,%xmm2,%xmm2
punpckhbw %xmm0,%xmm1
pshufd $0x4e,%xmm1,%xmm1
pshuflw $0x1b,%xmm1,%xmm1
pshufhw $0x1b,%xmm1,%xmm1
packuswb %xmm2,%xmm1
movdqu %xmm1,-0x10(%rsi,%rcx,1)
add    $0x10,%rax
add    $0xfffffffffffffff0,%rcx
cmp    %rcx,%r11
jne    11a0 <reverse+0xa0>
cmp    %rdx,%r9
je     1178 <reverse+0x78>
test   $0xc,%r9b
je     12a9 <reverse+0x1a9>
cmp    %r8,%r10
cmova  %r10,%r8
sub    %rdi,%r8
mov    %r8,%r11
and    $0xfffffffffffffffc,%r11
mov    %rsi,%rcx
sub    %r11,%rcx
lea    (%rdi,%r11,1),%rax
add    %rdx,%rdi
neg    %rdx
and    $0xfffffffffffffffc,%r9
neg    %r9
pxor   %xmm0,%xmm0
nopl   0x0(%rax,%rax,1)
movd   (%rdi),%xmm1
movd   -0x4(%rsi,%rdx,1),%xmm2
punpcklbw %xmm0,%xmm2
pshuflw $0x1b,%xmm2,%xmm2
packuswb %xmm2,%xmm2
movd   %xmm2,(%rdi)
punpcklbw %xmm0,%xmm1
pshuflw $0x1b,%xmm1,%xmm1
packuswb %xmm1,%xmm1
movd   %xmm1,-0x4(%rsi,%rdx,1)
add    $0x4,%rdi
add    $0xfffffffffffffffc,%rdx
cmp    %rdx,%r9
jne    1260 <reverse+0x160>
cmp    %r11,%r8
jne    1156 <reverse+0x56>
jmp    1178 <reverse+0x78>
add    %rdx,%rdi
sub    %rdx,%rsi
jmp    1150 <reverse+0x50>

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

LLVM IR (-O2):
define void @reverse(i8* %0, i8* %1) {
%3 = ptrtoint i8* %1 to i64
%4 = ptrtoint i8* %0 to i64
%5 = sub i64 %3, %4
%6 = sdiv i64 %5, 2
%7 = getelementptr inbounds i8, i8* %0, i64 %6
%8 = icmp sgt i64 %5, 1
br i1 %8, label %9, label %93
9: ; preds = %2
%10 = add i64 %6, %4
%11 = add i64 %4, 1
%12 = call i64 @llvm.umax.i64(i64 %10, i64 %11)
%13 = sub i64 %12, %4
%14 = icmp ult i64 %13, 4
br i1 %14, label %82, label %15
15: ; preds = %9
%16 = add i64 %6, %4
%17 = add i64 %4, 1
%18 = call i64 @llvm.umax.i64(i64 %16, i64 %17)
%19 = sub i64 %18, %4
%20 = getelementptr i8, i8* %0, i64 %19
%21 = sub i64 %4, %18
%22 = getelementptr i8, i8* %1, i64 %21
%23 = icmp ult i8* %0, %1
%24 = icmp ult i8* %22, %20
%25 = and i1 %23, %24
br i1 %25, label %82, label %26
26: ; preds = %15
%27 = icmp ult i64 %13, 16
br i1 %27, label %54, label %28
28: ; preds = %26
%29 = and i64 %13, -16
%30 = getelementptr i8, i8* %1, i64 -16
br label %31
31: ; preds = %31, %28
%32 = phi i64 [ 0, %28 ], [ %44, %31 ]
%33 = sub i64 0, %32
%34 = getelementptr i8, i8* %0, i64 %32
%35 = bitcast i8* %34 to <16 x i8>*
%36 = load <16 x i8>, <16 x i8>* %35
%37 = getelementptr inbounds i8, i8* %30, i64 %33
%38 = bitcast i8* %37 to <16 x i8>*
%39 = load <16 x i8>, <16 x i8>* %38
%40 = shufflevector <16 x i8> %39, <16 x i8> poison, <16 x i32> <i32 15, i32 14, i32 13, i32 12, i32 11, i32 10, i32 9, i32 8, i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
%41 = bitcast i8* %34 to <16 x i8>*
store <16 x i8> %40, <16 x i8>* %41
%42 = shufflevector <16 x i8> %36, <16 x i8> poison, <16 x i32> <i32 15, i32 14, i32 13, i32 12, i32 11, i32 10, i32 9, i32 8, i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
%43 = bitcast i8* %37 to <16 x i8>*
store <16 x i8> %42, <16 x i8>* %43
%44 = add nuw i64 %32, 16
%45 = icmp eq i64 %44, %29
br i1 %45, label %46, label %31
46: ; preds = %31
%47 = icmp eq i64 %13, %29
br i1 %47, label %93, label %48
48: ; preds = %46
%49 = getelementptr i8, i8* %0, i64 %29
%50 = sub i64 0, %29
%51 = getelementptr i8, i8* %1, i64 %50
%52 = and i64 %13, 12
%53 = icmp eq i64 %52, 0
br i1 %53, label %82, label %54
54: ; preds = %26, %48
%55 = phi i64 [ %29, %48 ], [ 0, %26 ]
%56 = add i64 %6, %4
%57 = add i64 %4, 1
%58 = call i64 @llvm.umax.i64(i64 %56, i64 %57)
%59 = sub i64 %58, %4
%60 = and i64 %59, -4
%61 = sub i64 0, %60
%62 = getelementptr i8, i8* %1, i64 %61
%63 = getelementptr i8, i8* %0, i64 %60
%64 = getelementptr i8, i8* %1, i64 -4
br label %65
65: ; preds = %65, %54
%66 = phi i64 [ %55, %54 ], [ %78, %65 ]
%67 = sub i64 0, %66
%68 = getelementptr i8, i8* %0, i64 %66
%69 = bitcast i8* %68 to <4 x i8>*
%70 = load <4 x i8>, <4 x i8>* %69
%71 = getelementptr inbounds i8, i8* %64, i64 %67
%72 = bitcast i8* %71 to <4 x i8>*
%73 = load <4 x i8>, <4 x i8>* %72
%74 = shufflevector <4 x i8> %73, <4 x i8> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
%75 = bitcast i8* %68 to <4 x i8>*
store <4 x i8> %74, <4 x i8>* %75
%76 = shufflevector <4 x i8> %70, <4 x i8> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
%77 = bitcast i8* %71 to <4 x i8>*
store <4 x i8> %76, <4 x i8>* %77
%78 = add nuw i64 %66, 4
%79 = icmp eq i64 %78, %60
br i1 %79, label %80, label %65
80: ; preds = %65
%81 = icmp eq i64 %59, %60
br i1 %81, label %93, label %82
82: ; preds = %15, %9, %48, %80
%83 = phi i8* [ %1, %9 ], [ %1, %15 ], [ %51, %48 ], [ %62, %80 ]
%84 = phi i8* [ %0, %9 ], [ %0, %15 ], [ %49, %48 ], [ %63, %80 ]
br label %85
85: ; preds = %82, %85
%86 = phi i8* [ %88, %85 ], [ %83, %82 ]
%87 = phi i8* [ %91, %85 ], [ %84, %82 ]
%88 = getelementptr inbounds i8, i8* %86, i64 -1
%89 = load i8, i8* %87
%90 = load i8, i8* %88
%91 = getelementptr inbounds i8, i8* %87, i64 1
store i8 %90, i8* %87
store i8 %89, i8* %88
%92 = icmp ult i8* %91, %7
br i1 %92, label %85, label %93
93: ; preds = %85, %46, %80, %2
ret void
}