void __attribute__((noipa))
f(unsigned short *restrict a, unsigned char *restrict b,
  unsigned char *restrict c) {
  for (long int i = 0; i < 50; ++i) {
    int bv = (unsigned char)b[i];
    int cv = (unsigned char)c[i];
    a[i] = bv * cv;
  }
}


x86 assembly (clang, -O0):
<f>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %rdx,-0x18(%rbp)
movq   $0x0,-0x20(%rbp)
cmpq   $0x32,-0x20(%rbp)
jge    1168 <f+0x68>
mov    -0x10(%rbp),%rax
mov    -0x20(%rbp),%rcx
movzbl (%rax,%rcx,1),%eax
mov    %eax,-0x24(%rbp)
mov    -0x18(%rbp),%rax
mov    -0x20(%rbp),%rcx
movzbl (%rax,%rcx,1),%eax
mov    %eax,-0x28(%rbp)
mov    -0x24(%rbp),%eax
imul   -0x28(%rbp),%eax
mov    %ax,%dx
mov    -0x8(%rbp),%rax
mov    -0x20(%rbp),%rcx
mov    %dx,(%rax,%rcx,2)
mov    -0x20(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x20(%rbp)
jmp    1118 <f+0x18>
pop    %rbp
ret

x86 assembly (clang, -O2):
<f>:
movq   (%rsi),%xmm1
pxor   %xmm0,%xmm0
punpcklbw %xmm0,%xmm1
movq   (%rdx),%xmm2
punpcklbw %xmm0,%xmm2
pmullw %xmm1,%xmm2
movdqu %xmm2,(%rdi)
movq   0x8(%rsi),%xmm1
punpcklbw %xmm0,%xmm1
movq   0x8(%rdx),%xmm2
punpcklbw %xmm0,%xmm2
pmullw %xmm1,%xmm2
movdqu %xmm2,0x10(%rdi)
movq   0x10(%rsi),%xmm1
punpcklbw %xmm0,%xmm1
movq   0x10(%rdx),%xmm2
punpcklbw %xmm0,%xmm2
pmullw %xmm1,%xmm2
movdqu %xmm2,0x20(%rdi)
movq   0x18(%rsi),%xmm1
punpcklbw %xmm0,%xmm1
movq   0x18(%rdx),%xmm2
punpcklbw %xmm0,%xmm2
pmullw %xmm1,%xmm2
movdqu %xmm2,0x30(%rdi)
movq   0x20(%rsi),%xmm1
punpcklbw %xmm0,%xmm1
movq   0x20(%rdx),%xmm2
punpcklbw %xmm0,%xmm2
pmullw %xmm1,%xmm2
movdqu %xmm2,0x40(%rdi)
movq   0x28(%rsi),%xmm1
punpcklbw %xmm0,%xmm1
movq   0x28(%rdx),%xmm2
punpcklbw %xmm0,%xmm2
pmullw %xmm1,%xmm2
movdqu %xmm2,0x50(%rdi)
movzbl 0x30(%rsi),%eax
movzbl 0x30(%rdx),%ecx
imul   %eax,%ecx
mov    %cx,0x60(%rdi)
movzbl 0x31(%rsi),%eax
movzbl 0x31(%rdx),%ecx
imul   %eax,%ecx
mov    %cx,0x62(%rdi)
ret

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

LLVM IR (-O2):
define void @f(i16* noalias nocapture writeonly %0, i8* noalias nocapture %1, i8* noalias nocapture %2) {
%4 = bitcast i8* %1 to <8 x i8>*
%5 = load <8 x i8>, <8 x i8>* %4
%6 = zext <8 x i8> %5 to <8 x i16>
%7 = bitcast i8* %2 to <8 x i8>*
%8 = load <8 x i8>, <8 x i8>* %7
%9 = zext <8 x i8> %8 to <8 x i16>
%10 = mul nuw <8 x i16> %9, %6
%11 = bitcast i16* %0 to <8 x i16>*
store <8 x i16> %10, <8 x i16>* %11
%12 = getelementptr inbounds i8, i8* %1, i64 8
%13 = bitcast i8* %12 to <8 x i8>*
%14 = load <8 x i8>, <8 x i8>* %13
%15 = zext <8 x i8> %14 to <8 x i16>
%16 = getelementptr inbounds i8, i8* %2, i64 8
%17 = bitcast i8* %16 to <8 x i8>*
%18 = load <8 x i8>, <8 x i8>* %17
%19 = zext <8 x i8> %18 to <8 x i16>
%20 = mul nuw <8 x i16> %19, %15
%21 = getelementptr inbounds i16, i16* %0, i64 8
%22 = bitcast i16* %21 to <8 x i16>*
store <8 x i16> %20, <8 x i16>* %22
%23 = getelementptr inbounds i8, i8* %1, i64 16
%24 = bitcast i8* %23 to <8 x i8>*
%25 = load <8 x i8>, <8 x i8>* %24
%26 = zext <8 x i8> %25 to <8 x i16>
%27 = getelementptr inbounds i8, i8* %2, i64 16
%28 = bitcast i8* %27 to <8 x i8>*
%29 = load <8 x i8>, <8 x i8>* %28
%30 = zext <8 x i8> %29 to <8 x i16>
%31 = mul nuw <8 x i16> %30, %26
%32 = getelementptr inbounds i16, i16* %0, i64 16
%33 = bitcast i16* %32 to <8 x i16>*
store <8 x i16> %31, <8 x i16>* %33
%34 = getelementptr inbounds i8, i8* %1, i64 24
%35 = bitcast i8* %34 to <8 x i8>*
%36 = load <8 x i8>, <8 x i8>* %35
%37 = zext <8 x i8> %36 to <8 x i16>
%38 = getelementptr inbounds i8, i8* %2, i64 24
%39 = bitcast i8* %38 to <8 x i8>*
%40 = load <8 x i8>, <8 x i8>* %39
%41 = zext <8 x i8> %40 to <8 x i16>
%42 = mul nuw <8 x i16> %41, %37
%43 = getelementptr inbounds i16, i16* %0, i64 24
%44 = bitcast i16* %43 to <8 x i16>*
store <8 x i16> %42, <8 x i16>* %44
%45 = getelementptr inbounds i8, i8* %1, i64 32
%46 = bitcast i8* %45 to <8 x i8>*
%47 = load <8 x i8>, <8 x i8>* %46
%48 = zext <8 x i8> %47 to <8 x i16>
%49 = getelementptr inbounds i8, i8* %2, i64 32
%50 = bitcast i8* %49 to <8 x i8>*
%51 = load <8 x i8>, <8 x i8>* %50
%52 = zext <8 x i8> %51 to <8 x i16>
%53 = mul nuw <8 x i16> %52, %48
%54 = getelementptr inbounds i16, i16* %0, i64 32
%55 = bitcast i16* %54 to <8 x i16>*
store <8 x i16> %53, <8 x i16>* %55
%56 = getelementptr inbounds i8, i8* %1, i64 40
%57 = bitcast i8* %56 to <8 x i8>*
%58 = load <8 x i8>, <8 x i8>* %57
%59 = zext <8 x i8> %58 to <8 x i16>
%60 = getelementptr inbounds i8, i8* %2, i64 40
%61 = bitcast i8* %60 to <8 x i8>*
%62 = load <8 x i8>, <8 x i8>* %61
%63 = zext <8 x i8> %62 to <8 x i16>
%64 = mul nuw <8 x i16> %63, %59
%65 = getelementptr inbounds i16, i16* %0, i64 40
%66 = bitcast i16* %65 to <8 x i16>*
store <8 x i16> %64, <8 x i16>* %66
%67 = getelementptr inbounds i8, i8* %1, i64 48
%68 = load i8, i8* %67
%69 = zext i8 %68 to i16
%70 = getelementptr inbounds i8, i8* %2, i64 48
%71 = load i8, i8* %70
%72 = zext i8 %71 to i16
%73 = mul nuw i16 %72, %69
%74 = getelementptr inbounds i16, i16* %0, i64 48
store i16 %73, i16* %74
%75 = getelementptr inbounds i8, i8* %1, i64 49
%76 = load i8, i8* %75
%77 = zext i8 %76 to i16
%78 = getelementptr inbounds i8, i8* %2, i64 49
%79 = load i8, i8* %78
%80 = zext i8 %79 to i16
%81 = mul nuw i16 %80, %77
%82 = getelementptr inbounds i16, i16* %0, i64 49
store i16 %81, i16* %82
ret void
}