#define NULL ((void *)0)
typedef unsigned long size_t; // Customize by platform.
typedef long intptr_t;
typedef unsigned long uintptr_t;
typedef long scalar_t__; // Either arithmetic or pointer type.
/* By default, we understand bool (as a convenience). */
typedef int bool;
#define false 0
#define true 1

/* Forward declarations */

/* Type definitions */
typedef int /*<<< orphan*/ bcwd;

/* Variables and functions */
char *getcwd(char *, int);
int /*<<< orphan*/ snprintf(char *, int, char *, char *);
char *strchrnul(char const *, char);
int /*<<< orphan*/ strcmp(char const *, char *);
int strlen(char const *);
char const *strrchr(char const *, char);
void crumb_canonize_path(const char *filename, char *ostr, int ostr_max) {
  char bcwd[0x200], *cwd;
  const char *b, *scan = filename;
  char *o, *x, *p;
  int dont_remove_slash = 0, last_is_dotted = 0;
  int lf = strlen(filename);
  if (lf == 0) {
    *ostr = '\0';
    return;
  }
  cwd = getcwd(bcwd, sizeof(bcwd));
  if (strrchr(filename, '/') == filename + lf - 1) {
    dont_remove_slash = 1;
  }
  if (filename[0] != '/') {
    snprintf(ostr, ostr_max, "%s/", cwd);
    o = ostr + strlen(ostr);
  } else {
    o = ostr;
    o[0] = '/';
    o[1] = '\0';
    o++;
  }
  while (*scan != '\0') {
    p = strchrnul(scan, '/');
    b = o;
    while (scan < p) {
      *o = *scan;
      o++;
      scan++;
    }
    if (*scan == '/')
      scan++;
    o[0] = '\0';
    last_is_dotted = 0;
    if (!strcmp(b, "")) {
      continue;
    }
    if (!strcmp(b, ".")) {
      o -= 1;
      o[0] = '\0';
      last_is_dotted = 1;
      continue;
    }
    if (!strcmp(b, "..")) {
      o -= 3;
      o[0] = '\0';
      x = strrchr(ostr, '/');
      if (x) {
        o = x + 1;
        *o = '\0';
      } else {
        o = ostr;
        *o = '\0';
      }
      last_is_dotted = 1;
      continue;
    }
    o[0] = '/';
    o++;
    o[0] = '\0';
  }
  if (!dont_remove_slash && !last_is_dotted) {
    if (o > ostr && o[-1] == '/')
      o[-1] = '\0';
  }
}


x86 assembly (clang, -O0):
<crumb_canonize_path>:
push   %rbp
mov    %rsp,%rbp
sub    $0x270,%rsp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %edx,-0x14(%rbp)
mov    -0x8(%rbp),%rax
mov    %rax,-0x238(%rbp)
movl   $0x0,-0x254(%rbp)
movl   $0x0,-0x258(%rbp)
mov    -0x8(%rbp),%rdi
call   1040 <strlen@plt>
mov    %eax,-0x25c(%rbp)
cmpl   $0x0,-0x25c(%rbp)
jne    11bd <crumb_canonize_path+0x5d>
mov    -0x10(%rbp),%rax
movb   $0x0,(%rax)
jmp    14db <crumb_canonize_path+0x37b>
lea    -0x220(%rbp),%rdi
mov    $0x200,%esi
call   1070 <getcwd@plt>
mov    %rax,-0x228(%rbp)
mov    -0x8(%rbp),%rdi
mov    $0x2f,%esi
call   1060 <strrchr@plt>
mov    -0x8(%rbp),%rcx
movslq -0x25c(%rbp),%rdx
add    %rdx,%rcx
add    $0xffffffffffffffff,%rcx
cmp    %rcx,%rax
jne    1208 <crumb_canonize_path+0xa8>
movl   $0x1,-0x254(%rbp)
mov    -0x8(%rbp),%rax
movsbl (%rax),%eax
cmp    $0x2f,%eax
je     1261 <crumb_canonize_path+0x101>
mov    -0x10(%rbp),%rdi
mov    -0x14(%rbp),%esi
mov    -0x228(%rbp),%rcx
lea    0xdd3(%rip),%rdx
call   1050 <snprintf@plt>
mov    -0x10(%rbp),%rax
mov    %rax,-0x268(%rbp)
mov    -0x10(%rbp),%rdi
call   1040 <strlen@plt>
mov    %eax,%ecx
mov    -0x268(%rbp),%rax
movslq %ecx,%rcx
add    %rcx,%rax
mov    %rax,-0x240(%rbp)
jmp    1293 <crumb_canonize_path+0x133>
mov    -0x10(%rbp),%rax
mov    %rax,-0x240(%rbp)
mov    -0x240(%rbp),%rax
movb   $0x2f,(%rax)
mov    -0x240(%rbp),%rax
movb   $0x0,0x1(%rax)
mov    -0x240(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x240(%rbp)
jmp    1298 <crumb_canonize_path+0x138>
mov    -0x238(%rbp),%rax
movsbl (%rax),%eax
cmp    $0x0,%eax
je     148c <crumb_canonize_path+0x32c>
mov    -0x238(%rbp),%rdi
mov    $0x2f,%esi
call   1030 <strchrnul@plt>
mov    %rax,-0x250(%rbp)
mov    -0x240(%rbp),%rax
mov    %rax,-0x230(%rbp)
mov    -0x238(%rbp),%rax
cmp    -0x250(%rbp),%rax
jae    1320 <crumb_canonize_path+0x1c0>
mov    -0x238(%rbp),%rax
mov    (%rax),%cl
mov    -0x240(%rbp),%rax
mov    %cl,(%rax)
mov    -0x240(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x240(%rbp)
mov    -0x238(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x238(%rbp)
jmp    12d1 <crumb_canonize_path+0x171>
mov    -0x238(%rbp),%rax
movsbl (%rax),%eax
cmp    $0x2f,%eax
jne    1345 <crumb_canonize_path+0x1e5>
mov    -0x238(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x238(%rbp)
mov    -0x240(%rbp),%rax
movb   $0x0,(%rax)
movl   $0x0,-0x258(%rbp)
mov    -0x230(%rbp),%rdi
lea    0xc9f(%rip),%rsi
call   1080 <strcmp@plt>
cmp    $0x0,%eax
jne    137a <crumb_canonize_path+0x21a>
jmp    1298 <crumb_canonize_path+0x138>
mov    -0x230(%rbp),%rdi
lea    0xc7d(%rip),%rsi
call   1080 <strcmp@plt>
cmp    $0x0,%eax
jne    13c1 <crumb_canonize_path+0x261>
mov    -0x240(%rbp),%rax
add    $0xffffffffffffffff,%rax
mov    %rax,-0x240(%rbp)
mov    -0x240(%rbp),%rax
movb   $0x0,(%rax)
movl   $0x1,-0x258(%rbp)
jmp    1298 <crumb_canonize_path+0x138>
mov    -0x230(%rbp),%rdi
lea    0xc35(%rip),%rsi
call   1080 <strcmp@plt>
cmp    $0x0,%eax
jne    1461 <crumb_canonize_path+0x301>
mov    -0x240(%rbp),%rax
add    $0xfffffffffffffffd,%rax
mov    %rax,-0x240(%rbp)
mov    -0x240(%rbp),%rax
movb   $0x0,(%rax)
mov    -0x10(%rbp),%rdi
mov    $0x2f,%esi
call   1060 <strrchr@plt>
mov    %rax,-0x248(%rbp)
cmpq   $0x0,-0x248(%rbp)
je     143d <crumb_canonize_path+0x2dd>
mov    -0x248(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x240(%rbp)
mov    -0x240(%rbp),%rax
movb   $0x0,(%rax)
jmp    1452 <crumb_canonize_path+0x2f2>
mov    -0x10(%rbp),%rax
mov    %rax,-0x240(%rbp)
mov    -0x240(%rbp),%rax
movb   $0x0,(%rax)
movl   $0x1,-0x258(%rbp)
jmp    1298 <crumb_canonize_path+0x138>
mov    -0x240(%rbp),%rax
movb   $0x2f,(%rax)
mov    -0x240(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x240(%rbp)
mov    -0x240(%rbp),%rax
movb   $0x0,(%rax)
jmp    1298 <crumb_canonize_path+0x138>
cmpl   $0x0,-0x254(%rbp)
jne    14db <crumb_canonize_path+0x37b>
cmpl   $0x0,-0x258(%rbp)
jne    14db <crumb_canonize_path+0x37b>
mov    -0x240(%rbp),%rax
cmp    -0x10(%rbp),%rax
jbe    14d6 <crumb_canonize_path+0x376>
mov    -0x240(%rbp),%rax
movsbl -0x1(%rax),%eax
cmp    $0x2f,%eax
jne    14d6 <crumb_canonize_path+0x376>
mov    -0x240(%rbp),%rax
movb   $0x0,-0x1(%rax)
jmp    14db <crumb_canonize_path+0x37b>
add    $0x270,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<crumb_canonize_path>:
push   %rbp
push   %r15
push   %r14
push   %r13
push   %r12
push   %rbx
sub    $0x218,%rsp
mov    %edx,%r13d
mov    %rsi,%r15
mov    %rdi,%rbx
call   1040 <strlen@plt>
test   %eax,%eax
je     1464 <crumb_canonize_path+0x304>
mov    %eax,%ebp
lea    0x10(%rsp),%rdi
mov    $0x200,%esi
call   1070 <getcwd@plt>
mov    %rax,%r12
mov    %rbx,%rdi
mov    $0x2f,%esi
call   1060 <strrchr@plt>
mov    %rax,0x8(%rsp)
movslq %ebp,%r14
cmpb   $0x2f,(%rbx)
jne    11c1 <crumb_canonize_path+0x61>
movw   $0x2f,(%r15)
lea    0x1(%r15),%rbp
jmp    11e4 <crumb_canonize_path+0x84>
lea    0xe38(%rip),%rdx
mov    %r15,%rdi
mov    %r13d,%esi
mov    %r12,%rcx
call   1050 <snprintf@plt>
mov    %r15,%rdi
call   1040 <strlen@plt>
movslq %eax,%rbp
add    %r15,%rbp
lea    (%rbx,%r14,1),%rax
add    $0xffffffffffffffff,%rax
mov    %rax,(%rsp)
cmpb   $0x0,(%rbx)
je     1441 <crumb_canonize_path+0x2e1>
lea    0xe05(%rip),%r12
lea    0xdfd(%rip),%r13
mov    %rbp,%r14
jmp    121e <crumb_canonize_path+0xbe>
nopl   0x0(%rax)
xor    %eax,%eax
cmpb   $0x0,(%rbx)
mov    %rbp,%r14
je     1443 <crumb_canonize_path+0x2e3>
mov    %rbx,%rdi
mov    $0x2f,%esi
call   1030 <strchrnul@plt>
cmp    %rax,%rbx
jae    12e0 <crumb_canonize_path+0x180>
mov    %rax,%rcx
sub    %rbx,%rcx
cmp    $0x20,%rcx
jb     1256 <crumb_canonize_path+0xf6>
cmp    %rax,%r14
jae    135d <crumb_canonize_path+0x1fd>
lea    (%r14,%rcx,1),%rdx
cmp    %rdx,%rbx
jae    135d <crumb_canonize_path+0x1fd>
mov    %r14,%rbp
mov    %eax,%edx
sub    %ebx,%edx
mov    %rbx,%rsi
not    %rsi
add    %rax,%rsi
and    $0x7,%rdx
je     1284 <crumb_canonize_path+0x124>
nopl   0x0(%rax)
movzbl (%rbx),%ecx
mov    %cl,0x0(%rbp)
add    $0x1,%rbp
add    $0x1,%rbx
add    $0xffffffffffffffff,%rdx
jne    1270 <crumb_canonize_path+0x110>
cmp    $0x7,%rsi
jb     12e6 <crumb_canonize_path+0x186>
nopw   0x0(%rax,%rax,1)
movzbl (%rbx),%ecx
mov    %cl,0x0(%rbp)
movzbl 0x1(%rbx),%ecx
mov    %cl,0x1(%rbp)
movzbl 0x2(%rbx),%ecx
mov    %cl,0x2(%rbp)
movzbl 0x3(%rbx),%ecx
mov    %cl,0x3(%rbp)
movzbl 0x4(%rbx),%ecx
mov    %cl,0x4(%rbp)
movzbl 0x5(%rbx),%ecx
mov    %cl,0x5(%rbp)
movzbl 0x6(%rbx),%ecx
mov    %cl,0x6(%rbp)
movzbl 0x7(%rbx),%ecx
mov    %cl,0x7(%rbp)
add    $0x8,%rbp
add    $0x8,%rbx
cmp    %rax,%rbx
jne    1290 <crumb_canonize_path+0x130>
jmp    12e6 <crumb_canonize_path+0x186>
cs nopw 0x0(%rax,%rax,1)
mov    %r14,%rbp
mov    %rbx,%rax
xor    %ebx,%ebx
cmpb   $0x2f,(%rax)
sete   %bl
add    %rax,%rbx
movb   $0x0,0x0(%rbp)
cmpb   $0x0,(%r14)
je     1210 <crumb_canonize_path+0xb0>
mov    %r14,%rdi
mov    %r12,%rsi
call   1080 <strcmp@plt>
test   %eax,%eax
je     1330 <crumb_canonize_path+0x1d0>
mov    %r14,%rdi
mov    %r13,%rsi
call   1080 <strcmp@plt>
test   %eax,%eax
je     1336 <crumb_canonize_path+0x1d6>
movb   $0x2f,0x0(%rbp)
add    $0x1,%rbp
xor    %eax,%eax
jmp    1354 <crumb_canonize_path+0x1f4>
nopl   0x0(%rax)
add    $0xffffffffffffffff,%rbp
jmp    1352 <crumb_canonize_path+0x1f2>
movb   $0x0,-0x3(%rbp)
mov    %r15,%rdi
mov    $0x2f,%esi
call   1060 <strrchr@plt>
lea    0x1(%rax),%rbp
test   %rax,%rax
cmove  %r15,%rbp
mov    $0x1,%al
movb   $0x0,0x0(%rbp)
jmp    1212 <crumb_canonize_path+0xb2>
mov    %rcx,%r8
and    $0xffffffffffffffe0,%r8
lea    -0x20(%r8),%rdx
mov    %rdx,%rdi
shr    $0x5,%rdi
add    $0x1,%rdi
mov    %edi,%esi
and    $0x3,%esi
cmp    $0x60,%rdx
jae    1382 <crumb_canonize_path+0x222>
xor    %ebp,%ebp
jmp    13f0 <crumb_canonize_path+0x290>
and    $0xfffffffffffffffc,%rdi
xor    %ebp,%ebp
nopl   0x0(%rax,%rax,1)
movups (%rbx,%rbp,1),%xmm0
movups 0x10(%rbx,%rbp,1),%xmm1
movups %xmm0,(%r14,%rbp,1)
movups %xmm1,0x10(%r14,%rbp,1)
movups 0x20(%rbx,%rbp,1),%xmm0
movups 0x30(%rbx,%rbp,1),%xmm1
movups %xmm0,0x20(%r14,%rbp,1)
movups %xmm1,0x30(%r14,%rbp,1)
movups 0x40(%rbx,%rbp,1),%xmm0
movups 0x50(%rbx,%rbp,1),%xmm1
movups %xmm0,0x40(%r14,%rbp,1)
movups %xmm1,0x50(%r14,%rbp,1)
movups 0x60(%rbx,%rbp,1),%xmm0
movups 0x70(%rbx,%rbp,1),%xmm1
movups %xmm0,0x60(%r14,%rbp,1)
movups %xmm1,0x70(%r14,%rbp,1)
sub    $0xffffffffffffff80,%rbp
add    $0xfffffffffffffffc,%rdi
jne    1390 <crumb_canonize_path+0x230>
test   %rsi,%rsi
je     142c <crumb_canonize_path+0x2cc>
lea    (%r14,%rbp,1),%rdi
add    $0x10,%rdi
add    %rbx,%rbp
add    $0x10,%rbp
shl    $0x5,%rsi
xor    %edx,%edx
nopw   0x0(%rax,%rax,1)
movups -0x10(%rbp,%rdx,1),%xmm0
movups 0x0(%rbp,%rdx,1),%xmm1
movups %xmm0,-0x10(%rdi,%rdx,1)
movups %xmm1,(%rdi,%rdx,1)
add    $0x20,%rdx
cmp    %rdx,%rsi
jne    1410 <crumb_canonize_path+0x2b0>
lea    (%r14,%r8,1),%rbp
cmp    %r8,%rcx
je     12e6 <crumb_canonize_path+0x186>
add    %r8,%rbx
jmp    1259 <crumb_canonize_path+0xf9>
xor    %eax,%eax
mov    (%rsp),%rcx
cmp    %rcx,0x8(%rsp)
je     1468 <crumb_canonize_path+0x308>
test   %al,%al
jne    1468 <crumb_canonize_path+0x308>
cmp    %r15,%rbp
jbe    1468 <crumb_canonize_path+0x308>
cmpb   $0x2f,-0x1(%rbp)
jne    1468 <crumb_canonize_path+0x308>
add    $0xffffffffffffffff,%rbp
mov    %rbp,%r15
movb   $0x0,(%r15)
add    $0x218,%rsp
pop    %rbx
pop    %r12
pop    %r13
pop    %r14
pop    %r15
pop    %rbp
ret

LLVM IR (-O0):
@.str = [4 x i8] c"%s/\00"
@.str.1 = [1 x i8] zeroinitializer
@.str.2 = [2 x i8] c".\00"
@.str.3 = [3 x i8] c"..\00"
define void @crumb_canonize_path(i8* %0, i8* %1, i32 %2) {
%4 = alloca i8*
%5 = alloca i8*
%6 = alloca i32
%7 = alloca [512 x i8]
%8 = alloca i8*
%9 = alloca i8*
%10 = alloca i8*
%11 = alloca i8*
%12 = alloca i8*
%13 = alloca i8*
%14 = alloca i32
%15 = alloca i32
%16 = alloca i32
store i8* %0, i8** %4
store i8* %1, i8** %5
store i32 %2, i32* %6
%17 = load i8*, i8** %4
store i8* %17, i8** %10
store i32 0, i32* %14
store i32 0, i32* %15
%18 = load i8*, i8** %4
%19 = call i32 @strlen(i8* %18)
store i32 %19, i32* %16
%20 = load i32, i32* %16
%21 = icmp eq i32 %20, 0
br i1 %21, label %22, label %24
22: ; preds = %3
%23 = load i8*, i8** %5
store i8 0, i8* %23
br label %154
24: ; preds = %3
%25 = getelementptr inbounds [512 x i8], [512 x i8]* %7, i64 0, i64 0
%26 = call i8* @getcwd(i8* %25, i32 512)
store i8* %26, i8** %8
%27 = load i8*, i8** %4
%28 = call i8* @strrchr(i8* %27, i8 signext 47)
%29 = load i8*, i8** %4
%30 = load i32, i32* %16
%31 = sext i32 %30 to i64
%32 = getelementptr inbounds i8, i8* %29, i64 %31
%33 = getelementptr inbounds i8, i8* %32, i64 -1
%34 = icmp eq i8* %28, %33
br i1 %34, label %35, label %36
35: ; preds = %24
store i32 1, i32* %14
br label %36
36: ; preds = %35, %24
%37 = load i8*, i8** %4
%38 = getelementptr inbounds i8, i8* %37, i64 0
%39 = load i8, i8* %38
%40 = sext i8 %39 to i32
%41 = icmp ne i32 %40, 47
br i1 %41, label %42, label %52
42: ; preds = %36
%43 = load i8*, i8** %5
%44 = load i32, i32* %6
%45 = load i8*, i8** %8
%46 = call i32 @snprintf(i8* %43, i32 %44, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), i8* %45)
%47 = load i8*, i8** %5
%48 = load i8*, i8** %5
%49 = call i32 @strlen(i8* %48)
%50 = sext i32 %49 to i64
%51 = getelementptr inbounds i8, i8* %47, i64 %50
store i8* %51, i8** %11
br label %60
52: ; preds = %36
%53 = load i8*, i8** %5
store i8* %53, i8** %11
%54 = load i8*, i8** %11
%55 = getelementptr inbounds i8, i8* %54, i64 0
store i8 47, i8* %55
%56 = load i8*, i8** %11
%57 = getelementptr inbounds i8, i8* %56, i64 1
store i8 0, i8* %57
%58 = load i8*, i8** %11
%59 = getelementptr inbounds i8, i8* %58, i32 1
store i8* %59, i8** %11
br label %60
60: ; preds = %52, %42
br label %61
61: ; preds = %127, %126, %101, %96, %60
%62 = load i8*, i8** %10
%63 = load i8, i8* %62
%64 = sext i8 %63 to i32
%65 = icmp ne i32 %64, 0
br i1 %65, label %66, label %134
66: ; preds = %61
%67 = load i8*, i8** %10
%68 = call i8* @strchrnul(i8* %67, i8 signext 47)
store i8* %68, i8** %13
%69 = load i8*, i8** %11
store i8* %69, i8** %9
br label %70
70: ; preds = %74, %66
%71 = load i8*, i8** %10
%72 = load i8*, i8** %13
%73 = icmp ult i8* %71, %72
br i1 %73, label %74, label %82
74: ; preds = %70
%75 = load i8*, i8** %10
%76 = load i8, i8* %75
%77 = load i8*, i8** %11
store i8 %76, i8* %77
%78 = load i8*, i8** %11
%79 = getelementptr inbounds i8, i8* %78, i32 1
store i8* %79, i8** %11
%80 = load i8*, i8** %10
%81 = getelementptr inbounds i8, i8* %80, i32 1
store i8* %81, i8** %10
br label %70
82: ; preds = %70
%83 = load i8*, i8** %10
%84 = load i8, i8* %83
%85 = sext i8 %84 to i32
%86 = icmp eq i32 %85, 47
br i1 %86, label %87, label %90
87: ; preds = %82
%88 = load i8*, i8** %10
%89 = getelementptr inbounds i8, i8* %88, i32 1
store i8* %89, i8** %10
br label %90
90: ; preds = %87, %82
%91 = load i8*, i8** %11
%92 = getelementptr inbounds i8, i8* %91, i64 0
store i8 0, i8* %92
store i32 0, i32* %15
%93 = load i8*, i8** %9
%94 = call i32 @strcmp(i8* %93, i8* getelementptr inbounds ([1 x i8], [1 x i8]* @.str.1, i64 0, i64 0))
%95 = icmp ne i32 %94, 0
br i1 %95, label %97, label %96
96: ; preds = %90
br label %61
97: ; preds = %90
%98 = load i8*, i8** %9
%99 = call i32 @strcmp(i8* %98, i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.2, i64 0, i64 0))
%100 = icmp ne i32 %99, 0
br i1 %100, label %106, label %101
101: ; preds = %97
%102 = load i8*, i8** %11
%103 = getelementptr inbounds i8, i8* %102, i64 -1
store i8* %103, i8** %11
%104 = load i8*, i8** %11
%105 = getelementptr inbounds i8, i8* %104, i64 0
store i8 0, i8* %105
store i32 1, i32* %15
br label %61
106: ; preds = %97
%107 = load i8*, i8** %9
%108 = call i32 @strcmp(i8* %107, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str.3, i64 0, i64 0))
%109 = icmp ne i32 %108, 0
br i1 %109, label %127, label %110
110: ; preds = %106
%111 = load i8*, i8** %11
%112 = getelementptr inbounds i8, i8* %111, i64 -3
store i8* %112, i8** %11
%113 = load i8*, i8** %11
%114 = getelementptr inbounds i8, i8* %113, i64 0
store i8 0, i8* %114
%115 = load i8*, i8** %5
%116 = call i8* @strrchr(i8* %115, i8 signext 47)
store i8* %116, i8** %12
%117 = load i8*, i8** %12
%118 = icmp ne i8* %117, null
br i1 %118, label %119, label %123
119: ; preds = %110
%120 = load i8*, i8** %12
%121 = getelementptr inbounds i8, i8* %120, i64 1
store i8* %121, i8** %11
%122 = load i8*, i8** %11
store i8 0, i8* %122
br label %126
123: ; preds = %110
%124 = load i8*, i8** %5
store i8* %124, i8** %11
%125 = load i8*, i8** %11
store i8 0, i8* %125
br label %126
126: ; preds = %123, %119
store i32 1, i32* %15
br label %61
127: ; preds = %106
%128 = load i8*, i8** %11
%129 = getelementptr inbounds i8, i8* %128, i64 0
store i8 47, i8* %129
%130 = load i8*, i8** %11
%131 = getelementptr inbounds i8, i8* %130, i32 1
store i8* %131, i8** %11
%132 = load i8*, i8** %11
%133 = getelementptr inbounds i8, i8* %132, i64 0
store i8 0, i8* %133
br label %61
134: ; preds = %61
%135 = load i32, i32* %14
%136 = icmp ne i32 %135, 0
br i1 %136, label %154, label %137
137: ; preds = %134
%138 = load i32, i32* %15
%139 = icmp ne i32 %138, 0
br i1 %139, label %154, label %140
140: ; preds = %137
%141 = load i8*, i8** %11
%142 = load i8*, i8** %5
%143 = icmp ugt i8* %141, %142
br i1 %143, label %144, label %153
144: ; preds = %140
%145 = load i8*, i8** %11
%146 = getelementptr inbounds i8, i8* %145, i64 -1
%147 = load i8, i8* %146
%148 = sext i8 %147 to i32
%149 = icmp eq i32 %148, 47
br i1 %149, label %150, label %153
150: ; preds = %144
%151 = load i8*, i8** %11
%152 = getelementptr inbounds i8, i8* %151, i64 -1
store i8 0, i8* %152
br label %153
153: ; preds = %150, %144, %140
br label %154
154: ; preds = %22, %153, %137, %134
ret void
}

LLVM IR (-O2):
@.str = [4 x i8] c"%s/\00"
@.str.2 = [2 x i8] c".\00"
@.str.3 = [3 x i8] c"..\00"
define void @crumb_canonize_path(i8* %0, i8* %1, i32 %2) {
%4 = alloca [512 x i8]
%5 = getelementptr inbounds [512 x i8], [512 x i8]* %4, i64 0, i64 0
%6 = tail call i32 @strlen(i8* %0)
%7 = icmp eq i32 %6, 0
br i1 %7, label %220, label %8
8: ; preds = %3
%9 = call i8* @getcwd(i8* %5, i32 512)
%10 = call i8* @strrchr(i8* dereferenceable(1) %0, i8 signext 47)
%11 = sext i32 %6 to i64
%12 = getelementptr inbounds i8, i8* %0, i64 %11
%13 = getelementptr inbounds i8, i8* %12, i64 -1
%14 = icmp eq i8* %10, %13
%15 = load i8, i8* %0
%16 = icmp eq i8 %15, 47
br i1 %16, label %22, label %17
17: ; preds = %8
%18 = call i32 @snprintf(i8* %1, i32 %2, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), i8* %9)
%19 = call i32 @strlen(i8* %1)
%20 = sext i32 %19 to i64
%21 = getelementptr inbounds i8, i8* %1, i64 %20
br label %24
22: ; preds = %8
store i8 47, i8* %1
%23 = getelementptr inbounds i8, i8* %1, i64 1
store i8 0, i8* %23
br label %24
24: ; preds = %22, %17
%25 = phi i8* [ %21, %17 ], [ %23, %22 ]
%26 = load i8, i8* %0
%27 = icmp eq i8 %26, 0
br i1 %27, label %209, label %28
28: ; preds = %24, %193
%29 = phi i8* [ %182, %193 ], [ %0, %24 ]
%30 = phi i8* [ %194, %193 ], [ %25, %24 ]
%31 = call i8* @strchrnul(i8* %29, i8 signext 47)
%32 = icmp ult i8* %29, %31
br i1 %32, label %33, label %176
33: ; preds = %28
%34 = ptrtoint i8* %31 to i64
%35 = ptrtoint i8* %29 to i64
%36 = sub i64 %34, %35
%37 = getelementptr i8, i8* %29, i64 %36
%38 = icmp ult i64 %36, 32
br i1 %38, label %125, label %39
39: ; preds = %33
%40 = getelementptr i8, i8* %30, i64 %36
%41 = icmp ult i8* %30, %37
%42 = icmp ult i8* %29, %40
%43 = and i1 %41, %42
br i1 %43, label %125, label %44
44: ; preds = %39
%45 = and i64 %36, -32
%46 = getelementptr i8, i8* %29, i64 %45
%47 = getelementptr i8, i8* %30, i64 %45
%48 = add i64 %45, -32
%49 = lshr exact i64 %48, 5
%50 = add nuw nsw i64 %49, 1
%51 = and i64 %50, 3
%52 = icmp ult i64 %48, 96
br i1 %52, label %104, label %53
53: ; preds = %44
%54 = and i64 %50, 1152921504606846972
br label %55
55: ; preds = %55, %53
%56 = phi i64 [ 0, %53 ], [ %101, %55 ]
%57 = phi i64 [ 0, %53 ], [ %102, %55 ]
%58 = getelementptr i8, i8* %29, i64 %56
%59 = getelementptr i8, i8* %30, i64 %56
%60 = bitcast i8* %58 to <16 x i8>*
%61 = load <16 x i8>, <16 x i8>* %60
%62 = getelementptr i8, i8* %58, i64 16
%63 = bitcast i8* %62 to <16 x i8>*
%64 = load <16 x i8>, <16 x i8>* %63
%65 = bitcast i8* %59 to <16 x i8>*
store <16 x i8> %61, <16 x i8>* %65
%66 = getelementptr i8, i8* %59, i64 16
%67 = bitcast i8* %66 to <16 x i8>*
store <16 x i8> %64, <16 x i8>* %67
%68 = or i64 %56, 32
%69 = getelementptr i8, i8* %29, i64 %68
%70 = getelementptr i8, i8* %30, i64 %68
%71 = bitcast i8* %69 to <16 x i8>*
%72 = load <16 x i8>, <16 x i8>* %71
%73 = getelementptr i8, i8* %69, i64 16
%74 = bitcast i8* %73 to <16 x i8>*
%75 = load <16 x i8>, <16 x i8>* %74
%76 = bitcast i8* %70 to <16 x i8>*
store <16 x i8> %72, <16 x i8>* %76
%77 = getelementptr i8, i8* %70, i64 16
%78 = bitcast i8* %77 to <16 x i8>*
store <16 x i8> %75, <16 x i8>* %78
%79 = or i64 %56, 64
%80 = getelementptr i8, i8* %29, i64 %79
%81 = getelementptr i8, i8* %30, i64 %79
%82 = bitcast i8* %80 to <16 x i8>*
%83 = load <16 x i8>, <16 x i8>* %82
%84 = getelementptr i8, i8* %80, i64 16
%85 = bitcast i8* %84 to <16 x i8>*
%86 = load <16 x i8>, <16 x i8>* %85
%87 = bitcast i8* %81 to <16 x i8>*
store <16 x i8> %83, <16 x i8>* %87
%88 = getelementptr i8, i8* %81, i64 16
%89 = bitcast i8* %88 to <16 x i8>*
store <16 x i8> %86, <16 x i8>* %89
%90 = or i64 %56, 96
%91 = getelementptr i8, i8* %29, i64 %90
%92 = getelementptr i8, i8* %30, i64 %90
%93 = bitcast i8* %91 to <16 x i8>*
%94 = load <16 x i8>, <16 x i8>* %93
%95 = getelementptr i8, i8* %91, i64 16
%96 = bitcast i8* %95 to <16 x i8>*
%97 = load <16 x i8>, <16 x i8>* %96
%98 = bitcast i8* %92 to <16 x i8>*
store <16 x i8> %94, <16 x i8>* %98
%99 = getelementptr i8, i8* %92, i64 16
%100 = bitcast i8* %99 to <16 x i8>*
store <16 x i8> %97, <16 x i8>* %100
%101 = add nuw i64 %56, 128
%102 = add i64 %57, 4
%103 = icmp eq i64 %102, %54
br i1 %103, label %104, label %55
104: ; preds = %55, %44
%105 = phi i64 [ 0, %44 ], [ %101, %55 ]
%106 = icmp eq i64 %51, 0
br i1 %106, label %123, label %107
107: ; preds = %104, %107
%108 = phi i64 [ %120, %107 ], [ %105, %104 ]
%109 = phi i64 [ %121, %107 ], [ 0, %104 ]
%110 = getelementptr i8, i8* %29, i64 %108
%111 = getelementptr i8, i8* %30, i64 %108
%112 = bitcast i8* %110 to <16 x i8>*
%113 = load <16 x i8>, <16 x i8>* %112
%114 = getelementptr i8, i8* %110, i64 16
%115 = bitcast i8* %114 to <16 x i8>*
%116 = load <16 x i8>, <16 x i8>* %115
%117 = bitcast i8* %111 to <16 x i8>*
store <16 x i8> %113, <16 x i8>* %117
%118 = getelementptr i8, i8* %111, i64 16
%119 = bitcast i8* %118 to <16 x i8>*
store <16 x i8> %116, <16 x i8>* %119
%120 = add nuw i64 %108, 32
%121 = add i64 %109, 1
%122 = icmp eq i64 %121, %51
br i1 %122, label %123, label %107
123: ; preds = %107, %104
%124 = icmp eq i64 %36, %45
br i1 %124, label %176, label %125
125: ; preds = %39, %33, %123
%126 = phi i8* [ %29, %39 ], [ %29, %33 ], [ %46, %123 ]
%127 = phi i8* [ %30, %39 ], [ %30, %33 ], [ %47, %123 ]
%128 = ptrtoint i8* %126 to i64
%129 = sub i64 %34, %128
%130 = xor i64 %128, -1
%131 = add i64 %130, %34
%132 = and i64 %129, 7
%133 = icmp eq i64 %132, 0
br i1 %133, label %143, label %134
134: ; preds = %125, %134
%135 = phi i8* [ %140, %134 ], [ %126, %125 ]
%136 = phi i8* [ %139, %134 ], [ %127, %125 ]
%137 = phi i64 [ %141, %134 ], [ 0, %125 ]
%138 = load i8, i8* %135
store i8 %138, i8* %136
%139 = getelementptr inbounds i8, i8* %136, i64 1
%140 = getelementptr inbounds i8, i8* %135, i64 1
%141 = add i64 %137, 1
%142 = icmp eq i64 %141, %132
br i1 %142, label %143, label %134
143: ; preds = %134, %125
%144 = phi i8* [ undef, %125 ], [ %139, %134 ]
%145 = phi i8* [ %126, %125 ], [ %140, %134 ]
%146 = phi i8* [ %127, %125 ], [ %139, %134 ]
%147 = icmp ult i64 %131, 7
br i1 %147, label %176, label %148
148: ; preds = %143, %148
%149 = phi i8* [ %174, %148 ], [ %145, %143 ]
%150 = phi i8* [ %173, %148 ], [ %146, %143 ]
%151 = load i8, i8* %149
store i8 %151, i8* %150
%152 = getelementptr inbounds i8, i8* %150, i64 1
%153 = getelementptr inbounds i8, i8* %149, i64 1
%154 = load i8, i8* %153
store i8 %154, i8* %152
%155 = getelementptr inbounds i8, i8* %150, i64 2
%156 = getelementptr inbounds i8, i8* %149, i64 2
%157 = load i8, i8* %156
store i8 %157, i8* %155
%158 = getelementptr inbounds i8, i8* %150, i64 3
%159 = getelementptr inbounds i8, i8* %149, i64 3
%160 = load i8, i8* %159
store i8 %160, i8* %158
%161 = getelementptr inbounds i8, i8* %150, i64 4
%162 = getelementptr inbounds i8, i8* %149, i64 4
%163 = load i8, i8* %162
store i8 %163, i8* %161
%164 = getelementptr inbounds i8, i8* %150, i64 5
%165 = getelementptr inbounds i8, i8* %149, i64 5
%166 = load i8, i8* %165
store i8 %166, i8* %164
%167 = getelementptr inbounds i8, i8* %150, i64 6
%168 = getelementptr inbounds i8, i8* %149, i64 6
%169 = load i8, i8* %168
store i8 %169, i8* %167
%170 = getelementptr inbounds i8, i8* %150, i64 7
%171 = getelementptr inbounds i8, i8* %149, i64 7
%172 = load i8, i8* %171
store i8 %172, i8* %170
%173 = getelementptr inbounds i8, i8* %150, i64 8
%174 = getelementptr inbounds i8, i8* %149, i64 8
%175 = icmp eq i8* %174, %37
br i1 %175, label %176, label %148
176: ; preds = %143, %148, %123, %28
%177 = phi i8* [ %30, %28 ], [ %47, %123 ], [ %144, %143 ], [ %173, %148 ]
%178 = phi i8* [ %29, %28 ], [ %37, %123 ], [ %37, %148 ], [ %37, %143 ]
%179 = load i8, i8* %178
%180 = icmp eq i8 %179, 47
%181 = zext i1 %180 to i64
%182 = getelementptr i8, i8* %178, i64 %181
store i8 0, i8* %177
%183 = load i8, i8* %30
%184 = icmp eq i8 %183, 0
br i1 %184, label %193, label %185
185: ; preds = %176
%186 = call i32 @strcmp(i8* %30, i8* dereferenceable(2) getelementptr inbounds ([2 x i8], [2 x i8]* @.str.2, i64 0, i64 0))
%187 = icmp eq i32 %186, 0
br i1 %187, label %188, label %198
188: ; preds = %185
%189 = getelementptr inbounds i8, i8* %177, i64 -1
br label %190
190: ; preds = %201, %207, %188
%191 = phi i8* [ %189, %188 ], [ %208, %207 ], [ %206, %201 ]
%192 = phi i1 [ true, %188 ], [ false, %207 ], [ true, %201 ]
store i8 0, i8* %191
br label %193
193: ; preds = %190, %176
%194 = phi i8* [ %177, %176 ], [ %191, %190 ]
%195 = phi i1 [ false, %176 ], [ %192, %190 ]
%196 = load i8, i8* %182
%197 = icmp eq i8 %196, 0
br i1 %197, label %209, label %28
198: ; preds = %185
%199 = call i32 @strcmp(i8* %30, i8* dereferenceable(3) getelementptr inbounds ([3 x i8], [3 x i8]* @.str.3, i64 0, i64 0))
%200 = icmp eq i32 %199, 0
br i1 %200, label %201, label %207
201: ; preds = %198
%202 = getelementptr inbounds i8, i8* %177, i64 -3
store i8 0, i8* %202
%203 = call i8* @strrchr(i8* dereferenceable(1) %1, i8 signext 47)
%204 = icmp eq i8* %203, null
%205 = getelementptr inbounds i8, i8* %203, i64 1
%206 = select i1 %204, i8* %1, i8* %205
br label %190
207: ; preds = %198
store i8 47, i8* %177
%208 = getelementptr inbounds i8, i8* %177, i64 1
br label %190
209: ; preds = %193, %24
%210 = phi i8* [ %25, %24 ], [ %194, %193 ]
%211 = phi i1 [ false, %24 ], [ %195, %193 ]
%212 = or i1 %14, %211
%213 = xor i1 %212, true
%214 = icmp ugt i8* %210, %1
%215 = select i1 %213, i1 %214, i1 false
br i1 %215, label %216, label %222
216: ; preds = %209
%217 = getelementptr inbounds i8, i8* %210, i64 -1
%218 = load i8, i8* %217
%219 = icmp eq i8 %218, 47
br i1 %219, label %220, label %222
220: ; preds = %216, %3
%221 = phi i8* [ %1, %3 ], [ %217, %216 ]
store i8 0, i8* %221
br label %222
222: ; preds = %220, %209, %216
ret void
}