int main() {
  volatile float fPos = 1.f;
  volatile float fNeg = -2.f;
  if (__builtin_copysign(fPos, fNeg) != -1.f) {
    return 1;
  }
  if (__builtin_copysign(fNeg, fPos) != 2.f) {
    return 1;
  }
  volatile double dPos = 1.;
  volatile double dNeg = -2.;
  if (__builtin_copysign(dPos, dNeg) != -1.) {
    return 1;
  }
  if (__builtin_copysign(dNeg, dPos) != 2.) {
    return 1;
  }
  volatile long double lPos = 1.;
  volatile long double lNeg = -2.;
  if (__builtin_copysign(lPos, lNeg) != -1.) {
    return 1;
  }
  if (__builtin_copysign(lNeg, lPos) != 2.) {
    return 1;
  }
  return 0;
}


x86 assembly (clang, -O0):
<main>:
push   %rbp
mov    %rsp,%rbp
movl   $0x0,-0x4(%rbp)
movss  0xf31(%rip),%xmm0
movss  %xmm0,-0x8(%rbp)
movss  0xf20(%rip),%xmm0
movss  %xmm0,-0xc(%rbp)
movss  -0x8(%rbp),%xmm0
cvtss2sd %xmm0,%xmm0
movss  -0xc(%rbp),%xmm1
cvtss2sd %xmm1,%xmm1
movaps 0xee2(%rip),%xmm2
pand   %xmm2,%xmm1
movaps 0xee7(%rip),%xmm2
pand   %xmm2,%xmm0
por    %xmm1,%xmm0
movsd  0xea7(%rip),%xmm1
ucomisd %xmm1,%xmm0
jne    116e <main+0x6e>
jp     116e <main+0x6e>
jmp    117a <main+0x7a>
movl   $0x1,-0x4(%rbp)
jmp    134a <main+0x24a>
movss  -0xc(%rbp),%xmm0
cvtss2sd %xmm0,%xmm0
movss  -0x8(%rbp),%xmm1
cvtss2sd %xmm1,%xmm1
movaps 0xe8d(%rip),%xmm2
pand   %xmm2,%xmm1
movaps 0xe92(%rip),%xmm2
pand   %xmm2,%xmm0
por    %xmm1,%xmm0
movsd  0xe5a(%rip),%xmm1
ucomisd %xmm1,%xmm0
jne    11c3 <main+0xc3>
jp     11c3 <main+0xc3>
jmp    11cf <main+0xcf>
movl   $0x1,-0x4(%rbp)
jmp    134a <main+0x24a>
movsd  0xe41(%rip),%xmm0
movsd  %xmm0,-0x18(%rbp)
movsd  0xe2c(%rip),%xmm0
movsd  %xmm0,-0x20(%rbp)
movsd  -0x18(%rbp),%xmm0
movsd  -0x20(%rbp),%xmm1
movaps 0xe26(%rip),%xmm2
pand   %xmm2,%xmm1
movaps 0xe2b(%rip),%xmm2
pand   %xmm2,%xmm0
por    %xmm1,%xmm0
movsd  0xdeb(%rip),%xmm1
ucomisd %xmm1,%xmm0
jne    122a <main+0x12a>
jp     122a <main+0x12a>
jmp    1236 <main+0x136>
movl   $0x1,-0x4(%rbp)
jmp    134a <main+0x24a>
movsd  -0x20(%rbp),%xmm0
movsd  -0x18(%rbp),%xmm1
movaps 0xdd9(%rip),%xmm2
pand   %xmm2,%xmm1
movaps 0xdde(%rip),%xmm2
pand   %xmm2,%xmm0
por    %xmm1,%xmm0
movsd  0xda6(%rip),%xmm1
ucomisd %xmm1,%xmm0
jne    1277 <main+0x177>
jp     1277 <main+0x177>
jmp    1283 <main+0x183>
movl   $0x1,-0x4(%rbp)
jmp    134a <main+0x24a>
fld1
fstpt  -0x30(%rbp)
flds   0xdb2(%rip)
fstpt  -0x40(%rbp)
fldt   -0x30(%rbp)
fstpl  -0x48(%rbp)
movsd  -0x48(%rbp),%xmm0
fldt   -0x40(%rbp)
fstpl  -0x50(%rbp)
movsd  -0x50(%rbp),%xmm1
movaps 0xd72(%rip),%xmm2
pand   %xmm2,%xmm1
movaps 0xd77(%rip),%xmm2
pand   %xmm2,%xmm0
por    %xmm1,%xmm0
movsd  0xd37(%rip),%xmm1
ucomisd %xmm1,%xmm0
jne    12de <main+0x1de>
jp     12de <main+0x1de>
jmp    12ea <main+0x1ea>
movl   $0x1,-0x4(%rbp)
jmp    134a <main+0x24a>
fldt   -0x40(%rbp)
fstpl  -0x58(%rbp)
movsd  -0x58(%rbp),%xmm0
fldt   -0x30(%rbp)
fstpl  -0x60(%rbp)
movsd  -0x60(%rbp),%xmm1
movaps 0xd19(%rip),%xmm2
pand   %xmm2,%xmm1
movaps 0xd1e(%rip),%xmm2
pand   %xmm2,%xmm0
por    %xmm1,%xmm0
movsd  0xce6(%rip),%xmm1
ucomisd %xmm1,%xmm0
jne    1337 <main+0x237>
jp     1337 <main+0x237>
jmp    1343 <main+0x243>
movl   $0x1,-0x4(%rbp)
jmp    134a <main+0x24a>
movl   $0x0,-0x4(%rbp)
mov    -0x4(%rbp),%eax
pop    %rbp
ret

x86 assembly (clang, -O2):
<main>:
movl   $0x3f800000,-0x5c(%rsp)
3f
movl   $0xc0000000,-0x60(%rsp)
c0
movss  -0x5c(%rsp),%xmm0
cvtss2sd %xmm0,%xmm0
movss  -0x60(%rsp),%xmm1
andps  0xed9(%rip),%xmm0
cvtss2sd %xmm1,%xmm1
andps  0xede(%rip),%xmm1
orps   %xmm0,%xmm1
mov    $0x1,%eax
ucomisd 0xede(%rip),%xmm1
jne    1146 <main+0x46>
jnp    1147 <main+0x47>
ret
movss  -0x60(%rsp),%xmm0
cvtss2sd %xmm0,%xmm0
andps  0xea8(%rip),%xmm0
movss  -0x5c(%rsp),%xmm1
cvtss2sd %xmm1,%xmm1
andps  0xea7(%rip),%xmm1
orps   %xmm0,%xmm1
ucomisd 0xeb4(%rip),%xmm1
jne    1146 <main+0x46>
jp     1146 <main+0x46>
movabs $0x3ff0000000000000,%rax
mov    %rax,-0x50(%rsp)
movabs $0xc000000000000000,%rax
mov    %rax,-0x58(%rsp)
movsd  -0x50(%rsp),%xmm0
andpd  0xe5c(%rip),%xmm0
movsd  -0x58(%rsp),%xmm1
andpd  0xe5e(%rip),%xmm1
orpd   %xmm0,%xmm1
mov    $0x1,%eax
ucomisd 0xe5d(%rip),%xmm1
jne    1146 <main+0x46>
jp     1146 <main+0x46>
movsd  -0x58(%rsp),%xmm0
andpd  0xe27(%rip),%xmm0
movsd  -0x50(%rsp),%xmm1
andpd  0xe29(%rip),%xmm1
orpd   %xmm0,%xmm1
ucomisd 0xe35(%rip),%xmm1
jne    1146 <main+0x46>
jp     1146 <main+0x46>
fld1
fstpt  -0x18(%rsp)
flds   0xe25(%rip)
fstpt  -0x28(%rsp)
fldt   -0x18(%rsp)
fstpl  -0x30(%rsp)
fldt   -0x28(%rsp)
fstpl  -0x38(%rsp)
movsd  -0x30(%rsp),%xmm0
andpd  0xdd3(%rip),%xmm0
movsd  -0x38(%rsp),%xmm1
andpd  0xdd5(%rip),%xmm1
orpd   %xmm0,%xmm1
mov    $0x1,%eax
ucomisd 0xdd4(%rip),%xmm1
jne    1146 <main+0x46>
jp     1146 <main+0x46>
fldt   -0x28(%rsp)
fstpl  -0x40(%rsp)
fldt   -0x18(%rsp)
fstpl  -0x48(%rsp)
movsd  -0x40(%rsp),%xmm0
andpd  0xd8a(%rip),%xmm0
movsd  -0x48(%rsp),%xmm1
andpd  0xd8c(%rip),%xmm1
orpd   %xmm0,%xmm1
cmpneqsd 0xd97(%rip),%xmm1
movq   %xmm1,%rax
and    $0x1,%eax
ret

LLVM IR (-O0):
define i32 @main() {
%1 = alloca i32
%2 = alloca float
%3 = alloca float
%4 = alloca double
%5 = alloca double
%6 = alloca x86_fp80
%7 = alloca x86_fp80
store i32 0, i32* %1
store volatile float 1.000000e+00, float* %2
store volatile float -2.000000e+00, float* %3
%8 = load volatile float, float* %2
%9 = fpext float %8 to double
%10 = load volatile float, float* %3
%11 = fpext float %10 to double
%12 = call double @llvm.copysign.f64(double %9, double %11)
%13 = fcmp une double %12, -1.000000e+00
br i1 %13, label %14, label %15
14: ; preds = %0
store i32 1, i32* %1
br label %52
15: ; preds = %0
%16 = load volatile float, float* %3
%17 = fpext float %16 to double
%18 = load volatile float, float* %2
%19 = fpext float %18 to double
%20 = call double @llvm.copysign.f64(double %17, double %19)
%21 = fcmp une double %20, 2.000000e+00
br i1 %21, label %22, label %23
22: ; preds = %15
store i32 1, i32* %1
br label %52
23: ; preds = %15
store volatile double 1.000000e+00, double* %4
store volatile double -2.000000e+00, double* %5
%24 = load volatile double, double* %4
%25 = load volatile double, double* %5
%26 = call double @llvm.copysign.f64(double %24, double %25)
%27 = fcmp une double %26, -1.000000e+00
br i1 %27, label %28, label %29
28: ; preds = %23
store i32 1, i32* %1
br label %52
29: ; preds = %23
%30 = load volatile double, double* %5
%31 = load volatile double, double* %4
%32 = call double @llvm.copysign.f64(double %30, double %31)
%33 = fcmp une double %32, 2.000000e+00
br i1 %33, label %34, label %35
34: ; preds = %29
store i32 1, i32* %1
br label %52
35: ; preds = %29
store volatile x86_fp80 0xK3FFF8000000000000000, x86_fp80* %6
store volatile x86_fp80 0xKC0008000000000000000, x86_fp80* %7
%36 = load volatile x86_fp80, x86_fp80* %6
%37 = fptrunc x86_fp80 %36 to double
%38 = load volatile x86_fp80, x86_fp80* %7
%39 = fptrunc x86_fp80 %38 to double
%40 = call double @llvm.copysign.f64(double %37, double %39)
%41 = fcmp une double %40, -1.000000e+00
br i1 %41, label %42, label %43
42: ; preds = %35
store i32 1, i32* %1
br label %52
43: ; preds = %35
%44 = load volatile x86_fp80, x86_fp80* %7
%45 = fptrunc x86_fp80 %44 to double
%46 = load volatile x86_fp80, x86_fp80* %6
%47 = fptrunc x86_fp80 %46 to double
%48 = call double @llvm.copysign.f64(double %45, double %47)
%49 = fcmp une double %48, 2.000000e+00
br i1 %49, label %50, label %51
50: ; preds = %43
store i32 1, i32* %1
br label %52
51: ; preds = %43
store i32 0, i32* %1
br label %52
52: ; preds = %51, %50, %42, %34, %28, %22, %14
%53 = load i32, i32* %1
ret i32 %53
}

LLVM IR (-O2):
define i32 @main() {
%1 = alloca float
%2 = alloca float
%3 = alloca double
%4 = alloca double
%5 = alloca x86_fp80
%6 = alloca x86_fp80
%7 = bitcast float* %1 to i8*
store volatile float 1.000000e+00, float* %1
%8 = bitcast float* %2 to i8*
store volatile float -2.000000e+00, float* %2
%9 = load volatile float, float* %1
%10 = fpext float %9 to double
%11 = load volatile float, float* %2
%12 = fpext float %11 to double
%13 = tail call double @llvm.copysign.f64(double %10, double %12)
%14 = fcmp une double %13, -1.000000e+00
br i1 %14, label %55, label %15
15: ; preds = %0
%16 = load volatile float, float* %2
%17 = fpext float %16 to double
%18 = load volatile float, float* %1
%19 = fpext float %18 to double
%20 = tail call double @llvm.copysign.f64(double %17, double %19)
%21 = fcmp une double %20, 2.000000e+00
br i1 %21, label %55, label %22
22: ; preds = %15
%23 = bitcast double* %3 to i8*
store volatile double 1.000000e+00, double* %3
%24 = bitcast double* %4 to i8*
store volatile double -2.000000e+00, double* %4
%25 = load volatile double, double* %3
%26 = load volatile double, double* %4
%27 = tail call double @llvm.copysign.f64(double %25, double %26)
%28 = fcmp une double %27, -1.000000e+00
br i1 %28, label %53, label %29
29: ; preds = %22
%30 = load volatile double, double* %4
%31 = load volatile double, double* %3
%32 = tail call double @llvm.copysign.f64(double %30, double %31)
%33 = fcmp une double %32, 2.000000e+00
br i1 %33, label %53, label %34
34: ; preds = %29
%35 = bitcast x86_fp80* %5 to i8*
store volatile x86_fp80 0xK3FFF8000000000000000, x86_fp80* %5
%36 = bitcast x86_fp80* %6 to i8*
store volatile x86_fp80 0xKC0008000000000000000, x86_fp80* %6
%37 = load volatile x86_fp80, x86_fp80* %5
%38 = fptrunc x86_fp80 %37 to double
%39 = load volatile x86_fp80, x86_fp80* %6
%40 = fptrunc x86_fp80 %39 to double
%41 = tail call double @llvm.copysign.f64(double %38, double %40)
%42 = fcmp une double %41, -1.000000e+00
br i1 %42, label %51, label %43
43: ; preds = %34
%44 = load volatile x86_fp80, x86_fp80* %6
%45 = fptrunc x86_fp80 %44 to double
%46 = load volatile x86_fp80, x86_fp80* %5
%47 = fptrunc x86_fp80 %46 to double
%48 = tail call double @llvm.copysign.f64(double %45, double %47)
%49 = fcmp une double %48, 2.000000e+00
%50 = zext i1 %49 to i32
br label %51
51: ; preds = %43, %34
%52 = phi i32 [ 1, %34 ], [ %50, %43 ]
br label %53
53: ; preds = %29, %22, %51
%54 = phi i32 [ %52, %51 ], [ 1, %22 ], [ 1, %29 ]
br label %55
55: ; preds = %15, %0, %53
%56 = phi i32 [ %54, %53 ], [ 1, %0 ], [ 1, %15 ]
ret i32 %56
}