#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 *malloc(int);
int round(double);
int *nbMonths(int start_price_old, int start_price_new, int saving_per_month,
              double percent_loss_by_month) {
  int *result = malloc(2 * sizeof *result);
  if (start_price_old >= start_price_new) {
    result[0] = 0;
    result[1] = start_price_old - start_price_new;
    return result;
  }
  int month = 1;
  double old = start_price_old;
  double new = start_price_new;
  double account = 0.0;
  while (1) {
    if (month % 2 == 0)
      percent_loss_by_month += 0.5;
    old -= old * (percent_loss_by_month / 100.0);
    new -= new *(percent_loss_by_month / 100.0);
    account += saving_per_month;
    if (account + old >= new)
      break;
    month += 1;
  }
  result[0] = month;
  result[1] = round(account + old - new);
  return result;
}


x86 assembly (clang, -O0):
<nbMonths>:
push   %rbp
mov    %rsp,%rbp
sub    $0x50,%rsp
mov    %edi,-0xc(%rbp)
mov    %esi,-0x10(%rbp)
mov    %edx,-0x14(%rbp)
movsd  %xmm0,-0x20(%rbp)
mov    $0x8,%edi
call   1030 <malloc@plt>
mov    %rax,-0x28(%rbp)
mov    -0xc(%rbp),%eax
cmp    -0x10(%rbp),%eax
jl     1174 <nbMonths+0x54>
mov    -0x28(%rbp),%rax
movl   $0x0,(%rax)
mov    -0xc(%rbp),%ecx
sub    -0x10(%rbp),%ecx
mov    -0x28(%rbp),%rax
mov    %ecx,0x4(%rax)
mov    -0x28(%rbp),%rax
mov    %rax,-0x8(%rbp)
jmp    12a0 <nbMonths+0x180>
movl   $0x1,-0x2c(%rbp)
cvtsi2sdl -0xc(%rbp),%xmm0
movsd  %xmm0,-0x38(%rbp)
cvtsi2sdl -0x10(%rbp),%xmm0
movsd  %xmm0,-0x40(%rbp)
xorps  %xmm0,%xmm0
movsd  %xmm0,-0x48(%rbp)
mov    -0x2c(%rbp),%eax
mov    $0x2,%ecx
cltd
idiv   %ecx
cmp    $0x0,%edx
jne    11bd <nbMonths+0x9d>
movsd  0xe4d(%rip),%xmm0
addsd  -0x20(%rbp),%xmm0
movsd  %xmm0,-0x20(%rbp)
movsd  -0x38(%rbp),%xmm0
movsd  -0x20(%rbp),%xmm2
movsd  0xe39(%rip),%xmm1
divsd  %xmm1,%xmm2
movsd  -0x38(%rbp),%xmm1
movq   %xmm0,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm0
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x38(%rbp)
movsd  -0x40(%rbp),%xmm0
movsd  -0x20(%rbp),%xmm2
movsd  0xdfa(%rip),%xmm1
divsd  %xmm1,%xmm2
movsd  -0x40(%rbp),%xmm1
movq   %xmm0,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm0
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x40(%rbp)
cvtsi2sdl -0x14(%rbp),%xmm0
addsd  -0x48(%rbp),%xmm0
movsd  %xmm0,-0x48(%rbp)
movsd  -0x48(%rbp),%xmm0
addsd  -0x38(%rbp),%xmm0
ucomisd -0x40(%rbp),%xmm0
jb     1264 <nbMonths+0x144>
jmp    1272 <nbMonths+0x152>
mov    -0x2c(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x2c(%rbp)
jmp    1197 <nbMonths+0x77>
mov    -0x2c(%rbp),%ecx
mov    -0x28(%rbp),%rax
mov    %ecx,(%rax)
movsd  -0x48(%rbp),%xmm0
addsd  -0x38(%rbp),%xmm0
subsd  -0x40(%rbp),%xmm0
call   1040 <round@plt>
mov    %eax,%ecx
mov    -0x28(%rbp),%rax
mov    %ecx,0x4(%rax)
mov    -0x28(%rbp),%rax
mov    %rax,-0x8(%rbp)
mov    -0x8(%rbp),%rax
add    $0x50,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<nbMonths>:
push   %rbp
push   %r15
push   %r14
push   %rbx
push   %rax
movsd  %xmm0,(%rsp)
mov    %edx,%r14d
mov    %esi,%ebx
mov    %edi,%ebp
mov    $0x8,%edi
call   1030 <malloc@plt>
mov    %rax,%r15
mov    %ebp,%eax
sub    %ebx,%eax
jge    11c4 <nbMonths+0xa4>
movd   %ebx,%xmm0
movd   %ebp,%xmm1
punpckldq %xmm0,%xmm1
cvtdq2pd %xmm1,%xmm1
cvtsi2sd %r14d,%xmm2
xorpd  %xmm3,%xmm3
xor    %eax,%eax
movsd  0xe96(%rip),%xmm8
movsd  0xe96(%rip),%xmm5
movsd  (%rsp),%xmm6
movapd %xmm6,%xmm4
jmp    11b2 <nbMonths+0x92>
nopl   (%rax)
movapd %xmm4,%xmm0
divsd  %xmm5,%xmm0
unpcklpd %xmm0,%xmm0
mulpd  %xmm1,%xmm0
subpd  %xmm0,%xmm1
addsd  %xmm2,%xmm3
movapd %xmm3,%xmm0
addsd  %xmm1,%xmm0
movapd %xmm1,%xmm7
unpckhpd %xmm1,%xmm7
ucomisd %xmm7,%xmm0
movapd %xmm4,%xmm6
jae    11cd <nbMonths+0xad>
add    $0x1,%eax
addsd  %xmm8,%xmm4
test   $0x1,%al
je     1180 <nbMonths+0x60>
movapd %xmm6,%xmm4
jmp    1180 <nbMonths+0x60>
movl   $0x0,(%r15)
jmp    11d9 <nbMonths+0xb9>
mov    %eax,(%r15)
subsd  %xmm7,%xmm0
call   1040 <round@plt>
mov    %eax,0x4(%r15)
mov    %r15,%rax
add    $0x8,%rsp
pop    %rbx
pop    %r14
pop    %r15
pop    %rbp
ret

LLVM IR (-O0):
define i32* @nbMonths(i32 %0, i32 %1, i32 %2, double %3) {
%5 = alloca i32*
%6 = alloca i32
%7 = alloca i32
%8 = alloca i32
%9 = alloca double
%10 = alloca i32*
%11 = alloca i32
%12 = alloca double
%13 = alloca double
%14 = alloca double
store i32 %0, i32* %6
store i32 %1, i32* %7
store i32 %2, i32* %8
store double %3, double* %9
%15 = call i32* @malloc(i32 8)
store i32* %15, i32** %10
%16 = load i32, i32* %6
%17 = load i32, i32* %7
%18 = icmp sge i32 %16, %17
br i1 %18, label %19, label %28
19: ; preds = %4
%20 = load i32*, i32** %10
%21 = getelementptr inbounds i32, i32* %20, i64 0
store i32 0, i32* %21
%22 = load i32, i32* %6
%23 = load i32, i32* %7
%24 = sub nsw i32 %22, %23
%25 = load i32*, i32** %10
%26 = getelementptr inbounds i32, i32* %25, i64 1
store i32 %24, i32* %26
%27 = load i32*, i32** %10
store i32* %27, i32** %5
br label %79
28: ; preds = %4
store i32 1, i32* %11
%29 = load i32, i32* %6
%30 = sitofp i32 %29 to double
store double %30, double* %12
%31 = load i32, i32* %7
%32 = sitofp i32 %31 to double
store double %32, double* %13
store double 0.000000e+00, double* %14
br label %33
33: ; preds = %28, %63
%34 = load i32, i32* %11
%35 = srem i32 %34, 2
%36 = icmp eq i32 %35, 0
br i1 %36, label %37, label %40
37: ; preds = %33
%38 = load double, double* %9
%39 = fadd double %38, 5.000000e-01
store double %39, double* %9
br label %40
40: ; preds = %37, %33
%41 = load double, double* %12
%42 = load double, double* %9
%43 = fdiv double %42, 1.000000e+02
%44 = load double, double* %12
%45 = fneg double %41
%46 = call double @llvm.fmuladd.f64(double %45, double %43, double %44)
store double %46, double* %12
%47 = load double, double* %13
%48 = load double, double* %9
%49 = fdiv double %48, 1.000000e+02
%50 = load double, double* %13
%51 = fneg double %47
%52 = call double @llvm.fmuladd.f64(double %51, double %49, double %50)
store double %52, double* %13
%53 = load i32, i32* %8
%54 = sitofp i32 %53 to double
%55 = load double, double* %14
%56 = fadd double %55, %54
store double %56, double* %14
%57 = load double, double* %14
%58 = load double, double* %12
%59 = fadd double %57, %58
%60 = load double, double* %13
%61 = fcmp oge double %59, %60
br i1 %61, label %62, label %63
62: ; preds = %40
br label %66
63: ; preds = %40
%64 = load i32, i32* %11
%65 = add nsw i32 %64, 1
store i32 %65, i32* %11
br label %33
66: ; preds = %62
%67 = load i32, i32* %11
%68 = load i32*, i32** %10
%69 = getelementptr inbounds i32, i32* %68, i64 0
store i32 %67, i32* %69
%70 = load double, double* %14
%71 = load double, double* %12
%72 = fadd double %70, %71
%73 = load double, double* %13
%74 = fsub double %72, %73
%75 = call i32 @round(double %74)
%76 = load i32*, i32** %10
%77 = getelementptr inbounds i32, i32* %76, i64 1
store i32 %75, i32* %77
%78 = load i32*, i32** %10
store i32* %78, i32** %5
br label %79
79: ; preds = %66, %19
%80 = load i32*, i32** %5
ret i32* %80
}

LLVM IR (-O2):
define noalias i32* @nbMonths(i32 %0, i32 %1, i32 %2, double %3) {
%5 = tail call i32* @malloc(i32 8)
%6 = icmp slt i32 %0, %1
br i1 %6, label %9, label %7
7: ; preds = %4
store i32 0, i32* %5
%8 = sub nsw i32 %0, %1
br label %37
9: ; preds = %4
%10 = insertelement <2 x i32> poison, i32 %0, i64 0
%11 = insertelement <2 x i32> %10, i32 %1, i64 1
%12 = sitofp <2 x i32> %11 to <2 x double>
%13 = sitofp i32 %2 to double
br label %14
14: ; preds = %14, %9
%15 = phi double [ %3, %9 ], [ %22, %14 ]
%16 = phi i32 [ 1, %9 ], [ %33, %14 ]
%17 = phi double [ 0.000000e+00, %9 ], [ %28, %14 ]
%18 = phi <2 x double> [ %12, %9 ], [ %27, %14 ]
%19 = and i32 %16, 1
%20 = icmp eq i32 %19, 0
%21 = fadd double %15, 5.000000e-01
%22 = select i1 %20, double %21, double %15
%23 = fdiv double %22, 1.000000e+02
%24 = fneg <2 x double> %18
%25 = insertelement <2 x double> poison, double %23, i64 0
%26 = shufflevector <2 x double> %25, <2 x double> poison, <2 x i32> zeroinitializer
%27 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %24, <2 x double> %26, <2 x double> %18)
%28 = fadd double %17, %13
%29 = extractelement <2 x double> %27, i64 0
%30 = fadd double %28, %29
%31 = extractelement <2 x double> %27, i64 1
%32 = fcmp ult double %30, %31
%33 = add nuw nsw i32 %16, 1
br i1 %32, label %14, label %34
34: ; preds = %14
store i32 %16, i32* %5
%35 = fsub double %30, %31
%36 = tail call i32 @round(double %35)
br label %37
37: ; preds = %34, %7
%38 = phi i32 [ %36, %34 ], [ %8, %7 ]
%39 = getelementptr inbounds i32, i32* %5, i64 1
store i32 %38, i32* %39
ret i32* %5
}