#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 */
typedef int /*<<< orphan*/ yl;
typedef int /*<<< orphan*/ xl;
struct timeval {
  scalar_t__ tv_usec;
  scalar_t__ tv_sec;
};

/* Variables and functions */
int /*<<< orphan*/ memcpy(struct timeval *, struct timeval const *, int);
scalar_t__ time_greater(struct timeval *, struct timeval *);
struct timeval time_sub(const struct timeval *xp, const struct timeval *yp) {
  struct timeval xl, yl;
  memcpy(&xl, xp, sizeof(xl));
  memcpy(&yl, yp, sizeof(yl));
  struct timeval *x = &xl;
  struct timeval *y = &yl;
  int neg_result = 0;
  if (time_greater(y, x)) {
    neg_result = 1;
    x = &yl;
    y = &xl;
  }
  struct timeval result;
  if (x->tv_usec < y->tv_usec) {
    x->tv_sec -= 1;
    x->tv_usec += 1e6;
  }
  result.tv_usec = x->tv_usec - y->tv_usec;
  result.tv_sec = x->tv_sec - y->tv_sec;
  if (neg_result) {
    result.tv_sec = -result.tv_sec;
    result.tv_usec = -result.tv_usec;
  }
  return result;
}


x86 assembly (clang, -O0):
<time_sub>:
push   %rbp
mov    %rsp,%rbp
sub    $0x60,%rsp
mov    %rdi,-0x18(%rbp)
mov    %rsi,-0x20(%rbp)
mov    -0x18(%rbp),%rsi
lea    -0x30(%rbp),%rdi
mov    $0x10,%edx
call   1030 <memcpy@plt>
mov    -0x20(%rbp),%rsi
lea    -0x40(%rbp),%rdi
mov    $0x10,%edx
call   1030 <memcpy@plt>
lea    -0x30(%rbp),%rax
mov    %rax,-0x48(%rbp)
lea    -0x40(%rbp),%rax
mov    %rax,-0x50(%rbp)
movl   $0x0,-0x54(%rbp)
mov    -0x50(%rbp),%rdi
mov    -0x48(%rbp),%rsi
call   1040 <time_greater@plt>
cmp    $0x0,%rax
je     1199 <time_sub+0x79>
movl   $0x1,-0x54(%rbp)
lea    -0x40(%rbp),%rax
mov    %rax,-0x48(%rbp)
lea    -0x30(%rbp),%rax
mov    %rax,-0x50(%rbp)
mov    -0x48(%rbp),%rax
mov    (%rax),%rax
mov    -0x50(%rbp),%rcx
cmp    (%rcx),%rax
jge    11da <time_sub+0xba>
mov    -0x48(%rbp),%rax
mov    0x8(%rax),%rcx
sub    $0x1,%rcx
mov    %rcx,0x8(%rax)
mov    -0x48(%rbp),%rax
cvtsi2sdq (%rax),%xmm0
movsd  0xe32(%rip),%xmm1
addsd  %xmm1,%xmm0
cvttsd2si %xmm0,%rcx
mov    %rcx,(%rax)
mov    -0x48(%rbp),%rax
mov    (%rax),%rax
mov    -0x50(%rbp),%rcx
sub    (%rcx),%rax
mov    %rax,-0x10(%rbp)
mov    -0x48(%rbp),%rax
mov    0x8(%rax),%rax
mov    -0x50(%rbp),%rcx
sub    0x8(%rcx),%rax
mov    %rax,-0x8(%rbp)
cmpl   $0x0,-0x54(%rbp)
je     121e <time_sub+0xfe>
xor    %eax,%eax
sub    -0x8(%rbp),%rax
mov    %rax,-0x8(%rbp)
xor    %eax,%eax
sub    -0x10(%rbp),%rax
mov    %rax,-0x10(%rbp)
mov    -0x10(%rbp),%rax
mov    -0x8(%rbp),%rdx
add    $0x60,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<time_sub>:
push   %r15
push   %r14
push   %rbx
sub    $0x20,%rsp
mov    %rsi,%r15
mov    %rdi,%rsi
lea    0x10(%rsp),%rbx
mov    %rsp,%r14
mov    %rbx,%rdi
mov    $0x10,%edx
call   1030 <memcpy@plt>
mov    %r14,%rdi
mov    %r15,%rsi
mov    $0x10,%edx
call   1030 <memcpy@plt>
mov    %r14,%rdi
mov    %rbx,%rsi
call   1040 <time_greater@plt>
test   %rax,%rax
je     116c <time_sub+0x4c>
mov    %rsp,%rbx
lea    0x10(%rsp),%r14
mov    (%rbx),%rdi
mov    (%r14),%rcx
mov    0x8(%rbx),%rsi
cmp    %rcx,%rdi
jge    1198 <time_sub+0x78>
add    $0xffffffffffffffff,%rsi
cvtsi2sd %rdi,%xmm0
addsd  0xe74(%rip),%xmm0
mov    %rsi,0x8(%rbx)
cvttsd2si %xmm0,%rdi
mov    %rdi,(%rbx)
sub    0x8(%r14),%rsi
sub    %rcx,%rdi
mov    %rsi,%rdx
neg    %rdx
mov    %rdi,%rcx
neg    %rcx
test   %rax,%rax
cmove  %rdi,%rcx
cmove  %rsi,%rdx
mov    %rcx,%rax
add    $0x20,%rsp
pop    %rbx
pop    %r14
pop    %r15
ret

LLVM IR (-O0):
%struct.timeval = type { i64, i64 }
define { i64, i64 } @time_sub(%struct.timeval* %0, %struct.timeval* %1) {
%3 = alloca %struct.timeval
%4 = alloca %struct.timeval*
%5 = alloca %struct.timeval*
%6 = alloca %struct.timeval
%7 = alloca %struct.timeval
%8 = alloca %struct.timeval*
%9 = alloca %struct.timeval*
%10 = alloca i32
store %struct.timeval* %0, %struct.timeval** %4
store %struct.timeval* %1, %struct.timeval** %5
%11 = load %struct.timeval*, %struct.timeval** %4
%12 = call i32 @memcpy(%struct.timeval* %6, %struct.timeval* %11, i32 16)
%13 = load %struct.timeval*, %struct.timeval** %5
%14 = call i32 @memcpy(%struct.timeval* %7, %struct.timeval* %13, i32 16)
store %struct.timeval* %6, %struct.timeval** %8
store %struct.timeval* %7, %struct.timeval** %9
store i32 0, i32* %10
%15 = load %struct.timeval*, %struct.timeval** %9
%16 = load %struct.timeval*, %struct.timeval** %8
%17 = call i64 @time_greater(%struct.timeval* %15, %struct.timeval* %16)
%18 = icmp ne i64 %17, 0
br i1 %18, label %19, label %20
19: ; preds = %2
store i32 1, i32* %10
store %struct.timeval* %7, %struct.timeval** %8
store %struct.timeval* %6, %struct.timeval** %9
br label %20
20: ; preds = %19, %2
%21 = load %struct.timeval*, %struct.timeval** %8
%22 = getelementptr inbounds %struct.timeval, %struct.timeval* %21, i32 0, i32 0
%23 = load i64, i64* %22
%24 = load %struct.timeval*, %struct.timeval** %9
%25 = getelementptr inbounds %struct.timeval, %struct.timeval* %24, i32 0, i32 0
%26 = load i64, i64* %25
%27 = icmp slt i64 %23, %26
br i1 %27, label %28, label %39
28: ; preds = %20
%29 = load %struct.timeval*, %struct.timeval** %8
%30 = getelementptr inbounds %struct.timeval, %struct.timeval* %29, i32 0, i32 1
%31 = load i64, i64* %30
%32 = sub nsw i64 %31, 1
store i64 %32, i64* %30
%33 = load %struct.timeval*, %struct.timeval** %8
%34 = getelementptr inbounds %struct.timeval, %struct.timeval* %33, i32 0, i32 0
%35 = load i64, i64* %34
%36 = sitofp i64 %35 to double
%37 = fadd double %36, 1.000000e+06
%38 = fptosi double %37 to i64
store i64 %38, i64* %34
br label %39
39: ; preds = %28, %20
%40 = load %struct.timeval*, %struct.timeval** %8
%41 = getelementptr inbounds %struct.timeval, %struct.timeval* %40, i32 0, i32 0
%42 = load i64, i64* %41
%43 = load %struct.timeval*, %struct.timeval** %9
%44 = getelementptr inbounds %struct.timeval, %struct.timeval* %43, i32 0, i32 0
%45 = load i64, i64* %44
%46 = sub nsw i64 %42, %45
%47 = getelementptr inbounds %struct.timeval, %struct.timeval* %3, i32 0, i32 0
store i64 %46, i64* %47
%48 = load %struct.timeval*, %struct.timeval** %8
%49 = getelementptr inbounds %struct.timeval, %struct.timeval* %48, i32 0, i32 1
%50 = load i64, i64* %49
%51 = load %struct.timeval*, %struct.timeval** %9
%52 = getelementptr inbounds %struct.timeval, %struct.timeval* %51, i32 0, i32 1
%53 = load i64, i64* %52
%54 = sub nsw i64 %50, %53
%55 = getelementptr inbounds %struct.timeval, %struct.timeval* %3, i32 0, i32 1
store i64 %54, i64* %55
%56 = load i32, i32* %10
%57 = icmp ne i32 %56, 0
br i1 %57, label %58, label %67
58: ; preds = %39
%59 = getelementptr inbounds %struct.timeval, %struct.timeval* %3, i32 0, i32 1
%60 = load i64, i64* %59
%61 = sub nsw i64 0, %60
%62 = getelementptr inbounds %struct.timeval, %struct.timeval* %3, i32 0, i32 1
store i64 %61, i64* %62
%63 = getelementptr inbounds %struct.timeval, %struct.timeval* %3, i32 0, i32 0
%64 = load i64, i64* %63
%65 = sub nsw i64 0, %64
%66 = getelementptr inbounds %struct.timeval, %struct.timeval* %3, i32 0, i32 0
store i64 %65, i64* %66
br label %67
67: ; preds = %58, %39
%68 = bitcast %struct.timeval* %3 to { i64, i64 }*
%69 = load { i64, i64 }, { i64, i64 }* %68
ret { i64, i64 } %69
}

LLVM IR (-O2):
%struct.timeval = type { i64, i64 }
define { i64, i64 } @time_sub(%struct.timeval* %0, %struct.timeval* %1) {
%3 = alloca %struct.timeval
%4 = getelementptr inbounds %struct.timeval, %struct.timeval* %3, i64 0, i32 0
%5 = alloca %struct.timeval
%6 = getelementptr inbounds %struct.timeval, %struct.timeval* %5, i64 0, i32 0
%7 = bitcast %struct.timeval* %3 to i8*
%8 = bitcast %struct.timeval* %5 to i8*
%9 = call i32 @memcpy(%struct.timeval* %3, %struct.timeval* %0, i32 16)
%10 = call i32 @memcpy(%struct.timeval* %5, %struct.timeval* %1, i32 16)
%11 = call i64 @time_greater(%struct.timeval* %5, %struct.timeval* %3)
%12 = icmp eq i64 %11, 0
br i1 %12, label %14, label %13
13: ; preds = %2
br label %14
14: ; preds = %13, %2
%15 = phi %struct.timeval* [ %5, %13 ], [ %3, %2 ]
%16 = phi %struct.timeval* [ %3, %13 ], [ %5, %2 ]
%17 = phi i64* [ %4, %13 ], [ %6, %2 ]
%18 = phi i64* [ %6, %13 ], [ %4, %2 ]
%19 = load i64, i64* %18
%20 = load i64, i64* %17
%21 = icmp slt i64 %19, %20
%22 = getelementptr inbounds %struct.timeval, %struct.timeval* %15, i64 0, i32 1
%23 = load i64, i64* %22
br i1 %21, label %24, label %30
24: ; preds = %14
%25 = add nsw i64 %23, -1
store i64 %25, i64* %22
%26 = getelementptr inbounds %struct.timeval, %struct.timeval* %15, i64 0, i32 0
%27 = sitofp i64 %19 to double
%28 = fadd double %27, 1.000000e+06
%29 = fptosi double %28 to i64
store i64 %29, i64* %26
br label %30
30: ; preds = %14, %24
%31 = phi i64 [ %25, %24 ], [ %23, %14 ]
%32 = phi i64 [ %29, %24 ], [ %19, %14 ]
%33 = sub nsw i64 %32, %20
%34 = getelementptr inbounds %struct.timeval, %struct.timeval* %16, i64 0, i32 1
%35 = load i64, i64* %34
%36 = sub nsw i64 %31, %35
%37 = sub nsw i64 0, %36
%38 = sub nsw i64 0, %33
%39 = select i1 %12, i64 %33, i64 %38
%40 = select i1 %12, i64 %36, i64 %37
%41 = insertvalue { i64, i64 } poison, i64 %39, 0
%42 = insertvalue { i64, i64 } %41, i64 %40, 1
ret { i64, i64 } %42
}