double randlc(double *x, double a) {
  printf("Starting RANDLC %d, %d\n", x, a);
  const double r23 = 1.1920928955078125e-07;
  const double r46 = r23 * r23;
  const double t23 = 8.388608e+06;
  const double t46 = t23 * t23;
  double t1, t2, t3, t4, a1, a2, x1, x2, z;
  double r;
  printf("Break A into two parts such that A = 2^23 * A1 + A2.\n");
  t1 = r23 * a;
  a1 = (int)t1;
  a2 = a - t23 * a1;
  t1 = r23 * (*x);
  x1 = (int)t1;
  x2 = *x - t23 * x1;
  t1 = a1 * x2 + a2 * x1;
  t2 = (int)(r23 * t1);
  z = t1 - t23 * t2;
  t3 = t23 * z + a2 * x2;
  t4 = (int)(r46 * t3);
  *x = t3 - t46 * t4;
  r = r46 * (*x);
  printf("Returning from RANDLC: %d \n", r);
  return r;
}


x86 assembly (clang, -O0):
<randlc>:
push   %rbp
mov    %rsp,%rbp
sub    $0x80,%rsp
mov    %rdi,-0x8(%rbp)
movsd  %xmm0,-0x10(%rbp)
mov    -0x8(%rbp),%rsi
movsd  -0x10(%rbp),%xmm0
lea    0xefc(%rip),%rdi
mov    $0x1,%al
call   1030 <printf@plt>
movsd  0xedd(%rip),%xmm0
movsd  %xmm0,-0x18(%rbp)
movsd  0xeb0(%rip),%xmm0
movsd  %xmm0,-0x20(%rbp)
movsd  0xeb3(%rip),%xmm0
movsd  %xmm0,-0x28(%rbp)
movsd  0xebe(%rip),%xmm0
movsd  %xmm0,-0x30(%rbp)
lea    0xed2(%rip),%rdi
mov    $0x0,%al
call   1030 <printf@plt>
movsd  0xe9b(%rip),%xmm0
mulsd  -0x10(%rbp),%xmm0
movsd  %xmm0,-0x38(%rbp)
cvttsd2si -0x38(%rbp),%eax
cvtsi2sd %eax,%xmm0
movsd  %xmm0,-0x58(%rbp)
movsd  -0x10(%rbp),%xmm1
movsd  -0x58(%rbp),%xmm0
movsd  0xe69(%rip),%xmm2
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x60(%rbp)
mov    -0x8(%rbp),%rax
movsd  0xe58(%rip),%xmm0
mulsd  (%rax),%xmm0
movsd  %xmm0,-0x38(%rbp)
cvttsd2si -0x38(%rbp),%eax
cvtsi2sd %eax,%xmm0
movsd  %xmm0,-0x68(%rbp)
mov    -0x8(%rbp),%rax
movsd  (%rax),%xmm1
movsd  -0x68(%rbp),%xmm0
movsd  0xe24(%rip),%xmm2
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x70(%rbp)
movsd  -0x58(%rbp),%xmm0
movsd  -0x70(%rbp),%xmm2
movsd  -0x60(%rbp),%xmm1
mulsd  -0x68(%rbp),%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x38(%rbp)
movsd  0xdf6(%rip),%xmm0
mulsd  -0x38(%rbp),%xmm0
cvttsd2si %xmm0,%eax
cvtsi2sd %eax,%xmm0
movsd  %xmm0,-0x40(%rbp)
movsd  -0x38(%rbp),%xmm1
movsd  -0x40(%rbp),%xmm0
movsd  0xdca(%rip),%xmm2
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x78(%rbp)
movsd  -0x78(%rbp),%xmm0
movsd  -0x60(%rbp),%xmm1
mulsd  -0x70(%rbp),%xmm1
movsd  0xd9e(%rip),%xmm2
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x48(%rbp)
movsd  0xd79(%rip),%xmm0
mulsd  -0x48(%rbp),%xmm0
cvttsd2si %xmm0,%eax
cvtsi2sd %eax,%xmm0
movsd  %xmm0,-0x50(%rbp)
movsd  -0x48(%rbp),%xmm1
movsd  -0x50(%rbp),%xmm0
movsd  0xd5d(%rip),%xmm2
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
mov    -0x8(%rbp),%rax
movsd  %xmm0,(%rax)
mov    -0x8(%rbp),%rax
movsd  0xd39(%rip),%xmm0
mulsd  (%rax),%xmm0
movsd  %xmm0,-0x80(%rbp)
movsd  -0x80(%rbp),%xmm0
lea    0xda2(%rip),%rdi
mov    $0x1,%al
call   1030 <printf@plt>
movsd  -0x80(%rbp),%xmm0
add    $0x80,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<randlc>:
push   %rbx
sub    $0x10,%rsp
movaps %xmm0,(%rsp)
mov    %rdi,%rbx
lea    0xf15(%rip),%rdi
mov    %rbx,%rsi
mov    $0x1,%al
call   1040 <printf@plt>
lea    0xf38(%rip),%rdi
call   1030 <puts@plt>
movapd (%rsp),%xmm1
movhpd (%rbx),%xmm1
movapd 0xea6(%rip),%xmm0
mulpd  %xmm1,%xmm0
movapd %xmm1,%xmm2
cvttpd2dq %xmm0,%xmm0
cvtdq2pd %xmm0,%xmm0
movapd 0xe9e(%rip),%xmm1
mulpd  %xmm0,%xmm1
addpd  %xmm2,%xmm1
movapd %xmm0,%xmm2
unpckhpd %xmm0,%xmm2
mulsd  %xmm1,%xmm2
movapd %xmm1,%xmm3
unpckhpd %xmm1,%xmm3
mulsd  %xmm3,%xmm0
addsd  %xmm2,%xmm0
movsd  0xe82(%rip),%xmm2
mulsd  %xmm0,%xmm2
cvttpd2dq %xmm2,%xmm2
cvtdq2pd %xmm2,%xmm2
mulsd  0xe76(%rip),%xmm2
addsd  %xmm0,%xmm2
mulsd  %xmm1,%xmm3
mulsd  0xe6e(%rip),%xmm2
addsd  %xmm3,%xmm2
movsd  0xe6a(%rip),%xmm3
movapd %xmm2,%xmm1
mulsd  %xmm3,%xmm1
cvttpd2dq %xmm1,%xmm1
cvtdq2pd %xmm1,%xmm0
mulsd  0xe5a(%rip),%xmm0
addsd  %xmm2,%xmm0
movsd  %xmm0,(%rbx)
mulsd  %xmm3,%xmm0
movapd %xmm0,(%rsp)
lea    0xe62(%rip),%rdi
mov    $0x1,%al
call   1040 <printf@plt>
movaps (%rsp),%xmm0
add    $0x10,%rsp
pop    %rbx
ret

LLVM IR (-O0):
@.str = [24 x i8] c"Starting RANDLC %d, %d\0A\00"
@.str.1 = [54 x i8] c"Break A into two parts such that A = 2^23 * A1 + A2.\0A\00"
@.str.2 = [28 x i8] c"Returning from RANDLC: %d \0A\00"
define double @randlc(double* %0, double %1) {
%3 = alloca double*
%4 = alloca double
%5 = alloca double
%6 = alloca double
%7 = alloca double
%8 = alloca double
%9 = alloca double
%10 = alloca double
%11 = alloca double
%12 = alloca double
%13 = alloca double
%14 = alloca double
%15 = alloca double
%16 = alloca double
%17 = alloca double
%18 = alloca double
store double* %0, double** %3
store double %1, double* %4
%19 = load double*, double** %3
%20 = load double, double* %4
%21 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([24 x i8], [24 x i8]* @.str, i64 0, i64 0), double* %19, double %20)
store double 0x3E80000000000000, double* %5
store double 0x3D10000000000000, double* %6
store double 0x4160000000000000, double* %7
store double 0x42D0000000000000, double* %8
%22 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([54 x i8], [54 x i8]* @.str.1, i64 0, i64 0))
%23 = load double, double* %4
%24 = fmul double 0x3E80000000000000, %23
store double %24, double* %9
%25 = load double, double* %9
%26 = fptosi double %25 to i32
%27 = sitofp i32 %26 to double
store double %27, double* %13
%28 = load double, double* %4
%29 = load double, double* %13
%30 = call double @llvm.fmuladd.f64(double 0xC160000000000000, double %29, double %28)
store double %30, double* %14
%31 = load double*, double** %3
%32 = load double, double* %31
%33 = fmul double 0x3E80000000000000, %32
store double %33, double* %9
%34 = load double, double* %9
%35 = fptosi double %34 to i32
%36 = sitofp i32 %35 to double
store double %36, double* %15
%37 = load double*, double** %3
%38 = load double, double* %37
%39 = load double, double* %15
%40 = call double @llvm.fmuladd.f64(double 0xC160000000000000, double %39, double %38)
store double %40, double* %16
%41 = load double, double* %13
%42 = load double, double* %16
%43 = load double, double* %14
%44 = load double, double* %15
%45 = fmul double %43, %44
%46 = call double @llvm.fmuladd.f64(double %41, double %42, double %45)
store double %46, double* %9
%47 = load double, double* %9
%48 = fmul double 0x3E80000000000000, %47
%49 = fptosi double %48 to i32
%50 = sitofp i32 %49 to double
store double %50, double* %10
%51 = load double, double* %9
%52 = load double, double* %10
%53 = call double @llvm.fmuladd.f64(double 0xC160000000000000, double %52, double %51)
store double %53, double* %17
%54 = load double, double* %17
%55 = load double, double* %14
%56 = load double, double* %16
%57 = fmul double %55, %56
%58 = call double @llvm.fmuladd.f64(double 0x4160000000000000, double %54, double %57)
store double %58, double* %11
%59 = load double, double* %11
%60 = fmul double 0x3D10000000000000, %59
%61 = fptosi double %60 to i32
%62 = sitofp i32 %61 to double
store double %62, double* %12
%63 = load double, double* %11
%64 = load double, double* %12
%65 = call double @llvm.fmuladd.f64(double 0xC2D0000000000000, double %64, double %63)
%66 = load double*, double** %3
store double %65, double* %66
%67 = load double*, double** %3
%68 = load double, double* %67
%69 = fmul double 0x3D10000000000000, %68
store double %69, double* %18
%70 = load double, double* %18
%71 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([28 x i8], [28 x i8]* @.str.2, i64 0, i64 0), double %70)
%72 = load double, double* %18
ret double %72
}

LLVM IR (-O2):
@.str = [24 x i8] c"Starting RANDLC %d, %d\0A\00"
@.str.2 = [28 x i8] c"Returning from RANDLC: %d \0A\00"
@str = [53 x i8] c"Break A into two parts such that A = 2^23 * A1 + A2.\00"
define double @randlc(double* %0, double %1) {
%3 = tail call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([24 x i8], [24 x i8]* @.str, i64 0, i64 0), double* %0, double %1)
%4 = tail call i32 @puts(i8* dereferenceable(1) getelementptr inbounds ([53 x i8], [53 x i8]* @str, i64 0, i64 0))
%5 = load double, double* %0
%6 = insertelement <2 x double> poison, double %1, i64 0
%7 = insertelement <2 x double> %6, double %5, i64 1
%8 = fmul <2 x double> %7, <double 0x3E80000000000000, double 0x3E80000000000000>
%9 = fptosi <2 x double> %8 to <2 x i32>
%10 = sitofp <2 x i32> %9 to <2 x double>
%11 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %10, <2 x double> <double 0xC160000000000000, double 0xC160000000000000>, <2 x double> %7)
%12 = extractelement <2 x double> %11, i64 0
%13 = shufflevector <2 x double> %10, <2 x double> poison, <2 x i32> <i32 1, i32 undef>
%14 = fmul <2 x double> %11, %13
%15 = extractelement <2 x double> %14, i64 0
%16 = extractelement <2 x double> %11, i64 1
%17 = extractelement <2 x double> %10, i64 0
%18 = tail call double @llvm.fmuladd.f64(double %17, double %16, double %15)
%19 = fmul double %18, 0x3E80000000000000
%20 = fptosi double %19 to i32
%21 = sitofp i32 %20 to double
%22 = tail call double @llvm.fmuladd.f64(double %21, double 0xC160000000000000, double %18)
%23 = fmul double %12, %16
%24 = tail call double @llvm.fmuladd.f64(double %22, double 0x4160000000000000, double %23)
%25 = fmul double %24, 0x3D10000000000000
%26 = fptosi double %25 to i32
%27 = sitofp i32 %26 to double
%28 = tail call double @llvm.fmuladd.f64(double %27, double 0xC2D0000000000000, double %24)
store double %28, double* %0
%29 = fmul double %28, 0x3D10000000000000
%30 = tail call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([28 x i8], [28 x i8]* @.str.2, i64 0, i64 0), double %29)
ret double %29
}