| // 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 -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" |
| |
| void __enzyme_autodiff(...); |
| |
| template <typename... Args> |
| double __enzyme_autodiff(void *, Args...); |
| |
| struct Object |
| { |
| virtual double eval(double v) = 0; |
| double val; |
| }; |
| |
| struct Object1 : Object |
| { |
| double eval(double v) |
| { |
| return val * v; |
| } |
| }; |
| |
| struct Object2 : Object |
| { |
| double eval(double v) |
| { |
| return val + v; |
| } |
| }; |
| |
| double eval(Object &o, double v) |
| { |
| return o.eval(v); |
| } |
| |
| double deval(Object &o, Object &d_o, double v) |
| { |
| return __enzyme_autodiff((void *)(eval), |
| enzyme_dup, &o, &d_o, |
| v); |
| } |
| |
| template<typename T> |
| T __enzyme_virtualreverse(T); |
| |
| int main() |
| { |
| double v = 10; |
| Object *o = new Object1(); |
| o->val = 2; |
| Object *d_o = new Object1(); |
| *((void**)d_o) = __enzyme_virtualreverse(*(void**)d_o); |
| d_o->val = 0; |
| double res; |
| res = deval(*o, *d_o, v); |
| printf("res=%f\n", res); |
| APPROX_EQ(res, 2.0, 1e-7); |
| |
| o = new Object2(); |
| o->val = 2; |
| d_o = new Object2(); |
| *((void**)d_o) = __enzyme_virtualreverse(*(void**)d_o); |
| d_o->val = 0; |
| res = deval(*o, *d_o, v); |
| printf("res=%f\n", res); |
| APPROX_EQ(res, 1.0, 1e-7); |
| } |