double *unit_fun(a, b, c)
double a, b, c;
{
  double res[3], len;
  len = sqrt(a * a + b * b + c * c);
  if (len == 0.0 || len != len)
    len = 1.0;
  res[0] = a / len;
  res[1] = b / len;
  res[2] = c / len;
  return (res);
}


x86 assembly (clang, -O0):
<unit_fun>:
push   %rbp
mov    %rsp,%rbp
sub    $0x40,%rsp
movsd  %xmm0,-0x8(%rbp)
movsd  %xmm1,-0x10(%rbp)
movsd  %xmm2,-0x18(%rbp)
movsd  -0x8(%rbp),%xmm1
movsd  -0x8(%rbp),%xmm2
movsd  -0x10(%rbp),%xmm0
mulsd  -0x10(%rbp),%xmm0
mulsd  %xmm2,%xmm1
addsd  %xmm0,%xmm1
movsd  -0x18(%rbp),%xmm0
movsd  -0x18(%rbp),%xmm2
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
call   1030 <sqrt@plt>
movsd  %xmm0,-0x38(%rbp)
movsd  -0x38(%rbp),%xmm0
xorps  %xmm1,%xmm1
ucomisd %xmm1,%xmm0
jne    117c <unit_fun+0x6c>
jp     117c <unit_fun+0x6c>
jmp    1197 <unit_fun+0x87>
movsd  -0x38(%rbp),%xmm0
ucomisd -0x38(%rbp),%xmm0
jne    1197 <unit_fun+0x87>
jp     1197 <unit_fun+0x87>
jmp    11a4 <unit_fun+0x94>
movsd  0xe61(%rip),%xmm0
movsd  %xmm0,-0x38(%rbp)
movsd  -0x8(%rbp),%xmm0
divsd  -0x38(%rbp),%xmm0
movsd  %xmm0,-0x30(%rbp)
movsd  -0x10(%rbp),%xmm0
divsd  -0x38(%rbp),%xmm0
movsd  %xmm0,-0x28(%rbp)
movsd  -0x18(%rbp),%xmm0
divsd  -0x38(%rbp),%xmm0
movsd  %xmm0,-0x20(%rbp)
lea    -0x30(%rbp),%rax
add    $0x40,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<unit_fun>:
sub    $0x18,%rsp
mulsd  %xmm1,%xmm1
mulsd  %xmm0,%xmm0
addsd  %xmm1,%xmm0
mulsd  %xmm2,%xmm2
addsd  %xmm0,%xmm2
xorpd  %xmm0,%xmm0
ucomisd %xmm0,%xmm2
jae    113b <unit_fun+0x2b>
movapd %xmm2,%xmm0
call   1030 <sqrt@plt>
mov    %rsp,%rax
add    $0x18,%rsp
ret

LLVM IR (-O0):
define double* @unit_fun(double %0, double %1, double %2) {
%4 = alloca double
%5 = alloca double
%6 = alloca double
%7 = alloca [3 x double]
%8 = alloca double
store double %0, double* %4
store double %1, double* %5
store double %2, double* %6
%9 = load double, double* %4
%10 = load double, double* %4
%11 = load double, double* %5
%12 = load double, double* %5
%13 = fmul double %11, %12
%14 = call double @llvm.fmuladd.f64(double %9, double %10, double %13)
%15 = load double, double* %6
%16 = load double, double* %6
%17 = call double @llvm.fmuladd.f64(double %15, double %16, double %14)
%18 = call double @sqrt(double %17)
store double %18, double* %8
%19 = load double, double* %8
%20 = fcmp oeq double %19, 0.000000e+00
br i1 %20, label %25, label %21
21: ; preds = %3
%22 = load double, double* %8
%23 = load double, double* %8
%24 = fcmp une double %22, %23
br i1 %24, label %25, label %26
25: ; preds = %21, %3
store double 1.000000e+00, double* %8
br label %26
26: ; preds = %25, %21
%27 = load double, double* %4
%28 = load double, double* %8
%29 = fdiv double %27, %28
%30 = getelementptr inbounds [3 x double], [3 x double]* %7, i64 0, i64 0
store double %29, double* %30
%31 = load double, double* %5
%32 = load double, double* %8
%33 = fdiv double %31, %32
%34 = getelementptr inbounds [3 x double], [3 x double]* %7, i64 0, i64 1
store double %33, double* %34
%35 = load double, double* %6
%36 = load double, double* %8
%37 = fdiv double %35, %36
%38 = getelementptr inbounds [3 x double], [3 x double]* %7, i64 0, i64 2
store double %37, double* %38
%39 = getelementptr inbounds [3 x double], [3 x double]* %7, i64 0, i64 0
ret double* %39
}

LLVM IR (-O2):
define noalias double* @unit_fun(double %0, double %1, double %2) {
%4 = alloca [3 x double]
%5 = bitcast [3 x double]* %4 to i8*
%6 = fmul double %1, %1
%7 = tail call double @llvm.fmuladd.f64(double %0, double %0, double %6)
%8 = tail call double @llvm.fmuladd.f64(double %2, double %2, double %7)
%9 = tail call double @sqrt(double %8)
%10 = getelementptr inbounds [3 x double], [3 x double]* %4, i64 0, i64 0
ret double* %10
}