int is_last_char_valid(char id[], int len) {
  int weights[17] = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};
  int sum = 0;
  for (int i = 0; i < len - 1; i++) {
    int num = id[i] - '0';
    sum += num * weights[i];
  }
  int z = sum % 11;
  int z_check[11] = {'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'};
  char last = z_check[z];
  if (last == id[len - 1]) {
    return 1;
  } else {
    return 0;
  }
}


x86 assembly (clang, -O0):
<is_last_char_valid>:
push   %rbp
mov    %rsp,%rbp
sub    $0xb0,%rsp
mov    %rdi,-0x10(%rbp)
mov    %esi,-0x14(%rbp)
lea    -0x60(%rbp),%rdi
lea    0xed3(%rip),%rsi
mov    $0x44,%edx
call   1030 <memcpy@plt>
movl   $0x0,-0x64(%rbp)
movl   $0x0,-0x68(%rbp)
mov    -0x68(%rbp),%eax
mov    -0x14(%rbp),%ecx
sub    $0x1,%ecx
cmp    %ecx,%eax
jge    1188 <is_last_char_valid+0x78>
mov    -0x10(%rbp),%rax
movslq -0x68(%rbp),%rcx
movsbl (%rax,%rcx,1),%eax
sub    $0x30,%eax
mov    %eax,-0x6c(%rbp)
mov    -0x6c(%rbp),%eax
movslq -0x68(%rbp),%rcx
imul   -0x60(%rbp,%rcx,4),%eax
add    -0x64(%rbp),%eax
mov    %eax,-0x64(%rbp)
mov    -0x68(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x68(%rbp)
jmp    1145 <is_last_char_valid+0x35>
mov    -0x64(%rbp),%eax
mov    $0xb,%ecx
cltd
idiv   %ecx
mov    %edx,-0x70(%rbp)
lea    -0xa0(%rbp),%rdi
lea    0xeac(%rip),%rsi
mov    $0x2c,%edx
call   1030 <memcpy@plt>
movslq -0x70(%rbp),%rax
mov    -0xa0(%rbp,%rax,4),%eax
mov    %al,-0xa1(%rbp)
movsbl -0xa1(%rbp),%eax
mov    -0x10(%rbp),%rcx
mov    -0x14(%rbp),%edx
sub    $0x1,%edx
movslq %edx,%rdx
movsbl (%rcx,%rdx,1),%ecx
cmp    %ecx,%eax
jne    11eb <is_last_char_valid+0xdb>
movl   $0x1,-0x4(%rbp)
jmp    11f2 <is_last_char_valid+0xe2>
movl   $0x0,-0x4(%rbp)
mov    -0x4(%rbp),%eax
add    $0xb0,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<is_last_char_valid>:
lea    -0x1(%rsi),%r8d
xor    %eax,%eax
cmp    $0x2,%esi
jl     1237 <is_last_char_valid+0x137>
mov    %r8d,%r10d
cmp    $0x8,%r8d
jae    1120 <is_last_char_valid+0x20>
xor    %r9d,%r9d
jmp    11ec <is_last_char_valid+0xec>
mov    %r10d,%r9d
and    $0xfffffff8,%r9d
pxor   %xmm0,%xmm0
xor    %eax,%eax
movdqa 0xecb(%rip),%xmm2
lea    0xed4(%rip),%rsi
pxor   %xmm1,%xmm1
movd   (%rdi,%rax,1),%xmm3
punpcklbw %xmm3,%xmm3
punpcklwd %xmm3,%xmm3
movd   0x4(%rdi,%rax,1),%xmm4
punpcklbw %xmm4,%xmm4
punpcklwd %xmm4,%xmm4
psrad  $0x18,%xmm3
psrad  $0x18,%xmm4
paddd  %xmm2,%xmm3
paddd  %xmm2,%xmm4
movdqa (%rsi,%rax,4),%xmm5
movdqa 0x10(%rsi,%rax,4),%xmm6
pshufd $0xf5,%xmm3,%xmm7
pmuludq %xmm5,%xmm3
pshufd $0xe8,%xmm3,%xmm3
pshufd $0xf5,%xmm5,%xmm5
pmuludq %xmm7,%xmm5
pshufd $0xe8,%xmm5,%xmm5
punpckldq %xmm5,%xmm3
paddd  %xmm3,%xmm0
pshufd $0xf5,%xmm4,%xmm3
pmuludq %xmm6,%xmm4
pshufd $0xe8,%xmm4,%xmm4
pshufd $0xf5,%xmm6,%xmm5
pmuludq %xmm3,%xmm5
pshufd $0xe8,%xmm5,%xmm3
punpckldq %xmm3,%xmm4
paddd  %xmm4,%xmm1
add    $0x8,%rax
cmp    %rax,%r9
jne    1140 <is_last_char_valid+0x40>
paddd  %xmm0,%xmm1
pshufd $0xee,%xmm1,%xmm0
paddd  %xmm1,%xmm0
pshufd $0x55,%xmm0,%xmm1
paddd  %xmm0,%xmm1
movd   %xmm1,%eax
cmp    %r10,%r9
je     1217 <is_last_char_valid+0x117>
lea    0xe1d(%rip),%rcx
lea    (%rcx,%r9,4),%r11
lea    (%rdi,%r9,1),%rdx
sub    %r9,%r10
xor    %ecx,%ecx
movsbl (%rdx,%rcx,1),%esi
add    $0xffffffd0,%esi
imul   (%r11,%rcx,4),%esi
add    %esi,%eax
add    $0x1,%rcx
cmp    %rcx,%r10
jne    1200 <is_last_char_valid+0x100>
cltq
imul   $0x2e8ba2e9,%rax,%rcx
mov    %rcx,%rdx
shr    $0x3f,%rdx
sar    $0x21,%rcx
add    %edx,%ecx
lea    (%rcx,%rcx,4),%edx
lea    (%rcx,%rdx,2),%ecx
sub    %ecx,%eax
cltq
lea    0xe22(%rip),%rcx
movsbl (%rcx,%rax,4),%ecx
movslq %r8d,%rax
movsbl (%rdi,%rax,1),%edx
xor    %eax,%eax
cmp    %edx,%ecx
sete   %al
ret

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

LLVM IR (-O2):
@__const.is_last_char_valid.weights = [17 x i32] [i32 7, i32 9, i32 10, i32 5, i32 8, i32 4, i32 2, i32 1, i32 6, i32 3, i32 7, i32 9, i32 10, i32 5, i32 8, i32 4, i32 2]
@__const.is_last_char_valid.z_check = [11 x i32] [i32 49, i32 48, i32 88, i32 57, i32 56, i32 55, i32 54, i32 53, i32 52, i32 51, i32 50]
define i32 @is_last_char_valid(i8* nocapture %0, i32 %1) {
%3 = add i32 %1, -1
%4 = icmp sgt i32 %1, 1
br i1 %4, label %5, label %47
5: ; preds = %2
%6 = zext i32 %3 to i64
%7 = icmp ult i32 %3, 8
br i1 %7, label %40, label %8
8: ; preds = %5
%9 = and i64 %6, 4294967288
br label %10
10: ; preds = %10, %8
%11 = phi i64 [ 0, %8 ], [ %34, %10 ]
%12 = phi <4 x i32> [ zeroinitializer, %8 ], [ %32, %10 ]
%13 = phi <4 x i32> [ zeroinitializer, %8 ], [ %33, %10 ]
%14 = getelementptr inbounds i8, i8* %0, i64 %11
%15 = bitcast i8* %14 to <4 x i8>*
%16 = load <4 x i8>, <4 x i8>* %15
%17 = getelementptr inbounds i8, i8* %14, i64 4
%18 = bitcast i8* %17 to <4 x i8>*
%19 = load <4 x i8>, <4 x i8>* %18
%20 = sext <4 x i8> %16 to <4 x i32>
%21 = sext <4 x i8> %19 to <4 x i32>
%22 = add nsw <4 x i32> %20, <i32 -48, i32 -48, i32 -48, i32 -48>
%23 = add nsw <4 x i32> %21, <i32 -48, i32 -48, i32 -48, i32 -48>
%24 = getelementptr inbounds [17 x i32], [17 x i32]* @__const.is_last_char_valid.weights, i64 0, i64 %11
%25 = bitcast i32* %24 to <4 x i32>*
%26 = load <4 x i32>, <4 x i32>* %25
%27 = getelementptr inbounds i32, i32* %24, i64 4
%28 = bitcast i32* %27 to <4 x i32>*
%29 = load <4 x i32>, <4 x i32>* %28
%30 = mul nsw <4 x i32> %22, %26
%31 = mul nsw <4 x i32> %23, %29
%32 = add <4 x i32> %30, %12
%33 = add <4 x i32> %31, %13
%34 = add nuw i64 %11, 8
%35 = icmp eq i64 %34, %9
br i1 %35, label %36, label %10
36: ; preds = %10
%37 = add <4 x i32> %33, %32
%38 = call i32 @llvm.vector.reduce.add.v4i32(<4 x i32> %37)
%39 = icmp eq i64 %9, %6
br i1 %39, label %43, label %40
40: ; preds = %5, %36
%41 = phi i64 [ 0, %5 ], [ %9, %36 ]
%42 = phi i32 [ 0, %5 ], [ %38, %36 ]
br label %59
43: ; preds = %59, %36
%44 = phi i32 [ %38, %36 ], [ %69, %59 ]
%45 = srem i32 %44, 11
%46 = sext i32 %45 to i64
br label %47
47: ; preds = %43, %2
%48 = phi i64 [ 0, %2 ], [ %46, %43 ]
%49 = getelementptr inbounds [11 x i32], [11 x i32]* @__const.is_last_char_valid.z_check, i64 0, i64 %48
%50 = load i32, i32* %49
%51 = shl i32 %50, 24
%52 = ashr exact i32 %51, 24
%53 = sext i32 %3 to i64
%54 = getelementptr inbounds i8, i8* %0, i64 %53
%55 = load i8, i8* %54
%56 = sext i8 %55 to i32
%57 = icmp eq i32 %52, %56
%58 = zext i1 %57 to i32
ret i32 %58
59: ; preds = %40, %59
%60 = phi i64 [ %70, %59 ], [ %41, %40 ]
%61 = phi i32 [ %69, %59 ], [ %42, %40 ]
%62 = getelementptr inbounds i8, i8* %0, i64 %60
%63 = load i8, i8* %62
%64 = sext i8 %63 to i32
%65 = add nsw i32 %64, -48
%66 = getelementptr inbounds [17 x i32], [17 x i32]* @__const.is_last_char_valid.weights, i64 0, i64 %60
%67 = load i32, i32* %66
%68 = mul nsw i32 %65, %67
%69 = add nsw i32 %68, %61
%70 = add nuw nsw i64 %60, 1
%71 = icmp eq i64 %70, %6
br i1 %71, label %43, label %59
}