#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 printf(char *, int, int, int, char *);
int puts(char *);
void song(int bottles) {
  while ((printf("%d bottles of beer on the wall, %d bottles of beer.\n"
                 "Take one down and pass it around, %d bottle%s of beer on the "
                 "wall.\n\n",
                 bottles, bottles, bottles - 1, bottles > 2 ? "s" : ""),
          bottles > 2))
    while ((--bottles, 0)) {
    }
  while ((
      puts(
          "1 bottle of beer on the wall, 1 bottle of beer.\n"
          "Take one down and pass it around, no more bottles of beer on the "
          "wall.\n\n"
          "No more bottles of beer on the wall, no more bottles of beer.\n"
          "Go to the store and buy some more, 99 bottles of beer on the wall."),
      0)) {
  }
}


x86 assembly (clang, -O0):
<song>:
push   %rbp
mov    %rsp,%rbp
sub    $0x10,%rsp
mov    %edi,-0x4(%rbp)
mov    -0x4(%rbp),%esi
mov    -0x4(%rbp),%edx
mov    -0x4(%rbp),%ecx
sub    $0x1,%ecx
mov    -0x4(%rbp),%edi
lea    0xf37(%rip),%r8
lea    0xf31(%rip),%rax
cmp    $0x2,%edi
cmovg  %rax,%r8
lea    0xeaa(%rip),%rdi
call   1040 <printf@plt>
cmpl   $0x2,-0x4(%rbp)
jle    118c <song+0x6c>
jmp    116a <song+0x4a>
mov    -0x4(%rbp),%eax
add    $0xffffffff,%eax
mov    %eax,-0x4(%rbp)
xor    %eax,%eax
test   $0x1,%al
jne    1182 <song+0x62>
jmp    1187 <song+0x67>
jmp    116a <song+0x4a>
jmp    112b <song+0xb>
jmp    1191 <song+0x71>
lea    0xee3(%rip),%rdi
call   1030 <puts@plt>
xor    %eax,%eax
test   $0x1,%al
jne    11ac <song+0x8c>
jmp    11b1 <song+0x91>
jmp    1191 <song+0x71>
add    $0x10,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<song>:
push   %rbp
push   %r15
push   %r14
push   %r12
push   %rbx
mov    %edi,%ebx
lea    0xf48(%rip),%r15
lea    0xf40(%rip),%r12
lea    0xec1(%rip),%r14
nop
lea    -0x1(%rbx),%ebp
cmp    $0x3,%ebx
mov    %r12,%r8
cmovge %r15,%r8
mov    %r14,%rdi
mov    %ebx,%esi
mov    %ebx,%edx
mov    %ebp,%ecx
call   1040 <printf@plt>
cmp    $0x2,%ebx
mov    %ebp,%ebx
jg     1140 <song+0x20>
lea    0xf12(%rip),%rdi
pop    %rbx
pop    %r12
pop    %r14
pop    %r15
pop    %rbp
jmp    1030 <puts@plt>

LLVM IR (-O0):
@.str = [121 x i8] c"%d bottles of beer on the wall, %d bottles of beer.\0ATake one down and pass it around, %d bottle%s of beer on the wall.\0A\0A\00"
@.str.1 = [2 x i8] c"s\00"
@.str.2 = [1 x i8] zeroinitializer
@.str.3 = [249 x i8] c"1 bottle of beer on the wall, 1 bottle of beer.\0ATake one down and pass it around, no more bottles of beer on the wall.\0A\0ANo more bottles of beer on the wall, no more bottles of beer.\0AGo to the store and buy some more, 99 bottles of beer on the wall.\00"
define void @song(i32 %0) {
%2 = alloca i32
store i32 %0, i32* %2
br label %3
3: ; preds = %20, %1
%4 = load i32, i32* %2
%5 = load i32, i32* %2
%6 = load i32, i32* %2
%7 = sub nsw i32 %6, 1
%8 = load i32, i32* %2
%9 = icmp sgt i32 %8, 2
%10 = zext i1 %9 to i64
%11 = select i1 %9, i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.1, i64 0, i64 0), i8* getelementptr inbounds ([1 x i8], [1 x i8]* @.str.2, i64 0, i64 0)
%12 = call i32 @printf(i8* getelementptr inbounds ([121 x i8], [121 x i8]* @.str, i64 0, i64 0), i32 %4, i32 %5, i32 %7, i8* %11)
%13 = load i32, i32* %2
%14 = icmp sgt i32 %13, 2
br i1 %14, label %15, label %21
15: ; preds = %3
br label %16
16: ; preds = %19, %15
%17 = load i32, i32* %2
%18 = add nsw i32 %17, -1
store i32 %18, i32* %2
br i1 false, label %19, label %20
19: ; preds = %16
br label %16
20: ; preds = %16
br label %3
21: ; preds = %3
br label %22
22: ; preds = %24, %21
%23 = call i32 @puts(i8* getelementptr inbounds ([249 x i8], [249 x i8]* @.str.3, i64 0, i64 0))
br i1 false, label %24, label %25
24: ; preds = %22
br label %22
25: ; preds = %22
ret void
}

LLVM IR (-O2):
@.str = [121 x i8] c"%d bottles of beer on the wall, %d bottles of beer.\0ATake one down and pass it around, %d bottle%s of beer on the wall.\0A\0A\00"
@.str.1 = [2 x i8] c"s\00"
@.str.2 = [1 x i8] zeroinitializer
@.str.3 = [249 x i8] c"1 bottle of beer on the wall, 1 bottle of beer.\0ATake one down and pass it around, no more bottles of beer on the wall.\0A\0ANo more bottles of beer on the wall, no more bottles of beer.\0AGo to the store and buy some more, 99 bottles of beer on the wall.\00"
define void @song(i32 %0) {
br label %2
2: ; preds = %2, %1
%3 = phi i32 [ %0, %1 ], [ %4, %2 ]
%4 = add nsw i32 %3, -1
%5 = icmp sgt i32 %3, 2
%6 = select i1 %5, i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.1, i64 0, i64 0), i8* getelementptr inbounds ([1 x i8], [1 x i8]* @.str.2, i64 0, i64 0)
%7 = tail call i32 @printf(i8* getelementptr inbounds ([121 x i8], [121 x i8]* @.str, i64 0, i64 0), i32 %3, i32 %3, i32 %4, i8* %6)
br i1 %5, label %2, label %8
8: ; preds = %2
%9 = tail call i32 @puts(i8* dereferenceable(1) getelementptr inbounds ([249 x i8], [249 x i8]* @.str.3, i64 0, i64 0))
ret void
}