| // RUN: %clang++ -std=c++11 -fno-exceptions -ffast-math -O0 %s -S -emit-llvm -o - | %opt - %OPloadEnzyme %enzyme -S | %lli - |
| // RUN: %clang++ -std=c++11 -fno-exceptions -ffast-math -O1 %s -S -emit-llvm -o - | %opt - %OPloadEnzyme %enzyme -S | %lli - |
| // RUN: %clang++ -std=c++11 -fno-exceptions -ffast-math -O2 %s -S -emit-llvm -o - | %opt - %OPloadEnzyme %enzyme -S | %lli - |
| // RUN: %clang++ -std=c++11 -fno-exceptions -ffast-math -O3 %s -S -emit-llvm -o - | %opt - %OPloadEnzyme %enzyme -S | %lli - |
| // RUN: %clang++ -std=c++11 -fno-exceptions -ffast-math -O0 %s -S -emit-llvm -o - | %opt - %OPloadEnzyme %enzyme -enzyme-inline=1 -S | %lli - |
| // RUN: %clang++ -std=c++11 -fno-exceptions -ffast-math -O1 %s -S -emit-llvm -o - | %opt - %OPloadEnzyme %enzyme -enzyme-inline=1 -S | %lli - |
| // RUN: %clang++ -std=c++11 -fno-exceptions -ffast-math -O2 %s -S -emit-llvm -o - | %opt - %OPloadEnzyme %enzyme -enzyme-inline=1 -S | %lli - |
| // RUN: %clang++ -std=c++11 -fno-exceptions -ffast-math -O3 %s -S -emit-llvm -o - | %opt - %OPloadEnzyme %enzyme -enzyme-inline=1 -S | %lli - |
| |
| #include <stdio.h> |
| #include "../test_utils.h" |
| |
| struct S { |
| double (*fn)(double); |
| double val; |
| }; |
| |
| double square(double x){ return x * x; } |
| |
| double foo(struct S* s) { |
| return square(s->val); |
| } |
| |
| |
| void primal() { |
| struct S s; |
| s.fn = square; |
| s.val = 3.0; |
| printf("%f\n", foo(&s)); |
| } |
| |
| void* __enzyme_virtualreverse(void*); |
| void __enzyme_autodiff(void*, void*, void*); |
| void reverse() { |
| struct S s; |
| s.fn = square; |
| s.val = 3.0; |
| struct S d_s; |
| d_s.fn = (double (*)(double))__enzyme_virtualreverse((void*)square); |
| d_s.val = 0.0; |
| __enzyme_autodiff((void*)foo, &s, &d_s); |
| printf("shadow res=%f\n", d_s.val); |
| APPROX_EQ(d_s.val, 6.0, 1e-7); |
| } |
| |
| int main() { |
| primal(); |
| reverse(); |
| } |