void reverse(char s[], char out[], int len) {
  int nl = 0;
  if (s[len - 1] == '\n') {
    nl = 1;
  }
  for (int i = 0; i < len - nl; i++) {
    out[i] = s[len - i - 1 - nl];
  }
  if (nl) {
    out[len - 1] = '\n';
  }
  out[len] = '\0';
}


x86 assembly (clang, -O0):
<reverse>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %edx,-0x14(%rbp)
movl   $0x0,-0x18(%rbp)
mov    -0x8(%rbp),%rax
mov    -0x14(%rbp),%ecx
sub    $0x1,%ecx
movslq %ecx,%rcx
movsbl (%rax,%rcx,1),%eax
cmp    $0xa,%eax
jne    1137 <reverse+0x37>
movl   $0x1,-0x18(%rbp)
movl   $0x0,-0x1c(%rbp)
mov    -0x1c(%rbp),%eax
mov    -0x14(%rbp),%ecx
sub    -0x18(%rbp),%ecx
cmp    %ecx,%eax
jge    117e <reverse+0x7e>
mov    -0x8(%rbp),%rax
mov    -0x14(%rbp),%ecx
sub    -0x1c(%rbp),%ecx
sub    $0x1,%ecx
sub    -0x18(%rbp),%ecx
movslq %ecx,%rcx
mov    (%rax,%rcx,1),%dl
mov    -0x10(%rbp),%rax
movslq -0x1c(%rbp),%rcx
mov    %dl,(%rax,%rcx,1)
mov    -0x1c(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x1c(%rbp)
jmp    113e <reverse+0x3e>
cmpl   $0x0,-0x18(%rbp)
je     1199 <reverse+0x99>
mov    -0x10(%rbp),%rax
mov    -0x14(%rbp),%ecx
sub    $0x1,%ecx
movslq %ecx,%rcx
movb   $0xa,(%rax,%rcx,1)
mov    -0x10(%rbp),%rax
movslq -0x14(%rbp),%rcx
movb   $0x0,(%rax,%rcx,1)
pop    %rbp
ret

x86 assembly (clang, -O2):
<reverse>:
push   %rbp
push   %r15
push   %r14
push   %rbx
movslq %edx,%r9
mov    -0x1(%r9,%rdi,1),%r8b
xor    %r10d,%r10d
cmp    $0xa,%r8b
sete   %r10b
mov    %r9d,%r11d
sub    %r10d,%r11d
test   %r11d,%r11d
jle    11a3 <reverse+0xa3>
neg    %r10d
mov    %r11d,%r15d
cmp    $0x8,%r11d
jae    11bb <reverse+0xbb>
xor    %r14d,%r14d
mov    %r14,%rax
not    %rax
test   $0x1,%r15b
je     1159 <reverse+0x59>
mov    %r14d,%ebx
not    %ebx
add    %ebx,%r11d
movslq %r11d,%rbp
mov    (%rdi,%rbp,1),%bl
mov    %bl,(%rsi,%r14,1)
or     $0x1,%r14
add    %r15,%rax
je     11a3 <reverse+0xa3>
sub    %r14,%r15
add    %r10d,%edx
mov    %r14d,%eax
not    %eax
add    %edx,%eax
lea    (%r14,%rsi,1),%rdx
add    $0x1,%rdx
xor    %ebx,%ebx
cs nopw 0x0(%rax,%rax,1)
nop
cltq
movzbl (%rdi,%rax,1),%ecx
mov    %cl,-0x1(%rdx,%rbx,1)
lea    -0x1(%rax),%ecx
movslq %ecx,%rcx
movzbl (%rdi,%rcx,1),%ecx
mov    %cl,(%rdx,%rbx,1)
add    $0x2,%rbx
add    $0xfffffffe,%eax
cmp    %rbx,%r15
jne    1180 <reverse+0x80>
cmp    $0xa,%r8b
jne    11af <reverse+0xaf>
movb   $0xa,-0x1(%rsi,%r9,1)
movb   $0x0,(%rsi,%r9,1)
pop    %rbx
pop    %r14
pop    %r15
pop    %rbp
ret
lea    -0x1(%r15),%rax
lea    (%r10,%rdx,1),%ebx
add    $0xffffffff,%ebx
mov    %ebx,%ebp
sub    %eax,%ebp
xor    %r14d,%r14d
cmp    %ebx,%ebp
jg     1137 <reverse+0x37>
shr    $0x20,%rax
jne    1137 <reverse+0x37>
lea    (%r10,%rdx,1),%eax
add    $0xffffffff,%eax
cltq
lea    (%rdi,%rax,1),%rbp
add    $0x1,%rbp
cmp    %rsi,%rbp
jbe    120c <reverse+0x10c>
lea    (%rsi,%r15,1),%rbp
add    $0x1,%rax
sub    %r15,%rax
add    %rdi,%rax
cmp    %rbp,%rax
jb     1134 <reverse+0x34>
cmp    $0x20,%r11d
jae    121a <reverse+0x11a>
xor    %r14d,%r14d
jmp    12c9 <reverse+0x1c9>
mov    %r15d,%r14d
and    $0xffffffe0,%r14d
xor    %eax,%eax
pxor   %xmm0,%xmm0
nopw   0x0(%rax,%rax,1)
movslq %ebx,%rbx
movdqu -0x1f(%rdi,%rbx,1),%xmm1
movdqu -0xf(%rdi,%rbx,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
movdqa %xmm1,%xmm3
punpcklbw %xmm0,%xmm3
pshufd $0x4e,%xmm3,%xmm3
pshuflw $0x1b,%xmm3,%xmm3
pshufhw $0x1b,%xmm3,%xmm3
punpckhbw %xmm0,%xmm1
pshufd $0x4e,%xmm1,%xmm1
pshuflw $0x1b,%xmm1,%xmm1
pshufhw $0x1b,%xmm1,%xmm1
packuswb %xmm3,%xmm1
movdqu %xmm2,(%rsi,%rax,1)
movdqu %xmm1,0x10(%rsi,%rax,1)
add    $0x20,%rax
add    $0xffffffe0,%ebx
cmp    %rax,%r14
jne    1230 <reverse+0x130>
cmp    %r15,%r14
je     11a3 <reverse+0xa3>
test   $0x18,%r15b
je     1137 <reverse+0x37>
mov    %r14,%rax
mov    %r15d,%r14d
and    $0xfffffff8,%r14d
mov    %eax,%ebx
not    %ebx
add    %edx,%ebx
add    %r10d,%ebx
pxor   %xmm0,%xmm0
movslq %ebx,%rbx
movq   -0x7(%rdi,%rbx,1),%xmm1
punpcklbw %xmm0,%xmm1
pshufd $0x4e,%xmm1,%xmm1
pshuflw $0x1b,%xmm1,%xmm1
pshufhw $0x1b,%xmm1,%xmm1
packuswb %xmm1,%xmm1
movq   %xmm1,(%rsi,%rax,1)
add    $0x8,%rax
add    $0xfffffff8,%ebx
cmp    %rax,%r14
jne    12e0 <reverse+0x1e0>
cmp    %r15,%r14
je     11a3 <reverse+0xa3>
jmp    1137 <reverse+0x37>

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

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