void str_list_free(char ***list) {
  char **tlist;
  if (!list || !*list)
    return;
  tlist = *list;
  for (; *tlist; tlist++)
    SAFE_FREE(*tlist);
  SAFE_FREE(*list);
}


x86 assembly (clang, -O0):
<str_list_free>:
push   %rbp
mov    %rsp,%rbp
sub    $0x10,%rsp
mov    %rdi,-0x8(%rbp)
cmpq   $0x0,-0x8(%rbp)
je     1135 <str_list_free+0x25>
mov    -0x8(%rbp),%rax
cmpq   $0x0,(%rax)
jne    113a <str_list_free+0x2a>
jmp    1180 <str_list_free+0x70>
mov    -0x8(%rbp),%rax
mov    (%rax),%rax
mov    %rax,-0x10(%rbp)
mov    -0x10(%rbp),%rax
cmpq   $0x0,(%rax)
je     1172 <str_list_free+0x62>
mov    -0x10(%rbp),%rax
mov    (%rax),%rdi
mov    $0x0,%al
call   1030 <SAFE_FREE@plt>
mov    -0x10(%rbp),%rax
add    $0x8,%rax
mov    %rax,-0x10(%rbp)
jmp    1145 <str_list_free+0x35>
mov    -0x8(%rbp),%rax
mov    (%rax),%rdi
mov    $0x0,%al
call   1030 <SAFE_FREE@plt>
add    $0x10,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<str_list_free>:
push   %r14
push   %rbx
push   %rax
test   %rdi,%rdi
je     1157 <str_list_free+0x47>
mov    %rdi,%r14
mov    (%rdi),%rbx
test   %rbx,%rbx
je     1157 <str_list_free+0x47>
mov    (%rbx),%rdi
test   %rdi,%rdi
je     1146 <str_list_free+0x36>
add    $0x8,%rbx
xor    %eax,%eax
call   1030 <SAFE_FREE@plt>
mov    (%rbx),%rdi
add    $0x8,%rbx
test   %rdi,%rdi
jne    1130 <str_list_free+0x20>
mov    (%r14),%rbx
mov    %rbx,%rdi
xor    %eax,%eax
add    $0x8,%rsp
pop    %rbx
pop    %r14
jmp    1030 <SAFE_FREE@plt>
add    $0x8,%rsp
pop    %rbx
pop    %r14
ret

LLVM IR (-O0):
define void @str_list_free(i8*** %0) {
%2 = alloca i8***
%3 = alloca i8**
store i8*** %0, i8**** %2
%4 = load i8***, i8**** %2
%5 = icmp ne i8*** %4, null
br i1 %5, label %6, label %10
6: ; preds = %1
%7 = load i8***, i8**** %2
%8 = load i8**, i8*** %7
%9 = icmp ne i8** %8, null
br i1 %9, label %11, label %10
10: ; preds = %6, %1
br label %29
11: ; preds = %6
%12 = load i8***, i8**** %2
%13 = load i8**, i8*** %12
store i8** %13, i8*** %3
br label %14
14: ; preds = %22, %11
%15 = load i8**, i8*** %3
%16 = load i8*, i8** %15
%17 = icmp ne i8* %16, null
br i1 %17, label %18, label %25
18: ; preds = %14
%19 = load i8**, i8*** %3
%20 = load i8*, i8** %19
%21 = call i32 (i8*, ...) bitcast (i32 (...)* @SAFE_FREE to i32 (i8*, ...)*)(i8* %20)
br label %22
22: ; preds = %18
%23 = load i8**, i8*** %3
%24 = getelementptr inbounds i8*, i8** %23, i32 1
store i8** %24, i8*** %3
br label %14
25: ; preds = %14
%26 = load i8***, i8**** %2
%27 = load i8**, i8*** %26
%28 = call i32 (i8**, ...) bitcast (i32 (...)* @SAFE_FREE to i32 (i8**, ...)*)(i8** %27)
br label %29
29: ; preds = %25, %10
ret void
}

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