#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 */
typedef int /*<<< orphan*/ __m128;

/* Variables and functions */
float FAST_ACOS(float);
float acosf(float const);
__m128 inv_cosine_sse(const __m128 X, const int order) {
  union cos {
    __m128 m;
    float x[4];
  };
  union cos union_costheta;
  union cos union_returnvalue;
  union_costheta.m = X;
  const float minus_one = (float)-1.0;
  const float one = (float)1.0;
  for (int ii = 0; ii < 4; ii++) {
    const float costheta = union_costheta.x[ii];
    union_costheta.x[ii] = costheta <= minus_one ? minus_one : costheta;
    union_costheta.x[ii] = costheta >= one ? one : costheta;
  }
  if (order == 0) {
    for (int ii = 0; ii < 4; ii++) {
      const float costheta = union_costheta.x[ii];
      union_returnvalue.x[ii] = acosf(costheta);
    }
  } else {
    for (int ii = 0; ii < 4; ii++) {
      union_returnvalue.x[ii] = FAST_ACOS(union_costheta.x[ii]);
    }
  }
  return union_returnvalue.m;
}


x86 assembly (clang, -O0):
<inv_cosine_sse>:
push   %rbp
mov    %rsp,%rbp
sub    $0x50,%rsp
mov    %edi,-0x4(%rbp)
mov    %esi,-0x8(%rbp)
mov    -0x4(%rbp),%eax
mov    %eax,-0x18(%rbp)
movss  0xec8(%rip),%xmm0
movss  %xmm0,-0x2c(%rbp)
movss  0xeb7(%rip),%xmm0
movss  %xmm0,-0x30(%rbp)
movl   $0x0,-0x34(%rbp)
cmpl   $0x4,-0x34(%rbp)
jge    11fa <inv_cosine_sse+0xda>
movslq -0x34(%rbp),%rax
movss  -0x18(%rbp,%rax,4),%xmm0
movss  %xmm0,-0x38(%rbp)
movss  0xe8e(%rip),%xmm0
ucomiss -0x38(%rbp),%xmm0
jb     1192 <inv_cosine_sse+0x72>
movss  0xe7c(%rip),%xmm0
movss  %xmm0,-0x48(%rbp)
jmp    119c <inv_cosine_sse+0x7c>
movss  -0x38(%rbp),%xmm0
movss  %xmm0,-0x48(%rbp)
movss  -0x48(%rbp),%xmm0
movslq -0x34(%rbp),%rax
movss  %xmm0,-0x18(%rbp,%rax,4)
movss  -0x38(%rbp),%xmm0
movss  0xe48(%rip),%xmm1
ucomiss %xmm1,%xmm0
jb     11d3 <inv_cosine_sse+0xb3>
movss  0xe37(%rip),%xmm0
movss  %xmm0,-0x4c(%rbp)
jmp    11dd <inv_cosine_sse+0xbd>
movss  -0x38(%rbp),%xmm0
movss  %xmm0,-0x4c(%rbp)
movss  -0x4c(%rbp),%xmm0
movslq -0x34(%rbp),%rax
movss  %xmm0,-0x18(%rbp,%rax,4)
mov    -0x34(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x34(%rbp)
jmp    1155 <inv_cosine_sse+0x35>
cmpl   $0x0,-0x8(%rbp)
jne    124b <inv_cosine_sse+0x12b>
movl   $0x0,-0x3c(%rbp)
cmpl   $0x4,-0x3c(%rbp)
jge    1246 <inv_cosine_sse+0x126>
movslq -0x3c(%rbp),%rax
movss  -0x18(%rbp,%rax,4),%xmm0
movss  %xmm0,-0x40(%rbp)
movss  -0x40(%rbp),%xmm0
call   1030 <acosf@plt>
movslq -0x3c(%rbp),%rax
movss  %xmm0,-0x28(%rbp,%rax,4)
mov    -0x3c(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x3c(%rbp)
jmp    120b <inv_cosine_sse+0xeb>
jmp    1288 <inv_cosine_sse+0x168>
movl   $0x0,-0x44(%rbp)
cmpl   $0x4,-0x44(%rbp)
jge    1283 <inv_cosine_sse+0x163>
movslq -0x44(%rbp),%rax
movss  -0x18(%rbp,%rax,4),%xmm0
call   1040 <FAST_ACOS@plt>
movslq -0x44(%rbp),%rax
movss  %xmm0,-0x28(%rbp,%rax,4)
mov    -0x44(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x44(%rbp)
jmp    1252 <inv_cosine_sse+0x132>
jmp    1288 <inv_cosine_sse+0x168>
mov    -0x28(%rbp),%eax
add    $0x50,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<inv_cosine_sse>:
push   %rax
movd   %edi,%xmm1
movss  0xed3(%rip),%xmm0
minss  %xmm1,%xmm0
test   %esi,%esi
je     1151 <inv_cosine_sse+0x31>
call   1040 <FAST_ACOS@plt>
movss  %xmm0,0x4(%rsp)
call   1040 <FAST_ACOS@plt>
call   1040 <FAST_ACOS@plt>
call   1040 <FAST_ACOS@plt>
jmp    116b <inv_cosine_sse+0x4b>
call   1030 <acosf@plt>
movss  %xmm0,0x4(%rsp)
call   1030 <acosf@plt>
call   1030 <acosf@plt>
call   1030 <acosf@plt>
movd   0x4(%rsp),%xmm0
movd   %xmm0,%eax
pop    %rcx
ret

LLVM IR (-O0):
%union.cos = type { [4 x float] }
define i32 @inv_cosine_sse(i32 %0, i32 %1) {
%3 = alloca i32
%4 = alloca i32
%5 = alloca %union.cos
%6 = alloca %union.cos
%7 = alloca float
%8 = alloca float
%9 = alloca i32
%10 = alloca float
%11 = alloca i32
%12 = alloca float
%13 = alloca i32
store i32 %0, i32* %3
store i32 %1, i32* %4
%14 = load i32, i32* %3
%15 = bitcast %union.cos* %5 to i32*
store i32 %14, i32* %15
store float -1.000000e+00, float* %7
store float 1.000000e+00, float* %8
store i32 0, i32* %9
br label %16
16: ; preds = %47, %2
%17 = load i32, i32* %9
%18 = icmp slt i32 %17, 4
br i1 %18, label %19, label %50
19: ; preds = %16
%20 = bitcast %union.cos* %5 to [4 x float]*
%21 = load i32, i32* %9
%22 = sext i32 %21 to i64
%23 = getelementptr inbounds [4 x float], [4 x float]* %20, i64 0, i64 %22
%24 = load float, float* %23
store float %24, float* %10
%25 = load float, float* %10
%26 = fcmp ole float %25, -1.000000e+00
br i1 %26, label %27, label %28
27: ; preds = %19
br label %30
28: ; preds = %19
%29 = load float, float* %10
br label %30
30: ; preds = %28, %27
%31 = phi float [ -1.000000e+00, %27 ], [ %29, %28 ]
%32 = bitcast %union.cos* %5 to [4 x float]*
%33 = load i32, i32* %9
%34 = sext i32 %33 to i64
%35 = getelementptr inbounds [4 x float], [4 x float]* %32, i64 0, i64 %34
store float %31, float* %35
%36 = load float, float* %10
%37 = fcmp oge float %36, 1.000000e+00
br i1 %37, label %38, label %39
38: ; preds = %30
br label %41
39: ; preds = %30
%40 = load float, float* %10
br label %41
41: ; preds = %39, %38
%42 = phi float [ 1.000000e+00, %38 ], [ %40, %39 ]
%43 = bitcast %union.cos* %5 to [4 x float]*
%44 = load i32, i32* %9
%45 = sext i32 %44 to i64
%46 = getelementptr inbounds [4 x float], [4 x float]* %43, i64 0, i64 %45
store float %42, float* %46
br label %47
47: ; preds = %41
%48 = load i32, i32* %9
%49 = add nsw i32 %48, 1
store i32 %49, i32* %9
br label %16
50: ; preds = %16
%51 = load i32, i32* %4
%52 = icmp eq i32 %51, 0
br i1 %52, label %53, label %73
53: ; preds = %50
store i32 0, i32* %11
br label %54
54: ; preds = %69, %53
%55 = load i32, i32* %11
%56 = icmp slt i32 %55, 4
br i1 %56, label %57, label %72
57: ; preds = %54
%58 = bitcast %union.cos* %5 to [4 x float]*
%59 = load i32, i32* %11
%60 = sext i32 %59 to i64
%61 = getelementptr inbounds [4 x float], [4 x float]* %58, i64 0, i64 %60
%62 = load float, float* %61
store float %62, float* %12
%63 = load float, float* %12
%64 = call float @acosf(float %63)
%65 = bitcast %union.cos* %6 to [4 x float]*
%66 = load i32, i32* %11
%67 = sext i32 %66 to i64
%68 = getelementptr inbounds [4 x float], [4 x float]* %65, i64 0, i64 %67
store float %64, float* %68
br label %69
69: ; preds = %57
%70 = load i32, i32* %11
%71 = add nsw i32 %70, 1
store i32 %71, i32* %11
br label %54
72: ; preds = %54
br label %92
73: ; preds = %50
store i32 0, i32* %13
br label %74
74: ; preds = %88, %73
%75 = load i32, i32* %13
%76 = icmp slt i32 %75, 4
br i1 %76, label %77, label %91
77: ; preds = %74
%78 = bitcast %union.cos* %5 to [4 x float]*
%79 = load i32, i32* %13
%80 = sext i32 %79 to i64
%81 = getelementptr inbounds [4 x float], [4 x float]* %78, i64 0, i64 %80
%82 = load float, float* %81
%83 = call float @FAST_ACOS(float %82)
%84 = bitcast %union.cos* %6 to [4 x float]*
%85 = load i32, i32* %13
%86 = sext i32 %85 to i64
%87 = getelementptr inbounds [4 x float], [4 x float]* %84, i64 0, i64 %86
store float %83, float* %87
br label %88
88: ; preds = %77
%89 = load i32, i32* %13
%90 = add nsw i32 %89, 1
store i32 %90, i32* %13
br label %74
91: ; preds = %74
br label %92
92: ; preds = %91, %72
%93 = bitcast %union.cos* %6 to i32*
%94 = load i32, i32* %93
ret i32 %94
}

LLVM IR (-O2):
define i32 @inv_cosine_sse(i32 %0, i32 %1) {
%3 = bitcast i32 %0 to float
%4 = fcmp oge float %3, 1.000000e+00
%5 = select i1 %4, float 1.000000e+00, float %3
%6 = icmp eq i32 %1, 0
br i1 %6, label %12, label %7
7: ; preds = %2
%8 = tail call float @FAST_ACOS(float %5)
%9 = tail call float @FAST_ACOS(float undef)
%10 = tail call float @FAST_ACOS(float undef)
%11 = tail call float @FAST_ACOS(float undef)
br label %17
12: ; preds = %2
%13 = tail call float @acosf(float %5)
%14 = tail call float @acosf(float undef)
%15 = tail call float @acosf(float undef)
%16 = tail call float @acosf(float undef)
br label %17
17: ; preds = %7, %12
%18 = phi float [ %13, %12 ], [ %8, %7 ]
%19 = bitcast float %18 to i32
ret i32 %19
}