float linearize_depth(float depth, float near, float far) {
  float proj_a = -(far + near) / (far - near);
  float proj_b = (-2 * far * near) / (far - near);
  return (-proj_b / (depth * 2 - 1 + proj_a)) / -far;
}


x86 assembly (clang, -O0):
<linearize_depth>:
push   %rbp
mov    %rsp,%rbp
movss  %xmm0,-0x4(%rbp)
movss  %xmm1,-0x8(%rbp)
movss  %xmm2,-0xc(%rbp)
movss  -0xc(%rbp),%xmm0
addss  -0x8(%rbp),%xmm0
movd   %xmm0,%eax
xor    $0x80000000,%eax
movd   %eax,%xmm0
movss  -0xc(%rbp),%xmm1
subss  -0x8(%rbp),%xmm1
divss  %xmm1,%xmm0
movss  %xmm0,-0x10(%rbp)
movss  0xebf(%rip),%xmm0
mulss  -0xc(%rbp),%xmm0
mulss  -0x8(%rbp),%xmm0
movss  -0xc(%rbp),%xmm1
subss  -0x8(%rbp),%xmm1
divss  %xmm1,%xmm0
movss  %xmm0,-0x14(%rbp)
movss  -0x14(%rbp),%xmm0
movd   %xmm0,%eax
xor    $0x80000000,%eax
movd   %eax,%xmm0
movss  -0x4(%rbp),%xmm1
addss  %xmm1,%xmm1
movss  0xe7b(%rip),%xmm2
addss  %xmm2,%xmm1
addss  -0x10(%rbp),%xmm1
divss  %xmm1,%xmm0
movss  -0xc(%rbp),%xmm1
movd   %xmm1,%eax
xor    $0x80000000,%eax
movd   %eax,%xmm1
divss  %xmm1,%xmm0
pop    %rbp
ret

x86 assembly (clang, -O2):
<linearize_depth>:
movaps %xmm2,%xmm3
subss  %xmm1,%xmm3
movaps %xmm2,%xmm4
addss  %xmm2,%xmm4
unpcklps %xmm1,%xmm5
movaps %xmm2,%xmm6
movlhps %xmm4,%xmm6
shufps $0xe2,%xmm4,%xmm6
mulps  %xmm1,%xmm6
unpcklps %xmm2,%xmm1
addps  %xmm5,%xmm1
shufps $0x1,%xmm6,%xmm1
shufps $0xe2,%xmm6,%xmm1
addss  %xmm0,%xmm0
addss  0xec8(%rip),%xmm0
shufps $0x0,%xmm3,%xmm3
divps  %xmm3,%xmm1
movaps %xmm1,%xmm3
shufps $0x55,%xmm1,%xmm3
subss  %xmm3,%xmm0
divss  %xmm0,%xmm1
xorps  0xebb(%rip),%xmm2
divss  %xmm2,%xmm1
movaps %xmm1,%xmm0
ret

LLVM IR (-O0):
define float @linearize_depth(float %0, float %1, float %2) {
%4 = alloca float
%5 = alloca float
%6 = alloca float
%7 = alloca float
%8 = alloca float
store float %0, float* %4
store float %1, float* %5
store float %2, float* %6
%9 = load float, float* %6
%10 = load float, float* %5
%11 = fadd float %9, %10
%12 = fneg float %11
%13 = load float, float* %6
%14 = load float, float* %5
%15 = fsub float %13, %14
%16 = fdiv float %12, %15
store float %16, float* %7
%17 = load float, float* %6
%18 = fmul float -2.000000e+00, %17
%19 = load float, float* %5
%20 = fmul float %18, %19
%21 = load float, float* %6
%22 = load float, float* %5
%23 = fsub float %21, %22
%24 = fdiv float %20, %23
store float %24, float* %8
%25 = load float, float* %8
%26 = fneg float %25
%27 = load float, float* %4
%28 = call float @llvm.fmuladd.f32(float %27, float 2.000000e+00, float -1.000000e+00)
%29 = load float, float* %7
%30 = fadd float %28, %29
%31 = fdiv float %26, %30
%32 = load float, float* %6
%33 = fneg float %32
%34 = fdiv float %31, %33
ret float %34
}

LLVM IR (-O2):
define float @linearize_depth(float %0, float %1, float %2) {
%4 = fsub float %2, %1
%5 = fmul float %2, 2.000000e+00
%6 = insertelement <2 x float> poison, float %1, i64 0
%7 = shufflevector <2 x float> %6, <2 x float> poison, <2 x i32> zeroinitializer
%8 = insertelement <2 x float> poison, float %2, i64 1
%9 = insertelement <2 x float> %8, float %5, i64 0
%10 = fmul <2 x float> %7, %9
%11 = fadd <2 x float> %7, %9
%12 = shufflevector <2 x float> %10, <2 x float> %11, <2 x i32> <i32 0, i32 3>
%13 = tail call float @llvm.fmuladd.f32(float %0, float 2.000000e+00, float -1.000000e+00)
%14 = insertelement <2 x float> poison, float %4, i64 0
%15 = shufflevector <2 x float> %14, <2 x float> poison, <2 x i32> zeroinitializer
%16 = fdiv <2 x float> %12, %15
%17 = extractelement <2 x float> %16, i64 1
%18 = fsub float %13, %17
%19 = extractelement <2 x float> %16, i64 0
%20 = fdiv float %19, %18
%21 = fneg float %2
%22 = fdiv float %20, %21
ret float %22
}