unsigned short multip(unsigned char x, unsigned char y) {
  unsigned char i;
  unsigned short res = 0;
  for (i = 0; i < 8; i++) {
    if (y & 1) {
      res += x << i;
    }
    y >>= 1;
  }
  return res;
}


x86 assembly (clang, -O0):
<multip>:
push   %rbp
mov    %rsp,%rbp
mov    %sil,%al
mov    %dil,%cl
mov    %cl,-0x1(%rbp)
mov    %al,-0x2(%rbp)
movw   $0x0,-0x6(%rbp)
movb   $0x0,-0x3(%rbp)
movzbl -0x3(%rbp),%eax
cmp    $0x8,%eax
jge    1164 <multip+0x64>
movzbl -0x2(%rbp),%eax
and    $0x1,%eax
cmp    $0x0,%eax
je     114d <multip+0x4d>
movzbl -0x1(%rbp),%eax
movzbl -0x3(%rbp),%ecx
shl    %cl,%eax
mov    %eax,%ecx
movzwl -0x6(%rbp),%eax
add    %ecx,%eax
mov    %ax,-0x6(%rbp)
movzbl -0x2(%rbp),%eax
sar    $0x1,%eax
mov    %al,-0x2(%rbp)
mov    -0x3(%rbp),%al
add    $0x1,%al
mov    %al,-0x3(%rbp)
jmp    111a <multip+0x1a>
movzwl -0x6(%rbp),%eax
pop    %rbp
ret

x86 assembly (clang, -O2):
<multip>:
mov    %esi,%eax
and    $0x1,%al
neg    %al
and    %dil,%al
movzbl %al,%r8d
lea    (%rdi,%rdi,1),%r9d
xor    %eax,%eax
test   $0x2,%sil
cmove  %eax,%r9d
lea    0x0(,%rdi,4),%ecx
test   $0x4,%sil
cmove  %eax,%ecx
movd   %esi,%xmm0
punpcklbw %xmm0,%xmm0
pshuflw $0x0,%xmm0,%xmm0
pand   0xec2(%rip),%xmm0
pxor   %xmm1,%xmm1
pcmpeqb %xmm0,%xmm1
punpcklbw %xmm1,%xmm0
psraw  $0x8,%xmm0
movd   %edi,%xmm1
pshuflw $0x0,%xmm1,%xmm1
pand   0xeb0(%rip),%xmm1
pmullw 0xeb8(%rip),%xmm1
pandn  %xmm1,%xmm0
pshufd $0x55,%xmm0,%xmm1
paddw  %xmm0,%xmm1
movdqa %xmm1,%xmm0
psrld  $0x10,%xmm0
paddw  %xmm1,%xmm0
movd   %xmm0,%edx
add    %ecx,%edx
add    %r9d,%edx
add    %r8d,%edx
shl    $0x7,%edi
test   %sil,%sil
cmovs  %edi,%eax
add    %edx,%eax
ret

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

LLVM IR (-O2):
define zeroext i16 @multip(i8 zeroext %0, i8 zeroext %1) {
%3 = zext i8 %0 to i16
%4 = and i8 %1, 1
%5 = icmp eq i8 %4, 0
%6 = select i1 %5, i8 0, i8 %0
%7 = zext i8 %6 to i16
%8 = and i8 %1, 2
%9 = icmp eq i8 %8, 0
%10 = zext i8 %0 to i16
%11 = shl nuw nsw i16 %10, 1
%12 = select i1 %9, i16 0, i16 %11
%13 = and i8 %1, 4
%14 = icmp eq i8 %13, 0
%15 = zext i8 %0 to i16
%16 = shl nuw nsw i16 %15, 2
%17 = select i1 %14, i16 0, i16 %16
%18 = insertelement <4 x i8> poison, i8 %1, i64 0
%19 = shufflevector <4 x i8> %18, <4 x i8> poison, <4 x i32> zeroinitializer
%20 = and <4 x i8> %19, <i8 64, i8 32, i8 16, i8 8>
%21 = icmp eq <4 x i8> %20, zeroinitializer
%22 = insertelement <4 x i8> poison, i8 %0, i64 0
%23 = shufflevector <4 x i8> %22, <4 x i8> poison, <4 x i32> zeroinitializer
%24 = zext <4 x i8> %23 to <4 x i16>
%25 = shl nuw nsw <4 x i16> %24, <i16 6, i16 5, i16 4, i16 3>
%26 = select <4 x i1> %21, <4 x i16> zeroinitializer, <4 x i16> %25
%27 = call i16 @llvm.vector.reduce.add.v4i16(<4 x i16> %26)
%28 = add nuw nsw i16 %27, %17
%29 = add nuw nsw i16 %28, %12
%30 = add nuw nsw i16 %29, %7
%31 = icmp sgt i8 %1, -1
%32 = shl nuw nsw i16 %3, 7
%33 = select i1 %31, i16 0, i16 %32
%34 = add nuw i16 %33, %30
ret i16 %34
}