#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 */
int /*<<< orphan*/ memset(char *, char, size_t);
int /*<<< orphan*/ printf(char *, size_t, size_t, size_t);
size_t strlen(char *);
size_t strnlen(char *, int);
int main(int argc, char *argv[]) {
  static const size_t lens[] = {0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4};
  char basebuf[24 + 32];
  size_t base;
  for (base = 0; base < 32; ++base) {
    char *buf = basebuf + base;
    size_t words;
    for (words = 0; words < 4; ++words) {
      size_t last;
      memset(buf, 'a', words * 4);
      for (last = 0; last < 16; ++last) {
        buf[words * 4 + 0] = (last & 1) != 0 ? 'b' : '\0';
        buf[words * 4 + 1] = (last & 2) != 0 ? 'c' : '\0';
        buf[words * 4 + 2] = (last & 4) != 0 ? 'd' : '\0';
        buf[words * 4 + 3] = (last & 8) != 0 ? 'e' : '\0';
        buf[words * 4 + 4] = '\0';
        if (strlen(buf) != words * 4 + lens[last] ||
            strnlen(buf, -1) != words * 4 + lens[last]) {
          printf("failed for base=%Zu, words=%Zu, and last=%Zu\n", base, words,
                 last);
          return 1;
        }
      }
    }
  }
  return 0;
}


x86 assembly (clang, -O0):
<main>:
push   %rbp
mov    %rsp,%rbp
sub    $0x70,%rsp
movl   $0x0,-0x4(%rbp)
mov    %edi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
movq   $0x0,-0x58(%rbp)
cmpq   $0x20,-0x58(%rbp)
jae    131e <main+0x1de>
lea    -0x50(%rbp),%rax
add    -0x58(%rbp),%rax
mov    %rax,-0x60(%rbp)
movq   $0x0,-0x68(%rbp)
cmpq   $0x4,-0x68(%rbp)
jae    1308 <main+0x1c8>
mov    -0x60(%rbp),%rdi
mov    -0x68(%rbp),%rdx
shl    $0x2,%rdx
mov    $0x61,%esi
call   1050 <memset@plt>
movq   $0x0,-0x70(%rbp)
cmpq   $0x10,-0x70(%rbp)
jae    12f2 <main+0x1b2>
mov    -0x70(%rbp),%rdx
and    $0x1,%rdx
xor    %eax,%eax
mov    $0x62,%ecx
cmp    $0x0,%rdx
cmovne %ecx,%eax
mov    %al,%dl
mov    -0x60(%rbp),%rax
mov    -0x68(%rbp),%rcx
shl    $0x2,%rcx
mov    %dl,(%rax,%rcx,1)
mov    -0x70(%rbp),%rdx
and    $0x2,%rdx
xor    %eax,%eax
mov    $0x63,%ecx
cmp    $0x0,%rdx
cmovne %ecx,%eax
mov    %al,%dl
mov    -0x60(%rbp),%rax
mov    -0x68(%rbp),%rcx
shl    $0x2,%rcx
mov    %dl,0x1(%rax,%rcx,1)
mov    -0x70(%rbp),%rdx
and    $0x4,%rdx
xor    %eax,%eax
mov    $0x64,%ecx
cmp    $0x0,%rdx
cmovne %ecx,%eax
mov    %al,%dl
mov    -0x60(%rbp),%rax
mov    -0x68(%rbp),%rcx
shl    $0x2,%rcx
mov    %dl,0x2(%rax,%rcx,1)
mov    -0x70(%rbp),%rdx
and    $0x8,%rdx
xor    %eax,%eax
mov    $0x65,%ecx
cmp    $0x0,%rdx
cmovne %ecx,%eax
mov    %al,%dl
mov    -0x60(%rbp),%rax
mov    -0x68(%rbp),%rcx
shl    $0x2,%rcx
mov    %dl,0x3(%rax,%rcx,1)
mov    -0x60(%rbp),%rax
mov    -0x68(%rbp),%rcx
shl    $0x2,%rcx
movb   $0x0,0x4(%rax,%rcx,1)
mov    -0x60(%rbp),%rdi
call   1030 <strlen@plt>
mov    -0x68(%rbp),%rcx
shl    $0x2,%rcx
mov    -0x70(%rbp),%rsi
lea    0xd83(%rip),%rdx
add    (%rdx,%rsi,8),%rcx
cmp    %rcx,%rax
jne    12b8 <main+0x178>
mov    -0x60(%rbp),%rdi
mov    $0xffffffff,%esi
call   1060 <strnlen@plt>
mov    -0x68(%rbp),%rcx
shl    $0x2,%rcx
mov    -0x70(%rbp),%rsi
lea    0xd55(%rip),%rdx
add    (%rdx,%rsi,8),%rcx
cmp    %rcx,%rax
je     12dc <main+0x19c>
mov    -0x58(%rbp),%rsi
mov    -0x68(%rbp),%rdx
mov    -0x70(%rbp),%rcx
lea    0xdb5(%rip),%rdi
call   1040 <printf@plt>
movl   $0x1,-0x4(%rbp)
jmp    1325 <main+0x1e5>
jmp    12e1 <main+0x1a1>
mov    -0x70(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x70(%rbp)
jmp    11a6 <main+0x66>
jmp    12f7 <main+0x1b7>
mov    -0x68(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x68(%rbp)
jmp    117d <main+0x3d>
jmp    130d <main+0x1cd>
mov    -0x58(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x58(%rbp)
jmp    115e <main+0x1e>
movl   $0x0,-0x4(%rbp)
mov    -0x4(%rbp),%eax
add    $0x70,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<main>:
push   %rbp
push   %r15
push   %r14
push   %r13
push   %r12
push   %rbx
sub    $0x68,%rsp
xor    %r15d,%r15d
xor    %r14d,%r14d
cs nopw 0x0(%rax,%rax,1)
xchg   %ax,%ax
lea    (%rsp,%r14,1),%rbx
add    $0x30,%rbx
mov    $0x1,%cl
xor    %ebp,%ebp
mov    %r14,0x8(%rsp)
mov    %cl,0x7(%rsp)
lea    0x0(,%rbp,4),%r13
mov    %rbx,%rdi
mov    $0x61,%esi
mov    %r13,%rdx
call   1050 <memset@plt>
lea    0x1(,%rbp,4),%rax
mov    %rax,0x28(%rsp)
lea    0x2(,%rbp,4),%rax
mov    %rax,0x20(%rsp)
mov    %rbp,0x10(%rsp)
lea    0x3(,%rbp,4),%rax
mov    %rax,0x18(%rsp)
lea    0xe40(%rip),%r12
xor    %ebp,%ebp
cs nopw 0x0(%rax,%rax,1)
nopl   0x0(%rax)
test   $0x1,%bpl
mov    $0x62,%eax
cmove  %r15d,%eax
mov    %al,(%rbx,%r13,1)
test   $0x2,%bpl
mov    $0x63,%eax
cmove  %r15d,%eax
test   $0x4,%bpl
mov    $0x64,%ecx
cmove  %r15d,%ecx
mov    0x28(%rsp),%rdx
mov    %al,(%rbx,%rdx,1)
mov    0x20(%rsp),%rax
mov    %cl,(%rbx,%rax,1)
test   $0x8,%bpl
mov    $0x65,%eax
cmove  %r15d,%eax
mov    0x18(%rsp),%rcx
mov    %al,(%rbx,%rcx,1)
movb   $0x0,0x4(%rbx,%r13,1)
mov    %rbx,%rdi
call   1030 <strlen@plt>
mov    %rax,%r14
mov    (%r12),%rax
add    %r13,%rax
cmp    %rax,%r14
jne    1290 <main+0x150>
mov    %rbx,%rdi
mov    $0xffffffff,%esi
call   1060 <strnlen@plt>
cmp    %r14,%rax
jne    1290 <main+0x150>
add    $0x1,%rbp
add    $0x8,%r12
cmp    $0x10,%rbp
jne    11d0 <main+0x90>
mov    0x10(%rsp),%rax
cmp    $0x3,%rax
lea    0x1(%rax),%rax
setb   %cl
mov    %rax,%rbp
cmp    $0x4,%rax
mov    0x8(%rsp),%r14
jne    1171 <main+0x31>
jmp    12b3 <main+0x173>
cs nopw 0x0(%rax,%rax,1)
nop
lea    0xde9(%rip),%rdi
mov    0x8(%rsp),%r14
mov    %r14,%rsi
mov    0x10(%rsp),%rdx
mov    %rbp,%rcx
call   1040 <printf@plt>
testb  $0x1,0x7(%rsp)
jne    12c5 <main+0x185>
add    $0x1,%r14
cmp    $0x20,%r14
jne    1160 <main+0x20>
xor    %eax,%eax
jmp    12ca <main+0x18a>
mov    $0x1,%eax
add    $0x68,%rsp
pop    %rbx
pop    %r12
pop    %r13
pop    %r14
pop    %r15
pop    %rbp
ret

LLVM IR (-O0):
@main.lens = internal constant [16 x i64] [i64 0, i64 1, i64 0, i64 2, i64 0, i64 1, i64 0, i64 3, i64 0, i64 1, i64 0, i64 2, i64 0, i64 1, i64 0, i64 4]
@.str = [46 x i8] c"failed for base=%Zu, words=%Zu, and last=%Zu\0A\00"
define i32 @main(i32 %0, i8** %1) {
%3 = alloca i32
%4 = alloca i32
%5 = alloca i8**
%6 = alloca [56 x i8]
%7 = alloca i64
%8 = alloca i8*
%9 = alloca i64
%10 = alloca i64
store i32 0, i32* %3
store i32 %0, i32* %4
store i8** %1, i8*** %5
store i64 0, i64* %7
br label %11
11: ; preds = %112, %2
%12 = load i64, i64* %7
%13 = icmp ult i64 %12, 32
br i1 %13, label %14, label %115
14: ; preds = %11
%15 = getelementptr inbounds [56 x i8], [56 x i8]* %6, i64 0, i64 0
%16 = load i64, i64* %7
%17 = getelementptr inbounds i8, i8* %15, i64 %16
store i8* %17, i8** %8
store i64 0, i64* %9
br label %18
18: ; preds = %108, %14
%19 = load i64, i64* %9
%20 = icmp ult i64 %19, 4
br i1 %20, label %21, label %111
21: ; preds = %18
%22 = load i8*, i8** %8
%23 = load i64, i64* %9
%24 = mul i64 %23, 4
%25 = call i32 @memset(i8* %22, i8 signext 97, i64 %24)
store i64 0, i64* %10
br label %26
26: ; preds = %104, %21
%27 = load i64, i64* %10
%28 = icmp ult i64 %27, 16
br i1 %28, label %29, label %107
29: ; preds = %26
%30 = load i64, i64* %10
%31 = and i64 %30, 1
%32 = icmp ne i64 %31, 0
%33 = zext i1 %32 to i64
%34 = select i1 %32, i32 98, i32 0
%35 = trunc i32 %34 to i8
%36 = load i8*, i8** %8
%37 = load i64, i64* %9
%38 = mul i64 %37, 4
%39 = add i64 %38, 0
%40 = getelementptr inbounds i8, i8* %36, i64 %39
store i8 %35, i8* %40
%41 = load i64, i64* %10
%42 = and i64 %41, 2
%43 = icmp ne i64 %42, 0
%44 = zext i1 %43 to i64
%45 = select i1 %43, i32 99, i32 0
%46 = trunc i32 %45 to i8
%47 = load i8*, i8** %8
%48 = load i64, i64* %9
%49 = mul i64 %48, 4
%50 = add i64 %49, 1
%51 = getelementptr inbounds i8, i8* %47, i64 %50
store i8 %46, i8* %51
%52 = load i64, i64* %10
%53 = and i64 %52, 4
%54 = icmp ne i64 %53, 0
%55 = zext i1 %54 to i64
%56 = select i1 %54, i32 100, i32 0
%57 = trunc i32 %56 to i8
%58 = load i8*, i8** %8
%59 = load i64, i64* %9
%60 = mul i64 %59, 4
%61 = add i64 %60, 2
%62 = getelementptr inbounds i8, i8* %58, i64 %61
store i8 %57, i8* %62
%63 = load i64, i64* %10
%64 = and i64 %63, 8
%65 = icmp ne i64 %64, 0
%66 = zext i1 %65 to i64
%67 = select i1 %65, i32 101, i32 0
%68 = trunc i32 %67 to i8
%69 = load i8*, i8** %8
%70 = load i64, i64* %9
%71 = mul i64 %70, 4
%72 = add i64 %71, 3
%73 = getelementptr inbounds i8, i8* %69, i64 %72
store i8 %68, i8* %73
%74 = load i8*, i8** %8
%75 = load i64, i64* %9
%76 = mul i64 %75, 4
%77 = add i64 %76, 4
%78 = getelementptr inbounds i8, i8* %74, i64 %77
store i8 0, i8* %78
%79 = load i8*, i8** %8
%80 = call i64 @strlen(i8* %79)
%81 = load i64, i64* %9
%82 = mul i64 %81, 4
%83 = load i64, i64* %10
%84 = getelementptr inbounds [16 x i64], [16 x i64]* @main.lens, i64 0, i64 %83
%85 = load i64, i64* %84
%86 = add i64 %82, %85
%87 = icmp ne i64 %80, %86
br i1 %87, label %98, label %88
88: ; preds = %29
%89 = load i8*, i8** %8
%90 = call i64 @strnlen(i8* %89, i32 -1)
%91 = load i64, i64* %9
%92 = mul i64 %91, 4
%93 = load i64, i64* %10
%94 = getelementptr inbounds [16 x i64], [16 x i64]* @main.lens, i64 0, i64 %93
%95 = load i64, i64* %94
%96 = add i64 %92, %95
%97 = icmp ne i64 %90, %96
br i1 %97, label %98, label %103
98: ; preds = %88, %29
%99 = load i64, i64* %7
%100 = load i64, i64* %9
%101 = load i64, i64* %10
%102 = call i32 @printf(i8* getelementptr inbounds ([46 x i8], [46 x i8]* @.str, i64 0, i64 0), i64 %99, i64 %100, i64 %101)
store i32 1, i32* %3
br label %116
103: ; preds = %88
br label %104
104: ; preds = %103
%105 = load i64, i64* %10
%106 = add i64 %105, 1
store i64 %106, i64* %10
br label %26
107: ; preds = %26
br label %108
108: ; preds = %107
%109 = load i64, i64* %9
%110 = add i64 %109, 1
store i64 %110, i64* %9
br label %18
111: ; preds = %18
br label %112
112: ; preds = %111
%113 = load i64, i64* %7
%114 = add i64 %113, 1
store i64 %114, i64* %7
br label %11
115: ; preds = %11
store i32 0, i32* %3
br label %116
116: ; preds = %115, %98
%117 = load i32, i32* %3
ret i32 %117
}

LLVM IR (-O2):
@main.lens = internal unnamed_addr constant [16 x i64] [i64 0, i64 1, i64 0, i64 2, i64 0, i64 1, i64 0, i64 3, i64 0, i64 1, i64 0, i64 2, i64 0, i64 1, i64 0, i64 4]
@.str = [46 x i8] c"failed for base=%Zu, words=%Zu, and last=%Zu\0A\00"
define i32 @main(i32 %0, i8** nocapture readnone %1) {
%3 = alloca [56 x i8]
%4 = getelementptr inbounds [56 x i8], [56 x i8]* %3, i64 0, i64 0
br label %5
5: ; preds = %2, %53
%6 = phi i64 [ 0, %2 ], [ %54, %53 ]
%7 = getelementptr inbounds [56 x i8], [56 x i8]* %3, i64 0, i64 %6
br label %8
8: ; preds = %5, %47
%9 = phi i1 [ true, %5 ], [ %49, %47 ]
%10 = phi i64 [ 0, %5 ], [ %48, %47 ]
%11 = shl nuw nsw i64 %10, 2
%12 = call i32 @memset(i8* %7, i8 signext 97, i64 %11)
%13 = getelementptr inbounds i8, i8* %7, i64 %11
%14 = or i64 %11, 1
%15 = getelementptr inbounds i8, i8* %7, i64 %14
%16 = or i64 %11, 2
%17 = getelementptr inbounds i8, i8* %7, i64 %16
%18 = or i64 %11, 3
%19 = getelementptr inbounds i8, i8* %7, i64 %18
%20 = add nuw nsw i64 %11, 4
%21 = getelementptr inbounds i8, i8* %7, i64 %20
br label %22
22: ; preds = %8, %44
%23 = phi i64 [ 0, %8 ], [ %45, %44 ]
%24 = and i64 %23, 1
%25 = icmp eq i64 %24, 0
%26 = select i1 %25, i8 0, i8 98
store i8 %26, i8* %13
%27 = and i64 %23, 2
%28 = icmp eq i64 %27, 0
%29 = select i1 %28, i8 0, i8 99
store i8 %29, i8* %15
%30 = and i64 %23, 4
%31 = icmp eq i64 %30, 0
%32 = select i1 %31, i8 0, i8 100
store i8 %32, i8* %17
%33 = and i64 %23, 8
%34 = icmp eq i64 %33, 0
%35 = select i1 %34, i8 0, i8 101
store i8 %35, i8* %19
store i8 0, i8* %21
%36 = call i64 @strlen(i8* %7)
%37 = getelementptr inbounds [16 x i64], [16 x i64]* @main.lens, i64 0, i64 %23
%38 = load i64, i64* %37
%39 = add i64 %38, %11
%40 = icmp eq i64 %36, %39
br i1 %40, label %41, label %51
41: ; preds = %22
%42 = call i64 @strnlen(i8* %7, i32 -1)
%43 = icmp eq i64 %42, %36
br i1 %43, label %44, label %51
44: ; preds = %41
%45 = add nuw nsw i64 %23, 1
%46 = icmp eq i64 %45, 16
br i1 %46, label %47, label %22
47: ; preds = %44
%48 = add nuw nsw i64 %10, 1
%49 = icmp ult i64 %10, 3
%50 = icmp eq i64 %48, 4
br i1 %50, label %53, label %8
51: ; preds = %22, %41
%52 = call i32 @printf(i8* getelementptr inbounds ([46 x i8], [46 x i8]* @.str, i64 0, i64 0), i64 %6, i64 %10, i64 %23)
br i1 %9, label %56, label %53
53: ; preds = %47, %51
%54 = add nuw nsw i64 %6, 1
%55 = icmp eq i64 %54, 32
br i1 %55, label %56, label %5
56: ; preds = %53, %51
%57 = phi i32 [ 1, %51 ], [ 0, %53 ]
ret i32 %57
}