double double_round(double val) {
  if (val >= 0) {
    return val - (long)val >= 0.5 ? (double)((long)(val + 1))
                                  : (double)((long)val);
  } else {
    return val - (long)val >= -0.5 ? (double)((long)val)
                                   : (double)((long)(val - 1));
  }
}


x86 assembly (clang, -O0):
<double_round>:
push   %rbp
mov    %rsp,%rbp
movsd  %xmm0,-0x10(%rbp)
movsd  -0x10(%rbp),%xmm0
xorps  %xmm1,%xmm1
ucomisd %xmm1,%xmm0
jb     1181 <double_round+0x81>
movsd  -0x10(%rbp),%xmm0
cvttsd2si -0x10(%rbp),%rax
cvtsi2sd %rax,%xmm1
subsd  %xmm1,%xmm0
movsd  0xed9(%rip),%xmm1
ucomisd %xmm1,%xmm0
jb     1162 <double_round+0x62>
movsd  0xebf(%rip),%xmm0
addsd  -0x10(%rbp),%xmm0
cvttsd2si %xmm0,%rax
cvtsi2sd %rax,%xmm0
movsd  %xmm0,-0x18(%rbp)
jmp    1172 <double_round+0x72>
cvttsd2si -0x10(%rbp),%rax
cvtsi2sd %rax,%xmm0
movsd  %xmm0,-0x18(%rbp)
movsd  -0x18(%rbp),%xmm0
movsd  %xmm0,-0x8(%rbp)
jmp    11e6 <double_round+0xe6>
movsd  -0x10(%rbp),%xmm0
cvttsd2si -0x10(%rbp),%rax
cvtsi2sd %rax,%xmm1
subsd  %xmm1,%xmm0
movsd  0xe63(%rip),%xmm1
ucomisd %xmm1,%xmm0
jb     11bc <double_round+0xbc>
cvttsd2si -0x10(%rbp),%rax
cvtsi2sd %rax,%xmm0
movsd  %xmm0,-0x20(%rbp)
jmp    11dc <double_round+0xdc>
movsd  -0x10(%rbp),%xmm0
movsd  0xe3f(%rip),%xmm1
subsd  %xmm1,%xmm0
cvttsd2si %xmm0,%rax
cvtsi2sd %rax,%xmm0
movsd  %xmm0,-0x20(%rbp)
movsd  -0x20(%rbp),%xmm0
movsd  %xmm0,-0x8(%rbp)
movsd  -0x8(%rbp),%xmm0
pop    %rbp
ret

x86 assembly (clang, -O2):
<double_round>:
movapd %xmm0,%xmm1
xorpd  %xmm0,%xmm0
ucomisd %xmm0,%xmm1
cvttsd2si %xmm1,%rax
xorps  %xmm0,%xmm0
cvtsi2sd %rax,%xmm0
movapd %xmm1,%xmm2
subsd  %xmm0,%xmm2
jae    114d <double_round+0x4d>
ucomisd 0xee5(%rip),%xmm2
setb   %al
addsd  0xee2(%rip),%xmm1
cvttsd2si %xmm1,%rcx
movapd %xmm0,%xmm1
xorps  %xmm0,%xmm0
cvtsi2sd %rcx,%xmm0
test   %al,%al
je     1171 <double_round+0x71>
jmp    1175 <double_round+0x75>
ucomisd 0xeab(%rip),%xmm2
setb   %al
addsd  0xea8(%rip),%xmm1
cvttsd2si %xmm1,%rcx
xorps  %xmm1,%xmm1
cvtsi2sd %rcx,%xmm1
test   %al,%al
jne    1175 <double_round+0x75>
movapd %xmm1,%xmm0
ret

LLVM IR (-O0):
define double @double_round(double %0) {
%2 = alloca double
%3 = alloca double
store double %0, double* %3
%4 = load double, double* %3
%5 = fcmp oge double %4, 0.000000e+00
br i1 %5, label %6, label %24
6: ; preds = %1
%7 = load double, double* %3
%8 = load double, double* %3
%9 = fptosi double %8 to i64
%10 = sitofp i64 %9 to double
%11 = fsub double %7, %10
%12 = fcmp oge double %11, 5.000000e-01
br i1 %12, label %13, label %18
13: ; preds = %6
%14 = load double, double* %3
%15 = fadd double %14, 1.000000e+00
%16 = fptosi double %15 to i64
%17 = sitofp i64 %16 to double
br label %22
18: ; preds = %6
%19 = load double, double* %3
%20 = fptosi double %19 to i64
%21 = sitofp i64 %20 to double
br label %22
22: ; preds = %18, %13
%23 = phi double [ %17, %13 ], [ %21, %18 ]
store double %23, double* %2
br label %42
24: ; preds = %1
%25 = load double, double* %3
%26 = load double, double* %3
%27 = fptosi double %26 to i64
%28 = sitofp i64 %27 to double
%29 = fsub double %25, %28
%30 = fcmp oge double %29, -5.000000e-01
br i1 %30, label %31, label %35
31: ; preds = %24
%32 = load double, double* %3
%33 = fptosi double %32 to i64
%34 = sitofp i64 %33 to double
br label %40
35: ; preds = %24
%36 = load double, double* %3
%37 = fsub double %36, 1.000000e+00
%38 = fptosi double %37 to i64
%39 = sitofp i64 %38 to double
br label %40
40: ; preds = %35, %31
%41 = phi double [ %34, %31 ], [ %39, %35 ]
store double %41, double* %2
br label %42
42: ; preds = %40, %22
%43 = load double, double* %2
ret double %43
}

LLVM IR (-O2):
define double @double_round(double %0) {
%2 = fcmp ult double %0, 0.000000e+00
%3 = fptosi double %0 to i64
%4 = sitofp i64 %3 to double
%5 = fsub double %0, %4
br i1 %2, label %11, label %6
6: ; preds = %1
%7 = fcmp ult double %5, 5.000000e-01
%8 = fadd double %0, 1.000000e+00
%9 = fptosi double %8 to i64
%10 = sitofp i64 %9 to double
br label %16
11: ; preds = %1
%12 = fcmp ult double %5, -5.000000e-01
%13 = fadd double %0, -1.000000e+00
%14 = fptosi double %13 to i64
%15 = sitofp i64 %14 to double
br label %16
16: ; preds = %11, %6
%17 = phi double [ %4, %11 ], [ %10, %6 ]
%18 = phi double [ %15, %11 ], [ %4, %6 ]
%19 = phi i1 [ %12, %11 ], [ %7, %6 ]
%20 = select i1 %19, double %18, double %17
ret double %20
}