| // RUN: %clang -std=c11 -ffast-math -O0 %s -S -emit-llvm -o - | %opt - %OPloadEnzyme %enzyme -S | %lli - |
| // RUN: %clang -std=c11 -ffast-math -O1 %s -S -emit-llvm -o - | %opt - %OPloadEnzyme %enzyme -S | %lli - |
| // RUN: %clang -std=c11 -ffast-math -O2 %s -S -emit-llvm -o - | %opt - %OPloadEnzyme %enzyme -S | %lli - |
| // RUN: %clang -std=c11 -ffast-math -O3 %s -S -emit-llvm -o - | %opt - %OPloadEnzyme %enzyme -S | %lli - |
| // RUN: %clang -std=c11 -ffast-math -O0 %s -S -emit-llvm -o - | %opt - %OPloadEnzyme %enzyme -enzyme-inline=1 -S | %lli - |
| // RUN: %clang -std=c11 -ffast-math -O1 %s -S -emit-llvm -o - | %opt - %OPloadEnzyme %enzyme -enzyme-inline=1 -S | %lli - |
| // RUN: %clang -std=c11 -ffast-math -O2 %s -S -emit-llvm -o - | %opt - %OPloadEnzyme %enzyme -enzyme-inline=1 -S | %lli - |
| // RUN: %clang -std=c11 -ffast-math -O3 %s -S -emit-llvm -o - | %opt - %OPloadEnzyme %enzyme -enzyme-inline=1 -S | %lli - |
| |
| #include "../test_utils.h" |
| |
| __attribute__((always_inline)) |
| inline void doA(double x[2]) |
| { |
| double t; |
| t = 4*__builtin_cos(x[0] + x[1]); |
| x[0] = 3*__builtin_sin(2*x[0] + x[1]); |
| x[1] = t; |
| } |
| |
| __attribute__((always_inline)) |
| inline void doB(double x[2]) |
| { |
| double t; |
| t = 4*__builtin_sin(2*x[0] + x[1]); |
| x[0] = 4*__builtin_cos(x[0] + 2*x[1]); |
| x[1] = t; |
| } |
| |
| // for input x = {0.9, 0.7} |
| void fcheck(double x[2]) |
| { |
| doA(x); |
| doA(x); |
| doB(x); |
| doB(x); |
| doA(x); |
| doB(x); |
| } |
| |
| void f(double x[2]) |
| { |
| A: doA(x); |
| if (x[0]*x[0] < x[1]) |
| return; |
| else if (x[0] > 0) |
| goto A; |
| else |
| goto B; |
| |
| B: doB(x); |
| if (x[0]*x[0] < x[1]) |
| return; |
| else if (x[0] > 0) |
| goto A; |
| else |
| goto B; |
| } |
| |
| extern void* __enzyme_augmentfwd(void*, double*, double*); |
| extern void __enzyme_reverse(void*, double*, double*, void*); |
| extern void __enzyme_autodiff(void*, double*, double*); |
| |
| int main() |
| { |
| double x[2], x_b[2], y[2], y_b[2]; |
| x[0] = y[0] = 0.9; |
| x[1] = y[1] = 0.7; |
| x_b[0] = y_b[0] = 1; |
| x_b[1] = y_b[1] = 2; |
| |
| void* tape = __enzyme_augmentfwd((void*)f, x, x_b); |
| __enzyme_reverse((void*)f, x, x_b, tape); |
| __enzyme_autodiff((void*)fcheck, y, y_b); |
| APPROX_EQ(x[0], y[0], 1e-10); |
| APPROX_EQ(x[1], y[1], 1e-10); |
| APPROX_EQ(x_b[0], y_b[0], 1e-10); |
| APPROX_EQ(x_b[1], y_b[1], 1e-10); |
| } |