#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*/ fprintf(int /*<<< orphan*/, char *, ...);
double hrtime();
int /*<<< orphan*/ si_format(char *, int, size_t);
int /*<<< orphan*/ stderr;
void progress(size_t bytes) {
  static size_t tot_bytes = 0, period_bytes = 0;
  static double period_start = 0;
  static long speed_bs = 0;
  const double period = 0.2;
  double now;
  char s_speed[32], s_tot_bytes[32];
  tot_bytes += bytes;
  period_bytes += bytes;
  now = hrtime();
  if (now > (period_start + period)) {
    speed_bs = (size_t)(period_bytes / period);
    period_bytes = 0;
    period_start = now;
    si_format(s_speed, 32, speed_bs);
    si_format(s_tot_bytes, 32, tot_bytes);
    fprintf(stderr, "\33[2K\r");
    fprintf(stderr, "Total: %sB\tSpeed: %sB/s", s_tot_bytes, s_speed);
  }
}


x86 assembly (clang, -O0):
<progress>:
push   %rbp
mov    %rsp,%rbp
sub    $0x60,%rsp
mov    %rdi,-0x8(%rbp)
movsd  0xebc(%rip),%xmm0
movsd  %xmm0,-0x10(%rbp)
mov    -0x8(%rbp),%rax
add    0x2eec(%rip),%rax
mov    %rax,0x2ee5(%rip)
mov    -0x8(%rbp),%rax
add    0x2ee2(%rip),%rax
mov    %rax,0x2edb(%rip)
mov    $0x0,%al
call   1030 <hrtime@plt>
movsd  %xmm0,-0x18(%rbp)
movsd  -0x18(%rbp),%xmm0
movsd  0xe7a(%rip),%xmm1
addsd  0x2ec2(%rip),%xmm1
ucomisd %xmm1,%xmm0
jbe    1273 <progress+0x143>
movaps 0xe71(%rip),%xmm1
movq   0x2ea1(%rip),%xmm0
punpckldq %xmm1,%xmm0
movapd 0xe6d(%rip),%xmm1
subpd  %xmm1,%xmm0
movaps %xmm0,%xmm1
unpckhpd %xmm0,%xmm0
addsd  %xmm1,%xmm0
movsd  0xe36(%rip),%xmm1
divsd  %xmm1,%xmm0
movaps %xmm0,%xmm1
cvttsd2si %xmm1,%rax
mov    %rax,%rdx
sar    $0x3f,%rdx
movsd  0xe23(%rip),%xmm1
subsd  %xmm1,%xmm0
cvttsd2si %xmm0,%rcx
and    %rdx,%rcx
or     %rcx,%rax
mov    %rax,0x2e5d(%rip)
movq   $0x0,0x2e42(%rip)
movsd  -0x18(%rbp),%xmm0
movsd  %xmm0,0x2e3d(%rip)
lea    -0x40(%rbp),%rdi
mov    0x2e3a(%rip),%rdx
mov    $0x20,%esi
call   1050 <si_format@plt>
lea    -0x60(%rbp),%rdi
mov    0x2e0d(%rip),%rdx
mov    $0x20,%esi
call   1050 <si_format@plt>
mov    0x2d9c(%rip),%rax
mov    (%rax),%edi
lea    0xde3(%rip),%rsi
mov    $0x0,%al
call   1040 <fprintf@plt>
mov    0x2d85(%rip),%rax
mov    (%rax),%edi
lea    -0x60(%rbp),%rdx
lea    -0x40(%rbp),%rcx
lea    0xdca(%rip),%rsi
mov    $0x0,%al
call   1040 <fprintf@plt>
add    $0x60,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<progress>:
push   %r15
push   %r14
push   %rbx
sub    $0x40,%rsp
add    %rdi,0x2f00(%rip)
add    %rdi,0x2f01(%rip)
xor    %eax,%eax
call   1030 <hrtime@plt>
movsd  0x2efa(%rip),%xmm1
addsd  0xea2(%rip),%xmm1
ucomisd %xmm1,%xmm0
jbe    121b <progress+0xeb>
movsd  0x2ed8(%rip),%xmm1
unpcklps 0xe99(%rip),%xmm1
subpd  0xea1(%rip),%xmm1
movapd %xmm1,%xmm2
unpckhpd %xmm1,%xmm2
addsd  %xmm1,%xmm2
divsd  0xe6d(%rip),%xmm2
cvttsd2si %xmm2,%rax
mov    %rax,%rcx
sar    $0x3f,%rcx
subsd  0xe61(%rip),%xmm2
cvttsd2si %xmm2,%rdx
and    %rcx,%rdx
or     %rax,%rdx
movq   $0x0,0x2e8b(%rip)
movsd  %xmm0,0x2e8b(%rip)
lea    0x20(%rsp),%r14
mov    %r14,%rdi
mov    $0x20,%esi
call   1050 <si_format@plt>
mov    0x2e62(%rip),%rdx
mov    %rsp,%r15
mov    %r15,%rdi
mov    $0x20,%esi
call   1050 <si_format@plt>
mov    0x2deb(%rip),%rbx
mov    (%rbx),%edi
lea    0xe32(%rip),%rsi
xor    %eax,%eax
call   1040 <fprintf@plt>
mov    (%rbx),%edi
lea    0xe28(%rip),%rsi
mov    %r15,%rdx
mov    %r14,%rcx
xor    %eax,%eax
call   1040 <fprintf@plt>
add    $0x40,%rsp
pop    %rbx
pop    %r14
pop    %r15
ret

LLVM IR (-O0):
@progress.tot_bytes = internal global i64 0
@progress.period_bytes = internal global i64 0
@progress.period_start = internal global double 0.000000e+00
@progress.speed_bs = internal global i64 0
@stderr = global i32 0
@.str = [6 x i8] c"\1B[2K\0D\00"
@.str.1 = [24 x i8] c"Total: %sB\09Speed: %sB/s\00"
define void @progress(i64 %0) {
%2 = alloca i64
%3 = alloca double
%4 = alloca double
%5 = alloca [32 x i8]
%6 = alloca [32 x i8]
store i64 %0, i64* %2
store double 2.000000e-01, double* %3
%7 = load i64, i64* %2
%8 = load i64, i64* @progress.tot_bytes
%9 = add i64 %8, %7
store i64 %9, i64* @progress.tot_bytes
%10 = load i64, i64* %2
%11 = load i64, i64* @progress.period_bytes
%12 = add i64 %11, %10
store i64 %12, i64* @progress.period_bytes
%13 = call double (...) @hrtime()
store double %13, double* %4
%14 = load double, double* %4
%15 = load double, double* @progress.period_start
%16 = fadd double %15, 2.000000e-01
%17 = fcmp ogt double %14, %16
br i1 %17, label %18, label %36
18: ; preds = %1
%19 = load i64, i64* @progress.period_bytes
%20 = uitofp i64 %19 to double
%21 = fdiv double %20, 2.000000e-01
%22 = fptoui double %21 to i64
store i64 %22, i64* @progress.speed_bs
store i64 0, i64* @progress.period_bytes
%23 = load double, double* %4
store double %23, double* @progress.period_start
%24 = getelementptr inbounds [32 x i8], [32 x i8]* %5, i64 0, i64 0
%25 = load i64, i64* @progress.speed_bs
%26 = call i32 @si_format(i8* %24, i32 32, i64 %25)
%27 = getelementptr inbounds [32 x i8], [32 x i8]* %6, i64 0, i64 0
%28 = load i64, i64* @progress.tot_bytes
%29 = call i32 @si_format(i8* %27, i32 32, i64 %28)
%30 = load i32, i32* @stderr
%31 = call i32 (i32, i8*, ...) @fprintf(i32 %30, i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str, i64 0, i64 0))
%32 = load i32, i32* @stderr
%33 = getelementptr inbounds [32 x i8], [32 x i8]* %6, i64 0, i64 0
%34 = getelementptr inbounds [32 x i8], [32 x i8]* %5, i64 0, i64 0
%35 = call i32 (i32, i8*, ...) @fprintf(i32 %32, i8* getelementptr inbounds ([24 x i8], [24 x i8]* @.str.1, i64 0, i64 0), i8* %33, i8* %34)
br label %36
36: ; preds = %18, %1
ret void
}

LLVM IR (-O2):
@progress.tot_bytes = internal unnamed_addr global i64 0
@progress.period_bytes = internal unnamed_addr global i64 0
@progress.period_start = internal unnamed_addr global double 0.000000e+00
@stderr = global i32 0
@.str = [6 x i8] c"\1B[2K\0D\00"
@.str.1 = [24 x i8] c"Total: %sB\09Speed: %sB/s\00"
define void @progress(i64 %0) {
%2 = alloca [32 x i8]
%3 = alloca [32 x i8]
%4 = getelementptr inbounds [32 x i8], [32 x i8]* %2, i64 0, i64 0
%5 = getelementptr inbounds [32 x i8], [32 x i8]* %3, i64 0, i64 0
%6 = load i64, i64* @progress.tot_bytes
%7 = add i64 %6, %0
store i64 %7, i64* @progress.tot_bytes
%8 = load i64, i64* @progress.period_bytes
%9 = add i64 %8, %0
store i64 %9, i64* @progress.period_bytes
%10 = tail call double (...) @hrtime()
%11 = load double, double* @progress.period_start
%12 = fadd double %11, 2.000000e-01
%13 = fcmp ogt double %10, %12
br i1 %13, label %14, label %26
14: ; preds = %1
%15 = load i64, i64* @progress.period_bytes
%16 = uitofp i64 %15 to double
%17 = fdiv double %16, 2.000000e-01
%18 = fptoui double %17 to i64
store i64 0, i64* @progress.period_bytes
store double %10, double* @progress.period_start
%19 = call i32 @si_format(i8* %4, i32 32, i64 %18)
%20 = load i64, i64* @progress.tot_bytes
%21 = call i32 @si_format(i8* %5, i32 32, i64 %20)
%22 = load i32, i32* @stderr
%23 = call i32 (i32, i8*, ...) @fprintf(i32 %22, i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str, i64 0, i64 0))
%24 = load i32, i32* @stderr
%25 = call i32 (i32, i8*, ...) @fprintf(i32 %24, i8* getelementptr inbounds ([24 x i8], [24 x i8]* @.str.1, i64 0, i64 0), i8* %5, i8* %4)
br label %26
26: ; preds = %14, %1
ret void
}