#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 */
struct timespec {
  unsigned int tv_nsec;
  scalar_t__ tv_sec;
};

/* Variables and functions */
void timespec_add(struct timespec *tp, unsigned int ms) {
  tp->tv_sec += ms / 1000;
  tp->tv_nsec += (ms % 1000) * 1e6;
  if (tp->tv_nsec >= 1e9) {
    tp->tv_nsec -= 1e9;
    tp->tv_sec++;
  }
}


x86 assembly (clang, -O0):
<timespec_add>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    %esi,-0xc(%rbp)
mov    -0xc(%rbp),%eax
imul   $0x10624dd3,%rax,%rdx
shr    $0x26,%rdx
mov    -0x8(%rbp),%rax
mov    0x8(%rax),%rcx
add    %rdx,%rcx
mov    %rcx,0x8(%rax)
mov    -0xc(%rbp),%eax
mov    %eax,%ecx
mov    %ecx,%eax
imul   $0x10624dd3,%rcx,%rcx
shr    $0x26,%rcx
imul   $0x3e8,%ecx,%ecx
sub    %ecx,%eax
cvtsi2sd %eax,%xmm0
mov    -0x8(%rbp),%rax
mov    (%rax),%ecx
cvtsi2sd %rcx,%xmm1
movsd  0xeaf(%rip),%xmm2
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
cvttsd2si %xmm0,%rcx
mov    %ecx,(%rax)
mov    -0x8(%rbp),%rax
mov    (%rax),%eax
cvtsi2sd %rax,%xmm0
movsd  0xe85(%rip),%xmm1
ucomisd %xmm1,%xmm0
jb     11b3 <timespec_add+0xb3>
mov    -0x8(%rbp),%rax
mov    (%rax),%ecx
cvtsi2sd %rcx,%xmm0
movsd  0xe78(%rip),%xmm1
addsd  %xmm1,%xmm0
cvttsd2si %xmm0,%rcx
mov    %ecx,(%rax)
mov    -0x8(%rbp),%rax
mov    0x8(%rax),%rcx
add    $0x1,%rcx
mov    %rcx,0x8(%rax)
pop    %rbp
ret

x86 assembly (clang, -O2):
<timespec_add>:
mov    %esi,%eax
imul   $0x10624dd3,%rax,%rcx
shr    $0x26,%rcx
mov    0x8(%rdi),%rax
add    %rcx,%rax
imul   $0x3e8,%ecx,%ecx
sub    %ecx,%esi
cvtsi2sd %esi,%xmm0
mov    %rax,0x8(%rdi)
mov    (%rdi),%ecx
cvtsi2sd %rcx,%xmm1
mulsd  0xecd(%rip),%xmm0
addsd  %xmm1,%xmm0
cvttsd2si %xmm0,%rcx
mov    %ecx,(%rdi)
cmp    $0x3b9aca00,%ecx
jb     1156 <timespec_add+0x56>
add    $0xc4653600,%ecx
mov    %ecx,(%rdi)
add    $0x1,%rax
mov    %rax,0x8(%rdi)
ret

LLVM IR (-O0):
%struct.timespec = type { i32, i64 }
define void @timespec_add(%struct.timespec* %0, i32 %1) {
%3 = alloca %struct.timespec*
%4 = alloca i32
store %struct.timespec* %0, %struct.timespec** %3
store i32 %1, i32* %4
%5 = load i32, i32* %4
%6 = udiv i32 %5, 1000
%7 = zext i32 %6 to i64
%8 = load %struct.timespec*, %struct.timespec** %3
%9 = getelementptr inbounds %struct.timespec, %struct.timespec* %8, i32 0, i32 1
%10 = load i64, i64* %9
%11 = add nsw i64 %10, %7
store i64 %11, i64* %9
%12 = load i32, i32* %4
%13 = urem i32 %12, 1000
%14 = uitofp i32 %13 to double
%15 = load %struct.timespec*, %struct.timespec** %3
%16 = getelementptr inbounds %struct.timespec, %struct.timespec* %15, i32 0, i32 0
%17 = load i32, i32* %16
%18 = uitofp i32 %17 to double
%19 = call double @llvm.fmuladd.f64(double %14, double 1.000000e+06, double %18)
%20 = fptoui double %19 to i32
store i32 %20, i32* %16
%21 = load %struct.timespec*, %struct.timespec** %3
%22 = getelementptr inbounds %struct.timespec, %struct.timespec* %21, i32 0, i32 0
%23 = load i32, i32* %22
%24 = uitofp i32 %23 to double
%25 = fcmp oge double %24, 1.000000e+09
br i1 %25, label %26, label %37
26: ; preds = %2
%27 = load %struct.timespec*, %struct.timespec** %3
%28 = getelementptr inbounds %struct.timespec, %struct.timespec* %27, i32 0, i32 0
%29 = load i32, i32* %28
%30 = uitofp i32 %29 to double
%31 = fsub double %30, 1.000000e+09
%32 = fptoui double %31 to i32
store i32 %32, i32* %28
%33 = load %struct.timespec*, %struct.timespec** %3
%34 = getelementptr inbounds %struct.timespec, %struct.timespec* %33, i32 0, i32 1
%35 = load i64, i64* %34
%36 = add nsw i64 %35, 1
store i64 %36, i64* %34
br label %37
37: ; preds = %26, %2
ret void
}

LLVM IR (-O2):
%struct.timespec = type { i32, i64 }
define void @timespec_add(%struct.timespec* nocapture %0, i32 %1) {
%3 = udiv i32 %1, 1000
%4 = zext i32 %3 to i64
%5 = getelementptr inbounds %struct.timespec, %struct.timespec* %0, i64 0, i32 1
%6 = load i64, i64* %5
%7 = add nsw i64 %6, %4
store i64 %7, i64* %5
%8 = urem i32 %1, 1000
%9 = uitofp i32 %8 to double
%10 = getelementptr inbounds %struct.timespec, %struct.timespec* %0, i64 0, i32 0
%11 = load i32, i32* %10
%12 = uitofp i32 %11 to double
%13 = tail call double @llvm.fmuladd.f64(double %9, double 1.000000e+06, double %12)
%14 = fptoui double %13 to i32
store i32 %14, i32* %10
%15 = icmp ugt i32 %14, 999999999
br i1 %15, label %16, label %19
16: ; preds = %2
%17 = add i32 %14, -1000000000
store i32 %17, i32* %10
%18 = add nsw i64 %7, 1
store i64 %18, i64* %5
br label %19
19: ; preds = %16, %2
ret void
}