void cap_str(char *p) {
  while (*p != '\0') {
    unsigned char c;
    c = (unsigned char)*p;
    if (c >= 'a' && c <= 'z') {
      *p = c & ~0x20;
    } else if (c == 0xc3) {
      p++;
      c = *p;
      if (c >= 0xa0 && c <= 0xbe && c != 0xb7)
        *p = c & ~0x20;
    } else if (c == 0xc4) {
      p++;
      c = *p;
      if (c >= 0x81 && c <= 0xb7 && (c & 0x01))
        (*p)--;
    }
    p++;
  }
}


x86 assembly (clang, -O0):
<cap_str>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    -0x8(%rbp),%rax
movsbl (%rax),%eax
cmp    $0x0,%eax
je     1231 <cap_str+0x131>
mov    -0x8(%rbp),%rax
mov    (%rax),%al
mov    %al,-0x9(%rbp)
movzbl -0x9(%rbp),%eax
cmp    $0x61,%eax
jl     114f <cap_str+0x4f>
movzbl -0x9(%rbp),%eax
cmp    $0x7a,%eax
jg     114f <cap_str+0x4f>
movzbl -0x9(%rbp),%eax
and    $0xffffffdf,%eax
mov    %al,%cl
mov    -0x8(%rbp),%rax
mov    %cl,(%rax)
jmp    1220 <cap_str+0x120>
movzbl -0x9(%rbp),%eax
cmp    $0xc3,%eax
jne    11b4 <cap_str+0xb4>
mov    -0x8(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x8(%rbp)
mov    -0x8(%rbp),%rax
mov    (%rax),%al
mov    %al,-0x9(%rbp)
movzbl -0x9(%rbp),%eax
cmp    $0xa0,%eax
jl     11af <cap_str+0xaf>
movzbl -0x9(%rbp),%eax
cmp    $0xbe,%eax
jg     11af <cap_str+0xaf>
movzbl -0x9(%rbp),%eax
cmp    $0xb7,%eax
je     11af <cap_str+0xaf>
movzbl -0x9(%rbp),%eax
and    $0xffffffdf,%eax
mov    %al,%cl
mov    -0x8(%rbp),%rax
mov    %cl,(%rax)
jmp    121b <cap_str+0x11b>
movzbl -0x9(%rbp),%eax
cmp    $0xc4,%eax
jne    1216 <cap_str+0x116>
mov    -0x8(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x8(%rbp)
mov    -0x8(%rbp),%rax
mov    (%rax),%al
mov    %al,-0x9(%rbp)
movzbl -0x9(%rbp),%eax
cmp    $0x81,%eax
jl     1211 <cap_str+0x111>
movzbl -0x9(%rbp),%eax
cmp    $0xb7,%eax
jg     1211 <cap_str+0x111>
movzbl -0x9(%rbp),%eax
and    $0x1,%eax
cmp    $0x0,%eax
je     1211 <cap_str+0x111>
mov    -0x8(%rbp),%rax
mov    (%rax),%cl
add    $0xff,%cl
mov    %cl,(%rax)
jmp    1216 <cap_str+0x116>
jmp    121b <cap_str+0x11b>
jmp    1220 <cap_str+0x120>
mov    -0x8(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x8(%rbp)
jmp    1108 <cap_str+0x8>
pop    %rbp
ret

x86 assembly (clang, -O2):
<cap_str>:
mov    (%rdi),%al
jmp    111c <cap_str+0x1c>
cs nopw 0x0(%rax,%rax,1)
xchg   %ax,%ax
and    $0xdf,%al
mov    %al,(%rdi)
movzbl 0x1(%rdi),%eax
add    $0x1,%rdi
test   %al,%al
je     1161 <cap_str+0x61>
lea    -0x61(%rax),%ecx
cmp    $0x19,%cl
jbe    1110 <cap_str+0x10>
cmp    $0xc4,%al
je     1146 <cap_str+0x46>
cmp    $0xc3,%al
jne    1114 <cap_str+0x14>
movzbl 0x1(%rdi),%eax
add    $0x1,%rdi
cmp    $0xb7,%al
je     1114 <cap_str+0x14>
lea    0x60(%rax),%ecx
cmp    $0x1e,%cl
jbe    1110 <cap_str+0x10>
jmp    1114 <cap_str+0x14>
movzbl 0x1(%rdi),%eax
add    $0x1,%rdi
lea    0x48(%rax),%ecx
cmp    $0xc9,%cl
jb     1114 <cap_str+0x14>
mov    %eax,%ecx
and    $0x1,%cl
je     1114 <cap_str+0x14>
add    $0xff,%al
jmp    1112 <cap_str+0x12>
ret

LLVM IR (-O0):
define void @cap_str(i8* %0) {
%2 = alloca i8*
%3 = alloca i8
store i8* %0, i8** %2
br label %4
4: ; preds = %80, %1
%5 = load i8*, i8** %2
%6 = load i8, i8* %5
%7 = sext i8 %6 to i32
%8 = icmp ne i32 %7, 0
br i1 %8, label %9, label %83
9: ; preds = %4
%10 = load i8*, i8** %2
%11 = load i8, i8* %10
store i8 %11, i8* %3
%12 = load i8, i8* %3
%13 = zext i8 %12 to i32
%14 = icmp sge i32 %13, 97
br i1 %14, label %15, label %25
15: ; preds = %9
%16 = load i8, i8* %3
%17 = zext i8 %16 to i32
%18 = icmp sle i32 %17, 122
br i1 %18, label %19, label %25
19: ; preds = %15
%20 = load i8, i8* %3
%21 = zext i8 %20 to i32
%22 = and i32 %21, -33
%23 = trunc i32 %22 to i8
%24 = load i8*, i8** %2
store i8 %23, i8* %24
br label %80
25: ; preds = %15, %9
%26 = load i8, i8* %3
%27 = zext i8 %26 to i32
%28 = icmp eq i32 %27, 195
br i1 %28, label %29, label %52
29: ; preds = %25
%30 = load i8*, i8** %2
%31 = getelementptr inbounds i8, i8* %30, i32 1
store i8* %31, i8** %2
%32 = load i8*, i8** %2
%33 = load i8, i8* %32
store i8 %33, i8* %3
%34 = load i8, i8* %3
%35 = zext i8 %34 to i32
%36 = icmp sge i32 %35, 160
br i1 %36, label %37, label %51
37: ; preds = %29
%38 = load i8, i8* %3
%39 = zext i8 %38 to i32
%40 = icmp sle i32 %39, 190
br i1 %40, label %41, label %51
41: ; preds = %37
%42 = load i8, i8* %3
%43 = zext i8 %42 to i32
%44 = icmp ne i32 %43, 183
br i1 %44, label %45, label %51
45: ; preds = %41
%46 = load i8, i8* %3
%47 = zext i8 %46 to i32
%48 = and i32 %47, -33
%49 = trunc i32 %48 to i8
%50 = load i8*, i8** %2
store i8 %49, i8* %50
br label %51
51: ; preds = %45, %41, %37, %29
br label %79
52: ; preds = %25
%53 = load i8, i8* %3
%54 = zext i8 %53 to i32
%55 = icmp eq i32 %54, 196
br i1 %55, label %56, label %78
56: ; preds = %52
%57 = load i8*, i8** %2
%58 = getelementptr inbounds i8, i8* %57, i32 1
store i8* %58, i8** %2
%59 = load i8*, i8** %2
%60 = load i8, i8* %59
store i8 %60, i8* %3
%61 = load i8, i8* %3
%62 = zext i8 %61 to i32
%63 = icmp sge i32 %62, 129
br i1 %63, label %64, label %77
64: ; preds = %56
%65 = load i8, i8* %3
%66 = zext i8 %65 to i32
%67 = icmp sle i32 %66, 183
br i1 %67, label %68, label %77
68: ; preds = %64
%69 = load i8, i8* %3
%70 = zext i8 %69 to i32
%71 = and i32 %70, 1
%72 = icmp ne i32 %71, 0
br i1 %72, label %73, label %77
73: ; preds = %68
%74 = load i8*, i8** %2
%75 = load i8, i8* %74
%76 = add i8 %75, -1
store i8 %76, i8* %74
br label %77
77: ; preds = %73, %68, %64, %56
br label %78
78: ; preds = %77, %52
br label %79
79: ; preds = %78, %51
br label %80
80: ; preds = %79, %19
%81 = load i8*, i8** %2
%82 = getelementptr inbounds i8, i8* %81, i32 1
store i8* %82, i8** %2
br label %4
83: ; preds = %4
ret void
}

LLVM IR (-O2):
define void @cap_str(i8* nocapture %0) {
%2 = load i8, i8* %0
%3 = icmp eq i8 %2, 0
br i1 %3, label %36, label %4
4: ; preds = %1, %31
%5 = phi i8 [ %34, %31 ], [ %2, %1 ]
%6 = phi i8* [ %33, %31 ], [ %0, %1 ]
%7 = add i8 %5, -97
%8 = icmp ult i8 %7, 26
br i1 %8, label %9, label %11
9: ; preds = %4
%10 = and i8 %5, -33
store i8 %10, i8* %6
br label %31
11: ; preds = %4
switch i8 %5, label %31 [
i8 -61, label %12
i8 -60, label %21
]
12: ; preds = %11
%13 = getelementptr inbounds i8, i8* %6, i64 1
%14 = load i8, i8* %13
%15 = add i8 %14, 96
%16 = icmp ult i8 %15, 31
%17 = icmp ne i8 %14, -73
%18 = and i1 %17, %16
br i1 %18, label %19, label %31
19: ; preds = %12
%20 = and i8 %14, -33
store i8 %20, i8* %13
br label %31
21: ; preds = %11
%22 = getelementptr inbounds i8, i8* %6, i64 1
%23 = load i8, i8* %22
%24 = add i8 %23, 72
%25 = icmp ult i8 %24, -55
%26 = and i8 %23, 1
%27 = icmp eq i8 %26, 0
%28 = or i1 %25, %27
br i1 %28, label %31, label %29
29: ; preds = %21
%30 = add nsw i8 %23, -1
store i8 %30, i8* %22
br label %31
31: ; preds = %11, %19, %12, %21, %29, %9
%32 = phi i8* [ %6, %9 ], [ %13, %19 ], [ %13, %12 ], [ %22, %29 ], [ %22, %21 ], [ %6, %11 ]
%33 = getelementptr inbounds i8, i8* %32, i64 1
%34 = load i8, i8* %33
%35 = icmp eq i8 %34, 0
br i1 %35, label %36, label %4
36: ; preds = %31, %1
ret void
}