const char *id_end(const char *p) {
  ++p;
  while ((*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z') ||
         (*p >= '0' && *p <= '9') || *p == '_') {
    ++p;
  }
  return p;
}


x86 assembly (clang, -O0):
<id_end>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    -0x8(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x8(%rbp)
mov    -0x8(%rbp),%rax
movsbl (%rax),%eax
cmp    $0x61,%eax
jl     1139 <id_end+0x39>
mov    -0x8(%rbp),%rax
movsbl (%rax),%ecx
mov    $0x1,%al
cmp    $0x7a,%ecx
mov    %al,-0x9(%rbp)
jle    1193 <id_end+0x93>
mov    -0x8(%rbp),%rax
movsbl (%rax),%eax
cmp    $0x41,%eax
jl     115e <id_end+0x5e>
mov    -0x8(%rbp),%rax
movsbl (%rax),%ecx
mov    $0x1,%al
cmp    $0x5a,%ecx
mov    %al,-0x9(%rbp)
jle    1193 <id_end+0x93>
mov    -0x8(%rbp),%rax
movsbl (%rax),%eax
cmp    $0x30,%eax
jl     1183 <id_end+0x83>
mov    -0x8(%rbp),%rax
movsbl (%rax),%ecx
mov    $0x1,%al
cmp    $0x39,%ecx
mov    %al,-0x9(%rbp)
jle    1193 <id_end+0x93>
mov    -0x8(%rbp),%rax
movsbl (%rax),%eax
cmp    $0x5f,%eax
sete   %al
mov    %al,-0x9(%rbp)
mov    -0x9(%rbp),%al
test   $0x1,%al
jne    11a3 <id_end+0xa3>
jmp    11b4 <id_end+0xb4>
mov    -0x8(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x8(%rbp)
jmp    1114 <id_end+0x14>
mov    -0x8(%rbp),%rax
pop    %rbp
ret

x86 assembly (clang, -O2):
<id_end>:
mov    %rdi,%rax
cs nopw 0x0(%rax,%rax,1)
nopl   (%rax)
add    $0x1,%rax
movzbl (%rax),%ecx
mov    %ecx,%edx
and    $0xdf,%dl
add    $0xbf,%dl
cmp    $0x1a,%dl
jb     1110 <id_end+0x10>
lea    -0x30(%rcx),%edx
cmp    $0x5f,%cl
je     1110 <id_end+0x10>
cmp    $0x9,%dl
jbe    1110 <id_end+0x10>
ret

LLVM IR (-O0):
define i8* @id_end(i8* %0) {
%2 = alloca i8*
store i8* %0, i8** %2
%3 = load i8*, i8** %2
%4 = getelementptr inbounds i8, i8* %3, i32 1
store i8* %4, i8** %2
br label %5
5: ; preds = %42, %1
%6 = load i8*, i8** %2
%7 = load i8, i8* %6
%8 = sext i8 %7 to i32
%9 = icmp sge i32 %8, 97
br i1 %9, label %10, label %15
10: ; preds = %5
%11 = load i8*, i8** %2
%12 = load i8, i8* %11
%13 = sext i8 %12 to i32
%14 = icmp sle i32 %13, 122
br i1 %14, label %40, label %15
15: ; preds = %10, %5
%16 = load i8*, i8** %2
%17 = load i8, i8* %16
%18 = sext i8 %17 to i32
%19 = icmp sge i32 %18, 65
br i1 %19, label %20, label %25
20: ; preds = %15
%21 = load i8*, i8** %2
%22 = load i8, i8* %21
%23 = sext i8 %22 to i32
%24 = icmp sle i32 %23, 90
br i1 %24, label %40, label %25
25: ; preds = %20, %15
%26 = load i8*, i8** %2
%27 = load i8, i8* %26
%28 = sext i8 %27 to i32
%29 = icmp sge i32 %28, 48
br i1 %29, label %30, label %35
30: ; preds = %25
%31 = load i8*, i8** %2
%32 = load i8, i8* %31
%33 = sext i8 %32 to i32
%34 = icmp sle i32 %33, 57
br i1 %34, label %40, label %35
35: ; preds = %30, %25
%36 = load i8*, i8** %2
%37 = load i8, i8* %36
%38 = sext i8 %37 to i32
%39 = icmp eq i32 %38, 95
br label %40
40: ; preds = %35, %30, %20, %10
%41 = phi i1 [ true, %30 ], [ true, %20 ], [ true, %10 ], [ %39, %35 ]
br i1 %41, label %42, label %45
42: ; preds = %40
%43 = load i8*, i8** %2
%44 = getelementptr inbounds i8, i8* %43, i32 1
store i8* %44, i8** %2
br label %5
45: ; preds = %40
%46 = load i8*, i8** %2
ret i8* %46
}

LLVM IR (-O2):
define i8* @id_end(i8* %0) {
br label %2
2: ; preds = %14, %1
%3 = phi i8* [ %0, %1 ], [ %4, %14 ]
%4 = getelementptr inbounds i8, i8* %3, i64 1
%5 = load i8, i8* %4
%6 = and i8 %5, -33
%7 = add i8 %6, -65
%8 = icmp ult i8 %7, 26
br i1 %8, label %14, label %9
9: ; preds = %2
%10 = add i8 %5, -48
%11 = icmp ult i8 %10, 10
%12 = icmp eq i8 %5, 95
%13 = or i1 %12, %11
br i1 %13, label %14, label %15
14: ; preds = %9, %2
br label %2
15: ; preds = %9
ret i8* %4
}