int Mcountch(int nargs, int *args) {
  char *from, *to;
  int ch;
  char *c;
  from = (char *)args[0];
  to = (char *)args[1];
  ch = args[2];
  int i;
  for (i = 0, c = from; c <= to; c++)
    i += (*c == ch);
  return i;
}


x86 assembly (clang, -O0):
<Mcountch>:
push   %rbp
mov    %rsp,%rbp
mov    %edi,-0x4(%rbp)
mov    %rsi,-0x10(%rbp)
mov    -0x10(%rbp),%rax
movslq (%rax),%rax
mov    %rax,-0x18(%rbp)
mov    -0x10(%rbp),%rax
movslq 0x4(%rax),%rax
mov    %rax,-0x20(%rbp)
mov    -0x10(%rbp),%rax
mov    0x8(%rax),%eax
mov    %eax,-0x24(%rbp)
movl   $0x0,-0x34(%rbp)
mov    -0x18(%rbp),%rax
mov    %rax,-0x30(%rbp)
mov    -0x30(%rbp),%rax
cmp    -0x20(%rbp),%rax
ja     1172 <Mcountch+0x72>
mov    -0x30(%rbp),%rax
movsbl (%rax),%eax
cmp    -0x24(%rbp),%eax
sete   %al
and    $0x1,%al
movzbl %al,%eax
add    -0x34(%rbp),%eax
mov    %eax,-0x34(%rbp)
mov    -0x30(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x30(%rbp)
jmp    113b <Mcountch+0x3b>
mov    -0x34(%rbp),%eax
pop    %rbp
ret

x86 assembly (clang, -O2):
<Mcountch>:
movslq (%rsi),%rcx
movslq 0x4(%rsi),%rdx
xor    %eax,%eax
cmp    %rdx,%rcx
ja     1267 <Mcountch+0x167>
lea    0x1(%rcx),%rax
lea    0x1(%rdx),%r10
cmp    %r10,%rax
cmova  %rax,%r10
mov    0x8(%rsi),%r11d
sub    %rcx,%r10
cmp    $0x8,%r10
jae    1135 <Mcountch+0x35>
xor    %eax,%eax
jmp    1250 <Mcountch+0x150>
mov    %r10,%r8
and    $0xfffffffffffffff8,%r8
movd   %r11d,%xmm0
pshufd $0x0,%xmm0,%xmm0
lea    -0x8(%r8),%rax
mov    %rax,%r9
shr    $0x3,%r9
add    $0x1,%r9
test   %rax,%rax
je     1268 <Mcountch+0x168>
mov    %r9,%rdi
and    $0xfffffffffffffffe,%rdi
pxor   %xmm1,%xmm1
xor    %eax,%eax
pxor   %xmm2,%xmm2
nop
movd   (%rcx,%rax,1),%xmm3
punpcklbw %xmm3,%xmm3
punpcklwd %xmm3,%xmm3
movd   0x4(%rcx,%rax,1),%xmm4
punpcklbw %xmm4,%xmm4
punpcklwd %xmm4,%xmm4
psrad  $0x18,%xmm3
psrad  $0x18,%xmm4
pcmpeqd %xmm0,%xmm3
psubd  %xmm3,%xmm1
pcmpeqd %xmm0,%xmm4
psubd  %xmm4,%xmm2
movd   0x8(%rcx,%rax,1),%xmm3
punpcklbw %xmm3,%xmm3
punpcklwd %xmm3,%xmm3
movd   0xc(%rcx,%rax,1),%xmm4
punpcklbw %xmm4,%xmm4
punpcklwd %xmm4,%xmm4
psrad  $0x18,%xmm3
psrad  $0x18,%xmm4
pcmpeqd %xmm0,%xmm3
psubd  %xmm3,%xmm1
pcmpeqd %xmm0,%xmm4
psubd  %xmm4,%xmm2
add    $0x10,%rax
add    $0xfffffffffffffffe,%rdi
jne    1170 <Mcountch+0x70>
test   $0x1,%r9b
je     1220 <Mcountch+0x120>
movd   (%rcx,%rax,1),%xmm3
movd   0x4(%rcx,%rax,1),%xmm4
punpcklbw %xmm3,%xmm3
punpcklwd %xmm3,%xmm3
psrad  $0x18,%xmm3
punpcklbw %xmm4,%xmm4
punpcklwd %xmm4,%xmm4
psrad  $0x18,%xmm4
pcmpeqd %xmm0,%xmm3
psubd  %xmm3,%xmm1
pcmpeqd %xmm0,%xmm4
psubd  %xmm4,%xmm2
paddd  %xmm2,%xmm1
pshufd $0xee,%xmm1,%xmm0
paddd  %xmm1,%xmm0
pshufd $0x55,%xmm0,%xmm1
paddd  %xmm0,%xmm1
movd   %xmm1,%eax
cmp    %r8,%r10
je     1267 <Mcountch+0x167>
add    %r8,%rcx
cs nopw 0x0(%rax,%rax,1)
nopl   0x0(%rax)
movsbl (%rcx),%edi
xor    %esi,%esi
cmp    %edi,%r11d
sete   %sil
add    %esi,%eax
add    $0x1,%rcx
cmp    %rdx,%rcx
jbe    1250 <Mcountch+0x150>
ret
pxor   %xmm1,%xmm1
xor    %eax,%eax
pxor   %xmm2,%xmm2
test   $0x1,%r9b
jne    11eb <Mcountch+0xeb>
jmp    1220 <Mcountch+0x120>

LLVM IR (-O0):
define i32 @Mcountch(i32 %0, i32* %1) {
%3 = alloca i32
%4 = alloca i32*
%5 = alloca i8*
%6 = alloca i8*
%7 = alloca i32
%8 = alloca i8*
%9 = alloca i32
store i32 %0, i32* %3
store i32* %1, i32** %4
%10 = load i32*, i32** %4
%11 = getelementptr inbounds i32, i32* %10, i64 0
%12 = load i32, i32* %11
%13 = sext i32 %12 to i64
%14 = inttoptr i64 %13 to i8*
store i8* %14, i8** %5
%15 = load i32*, i32** %4
%16 = getelementptr inbounds i32, i32* %15, i64 1
%17 = load i32, i32* %16
%18 = sext i32 %17 to i64
%19 = inttoptr i64 %18 to i8*
store i8* %19, i8** %6
%20 = load i32*, i32** %4
%21 = getelementptr inbounds i32, i32* %20, i64 2
%22 = load i32, i32* %21
store i32 %22, i32* %7
store i32 0, i32* %9
%23 = load i8*, i8** %5
store i8* %23, i8** %8
br label %24
24: ; preds = %37, %2
%25 = load i8*, i8** %8
%26 = load i8*, i8** %6
%27 = icmp ule i8* %25, %26
br i1 %27, label %28, label %40
28: ; preds = %24
%29 = load i8*, i8** %8
%30 = load i8, i8* %29
%31 = sext i8 %30 to i32
%32 = load i32, i32* %7
%33 = icmp eq i32 %31, %32
%34 = zext i1 %33 to i32
%35 = load i32, i32* %9
%36 = add nsw i32 %35, %34
store i32 %36, i32* %9
br label %37
37: ; preds = %28
%38 = load i8*, i8** %8
%39 = getelementptr inbounds i8, i8* %38, i32 1
store i8* %39, i8** %8
br label %24
40: ; preds = %24
%41 = load i32, i32* %9
ret i32 %41
}

LLVM IR (-O2):
define i32 @Mcountch(i32 %0, i32* nocapture %1) {
%3 = load i32, i32* %1
%4 = sext i32 %3 to i64
%5 = inttoptr i64 %4 to i8*
%6 = getelementptr inbounds i32, i32* %1, i64 1
%7 = load i32, i32* %6
%8 = sext i32 %7 to i64
%9 = inttoptr i64 %8 to i8*
%10 = getelementptr inbounds i32, i32* %1, i64 2
%11 = load i32, i32* %10
%12 = icmp ugt i8* %5, %9
br i1 %12, label %111, label %13
13: ; preds = %2
%14 = add nsw i64 %4, 1
%15 = add nuw nsw i64 %8, 1
%16 = call i64 @llvm.umax.i64(i64 %14, i64 %15)
%17 = sub i64 %16, %4
%18 = icmp ult i64 %17, 8
br i1 %18, label %98, label %19
19: ; preds = %13
%20 = and i64 %17, -8
%21 = getelementptr i8, i8* %5, i64 %20
%22 = insertelement <4 x i32> poison, i32 %11, i64 0
%23 = shufflevector <4 x i32> %22, <4 x i32> poison, <4 x i32> zeroinitializer
%24 = insertelement <4 x i32> poison, i32 %11, i64 0
%25 = shufflevector <4 x i32> %24, <4 x i32> poison, <4 x i32> zeroinitializer
%26 = add i64 %20, -8
%27 = lshr exact i64 %26, 3
%28 = add nuw nsw i64 %27, 1
%29 = and i64 %28, 1
%30 = icmp eq i64 %26, 0
br i1 %30, label %70, label %31
31: ; preds = %19
%32 = and i64 %28, 4611686018427387902
br label %33
33: ; preds = %33, %31
%34 = phi i64 [ 0, %31 ], [ %67, %33 ]
%35 = phi <4 x i32> [ zeroinitializer, %31 ], [ %65, %33 ]
%36 = phi <4 x i32> [ zeroinitializer, %31 ], [ %66, %33 ]
%37 = phi i64 [ 0, %31 ], [ %68, %33 ]
%38 = getelementptr i8, i8* %5, i64 %34
%39 = bitcast i8* %38 to <4 x i8>*
%40 = load <4 x i8>, <4 x i8>* %39
%41 = getelementptr i8, i8* %38, i64 4
%42 = bitcast i8* %41 to <4 x i8>*
%43 = load <4 x i8>, <4 x i8>* %42
%44 = sext <4 x i8> %40 to <4 x i32>
%45 = sext <4 x i8> %43 to <4 x i32>
%46 = icmp eq <4 x i32> %23, %44
%47 = icmp eq <4 x i32> %25, %45
%48 = zext <4 x i1> %46 to <4 x i32>
%49 = zext <4 x i1> %47 to <4 x i32>
%50 = add <4 x i32> %35, %48
%51 = add <4 x i32> %36, %49
%52 = or i64 %34, 8
%53 = getelementptr i8, i8* %5, i64 %52
%54 = bitcast i8* %53 to <4 x i8>*
%55 = load <4 x i8>, <4 x i8>* %54
%56 = getelementptr i8, i8* %53, i64 4
%57 = bitcast i8* %56 to <4 x i8>*
%58 = load <4 x i8>, <4 x i8>* %57
%59 = sext <4 x i8> %55 to <4 x i32>
%60 = sext <4 x i8> %58 to <4 x i32>
%61 = icmp eq <4 x i32> %23, %59
%62 = icmp eq <4 x i32> %25, %60
%63 = zext <4 x i1> %61 to <4 x i32>
%64 = zext <4 x i1> %62 to <4 x i32>
%65 = add <4 x i32> %50, %63
%66 = add <4 x i32> %51, %64
%67 = add nuw i64 %34, 16
%68 = add i64 %37, 2
%69 = icmp eq i64 %68, %32
br i1 %69, label %70, label %33
70: ; preds = %33, %19
%71 = phi <4 x i32> [ undef, %19 ], [ %65, %33 ]
%72 = phi <4 x i32> [ undef, %19 ], [ %66, %33 ]
%73 = phi i64 [ 0, %19 ], [ %67, %33 ]
%74 = phi <4 x i32> [ zeroinitializer, %19 ], [ %65, %33 ]
%75 = phi <4 x i32> [ zeroinitializer, %19 ], [ %66, %33 ]
%76 = icmp eq i64 %29, 0
br i1 %76, label %92, label %77
77: ; preds = %70
%78 = getelementptr i8, i8* %5, i64 %73
%79 = bitcast i8* %78 to <4 x i8>*
%80 = load <4 x i8>, <4 x i8>* %79
%81 = getelementptr i8, i8* %78, i64 4
%82 = bitcast i8* %81 to <4 x i8>*
%83 = load <4 x i8>, <4 x i8>* %82
%84 = sext <4 x i8> %80 to <4 x i32>
%85 = sext <4 x i8> %83 to <4 x i32>
%86 = icmp eq <4 x i32> %23, %84
%87 = icmp eq <4 x i32> %25, %85
%88 = zext <4 x i1> %86 to <4 x i32>
%89 = zext <4 x i1> %87 to <4 x i32>
%90 = add <4 x i32> %74, %88
%91 = add <4 x i32> %75, %89
br label %92
92: ; preds = %70, %77
%93 = phi <4 x i32> [ %71, %70 ], [ %90, %77 ]
%94 = phi <4 x i32> [ %72, %70 ], [ %91, %77 ]
%95 = add <4 x i32> %94, %93
%96 = call i32 @llvm.vector.reduce.add.v4i32(<4 x i32> %95)
%97 = icmp eq i64 %17, %20
br i1 %97, label %111, label %98
98: ; preds = %13, %92
%99 = phi i32 [ 0, %13 ], [ %96, %92 ]
%100 = phi i8* [ %5, %13 ], [ %21, %92 ]
br label %101
101: ; preds = %98, %101
%102 = phi i32 [ %108, %101 ], [ %99, %98 ]
%103 = phi i8* [ %109, %101 ], [ %100, %98 ]
%104 = load i8, i8* %103
%105 = sext i8 %104 to i32
%106 = icmp eq i32 %11, %105
%107 = zext i1 %106 to i32
%108 = add nuw nsw i32 %102, %107
%109 = getelementptr inbounds i8, i8* %103, i64 1
%110 = icmp ugt i8* %109, %9
br i1 %110, label %111, label %101
111: ; preds = %101, %92, %2
%112 = phi i32 [ 0, %2 ], [ %96, %92 ], [ %108, %101 ]
ret i32 %112
}