| // 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); | |
| } |