#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 */
int /*<<< orphan*/ bernstein2(double *, double);
float *memcpy(float *, float const *, int);
float *bezier2(float *dest, size_t d, float const *p, double t) {
  double c[3];
  float const *p0, *p1, *p2;
  size_t i;
  if (t <= 0.0) {
    return memcpy(dest, p, sizeof(float) * d);
  }
  if (t >= 1.0) {
    return memcpy(dest, p + 2 * d, sizeof(float) * d);
  }
  p0 = p;
  p1 = p0 + d;
  p2 = p1 + d;
  bernstein2(c, t);
  for (i = 0; i < d; i++) {
    dest[i] = c[0] * p0[i] + c[1] * p1[i] + c[2] * p2[i];
  }
  return dest;
}


x86 assembly (clang, -O0):
<bezier2>:
push   %rbp
mov    %rsp,%rbp
sub    $0x60,%rsp
mov    %rdi,-0x10(%rbp)
mov    %rsi,-0x18(%rbp)
mov    %rdx,-0x20(%rbp)
movsd  %xmm0,-0x28(%rbp)
xorps  %xmm0,%xmm0
ucomisd -0x28(%rbp),%xmm0
jb     1167 <bezier2+0x47>
mov    -0x10(%rbp),%rdi
mov    -0x20(%rbp),%rsi
mov    -0x18(%rbp),%rax
shl    $0x2,%rax
mov    %eax,%edx
call   1030 <memcpy@plt>
mov    %rax,-0x8(%rbp)
jmp    127f <bezier2+0x15f>
movsd  -0x28(%rbp),%xmm0
movsd  0xe8c(%rip),%xmm1
ucomisd %xmm1,%xmm0
jb     11ad <bezier2+0x8d>
mov    -0x10(%rbp),%rdi
mov    -0x20(%rbp),%rsi
mov    -0x18(%rbp),%rax
shl    $0x1,%rax
shl    $0x2,%rax
add    %rax,%rsi
mov    -0x18(%rbp),%rax
shl    $0x2,%rax
mov    %eax,%edx
call   1030 <memcpy@plt>
mov    %rax,-0x8(%rbp)
jmp    127f <bezier2+0x15f>
mov    -0x20(%rbp),%rax
mov    %rax,-0x48(%rbp)
mov    -0x48(%rbp),%rax
mov    -0x18(%rbp),%rcx
shl    $0x2,%rcx
add    %rcx,%rax
mov    %rax,-0x50(%rbp)
mov    -0x50(%rbp),%rax
mov    -0x18(%rbp),%rcx
shl    $0x2,%rcx
add    %rcx,%rax
mov    %rax,-0x58(%rbp)
lea    -0x40(%rbp),%rdi
movsd  -0x28(%rbp),%xmm0
call   1040 <bernstein2@plt>
movq   $0x0,-0x60(%rbp)
mov    -0x60(%rbp),%rax
cmp    -0x18(%rbp),%rax
jae    1277 <bezier2+0x157>
movsd  -0x40(%rbp),%xmm1
mov    -0x48(%rbp),%rax
mov    -0x60(%rbp),%rcx
movss  (%rax,%rcx,4),%xmm0
cvtss2sd %xmm0,%xmm2
movsd  -0x38(%rbp),%xmm0
mov    -0x50(%rbp),%rax
mov    -0x60(%rbp),%rcx
movss  (%rax,%rcx,4),%xmm3
cvtss2sd %xmm3,%xmm3
mulsd  %xmm3,%xmm0
mulsd  %xmm2,%xmm1
addsd  %xmm0,%xmm1
movsd  -0x30(%rbp),%xmm0
mov    -0x58(%rbp),%rax
mov    -0x60(%rbp),%rcx
movss  (%rax,%rcx,4),%xmm2
cvtss2sd %xmm2,%xmm2
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
cvtsd2ss %xmm0,%xmm0
mov    -0x10(%rbp),%rax
mov    -0x60(%rbp),%rcx
movss  %xmm0,(%rax,%rcx,4)
mov    -0x60(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x60(%rbp)
jmp    11f1 <bezier2+0xd1>
mov    -0x10(%rbp),%rax
mov    %rax,-0x8(%rbp)
mov    -0x8(%rbp),%rax
add    $0x60,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<bezier2>:
push   %r15
push   %r14
push   %rbx
sub    $0x20,%rsp
mov    %rdx,%r14
mov    %rsi,%rbx
mov    %rdi,%r15
xorpd  %xmm1,%xmm1
ucomisd %xmm0,%xmm1
jae    1183 <bezier2+0x63>
ucomisd 0xebc(%rip),%xmm0
jae    117f <bezier2+0x5f>
mov    %rsp,%rdi
call   1040 <bernstein2@plt>
test   %rbx,%rbx
je     12d8 <bezier2+0x1b8>
lea    (%r14,%rbx,4),%rax
lea    (%rax,%rbx,4),%rcx
movsd  (%rsp),%xmm8
movsd  0x8(%rsp),%xmm9
movsd  0x10(%rsp),%xmm2
cmp    $0x4,%rbx
jae    119c <bezier2+0x7c>
xor    %edx,%edx
jmp    1290 <bezier2+0x170>
lea    (%r14,%rbx,8),%r14
shl    $0x2,%ebx
mov    %r15,%rdi
mov    %r14,%rsi
mov    %ebx,%edx
add    $0x20,%rsp
pop    %rbx
pop    %r14
pop    %r15
jmp    1030 <memcpy@plt>
lea    (%rbx,%rbx,2),%rdx
lea    (%r14,%rdx,4),%rdx
cmp    %r15,%rdx
seta   %r10b
cmp    %r15,%rcx
seta   %sil
lea    (%r15,%rbx,4),%rdx
cmp    %r15,%r14
setb   %r8b
cmp    %r15,%rax
setb   %r11b
seta   %dil
cmp    %r14,%rdx
seta   %r9b
xor    %edx,%edx
test   %r11b,%r10b
jne    1290 <bezier2+0x170>
and    %r8b,%sil
jne    1290 <bezier2+0x170>
and    %r9b,%dil
jne    1290 <bezier2+0x170>
mov    %rbx,%rdx
and    $0xfffffffffffffffc,%rdx
movapd %xmm9,%xmm3
unpcklpd %xmm9,%xmm3
movapd %xmm8,%xmm4
unpcklpd %xmm8,%xmm4
movapd %xmm2,%xmm5
unpcklpd %xmm2,%xmm5
xor    %esi,%esi
mov    %r14,%rdi
cs nopw 0x0(%rax,%rax,1)
xchg   %ax,%ax
cvtps2pd (%rdi),%xmm6
cvtps2pd 0x8(%rdi),%xmm7
cvtps2pd 0x8(%rdi,%rbx,4),%xmm0
cvtps2pd (%rdi,%rbx,4),%xmm1
mulpd  %xmm3,%xmm1
mulpd  %xmm3,%xmm0
mulpd  %xmm4,%xmm7
addpd  %xmm0,%xmm7
mulpd  %xmm4,%xmm6
cvtps2pd 0x8(%rdi,%rbx,8),%xmm0
addpd  %xmm1,%xmm6
cvtps2pd (%rdi,%rbx,8),%xmm1
mulpd  %xmm5,%xmm1
mulpd  %xmm5,%xmm0
addpd  %xmm7,%xmm0
cvtpd2ps %xmm0,%xmm0
addpd  %xmm6,%xmm1
cvtpd2ps %xmm1,%xmm1
unpcklpd %xmm0,%xmm1
movupd %xmm1,(%r15,%rsi,4)
add    $0x4,%rsi
add    $0x10,%rdi
cmp    %rsi,%rdx
jne    1220 <bezier2+0x100>
cmp    %rbx,%rdx
je     12d8 <bezier2+0x1b8>
cs nopw 0x0(%rax,%rax,1)
nop
movss  (%r14,%rdx,4),%xmm0
cvtss2sd %xmm0,%xmm0
movss  (%rax,%rdx,4),%xmm1
cvtss2sd %xmm1,%xmm1
mulsd  %xmm9,%xmm1
mulsd  %xmm8,%xmm0
addsd  %xmm1,%xmm0
movss  (%rcx,%rdx,4),%xmm1
cvtss2sd %xmm1,%xmm1
mulsd  %xmm2,%xmm1
addsd  %xmm0,%xmm1
xorps  %xmm0,%xmm0
cvtsd2ss %xmm1,%xmm0
movss  %xmm0,(%r15,%rdx,4)
add    $0x1,%rdx
cmp    %rdx,%rbx
jne    1290 <bezier2+0x170>
mov    %r15,%rax
add    $0x20,%rsp
pop    %rbx
pop    %r14
pop    %r15
ret

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

LLVM IR (-O2):
define float* @bezier2(float* %0, i64 %1, float* %2, double %3) {
%5 = alloca [3 x double]
%6 = bitcast [3 x double]* %5 to i8*
%7 = fcmp ugt double %3, 0.000000e+00
br i1 %7, label %8, label %93
8: ; preds = %4
%9 = fcmp ult double %3, 1.000000e+00
br i1 %9, label %13, label %10
10: ; preds = %8
%11 = shl i64 %1, 1
%12 = getelementptr inbounds float, float* %2, i64 %11
br label %93
13: ; preds = %8
%14 = getelementptr float, float* %2, i64 %1
%15 = getelementptr float, float* %14, i64 %1
%16 = getelementptr inbounds [3 x double], [3 x double]* %5, i64 0, i64 0
%17 = call i32 @bernstein2(double* %16, double %3)
%18 = icmp eq i64 %1, 0
br i1 %18, label %98, label %19
19: ; preds = %13
%20 = load double, double* %16
%21 = getelementptr inbounds [3 x double], [3 x double]* %5, i64 0, i64 1
%22 = load double, double* %21
%23 = getelementptr inbounds [3 x double], [3 x double]* %5, i64 0, i64 2
%24 = load double, double* %23
%25 = icmp ult i64 %1, 4
br i1 %25, label %73, label %26
26: ; preds = %19
%27 = getelementptr float, float* %0, i64 %1
%28 = mul i64 %1, 3
%29 = getelementptr float, float* %2, i64 %28
%30 = icmp ugt float* %29, %0
%31 = icmp ult float* %14, %0
%32 = and i1 %30, %31
%33 = icmp ugt float* %15, %0
%34 = icmp ult float* %2, %0
%35 = and i1 %33, %34
%36 = or i1 %32, %35
%37 = icmp ugt float* %14, %0
%38 = icmp ugt float* %27, %2
%39 = and i1 %37, %38
%40 = or i1 %36, %39
br i1 %40, label %73, label %41
41: ; preds = %26
%42 = and i64 %1, -4
%43 = insertelement <4 x double> poison, double %22, i64 0
%44 = shufflevector <4 x double> %43, <4 x double> poison, <4 x i32> zeroinitializer
%45 = insertelement <4 x double> poison, double %20, i64 0
%46 = shufflevector <4 x double> %45, <4 x double> poison, <4 x i32> zeroinitializer
%47 = insertelement <4 x double> poison, double %24, i64 0
%48 = shufflevector <4 x double> %47, <4 x double> poison, <4 x i32> zeroinitializer
br label %49
49: ; preds = %49, %41
%50 = phi i64 [ 0, %41 ], [ %69, %49 ]
%51 = getelementptr inbounds float, float* %2, i64 %50
%52 = bitcast float* %51 to <4 x float>*
%53 = load <4 x float>, <4 x float>* %52
%54 = fpext <4 x float> %53 to <4 x double>
%55 = getelementptr inbounds float, float* %14, i64 %50
%56 = bitcast float* %55 to <4 x float>*
%57 = load <4 x float>, <4 x float>* %56
%58 = fpext <4 x float> %57 to <4 x double>
%59 = fmul <4 x double> %44, %58
%60 = call <4 x double> @llvm.fmuladd.v4f64(<4 x double> %46, <4 x double> %54, <4 x double> %59)
%61 = getelementptr inbounds float, float* %15, i64 %50
%62 = bitcast float* %61 to <4 x float>*
%63 = load <4 x float>, <4 x float>* %62
%64 = fpext <4 x float> %63 to <4 x double>
%65 = call <4 x double> @llvm.fmuladd.v4f64(<4 x double> %48, <4 x double> %64, <4 x double> %60)
%66 = fptrunc <4 x double> %65 to <4 x float>
%67 = getelementptr inbounds float, float* %0, i64 %50
%68 = bitcast float* %67 to <4 x float>*
store <4 x float> %66, <4 x float>* %68
%69 = add nuw i64 %50, 4
%70 = icmp eq i64 %69, %42
br i1 %70, label %71, label %49
71: ; preds = %49
%72 = icmp eq i64 %42, %1
br i1 %72, label %98, label %73
73: ; preds = %26, %19, %71
%74 = phi i64 [ 0, %26 ], [ 0, %19 ], [ %42, %71 ]
br label %75
75: ; preds = %73, %75
%76 = phi i64 [ %91, %75 ], [ %74, %73 ]
%77 = getelementptr inbounds float, float* %2, i64 %76
%78 = load float, float* %77
%79 = fpext float %78 to double
%80 = getelementptr inbounds float, float* %14, i64 %76
%81 = load float, float* %80
%82 = fpext float %81 to double
%83 = fmul double %22, %82
%84 = call double @llvm.fmuladd.f64(double %20, double %79, double %83)
%85 = getelementptr inbounds float, float* %15, i64 %76
%86 = load float, float* %85
%87 = fpext float %86 to double
%88 = call double @llvm.fmuladd.f64(double %24, double %87, double %84)
%89 = fptrunc double %88 to float
%90 = getelementptr inbounds float, float* %0, i64 %76
store float %89, float* %90
%91 = add nuw i64 %76, 1
%92 = icmp eq i64 %91, %1
br i1 %92, label %98, label %75
93: ; preds = %4, %10
%94 = phi float* [ %12, %10 ], [ %2, %4 ]
%95 = trunc i64 %1 to i32
%96 = shl i32 %95, 2
%97 = tail call float* @memcpy(float* %0, float* %94, i32 %96)
br label %98
98: ; preds = %75, %71, %93, %13
%99 = phi float* [ %0, %13 ], [ %97, %93 ], [ %0, %71 ], [ %0, %75 ]
ret float* %99
}