#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, 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]) {
          printf("strlen failed for base=%Zu, words=%Zu, and last=%Zu (is %zd, "
                 "expected %zd)\n",
                 base, words, last, strlen(buf), words * 4 + lens[last]);
          return 1;
        }
        if (strnlen(buf, -1) != words * 4 + lens[last]) {
          printf("strnlen failed for base=%Zu, words=%Zu, and last=%Zu (is "
                 "%zd, expected %zd)\n",
                 base, words, last, strnlen(buf, -1), words * 4 + lens[last]);
          return 1;
        }
      }
    }
  }
  return 0;
}


x86 assembly (clang, -O0):
<main>:
push   %rbp
mov    %rsp,%rbp
sub    $0xa0,%rsp
movl   $0x0,-0x4(%rbp)
mov    %edi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
movq   $0x0,-0x58(%rbp)
cmpq   $0x20,-0x58(%rbp)
jae    13d8 <main+0x298>
lea    -0x50(%rbp),%rax
add    -0x58(%rbp),%rax
mov    %rax,-0x60(%rbp)
movq   $0x0,-0x68(%rbp)
cmpq   $0x4,-0x68(%rbp)
jae    13c2 <main+0x282>
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    13ac <main+0x26c>
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    0xd80(%rip),%rdx
add    (%rdx,%rsi,8),%rcx
cmp    %rcx,%rax
je     12f2 <main+0x1b2>
mov    -0x58(%rbp),%rax
mov    %rax,-0x88(%rbp)
mov    -0x68(%rbp),%rax
mov    %rax,-0x80(%rbp)
mov    -0x70(%rbp),%rax
mov    %rax,-0x78(%rbp)
mov    -0x60(%rbp),%rdi
call   1030 <strlen@plt>
mov    -0x88(%rbp),%rsi
mov    -0x80(%rbp),%rdx
mov    -0x78(%rbp),%rcx
mov    %rax,%r8
mov    -0x68(%rbp),%r9
shl    $0x2,%r9
mov    -0x70(%rbp),%rdi
lea    0xd2a(%rip),%rax
add    (%rax,%rdi,8),%r9
lea    0xd9f(%rip),%rdi
call   1040 <printf@plt>
movl   $0x1,-0x4(%rbp)
jmp    13df <main+0x29f>
mov    -0x60(%rbp),%rdi
mov    $0xffffffff,%esi
call   1060 <strnlen@plt>
mov    -0x68(%rbp),%rcx
shl    $0x2,%rcx
mov    -0x70(%rbp),%rsi
lea    0xced(%rip),%rdx
add    (%rdx,%rsi,8),%rcx
cmp    %rcx,%rax
je     1396 <main+0x256>
mov    -0x58(%rbp),%rax
mov    %rax,-0xa0(%rbp)
mov    -0x68(%rbp),%rax
mov    %rax,-0x98(%rbp)
mov    -0x70(%rbp),%rax
mov    %rax,-0x90(%rbp)
mov    -0x60(%rbp),%rdi
mov    $0xffffffff,%esi
call   1060 <strnlen@plt>
mov    -0xa0(%rbp),%rsi
mov    -0x98(%rbp),%rdx
mov    -0x90(%rbp),%rcx
mov    %rax,%r8
mov    -0x68(%rbp),%r9
shl    $0x2,%r9
mov    -0x70(%rbp),%rdi
lea    0xc86(%rip),%rax
add    (%rax,%rdi,8),%r9
lea    0xd47(%rip),%rdi
call   1040 <printf@plt>
movl   $0x1,-0x4(%rbp)
jmp    13df <main+0x29f>
jmp    139b <main+0x25b>
mov    -0x70(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x70(%rbp)
jmp    11a9 <main+0x69>
jmp    13b1 <main+0x271>
mov    -0x68(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x68(%rbp)
jmp    1180 <main+0x40>
jmp    13c7 <main+0x287>
mov    -0x58(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x58(%rbp)
jmp    1161 <main+0x21>
movl   $0x0,-0x4(%rbp)
mov    -0x4(%rbp),%eax
add    $0xa0,%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    %r14d,%r14d
cs nopw 0x0(%rax,%rax,1)
nopl   0x0(%rax,%rax,1)
lea    (%rsp,%r14,1),%rbx
add    $0x30,%rbx
mov    $0x1,%cl
xor    %ebp,%ebp
mov    %r14,0x10(%rsp)
mov    %cl,0xf(%rsp)
lea    0x0(,%rbp,4),%r14
mov    %rbx,%rdi
mov    $0x61,%esi
mov    %r14,%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,0x18(%rsp)
lea    0x3(,%rbp,4),%r13
lea    0xe45(%rip),%r12
xor    %ebp,%ebp
nopl   (%rax)
test   $0x1,%bpl
mov    $0x62,%eax
mov    $0x0,%edx
cmove  %edx,%eax
mov    %al,(%rbx,%r14,1)
test   $0x2,%bpl
mov    $0x63,%eax
cmove  %edx,%eax
test   $0x4,%bpl
mov    $0x64,%ecx
cmove  %edx,%ecx
mov    0x28(%rsp),%rsi
mov    %al,(%rbx,%rsi,1)
mov    0x20(%rsp),%rax
mov    %cl,(%rbx,%rax,1)
test   $0x8,%bpl
mov    $0x65,%eax
cmove  %edx,%eax
mov    %al,(%rbx,%r13,1)
movb   $0x0,0x4(%rbx,%r14,1)
mov    %rbx,%rdi
call   1030 <strlen@plt>
mov    %rax,%r15
mov    (%r12),%r9
add    %r14,%r9
cmp    %r9,%rax
jne    1280 <main+0x140>
mov    %rbx,%rdi
mov    $0xffffffff,%esi
call   1060 <strnlen@plt>
cmp    %r15,%rax
jne    12a0 <main+0x160>
add    $0x1,%rbp
add    $0x8,%r12
cmp    $0x10,%rbp
jne    11c0 <main+0x80>
mov    0x18(%rsp),%rax
cmp    $0x3,%rax
lea    0x1(%rax),%rax
setb   %cl
mov    %rax,%rbp
cmp    $0x4,%rax
mov    0x10(%rsp),%r14
jne    1171 <main+0x31>
jmp    12d6 <main+0x196>
cs nopw 0x0(%rax,%rax,1)
nopl   0x0(%rax)
lea    0xdf9(%rip),%rdi
mov    0x10(%rsp),%r14
mov    %r14,%rsi
mov    0x18(%rsp),%rdx
mov    %rbp,%rcx
mov    %r15,%r8
jmp    12ca <main+0x18a>
nopl   0x0(%rax)
mov    %rbx,%rdi
mov    $0xffffffff,%esi
call   1060 <strnlen@plt>
lea    0xe18(%rip),%rdi
mov    0x10(%rsp),%r14
mov    %r14,%rsi
mov    0x18(%rsp),%rdx
mov    %rbp,%rcx
mov    %rax,%r8
mov    %r15,%r9
call   1040 <printf@plt>
testb  $0x1,0xf(%rsp)
jne    12e8 <main+0x1a8>
add    $0x1,%r14
cmp    $0x20,%r14
jne    1160 <main+0x20>
xor    %eax,%eax
jmp    12ed <main+0x1ad>
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 = [76 x i8] c"strlen failed for base=%Zu, words=%Zu, and last=%Zu (is %zd, expected %zd)\0A\00"
@.str.1 = [77 x i8] c"strnlen failed for base=%Zu, words=%Zu, and last=%Zu (is %zd, expected %zd)\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 = %133, %2
%12 = load i64, i64* %7
%13 = icmp ult i64 %12, 32
br i1 %13, label %14, label %136
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 = %129, %14
%19 = load i64, i64* %9
%20 = icmp ult i64 %19, 4
br i1 %20, label %21, label %132
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 = %125, %21
%27 = load i64, i64* %10
%28 = icmp ult i64 %27, 16
br i1 %28, label %29, label %128
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 %88, label %101
88: ; preds = %29
%89 = load i64, i64* %7
%90 = load i64, i64* %9
%91 = load i64, i64* %10
%92 = load i8*, i8** %8
%93 = call i64 @strlen(i8* %92)
%94 = load i64, i64* %9
%95 = mul i64 %94, 4
%96 = load i64, i64* %10
%97 = getelementptr inbounds [16 x i64], [16 x i64]* @main.lens, i64 0, i64 %96
%98 = load i64, i64* %97
%99 = add i64 %95, %98
%100 = call i32 @printf(i8* getelementptr inbounds ([76 x i8], [76 x i8]* @.str, i64 0, i64 0), i64 %89, i64 %90, i64 %91, i64 %93, i64 %99)
store i32 1, i32* %3
br label %137
101: ; preds = %29
%102 = load i8*, i8** %8
%103 = call i64 @strnlen(i8* %102, i32 -1)
%104 = load i64, i64* %9
%105 = mul i64 %104, 4
%106 = load i64, i64* %10
%107 = getelementptr inbounds [16 x i64], [16 x i64]* @main.lens, i64 0, i64 %106
%108 = load i64, i64* %107
%109 = add i64 %105, %108
%110 = icmp ne i64 %103, %109
br i1 %110, label %111, label %124
111: ; preds = %101
%112 = load i64, i64* %7
%113 = load i64, i64* %9
%114 = load i64, i64* %10
%115 = load i8*, i8** %8
%116 = call i64 @strnlen(i8* %115, i32 -1)
%117 = load i64, i64* %9
%118 = mul i64 %117, 4
%119 = load i64, i64* %10
%120 = getelementptr inbounds [16 x i64], [16 x i64]* @main.lens, i64 0, i64 %119
%121 = load i64, i64* %120
%122 = add i64 %118, %121
%123 = call i32 @printf(i8* getelementptr inbounds ([77 x i8], [77 x i8]* @.str.1, i64 0, i64 0), i64 %112, i64 %113, i64 %114, i64 %116, i64 %122)
store i32 1, i32* %3
br label %137
124: ; preds = %101
br label %125
125: ; preds = %124
%126 = load i64, i64* %10
%127 = add i64 %126, 1
store i64 %127, i64* %10
br label %26
128: ; preds = %26
br label %129
129: ; preds = %128
%130 = load i64, i64* %9
%131 = add i64 %130, 1
store i64 %131, i64* %9
br label %18
132: ; preds = %18
br label %133
133: ; preds = %132
%134 = load i64, i64* %7
%135 = add i64 %134, 1
store i64 %135, i64* %7
br label %11
136: ; preds = %11
store i32 0, i32* %3
br label %137
137: ; preds = %136, %111, %88
%138 = load i32, i32* %3
ret i32 %138
}

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 = [76 x i8] c"strlen failed for base=%Zu, words=%Zu, and last=%Zu (is %zd, expected %zd)\0A\00"
@.str.1 = [77 x i8] c"strnlen failed for base=%Zu, words=%Zu, and last=%Zu (is %zd, expected %zd)\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, %57
%6 = phi i64 [ 0, %2 ], [ %58, %57 ]
%7 = getelementptr inbounds [56 x i8], [56 x i8]* %3, i64 0, i64 %6
br label %8
8: ; preds = %5, %52
%9 = phi i1 [ true, %5 ], [ %54, %52 ]
%10 = phi i64 [ 0, %5 ], [ %53, %52 ]
%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, %49
%23 = phi i64 [ 0, %8 ], [ %50, %49 ]
%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 %43, label %41
41: ; preds = %22
%42 = call i32 @printf(i8* getelementptr inbounds ([76 x i8], [76 x i8]* @.str, i64 0, i64 0), i64 %6, i64 %10, i64 %23, i64 %36, i64 %39)
br label %56
43: ; preds = %22
%44 = call i64 @strnlen(i8* %7, i32 -1)
%45 = icmp eq i64 %44, %36
br i1 %45, label %49, label %46
46: ; preds = %43
%47 = call i64 @strnlen(i8* %7, i32 -1)
%48 = call i32 @printf(i8* getelementptr inbounds ([77 x i8], [77 x i8]* @.str.1, i64 0, i64 0), i64 %6, i64 %10, i64 %23, i64 %47, i64 %36)
br label %56
49: ; preds = %43
%50 = add nuw nsw i64 %23, 1
%51 = icmp eq i64 %50, 16
br i1 %51, label %52, label %22
52: ; preds = %49
%53 = add nuw nsw i64 %10, 1
%54 = icmp ult i64 %10, 3
%55 = icmp eq i64 %53, 4
br i1 %55, label %57, label %8
56: ; preds = %41, %46
br i1 %9, label %60, label %57
57: ; preds = %52, %56
%58 = add nuw nsw i64 %6, 1
%59 = icmp eq i64 %58, 32
br i1 %59, label %60, label %5
60: ; preds = %57, %56
%61 = phi i32 [ 1, %56 ], [ 0, %57 ]
ret i32 %61
}