int char_find_from(char *value, int value_length, char *key, int key_length,
                   int from) {
  register int i;
  register int j;
  int max_i = value_length - key_length;
  char qs_table[256];
  for (i = 0; i < 256; i++) {
    qs_table[i] = key_length + 1;
  }
  for (i = 0; i < key_length; i++) {
    qs_table[(int)key[i]] = key_length - i;
  }
  i = from;
  while (i <= max_i) {
    for (j = 0; j < key_length; j++) {
      if (value[i + j] != key[j]) {
        break;
      }
    }
    if (j == key_length) {
      return i;
    }
    i += qs_table[(int)value[i + key_length]];
  }
  return -1;
}


x86 assembly (clang, -O0):
<char_find_from>:
push   %rbp
mov    %rsp,%rbp
sub    $0xc0,%rsp
mov    %rdi,-0x10(%rbp)
mov    %esi,-0x14(%rbp)
mov    %rdx,-0x20(%rbp)
mov    %ecx,-0x24(%rbp)
mov    %r8d,-0x28(%rbp)
mov    -0x14(%rbp),%eax
sub    -0x24(%rbp),%eax
mov    %eax,-0x34(%rbp)
movl   $0x0,-0x2c(%rbp)
cmpl   $0x100,-0x2c(%rbp)
jge    115b <char_find_from+0x5b>
mov    -0x24(%rbp),%eax
add    $0x1,%eax
mov    %al,%cl
movslq -0x2c(%rbp),%rax
mov    %cl,-0x140(%rbp,%rax,1)
mov    -0x2c(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x2c(%rbp)
jmp    112d <char_find_from+0x2d>
movl   $0x0,-0x2c(%rbp)
mov    -0x2c(%rbp),%eax
cmp    -0x24(%rbp),%eax
jge    1199 <char_find_from+0x99>
mov    -0x24(%rbp),%eax
sub    -0x2c(%rbp),%eax
mov    %al,%cl
mov    -0x20(%rbp),%rax
movslq -0x2c(%rbp),%rdx
movsbl (%rax,%rdx,1),%eax
cltq
mov    %cl,-0x140(%rbp,%rax,1)
mov    -0x2c(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x2c(%rbp)
jmp    1162 <char_find_from+0x62>
mov    -0x28(%rbp),%eax
mov    %eax,-0x2c(%rbp)
mov    -0x2c(%rbp),%eax
cmp    -0x34(%rbp),%eax
jg     1238 <char_find_from+0x138>
movl   $0x0,-0x30(%rbp)
mov    -0x30(%rbp),%eax
cmp    -0x24(%rbp),%eax
jge    11fb <char_find_from+0xfb>
mov    -0x10(%rbp),%rax
mov    -0x2c(%rbp),%ecx
add    -0x30(%rbp),%ecx
movslq %ecx,%rcx
movsbl (%rax,%rcx,1),%eax
mov    -0x20(%rbp),%rcx
movslq -0x30(%rbp),%rdx
movsbl (%rcx,%rdx,1),%ecx
cmp    %ecx,%eax
je     11e8 <char_find_from+0xe8>
jmp    11fb <char_find_from+0xfb>
jmp    11ed <char_find_from+0xed>
mov    -0x30(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x30(%rbp)
jmp    11b2 <char_find_from+0xb2>
mov    -0x30(%rbp),%eax
cmp    -0x24(%rbp),%eax
jne    1212 <char_find_from+0x112>
mov    -0x2c(%rbp),%eax
mov    %eax,-0x4(%rbp)
jmp    123f <char_find_from+0x13f>
mov    -0x10(%rbp),%rax
mov    -0x2c(%rbp),%ecx
add    -0x24(%rbp),%ecx
movslq %ecx,%rcx
movsbl (%rax,%rcx,1),%eax
cltq
movsbl -0x140(%rbp,%rax,1),%eax
ff
add    -0x2c(%rbp),%eax
mov    %eax,-0x2c(%rbp)
jmp    119f <char_find_from+0x9f>
movl   $0xffffffff,-0x4(%rbp)
mov    -0x4(%rbp),%eax
add    $0xc0,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<char_find_from>:
push   %rbp
push   %r14
push   %rbx
sub    $0x80,%rsp
lea    0x1(%rcx),%eax
movzbl %al,%eax
movd   %eax,%xmm0
punpcklbw %xmm0,%xmm0
pshuflw $0x0,%xmm0,%xmm0
pshufd $0x0,%xmm0,%xmm0
movdqa %xmm0,0x70(%rsp)
movdqa %xmm0,0x60(%rsp)
movdqa %xmm0,0x50(%rsp)
movdqa %xmm0,0x40(%rsp)
movdqa %xmm0,0x30(%rsp)
movdqa %xmm0,0x20(%rsp)
movdqa %xmm0,0x10(%rsp)
movdqa %xmm0,(%rsp)
movdqa %xmm0,-0x10(%rsp)
movdqa %xmm0,-0x20(%rsp)
movdqa %xmm0,-0x30(%rsp)
movdqa %xmm0,-0x40(%rsp)
movdqa %xmm0,-0x50(%rsp)
movdqa %xmm0,-0x60(%rsp)
movdqa %xmm0,-0x70(%rsp)
movdqa %xmm0,-0x80(%rsp)
sub    %ecx,%esi
mov    %ecx,%r9d
test   %ecx,%ecx
jle    1227 <char_find_from+0x127>
lea    -0x1(%r9),%rax
mov    %r9d,%r10d
and    $0x3,%r10d
cmp    $0x3,%rax
jae    11a4 <char_find_from+0xa4>
xor    %eax,%eax
jmp    11f2 <char_find_from+0xf2>
mov    %r9d,%r11d
and    $0xfffffffc,%r11d
xor    %eax,%eax
mov    %ecx,%ebx
nop
movsbq (%rdx,%rax,1),%rbp
mov    %bl,-0x80(%rsp,%rbp,1)
lea    -0x1(%rbx),%r14d
movsbq 0x1(%rdx,%rax,1),%rbp
mov    %r14b,-0x80(%rsp,%rbp,1)
lea    -0x2(%rbx),%r14d
movsbq 0x2(%rdx,%rax,1),%rbp
mov    %r14b,-0x80(%rsp,%rbp,1)
lea    -0x3(%rbx),%r14d
movsbq 0x3(%rdx,%rax,1),%rbp
mov    %r14b,-0x80(%rsp,%rbp,1)
add    $0x4,%rax
add    $0xfc,%bl
cmp    %rax,%r11
jne    11b0 <char_find_from+0xb0>
test   %r10,%r10
je     1227 <char_find_from+0x127>
lea    (%rdx,%rax,1),%r11
mov    %ecx,%ebp
sub    %al,%bpl
xor    %eax,%eax
cs nopw 0x0(%rax,%rax,1)
nopl   0x0(%rax)
movsbq (%r11,%rax,1),%rbx
mov    %bpl,-0x80(%rsp,%rbx,1)
add    $0x1,%rax
add    $0xff,%bpl
cmp    %rax,%r10
jne    1210 <char_find_from+0x110>
mov    $0xffffffff,%eax
cmp    %r8d,%esi
jl     1294 <char_find_from+0x194>
mov    $0x0,%ebp
test   %ecx,%ecx
jle    1270 <char_find_from+0x170>
movslq %r8d,%r10
add    %rdi,%r10
xor    %ebp,%ebp
cs nopw 0x0(%rax,%rax,1)
nopl   0x0(%rax)
movzbl (%r10,%rbp,1),%ebx
cmp    (%rdx,%rbp,1),%bl
jne    1270 <char_find_from+0x170>
add    $0x1,%rbp
cmp    %rbp,%r9
jne    1250 <char_find_from+0x150>
jmp    1291 <char_find_from+0x191>
cs nopw 0x0(%rax,%rax,1)
nop
cmp    %ecx,%ebp
je     1291 <char_find_from+0x191>
lea    (%r8,%rcx,1),%ebp
movslq %ebp,%rbp
movsbq (%rdi,%rbp,1),%rbp
movsbl -0x80(%rsp,%rbp,1),%ebp
add    %r8d,%ebp
mov    %ebp,%r8d
cmp    %esi,%ebp
jle    1231 <char_find_from+0x131>
jmp    1294 <char_find_from+0x194>
mov    %r8d,%eax
add    $0x80,%rsp
pop    %rbx
pop    %r14
pop    %rbp
ret

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

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