char *StrRChr(const char *str, int ch) {
  char c = (unsigned char)ch;
  char *strend = str;
  while (*strend != '\0') {
    strend++;
  }
  while (1) {
    if (*strend == c) {
      return strend;
    } else if (strend == str) {
      return ((void *)0);
    }
    strend--;
  }
}


x86 assembly (clang, -O0):
<StrRChr>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x10(%rbp)
mov    %esi,-0x14(%rbp)
mov    -0x14(%rbp),%eax
mov    %al,-0x15(%rbp)
mov    -0x10(%rbp),%rax
mov    %rax,-0x20(%rbp)
mov    -0x20(%rbp),%rax
movsbl (%rax),%eax
cmp    $0x0,%eax
je     113a <StrRChr+0x3a>
mov    -0x20(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x20(%rbp)
jmp    1119 <StrRChr+0x19>
jmp    113f <StrRChr+0x3f>
mov    -0x20(%rbp),%rax
movsbl (%rax),%eax
movsbl -0x15(%rbp),%ecx
cmp    %ecx,%eax
jne    115f <StrRChr+0x5f>
mov    -0x20(%rbp),%rax
mov    %rax,-0x8(%rbp)
jmp    1190 <StrRChr+0x90>
mov    -0x20(%rbp),%rax
cmp    -0x10(%rbp),%rax
jne    117a <StrRChr+0x7a>
movq   $0x0,-0x8(%rbp)
jmp    1190 <StrRChr+0x90>
jmp    117f <StrRChr+0x7f>
mov    -0x20(%rbp),%rax
add    $0xffffffffffffffff,%rax
mov    %rax,-0x20(%rbp)
jmp    113f <StrRChr+0x3f>
mov    -0x8(%rbp),%rax
pop    %rbp
ret

x86 assembly (clang, -O2):
<StrRChr>:
mov    %rdi,%rax
mov    $0x1,%ecx
xor    %edx,%edx
nopw   0x0(%rax,%rax,1)
add    $0xffffffffffffffff,%rcx
cmpb   $0x0,(%rax,%rdx,1)
lea    0x1(%rdx),%rdx
jne    1110 <StrRChr+0x10>
sub    %rcx,%rax
test   $0xff,%sil
je     1145 <StrRChr+0x45>
movsbl %sil,%edx
nopl   0x0(%rax,%rax,1)
test   %rcx,%rcx
je     1146 <StrRChr+0x46>
movsbl -0x1(%rax),%esi
add    $0xffffffffffffffff,%rax
add    $0x1,%rcx
cmp    %esi,%edx
jne    1130 <StrRChr+0x30>
ret
xor    %eax,%eax
ret

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

LLVM IR (-O2):
define i8* @StrRChr(i8* %0, i32 %1) {
br label %3
3: ; preds = %3, %2
%4 = phi i8* [ %0, %2 ], [ %7, %3 ]
%5 = load i8, i8* %4
%6 = icmp eq i8 %5, 0
%7 = getelementptr inbounds i8, i8* %4, i64 1
br i1 %6, label %8, label %3
8: ; preds = %3
%9 = shl i32 %1, 24
%10 = ashr exact i32 %9, 24
%11 = icmp eq i32 %9, 0
br i1 %11, label %20, label %12
12: ; preds = %8, %15
%13 = phi i8* [ %16, %15 ], [ %4, %8 ]
%14 = icmp eq i8* %13, %0
br i1 %14, label %20, label %15
15: ; preds = %12
%16 = getelementptr inbounds i8, i8* %13, i64 -1
%17 = load i8, i8* %16
%18 = sext i8 %17 to i32
%19 = icmp eq i32 %10, %18
br i1 %19, label %20, label %12
20: ; preds = %15, %12, %8
%21 = phi i8* [ %4, %8 ], [ null, %12 ], [ %16, %15 ]
ret i8* %21
}