#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 */

/* Variables and functions */
char *memrchr(char const *, char, int);
char *strdup(char *);
char *strrchr(char const *, char);
char *substr(char const *, int);
char *dirname(const char *filename) {
  char *c = strrchr(filename, '/');
  if (!c)
    return strdup(".");
  if (c[1] == '\0') {
    while (c != filename && c[-1] == '/')
      --c;
    c = memrchr(filename, '/', c - filename);
  }
  while (c != filename && c[-1] == '/')
    --c;
  return (c != filename)        ? substr(filename, c - filename)
         : (filename[1] == '/') ? strdup("//")
                                : strdup("/");
}


x86 assembly (clang, -O0):
<dirname>:
push   %rbp
mov    %rsp,%rbp
sub    $0x30,%rsp
mov    %rdi,-0x10(%rbp)
mov    -0x10(%rbp),%rdi
mov    $0x2f,%esi
call   1040 <strrchr@plt>
mov    %rax,-0x18(%rbp)
cmpq   $0x0,-0x18(%rbp)
jne    117e <dirname+0x3e>
lea    0xe90(%rip),%rdi
call   1060 <strdup@plt>
mov    %rax,-0x8(%rbp)
jmp    12b5 <dirname+0x175>
mov    -0x18(%rbp),%rax
movsbl 0x1(%rax),%eax
cmp    $0x0,%eax
jne    11f8 <dirname+0xb8>
jmp    1194 <dirname+0x54>
mov    -0x18(%rbp),%rcx
xor    %eax,%eax
cmp    -0x10(%rbp),%rcx
mov    %al,-0x19(%rbp)
je     11b8 <dirname+0x78>
mov    -0x18(%rbp),%rax
movsbl -0x1(%rax),%eax
cmp    $0x2f,%eax
sete   %al
mov    %al,-0x19(%rbp)
mov    -0x19(%rbp),%al
test   $0x1,%al
jne    11c8 <dirname+0x88>
jmp    11d9 <dirname+0x99>
mov    -0x18(%rbp),%rax
add    $0xffffffffffffffff,%rax
mov    %rax,-0x18(%rbp)
jmp    1194 <dirname+0x54>
mov    -0x10(%rbp),%rdi
mov    -0x18(%rbp),%rax
mov    -0x10(%rbp),%rcx
sub    %rcx,%rax
mov    %eax,%edx
mov    $0x2f,%esi
call   1050 <memrchr@plt>
mov    %rax,-0x18(%rbp)
jmp    11fd <dirname+0xbd>
mov    -0x18(%rbp),%rcx
xor    %eax,%eax
cmp    -0x10(%rbp),%rcx
mov    %al,-0x1a(%rbp)
je     1221 <dirname+0xe1>
mov    -0x18(%rbp),%rax
movsbl -0x1(%rax),%eax
cmp    $0x2f,%eax
sete   %al
mov    %al,-0x1a(%rbp)
mov    -0x1a(%rbp),%al
test   $0x1,%al
jne    1231 <dirname+0xf1>
jmp    1242 <dirname+0x102>
mov    -0x18(%rbp),%rax
add    $0xffffffffffffffff,%rax
mov    %rax,-0x18(%rbp)
jmp    11fd <dirname+0xbd>
mov    -0x18(%rbp),%rax
cmp    -0x10(%rbp),%rax
je     126f <dirname+0x12f>
mov    -0x10(%rbp),%rdi
mov    -0x18(%rbp),%rax
mov    -0x10(%rbp),%rcx
sub    %rcx,%rax
mov    %eax,%esi
call   1030 <substr@plt>
mov    %rax,-0x28(%rbp)
jmp    12ad <dirname+0x16d>
mov    -0x10(%rbp),%rax
movsbl 0x1(%rax),%eax
cmp    $0x2f,%eax
jne    1295 <dirname+0x155>
lea    0xd7b(%rip),%rdi
call   1060 <strdup@plt>
mov    %rax,-0x30(%rbp)
jmp    12a5 <dirname+0x165>
lea    0xd67(%rip),%rdi
call   1060 <strdup@plt>
mov    %rax,-0x30(%rbp)
mov    -0x30(%rbp),%rax
mov    %rax,-0x28(%rbp)
mov    -0x28(%rbp),%rax
mov    %rax,-0x8(%rbp)
mov    -0x8(%rbp),%rax
add    $0x30,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<dirname>:
push   %rbx
mov    %rdi,%rbx
mov    $0x2f,%esi
call   1040 <strrchr@plt>
test   %rax,%rax
je     1177 <dirname+0x37>
cmpb   $0x0,0x1(%rax)
jne    1197 <dirname+0x57>
jmp    116d <dirname+0x2d>
nopl   0x0(%rax,%rax,1)
lea    -0x1(%rax),%rdx
cmpb   $0x2f,-0x1(%rax)
mov    %rdx,%rax
jne    1184 <dirname+0x44>
cmp    %rbx,%rax
jne    1160 <dirname+0x20>
mov    %rbx,%rdx
jmp    1188 <dirname+0x48>
lea    0xe82(%rip),%rdi
pop    %rbx
jmp    1060 <strdup@plt>
add    $0x1,%rdx
sub    %ebx,%edx
mov    %rbx,%rdi
mov    $0x2f,%esi
call   1050 <memrchr@plt>
mov    %eax,%esi
sub    %ebx,%esi
add    $0x1,%esi
xchg   %ax,%ax
cmp    %rbx,%rax
je     11bb <dirname+0x7b>
add    $0xffffffff,%esi
cmpb   $0x2f,-0x1(%rax)
lea    -0x1(%rax),%rax
je     11a0 <dirname+0x60>
mov    %rbx,%rdi
pop    %rbx
jmp    1030 <substr@plt>
cmpb   $0x2f,0x1(%rbx)
jne    11ce <dirname+0x8e>
lea    0xe3a(%rip),%rdi
pop    %rbx
jmp    1060 <strdup@plt>
lea    0xe2e(%rip),%rdi
pop    %rbx
jmp    1060 <strdup@plt>

LLVM IR (-O0):
@.str = [2 x i8] c".\00"
@.str.1 = [3 x i8] c"//\00"
@.str.2 = [2 x i8] c"/\00"
define i8* @dirname(i8* %0) {
%2 = alloca i8*
%3 = alloca i8*
%4 = alloca i8*
store i8* %0, i8** %3
%5 = load i8*, i8** %3
%6 = call i8* @strrchr(i8* %5, i8 signext 47)
store i8* %6, i8** %4
%7 = load i8*, i8** %4
%8 = icmp ne i8* %7, null
br i1 %8, label %11, label %9
9: ; preds = %1
%10 = call i8* @strdup(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str, i64 0, i64 0))
store i8* %10, i8** %2
br label %85
11: ; preds = %1
%12 = load i8*, i8** %4
%13 = getelementptr inbounds i8, i8* %12, i64 1
%14 = load i8, i8* %13
%15 = sext i8 %14 to i32
%16 = icmp eq i32 %15, 0
br i1 %16, label %17, label %42
17: ; preds = %11
br label %18
18: ; preds = %30, %17
%19 = load i8*, i8** %4
%20 = load i8*, i8** %3
%21 = icmp ne i8* %19, %20
br i1 %21, label %22, label %28
22: ; preds = %18
%23 = load i8*, i8** %4
%24 = getelementptr inbounds i8, i8* %23, i64 -1
%25 = load i8, i8* %24
%26 = sext i8 %25 to i32
%27 = icmp eq i32 %26, 47
br label %28
28: ; preds = %22, %18
%29 = phi i1 [ false, %18 ], [ %27, %22 ]
br i1 %29, label %30, label %33
30: ; preds = %28
%31 = load i8*, i8** %4
%32 = getelementptr inbounds i8, i8* %31, i32 -1
store i8* %32, i8** %4
br label %18
33: ; preds = %28
%34 = load i8*, i8** %3
%35 = load i8*, i8** %4
%36 = load i8*, i8** %3
%37 = ptrtoint i8* %35 to i64
%38 = ptrtoint i8* %36 to i64
%39 = sub i64 %37, %38
%40 = trunc i64 %39 to i32
%41 = call i8* @memrchr(i8* %34, i8 signext 47, i32 %40)
store i8* %41, i8** %4
br label %42
42: ; preds = %33, %11
br label %43
43: ; preds = %55, %42
%44 = load i8*, i8** %4
%45 = load i8*, i8** %3
%46 = icmp ne i8* %44, %45
br i1 %46, label %47, label %53
47: ; preds = %43
%48 = load i8*, i8** %4
%49 = getelementptr inbounds i8, i8* %48, i64 -1
%50 = load i8, i8* %49
%51 = sext i8 %50 to i32
%52 = icmp eq i32 %51, 47
br label %53
53: ; preds = %47, %43
%54 = phi i1 [ false, %43 ], [ %52, %47 ]
br i1 %54, label %55, label %58
55: ; preds = %53
%56 = load i8*, i8** %4
%57 = getelementptr inbounds i8, i8* %56, i32 -1
store i8* %57, i8** %4
br label %43
58: ; preds = %53
%59 = load i8*, i8** %4
%60 = load i8*, i8** %3
%61 = icmp ne i8* %59, %60
br i1 %61, label %62, label %71
62: ; preds = %58
%63 = load i8*, i8** %3
%64 = load i8*, i8** %4
%65 = load i8*, i8** %3
%66 = ptrtoint i8* %64 to i64
%67 = ptrtoint i8* %65 to i64
%68 = sub i64 %66, %67
%69 = trunc i64 %68 to i32
%70 = call i8* @substr(i8* %63, i32 %69)
br label %83
71: ; preds = %58
%72 = load i8*, i8** %3
%73 = getelementptr inbounds i8, i8* %72, i64 1
%74 = load i8, i8* %73
%75 = sext i8 %74 to i32
%76 = icmp eq i32 %75, 47
br i1 %76, label %77, label %79
77: ; preds = %71
%78 = call i8* @strdup(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str.1, i64 0, i64 0))
br label %81
79: ; preds = %71
%80 = call i8* @strdup(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.2, i64 0, i64 0))
br label %81
81: ; preds = %79, %77
%82 = phi i8* [ %78, %77 ], [ %80, %79 ]
br label %83
83: ; preds = %81, %62
%84 = phi i8* [ %70, %62 ], [ %82, %81 ]
store i8* %84, i8** %2
br label %85
85: ; preds = %83, %9
%86 = load i8*, i8** %2
ret i8* %86
}

LLVM IR (-O2):
@.str = [2 x i8] c".\00"
@.str.1 = [3 x i8] c"//\00"
@.str.2 = [2 x i8] c"/\00"
define i8* @dirname(i8* %0) {
%2 = ptrtoint i8* %0 to i64
%3 = tail call i8* @strrchr(i8* dereferenceable(1) %0, i8 signext 47)
%4 = ptrtoint i8* %3 to i64
%5 = icmp eq i8* %3, null
br i1 %5, label %6, label %8
6: ; preds = %1
%7 = tail call dereferenceable_or_null(2) i8* @strdup(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str, i64 0, i64 0))
br label %50
8: ; preds = %1
%9 = getelementptr inbounds i8, i8* %3, i64 1
%10 = load i8, i8* %9
%11 = icmp eq i8 %10, 0
br i1 %11, label %12, label %28
12: ; preds = %8
%13 = sub i64 %2, %4
%14 = getelementptr i8, i8* %3, i64 %13
br label %15
15: ; preds = %12, %18
%16 = phi i8* [ %19, %18 ], [ %3, %12 ]
%17 = icmp eq i8* %16, %0
br i1 %17, label %22, label %18
18: ; preds = %15
%19 = getelementptr inbounds i8, i8* %16, i64 -1
%20 = load i8, i8* %19
%21 = icmp eq i8 %20, 47
br i1 %21, label %15, label %22
22: ; preds = %15, %18
%23 = phi i8* [ %14, %15 ], [ %16, %18 ]
%24 = ptrtoint i8* %23 to i64
%25 = sub i64 %24, %2
%26 = trunc i64 %25 to i32
%27 = tail call i8* @memrchr(i8* %0, i8 signext 47, i32 %26)
br label %28
28: ; preds = %22, %8
%29 = phi i8* [ %3, %8 ], [ %27, %22 ]
br label %30
30: ; preds = %28, %33
%31 = phi i8* [ %34, %33 ], [ %29, %28 ]
%32 = icmp eq i8* %31, %0
br i1 %32, label %42, label %33
33: ; preds = %30
%34 = getelementptr inbounds i8, i8* %31, i64 -1
%35 = load i8, i8* %34
%36 = icmp eq i8 %35, 47
br i1 %36, label %30, label %37
37: ; preds = %33
%38 = ptrtoint i8* %31 to i64
%39 = sub i64 %38, %2
%40 = trunc i64 %39 to i32
%41 = tail call i8* @substr(i8* %0, i32 %40)
br label %50
42: ; preds = %30
%43 = getelementptr inbounds i8, i8* %0, i64 1
%44 = load i8, i8* %43
%45 = icmp eq i8 %44, 47
br i1 %45, label %46, label %48
46: ; preds = %42
%47 = tail call dereferenceable_or_null(3) i8* @strdup(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str.1, i64 0, i64 0))
br label %50
48: ; preds = %42
%49 = tail call dereferenceable_or_null(2) i8* @strdup(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.2, i64 0, i64 0))
br label %50
50: ; preds = %37, %48, %46, %6
%51 = phi i8* [ %7, %6 ], [ %41, %37 ], [ %47, %46 ], [ %49, %48 ]
ret i8* %51
}