void m16m(a, b, c) unsigned short a;
unsigned short b[], c[];
{
  register unsigned short *pp;
  register unsigned long carry;
  unsigned short *ps;
  unsigned short p[(6 + 3)];
  unsigned long aa, m;
  int i;
  aa = a;
  pp = &p[(6 + 3) - 2];
  *pp++ = 0;
  *pp = 0;
  ps = &b[(6 + 3) - 1];
  for (i = 2 + 1; i < (6 + 3); i++) {
    if (*ps == 0) {
      --ps;
      --pp;
      *(pp - 1) = 0;
    } else {
      m = (unsigned long)aa * *ps--;
      carry = (m & 0xffff) + *pp;
      *pp-- = (unsigned short)carry;
      carry = (carry >> 16) + (m >> 16) + *pp;
      *pp = (unsigned short)carry;
      *(pp - 1) = carry >> 16;
    }
  }
  for (i = 2; i < (6 + 3); i++)
    c[i] = p[i];
}


x86 assembly (clang, -O0):
<m16m>:
push   %rbp
mov    %rsp,%rbp
mov    %di,%ax
mov    %ax,-0x2(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %rdx,-0x18(%rbp)
movzwl -0x2(%rbp),%eax
mov    %rax,-0x58(%rbp)
lea    -0x50(%rbp),%rax
add    $0xe,%rax
mov    %rax,-0x20(%rbp)
mov    -0x20(%rbp),%rax
mov    %rax,%rcx
add    $0x2,%rcx
mov    %rcx,-0x20(%rbp)
movw   $0x0,(%rax)
mov    -0x20(%rbp),%rax
movw   $0x0,(%rax)
mov    -0x10(%rbp),%rax
add    $0x10,%rax
mov    %rax,-0x30(%rbp)
movl   $0x3,-0x64(%rbp)
cmpl   $0x9,-0x64(%rbp)
jge    123c <m16m+0x13c>
mov    -0x30(%rbp),%rax
movzwl (%rax),%eax
cmp    $0x0,%eax
jne    1198 <m16m+0x98>
mov    -0x30(%rbp),%rax
add    $0xfffffffffffffffe,%rax
mov    %rax,-0x30(%rbp)
mov    -0x20(%rbp),%rax
add    $0xfffffffffffffffe,%rax
mov    %rax,-0x20(%rbp)
mov    -0x20(%rbp),%rax
movw   $0x0,-0x2(%rax)
jmp    1229 <m16m+0x129>
mov    -0x58(%rbp),%rax
mov    -0x30(%rbp),%rcx
mov    %rcx,%rdx
add    $0xfffffffffffffffe,%rdx
mov    %rdx,-0x30(%rbp)
movzwl (%rcx),%ecx
imul   %rcx,%rax
mov    %rax,-0x60(%rbp)
mov    -0x60(%rbp),%rax
and    $0xffff,%rax
mov    -0x20(%rbp),%rcx
movzwl (%rcx),%ecx
add    %rcx,%rax
mov    %rax,-0x28(%rbp)
mov    -0x28(%rbp),%rax
mov    %ax,%cx
mov    -0x20(%rbp),%rax
mov    %rax,%rdx
add    $0xfffffffffffffffe,%rdx
mov    %rdx,-0x20(%rbp)
mov    %cx,(%rax)
mov    -0x28(%rbp),%rax
shr    $0x10,%rax
mov    -0x60(%rbp),%rcx
shr    $0x10,%rcx
add    %rcx,%rax
mov    -0x20(%rbp),%rcx
movzwl (%rcx),%ecx
add    %rcx,%rax
mov    %rax,-0x28(%rbp)
mov    -0x28(%rbp),%rax
mov    %ax,%cx
mov    -0x20(%rbp),%rax
mov    %cx,(%rax)
mov    -0x28(%rbp),%rax
shr    $0x10,%rax
mov    %ax,%cx
mov    -0x20(%rbp),%rax
mov    %cx,-0x2(%rax)
jmp    122e <m16m+0x12e>
mov    -0x64(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x64(%rbp)
jmp    1157 <m16m+0x57>
movl   $0x2,-0x64(%rbp)
cmpl   $0x9,-0x64(%rbp)
jge    1270 <m16m+0x170>
movslq -0x64(%rbp),%rax
mov    -0x50(%rbp,%rax,2),%dx
mov    -0x18(%rbp),%rax
movslq -0x64(%rbp),%rcx
mov    %dx,(%rax,%rcx,2)
mov    -0x64(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x64(%rbp)
jmp    1243 <m16m+0x143>
pop    %rbp
ret

x86 assembly (clang, -O2):
<m16m>:
movzwl %di,%r8d
movl   $0x0,-0xa(%rsp)
movzwl 0x10(%rsi),%edi
test   %rdi,%rdi
je     1129 <m16m+0x29>
imul   %r8,%rdi
mov    %rdi,%rcx
shr    $0x10,%rcx
ror    $0x10,%edi
mov    %edi,-0xa(%rsp)
jmp    112b <m16m+0x2b>
xor    %ecx,%ecx
movw   $0x0,-0xc(%rsp)
movzwl 0xe(%rsi),%edi
test   %rdi,%rdi
je     1168 <m16m+0x68>
imul   %r8,%rdi
movzwl %di,%eax
add    %rcx,%rax
mov    %ax,-0xa(%rsp)
shr    $0x10,%rax
shr    $0x10,%rdi
add    %rax,%rdi
movzwl -0xc(%rsp),%ecx
add    %rdi,%rcx
mov    %cx,-0xc(%rsp)
shr    $0x10,%rcx
jmp    116a <m16m+0x6a>
xor    %ecx,%ecx
mov    %cx,-0xe(%rsp)
movzwl 0xc(%rsi),%ecx
test   %rcx,%rcx
je     11aa <m16m+0xaa>
imul   %r8,%rcx
movzwl %cx,%eax
movzwl -0xc(%rsp),%edi
add    %rax,%rdi
mov    %di,-0xc(%rsp)
shr    $0x10,%rdi
shr    $0x10,%rcx
add    %rdi,%rcx
movzwl -0xe(%rsp),%edi
add    %rcx,%rdi
mov    %di,-0xe(%rsp)
shr    $0x10,%rdi
jmp    11ac <m16m+0xac>
xor    %edi,%edi
mov    %di,-0x10(%rsp)
movzwl 0xa(%rsi),%ecx
test   %rcx,%rcx
je     11ec <m16m+0xec>
imul   %r8,%rcx
movzwl %cx,%eax
movzwl -0xe(%rsp),%edi
add    %rax,%rdi
mov    %di,-0xe(%rsp)
shr    $0x10,%rdi
shr    $0x10,%rcx
add    %rdi,%rcx
movzwl -0x10(%rsp),%edi
add    %rcx,%rdi
mov    %di,-0x10(%rsp)
shr    $0x10,%rdi
jmp    11ee <m16m+0xee>
xor    %edi,%edi
mov    %di,-0x12(%rsp)
movzwl 0x8(%rsi),%ecx
test   %rcx,%rcx
je     122e <m16m+0x12e>
imul   %r8,%rcx
movzwl %cx,%eax
movzwl -0x10(%rsp),%edi
add    %rax,%rdi
mov    %di,-0x10(%rsp)
shr    $0x10,%rdi
shr    $0x10,%rcx
add    %rdi,%rcx
movzwl -0x12(%rsp),%edi
add    %rcx,%rdi
mov    %di,-0x12(%rsp)
shr    $0x10,%rdi
jmp    1230 <m16m+0x130>
xor    %edi,%edi
mov    %di,-0x14(%rsp)
movzwl 0x6(%rsi),%ecx
test   %rcx,%rcx
je     125f <m16m+0x15f>
imul   %r8,%rcx
movzwl %cx,%eax
movzwl -0x12(%rsp),%esi
add    %rax,%rsi
mov    %si,-0x12(%rsp)
shr    $0x10,%ecx
shr    $0x10,%esi
add    %ecx,%esi
add    %si,-0x14(%rsp)
mov    -0x14(%rsp),%rax
mov    -0xe(%rsp),%rcx
mov    %rcx,0xa(%rdx)
mov    %rax,0x4(%rdx)
ret

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

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