unsigned long bn_sub_words(unsigned long *r, unsigned long *a, unsigned long *b,
                           int n) {
  unsigned long t1, t2;
  int c = 0;
  ;
  if (n <= 0)
    return ((unsigned long)0);
  for (;;) {
    t1 = a[0];
    t2 = b[0];
    r[0] = (t1 - t2 - c) & (0xffffffffL);
    if (t1 != t2)
      c = (t1 < t2);
    if (--n <= 0)
      break;
    t1 = a[1];
    t2 = b[1];
    r[1] = (t1 - t2 - c) & (0xffffffffL);
    if (t1 != t2)
      c = (t1 < t2);
    if (--n <= 0)
      break;
    t1 = a[2];
    t2 = b[2];
    r[2] = (t1 - t2 - c) & (0xffffffffL);
    if (t1 != t2)
      c = (t1 < t2);
    if (--n <= 0)
      break;
    t1 = a[3];
    t2 = b[3];
    r[3] = (t1 - t2 - c) & (0xffffffffL);
    if (t1 != t2)
      c = (t1 < t2);
    if (--n <= 0)
      break;
    a += 4;
    b += 4;
    r += 4;
  }
  return (c);
}


x86 assembly (clang, -O0):
<bn_sub_words>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x10(%rbp)
mov    %rsi,-0x18(%rbp)
mov    %rdx,-0x20(%rbp)
mov    %ecx,-0x24(%rbp)
movl   $0x0,-0x3c(%rbp)
cmpl   $0x0,-0x24(%rbp)
jg     1131 <bn_sub_words+0x31>
movq   $0x0,-0x8(%rbp)
jmp    1334 <bn_sub_words+0x234>
jmp    1136 <bn_sub_words+0x36>
mov    -0x18(%rbp),%rax
mov    (%rax),%rax
mov    %rax,-0x30(%rbp)
mov    -0x20(%rbp),%rax
mov    (%rax),%rax
mov    %rax,-0x38(%rbp)
mov    -0x30(%rbp),%rcx
sub    -0x38(%rbp),%rcx
movslq -0x3c(%rbp),%rax
sub    %rax,%rcx
movabs $0xffffffff,%rax
and    %rax,%rcx
mov    -0x10(%rbp),%rax
mov    %rcx,(%rax)
mov    -0x30(%rbp),%rax
cmp    -0x38(%rbp),%rax
je     1190 <bn_sub_words+0x90>
mov    -0x30(%rbp),%rax
cmp    -0x38(%rbp),%rax
setb   %al
and    $0x1,%al
movzbl %al,%eax
mov    %eax,-0x3c(%rbp)
mov    -0x24(%rbp),%eax
add    $0xffffffff,%eax
mov    %eax,-0x24(%rbp)
cmp    $0x0,%eax
jg     11a7 <bn_sub_words+0xa7>
jmp    132c <bn_sub_words+0x22c>
mov    -0x18(%rbp),%rax
mov    0x8(%rax),%rax
mov    %rax,-0x30(%rbp)
mov    -0x20(%rbp),%rax
mov    0x8(%rax),%rax
mov    %rax,-0x38(%rbp)
mov    -0x30(%rbp),%rcx
sub    -0x38(%rbp),%rcx
movslq -0x3c(%rbp),%rax
sub    %rax,%rcx
movabs $0xffffffff,%rax
and    %rax,%rcx
mov    -0x10(%rbp),%rax
mov    %rcx,0x8(%rax)
mov    -0x30(%rbp),%rax
cmp    -0x38(%rbp),%rax
je     1204 <bn_sub_words+0x104>
mov    -0x30(%rbp),%rax
cmp    -0x38(%rbp),%rax
setb   %al
and    $0x1,%al
movzbl %al,%eax
mov    %eax,-0x3c(%rbp)
mov    -0x24(%rbp),%eax
add    $0xffffffff,%eax
mov    %eax,-0x24(%rbp)
cmp    $0x0,%eax
jg     121b <bn_sub_words+0x11b>
jmp    132c <bn_sub_words+0x22c>
mov    -0x18(%rbp),%rax
mov    0x10(%rax),%rax
mov    %rax,-0x30(%rbp)
mov    -0x20(%rbp),%rax
mov    0x10(%rax),%rax
mov    %rax,-0x38(%rbp)
mov    -0x30(%rbp),%rcx
sub    -0x38(%rbp),%rcx
movslq -0x3c(%rbp),%rax
sub    %rax,%rcx
movabs $0xffffffff,%rax
and    %rax,%rcx
mov    -0x10(%rbp),%rax
mov    %rcx,0x10(%rax)
mov    -0x30(%rbp),%rax
cmp    -0x38(%rbp),%rax
je     1278 <bn_sub_words+0x178>
mov    -0x30(%rbp),%rax
cmp    -0x38(%rbp),%rax
setb   %al
and    $0x1,%al
movzbl %al,%eax
mov    %eax,-0x3c(%rbp)
mov    -0x24(%rbp),%eax
add    $0xffffffff,%eax
mov    %eax,-0x24(%rbp)
cmp    $0x0,%eax
jg     128f <bn_sub_words+0x18f>
jmp    132c <bn_sub_words+0x22c>
mov    -0x18(%rbp),%rax
mov    0x18(%rax),%rax
mov    %rax,-0x30(%rbp)
mov    -0x20(%rbp),%rax
mov    0x18(%rax),%rax
mov    %rax,-0x38(%rbp)
mov    -0x30(%rbp),%rcx
sub    -0x38(%rbp),%rcx
movslq -0x3c(%rbp),%rax
sub    %rax,%rcx
movabs $0xffffffff,%rax
and    %rax,%rcx
mov    -0x10(%rbp),%rax
mov    %rcx,0x18(%rax)
mov    -0x30(%rbp),%rax
cmp    -0x38(%rbp),%rax
je     12ec <bn_sub_words+0x1ec>
mov    -0x30(%rbp),%rax
cmp    -0x38(%rbp),%rax
setb   %al
and    $0x1,%al
movzbl %al,%eax
mov    %eax,-0x3c(%rbp)
mov    -0x24(%rbp),%eax
add    $0xffffffff,%eax
mov    %eax,-0x24(%rbp)
cmp    $0x0,%eax
jg     1303 <bn_sub_words+0x203>
jmp    132c <bn_sub_words+0x22c>
mov    -0x18(%rbp),%rax
add    $0x20,%rax
mov    %rax,-0x18(%rbp)
mov    -0x20(%rbp),%rax
add    $0x20,%rax
mov    %rax,-0x20(%rbp)
mov    -0x10(%rbp),%rax
add    $0x20,%rax
mov    %rax,-0x10(%rbp)
jmp    1136 <bn_sub_words+0x36>
movslq -0x3c(%rbp),%rax
mov    %rax,-0x8(%rbp)
mov    -0x8(%rbp),%rax
pop    %rbp
ret

x86 assembly (clang, -O2):
<bn_sub_words>:
test   %ecx,%ecx
jle    11f0 <bn_sub_words+0xf0>
push   %rbp
push   %r14
push   %rbx
mov    (%rsi),%rax
xor    %r11d,%r11d
sub    (%rdx),%rax
setb   %r11b
mov    %eax,%eax
mov    %rax,(%rdi)
cmp    $0x1,%ecx
je     11f6 <bn_sub_words+0xf6>
mov    %ecx,%r9d
lea    -0x2(%r9),%r8
add    $0xfffffffffffffffc,%r9
xor    %r10d,%r10d
cs nopw 0x0(%rax,%rax,1)
nop
mov    0x8(%rsi,%r10,8),%r14
mov    0x8(%rdx,%r10,8),%rbx
mov    %r14d,%eax
sub    %ebx,%eax
sub    %r11d,%eax
mov    %rax,0x8(%rdi,%r10,8)
xor    %eax,%eax
cmp    %rbx,%r14
setb   %al
cmove  %r11d,%eax
cmp    %r10d,%r8d
je     11f3 <bn_sub_words+0xf3>
mov    0x10(%rsi,%r10,8),%r14
mov    0x10(%rdx,%r10,8),%rbp
mov    %r14d,%ebx
sub    %ebp,%ebx
sub    %eax,%ebx
mov    %rbx,0x10(%rdi,%r10,8)
xor    %r11d,%r11d
cmp    %rbp,%r14
setb   %r11b
cmove  %eax,%r11d
sub    $0x4,%ecx
jb     11f6 <bn_sub_words+0xf6>
mov    0x18(%rsi,%r10,8),%r14
mov    0x18(%rdx,%r10,8),%rbp
mov    %r14d,%ebx
sub    %ebp,%ebx
sub    %r11d,%ebx
mov    %rbx,0x18(%rdi,%r10,8)
xor    %eax,%eax
cmp    %rbp,%r14
setb   %al
cmove  %r11d,%eax
cmp    %r10d,%r9d
je     11f3 <bn_sub_words+0xf3>
mov    0x20(%rsi,%r10,8),%r14
mov    0x20(%rdx,%r10,8),%rbp
mov    %r14d,%ebx
sub    %ebp,%ebx
sub    %eax,%ebx
mov    %rbx,0x20(%rdi,%r10,8)
xor    %r11d,%r11d
cmp    %rbp,%r14
setb   %r11b
cmove  %eax,%r11d
add    $0x4,%r10
cmp    $0x1,%ecx
ja     1140 <bn_sub_words+0x40>
jmp    11f6 <bn_sub_words+0xf6>
xor    %eax,%eax
ret
mov    %eax,%r11d
mov    %r11d,%eax
pop    %rbx
pop    %r14
pop    %rbp
ret

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

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