void u8_dec_ptr(char **sp) {
  (void)((((*(--(*sp))) & 0xC0) != 0x80) || (((*(--(*sp))) & 0xC0) != 0x80) ||
         (((*(--(*sp))) & 0xC0) != 0x80) || --(*sp));
}


x86 assembly (clang, -O0):
<u8_dec_ptr>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    -0x8(%rbp),%rcx
mov    (%rcx),%rax
mov    %rax,%rdx
add    $0xffffffffffffffff,%rdx
mov    %rdx,(%rcx)
movsbl -0x1(%rax),%ecx
and    $0xc0,%ecx
mov    $0x1,%al
cmp    $0x80,%ecx
mov    %al,-0x9(%rbp)
jne    11a4 <u8_dec_ptr+0xa4>
mov    -0x8(%rbp),%rcx
mov    (%rcx),%rax
mov    %rax,%rdx
add    $0xffffffffffffffff,%rdx
mov    %rdx,(%rcx)
movsbl -0x1(%rax),%ecx
and    $0xc0,%ecx
mov    $0x1,%al
cmp    $0x80,%ecx
mov    %al,-0x9(%rbp)
jne    11a4 <u8_dec_ptr+0xa4>
mov    -0x8(%rbp),%rcx
mov    (%rcx),%rax
mov    %rax,%rdx
add    $0xffffffffffffffff,%rdx
mov    %rdx,(%rcx)
movsbl -0x1(%rax),%ecx
and    $0xc0,%ecx
mov    $0x1,%al
cmp    $0x80,%ecx
mov    %al,-0x9(%rbp)
jne    11a4 <u8_dec_ptr+0xa4>
mov    -0x8(%rbp),%rcx
mov    (%rcx),%rax
add    $0xffffffffffffffff,%rax
mov    %rax,(%rcx)
cmp    $0x0,%rax
setne  %al
mov    %al,-0x9(%rbp)
mov    -0x9(%rbp),%al
pop    %rbp
ret

x86 assembly (clang, -O2):
<u8_dec_ptr>:
mov    (%rdi),%rax
lea    -0x1(%rax),%rcx
mov    %rcx,(%rdi)
mov    -0x1(%rax),%cl
and    $0xc0,%cl
cmp    $0x80,%cl
jne    1140 <u8_dec_ptr+0x40>
lea    -0x2(%rax),%rcx
mov    %rcx,(%rdi)
mov    -0x2(%rax),%cl
and    $0xc0,%cl
cmp    $0x80,%cl
jne    1140 <u8_dec_ptr+0x40>
lea    -0x3(%rax),%rcx
mov    %rcx,(%rdi)
mov    -0x3(%rax),%cl
and    $0xc0,%cl
cmp    $0x80,%cl
jne    1140 <u8_dec_ptr+0x40>
add    $0xfffffffffffffffc,%rax
mov    %rax,(%rdi)
ret

LLVM IR (-O0):
define void @u8_dec_ptr(i8** %0) {
%2 = alloca i8**
store i8** %0, i8*** %2
%3 = load i8**, i8*** %2
%4 = load i8*, i8** %3
%5 = getelementptr inbounds i8, i8* %4, i32 -1
store i8* %5, i8** %3
%6 = load i8, i8* %5
%7 = sext i8 %6 to i32
%8 = and i32 %7, 192
%9 = icmp ne i32 %8, 128
br i1 %9, label %31, label %10
10: ; preds = %1
%11 = load i8**, i8*** %2
%12 = load i8*, i8** %11
%13 = getelementptr inbounds i8, i8* %12, i32 -1
store i8* %13, i8** %11
%14 = load i8, i8* %13
%15 = sext i8 %14 to i32
%16 = and i32 %15, 192
%17 = icmp ne i32 %16, 128
br i1 %17, label %31, label %18
18: ; preds = %10
%19 = load i8**, i8*** %2
%20 = load i8*, i8** %19
%21 = getelementptr inbounds i8, i8* %20, i32 -1
store i8* %21, i8** %19
%22 = load i8, i8* %21
%23 = sext i8 %22 to i32
%24 = and i32 %23, 192
%25 = icmp ne i32 %24, 128
br i1 %25, label %31, label %26
26: ; preds = %18
%27 = load i8**, i8*** %2
%28 = load i8*, i8** %27
%29 = getelementptr inbounds i8, i8* %28, i32 -1
store i8* %29, i8** %27
%30 = icmp ne i8* %29, null
br label %31
31: ; preds = %26, %18, %10, %1
%32 = phi i1 [ true, %18 ], [ true, %10 ], [ true, %1 ], [ %30, %26 ]
%33 = zext i1 %32 to i32
ret void
}

LLVM IR (-O2):
define void @u8_dec_ptr(i8** nocapture %0) {
%2 = load i8*, i8** %0
%3 = getelementptr inbounds i8, i8* %2, i64 -1
store i8* %3, i8** %0
%4 = load i8, i8* %3
%5 = and i8 %4, -64
%6 = icmp eq i8 %5, -128
br i1 %6, label %7, label %19
7: ; preds = %1
%8 = getelementptr inbounds i8, i8* %2, i64 -2
store i8* %8, i8** %0
%9 = load i8, i8* %8
%10 = and i8 %9, -64
%11 = icmp eq i8 %10, -128
br i1 %11, label %12, label %19
12: ; preds = %7
%13 = getelementptr inbounds i8, i8* %2, i64 -3
store i8* %13, i8** %0
%14 = load i8, i8* %13
%15 = and i8 %14, -64
%16 = icmp eq i8 %15, -128
br i1 %16, label %17, label %19
17: ; preds = %12
%18 = getelementptr inbounds i8, i8* %2, i64 -4
store i8* %18, i8** %0
br label %19
19: ; preds = %17, %12, %7, %1
ret void
}