#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 */

/* Variables and functions */
double fabs(double);
double sqrt(double);
double geomean4(double x1, double x2, double x3, double x4) {
  int neg = (x1 < 0) + (x2 < 0) + (x3 < 0) + (x4 < 0);
  x1 *= x2 * x3 * x4;
  if (x1 == 0)
    return 0;
  x1 = sqrt(sqrt(fabs(x1)));
  return (neg <= 2) ? x1 : -x1;
}


x86 assembly (clang, -O0):
<geomean4>:
push   %rbp
mov    %rsp,%rbp
sub    $0x40,%rsp
movsd  %xmm0,-0x10(%rbp)
movsd  %xmm1,-0x18(%rbp)
movsd  %xmm2,-0x20(%rbp)
movsd  %xmm3,-0x28(%rbp)
xorps  %xmm0,%xmm0
ucomisd -0x10(%rbp),%xmm0
seta   %al
and    $0x1,%al
movzbl %al,%eax
xorps  %xmm0,%xmm0
ucomisd -0x18(%rbp),%xmm0
seta   %cl
and    $0x1,%cl
movzbl %cl,%ecx
add    %ecx,%eax
xorps  %xmm0,%xmm0
ucomisd -0x20(%rbp),%xmm0
seta   %cl
and    $0x1,%cl
movzbl %cl,%ecx
add    %ecx,%eax
xorps  %xmm0,%xmm0
ucomisd -0x28(%rbp),%xmm0
seta   %cl
and    $0x1,%cl
movzbl %cl,%ecx
add    %ecx,%eax
mov    %eax,-0x2c(%rbp)
movsd  -0x18(%rbp),%xmm0
mulsd  -0x20(%rbp),%xmm0
mulsd  -0x28(%rbp),%xmm0
mulsd  -0x10(%rbp),%xmm0
movsd  %xmm0,-0x10(%rbp)
movsd  -0x10(%rbp),%xmm0
xorps  %xmm1,%xmm1
ucomisd %xmm1,%xmm0
jne    11b6 <geomean4+0xa6>
jp     11b6 <geomean4+0xa6>
xorps  %xmm0,%xmm0
movsd  %xmm0,-0x8(%rbp)
jmp    1219 <geomean4+0x109>
movsd  -0x10(%rbp),%xmm0
movaps 0xe3e(%rip),%xmm1
pand   %xmm1,%xmm0
call   1030 <sqrt@plt>
call   1030 <sqrt@plt>
movsd  %xmm0,-0x10(%rbp)
cmpl   $0x2,-0x2c(%rbp)
jg     11ee <geomean4+0xde>
movsd  -0x10(%rbp),%xmm0
movsd  %xmm0,-0x38(%rbp)
jmp    120f <geomean4+0xff>
movsd  -0x10(%rbp),%xmm0
movq   %xmm0,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm0
movsd  %xmm0,-0x38(%rbp)
movsd  -0x38(%rbp),%xmm0
movsd  %xmm0,-0x8(%rbp)
movsd  -0x8(%rbp),%xmm0
add    $0x40,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<geomean4>:
movapd %xmm0,%xmm5
movapd %xmm1,%xmm0
mulsd  %xmm2,%xmm0
mulsd  %xmm3,%xmm0
mulsd  %xmm5,%xmm0
xorpd  %xmm4,%xmm4
ucomisd %xmm4,%xmm0
jne    1135 <geomean4+0x25>
jp     1135 <geomean4+0x25>
movapd %xmm4,%xmm0
ret
push   %rbx
unpcklpd %xmm5,%xmm1
unpcklpd %xmm3,%xmm2
xorpd  %xmm3,%xmm3
cmpltpd %xmm3,%xmm2
cmpltpd %xmm3,%xmm1
packssdw %xmm2,%xmm1
movmskps %xmm1,%eax
mov    %eax,%ecx
shr    %cl
and    $0x5,%cl
sub    %cl,%al
mov    %eax,%ecx
and    $0x33,%cl
shr    $0x2,%al
and    $0x33,%al
add    %cl,%al
mov    %eax,%ebx
shr    $0x4,%bl
andpd  0xe8b(%rip),%xmm0
add    %al,%bl
xorps  %xmm1,%xmm1
ucomisd %xmm1,%xmm0
jb     1186 <geomean4+0x76>
sqrtsd %xmm0,%xmm0
jmp    118e <geomean4+0x7e>
call   1030 <sqrt@plt>
xorps  %xmm1,%xmm1
and    $0xf,%bl
ucomisd %xmm1,%xmm0
jb     11a5 <geomean4+0x95>
xorps  %xmm4,%xmm4
sqrtsd %xmm0,%xmm4
cmp    $0x3,%bl
jae    11b3 <geomean4+0xa3>
jmp    11bb <geomean4+0xab>
call   1030 <sqrt@plt>
movapd %xmm0,%xmm4
cmp    $0x3,%bl
jb     11bb <geomean4+0xab>
xorpd  0xe55(%rip),%xmm4
pop    %rbx
movapd %xmm4,%xmm0
ret

LLVM IR (-O0):
define double @geomean4(double %0, double %1, double %2, double %3) {
%5 = alloca double
%6 = alloca double
%7 = alloca double
%8 = alloca double
%9 = alloca double
%10 = alloca i32
store double %0, double* %6
store double %1, double* %7
store double %2, double* %8
store double %3, double* %9
%11 = load double, double* %6
%12 = fcmp olt double %11, 0.000000e+00
%13 = zext i1 %12 to i32
%14 = load double, double* %7
%15 = fcmp olt double %14, 0.000000e+00
%16 = zext i1 %15 to i32
%17 = add nsw i32 %13, %16
%18 = load double, double* %8
%19 = fcmp olt double %18, 0.000000e+00
%20 = zext i1 %19 to i32
%21 = add nsw i32 %17, %20
%22 = load double, double* %9
%23 = fcmp olt double %22, 0.000000e+00
%24 = zext i1 %23 to i32
%25 = add nsw i32 %21, %24
store i32 %25, i32* %10
%26 = load double, double* %7
%27 = load double, double* %8
%28 = fmul double %26, %27
%29 = load double, double* %9
%30 = fmul double %28, %29
%31 = load double, double* %6
%32 = fmul double %31, %30
store double %32, double* %6
%33 = load double, double* %6
%34 = fcmp oeq double %33, 0.000000e+00
br i1 %34, label %35, label %36
35: ; preds = %4
store double 0.000000e+00, double* %5
br label %50
36: ; preds = %4
%37 = load double, double* %6
%38 = call double @llvm.fabs.f64(double %37)
%39 = call double @sqrt(double %38)
%40 = call double @sqrt(double %39)
store double %40, double* %6
%41 = load i32, i32* %10
%42 = icmp sle i32 %41, 2
br i1 %42, label %43, label %45
43: ; preds = %36
%44 = load double, double* %6
br label %48
45: ; preds = %36
%46 = load double, double* %6
%47 = fneg double %46
br label %48
48: ; preds = %45, %43
%49 = phi double [ %44, %43 ], [ %47, %45 ]
store double %49, double* %5
br label %50
50: ; preds = %48, %35
%51 = load double, double* %5
ret double %51
}

LLVM IR (-O2):
define double @geomean4(double %0, double %1, double %2, double %3) {
%5 = fmul double %1, %2
%6 = fmul double %5, %3
%7 = fmul double %6, %0
%8 = fcmp oeq double %7, 0.000000e+00
br i1 %8, label %23, label %9
9: ; preds = %4
%10 = insertelement <4 x double> poison, double %1, i64 0
%11 = insertelement <4 x double> %10, double %0, i64 1
%12 = insertelement <4 x double> %11, double %2, i64 2
%13 = insertelement <4 x double> %12, double %3, i64 3
%14 = fcmp olt <4 x double> %13, zeroinitializer
%15 = bitcast <4 x i1> %14 to i4
%16 = call i4 @llvm.ctpop.i4(i4 %15)
%17 = tail call double @llvm.fabs.f64(double %7)
%18 = tail call double @sqrt(double %17)
%19 = tail call double @sqrt(double %18)
%20 = icmp ult i4 %16, 3
%21 = fneg double %19
%22 = select i1 %20, double %19, double %21
br label %23
23: ; preds = %4, %9
%24 = phi double [ %22, %9 ], [ 0.000000e+00, %4 ]
ret double %24
}