#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 *);
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("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    12e0 <main+0x1b0>
lea    -0x50(%rbp),%rax
add    -0x58(%rbp),%rax
mov    %rax,-0x60(%rbp)
movq   $0x0,-0x68(%rbp)
cmpq   $0x4,-0x68(%rbp)
jae    12ca <main+0x19a>
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    12b4 <main+0x184>
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    0xd93(%rip),%rdx
add    (%rdx,%rsi,8),%rcx
cmp    %rcx,%rax
je     129e <main+0x16e>
mov    -0x58(%rbp),%rsi
mov    -0x68(%rbp),%rdx
mov    -0x70(%rbp),%rcx
lea    0xdf3(%rip),%rdi
call   1040 <printf@plt>
movl   $0x1,-0x4(%rbp)
jmp    12e7 <main+0x1b7>
jmp    12a3 <main+0x173>
mov    -0x70(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x70(%rbp)
jmp    1196 <main+0x66>
jmp    12b9 <main+0x189>
mov    -0x68(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x68(%rbp)
jmp    116d <main+0x3d>
jmp    12cf <main+0x19f>
mov    -0x58(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x58(%rbp)
jmp    114e <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    %r14d,%r14d
xor    %r15d,%r15d
cs nopw 0x0(%rax,%rax,1)
xchg   %ax,%ax
lea    (%rsp,%r15,1),%rbx
add    $0x30,%rbx
mov    $0x1,%cl
xor    %ebp,%ebp
mov    %r15,0x10(%rsp)
mov    %cl,0xf(%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,0x18(%rsp)
lea    0x3(,%rbp,4),%r15
lea    0xe55(%rip),%r12
xor    %ebp,%ebp
nopl   (%rax)
test   $0x1,%bpl
mov    $0x62,%eax
cmove  %r14d,%eax
mov    %al,(%rbx,%r13,1)
test   $0x2,%bpl
mov    $0x63,%eax
cmove  %r14d,%eax
test   $0x4,%bpl
mov    $0x64,%ecx
cmove  %r14d,%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  %r14d,%eax
mov    %al,(%rbx,%r15,1)
movb   $0x0,0x4(%rbx,%r13,1)
mov    %rbx,%rdi
call   1030 <strlen@plt>
mov    (%r12),%rcx
add    %r13,%rcx
cmp    %rcx,%rax
jne    1250 <main+0x120>
add    $0x1,%rbp
add    $0x8,%r12
cmp    $0x10,%rbp
jne    11b0 <main+0x80>
mov    0x18(%rsp),%rax
cmp    $0x3,%rax
lea    0x1(%rax),%rax
setb   %cl
mov    %rax,%rbp
cmp    $0x4,%rax
mov    0x10(%rsp),%r15
jne    1161 <main+0x31>
jmp    1273 <main+0x143>
nopl   0x0(%rax,%rax,1)
lea    0xe29(%rip),%rdi
mov    0x10(%rsp),%r15
mov    %r15,%rsi
mov    0x18(%rsp),%rdx
mov    %rbp,%rcx
call   1040 <printf@plt>
testb  $0x1,0xf(%rsp)
jne    1285 <main+0x155>
add    $0x1,%r15
cmp    $0x20,%r15
jne    1150 <main+0x20>
xor    %eax,%eax
jmp    128a <main+0x15a>
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 = %102, %2
%12 = load i64, i64* %7
%13 = icmp ult i64 %12, 32
br i1 %13, label %14, label %105
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 = %98, %14
%19 = load i64, i64* %9
%20 = icmp ult i64 %19, 4
br i1 %20, label %21, label %101
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 = %94, %21
%27 = load i64, i64* %10
%28 = icmp ult i64 %27, 16
br i1 %28, label %29, label %97
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 %93
88: ; preds = %29
%89 = load i64, i64* %7
%90 = load i64, i64* %9
%91 = load i64, i64* %10
%92 = call i32 @printf(i8* getelementptr inbounds ([46 x i8], [46 x i8]* @.str, i64 0, i64 0), i64 %89, i64 %90, i64 %91)
store i32 1, i32* %3
br label %106
93: ; preds = %29
br label %94
94: ; preds = %93
%95 = load i64, i64* %10
%96 = add i64 %95, 1
store i64 %96, i64* %10
br label %26
97: ; preds = %26
br label %98
98: ; preds = %97
%99 = load i64, i64* %9
%100 = add i64 %99, 1
store i64 %100, i64* %9
br label %18
101: ; preds = %18
br label %102
102: ; preds = %101
%103 = load i64, i64* %7
%104 = add i64 %103, 1
store i64 %104, i64* %7
br label %11
105: ; preds = %11
store i32 0, i32* %3
br label %106
106: ; preds = %105, %88
%107 = load i32, i32* %3
ret i32 %107
}

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, %50
%6 = phi i64 [ 0, %2 ], [ %51, %50 ]
%7 = getelementptr inbounds [56 x i8], [56 x i8]* %3, i64 0, i64 %6
br label %8
8: ; preds = %5, %44
%9 = phi i1 [ true, %5 ], [ %46, %44 ]
%10 = phi i64 [ 0, %5 ], [ %45, %44 ]
%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, %41
%23 = phi i64 [ 0, %8 ], [ %42, %41 ]
%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 %48
41: ; preds = %22
%42 = add nuw nsw i64 %23, 1
%43 = icmp eq i64 %42, 16
br i1 %43, label %44, label %22
44: ; preds = %41
%45 = add nuw nsw i64 %10, 1
%46 = icmp ult i64 %10, 3
%47 = icmp eq i64 %45, 4
br i1 %47, label %50, label %8
48: ; preds = %22
%49 = 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 %53, label %50
50: ; preds = %44, %48
%51 = add nuw nsw i64 %6, 1
%52 = icmp eq i64 %51, 32
br i1 %52, label %53, label %5
53: ; preds = %50, %48
%54 = phi i32 [ 1, %48 ], [ 0, %50 ]
ret i32 %54
}