| // RUN: %clang++ -std=c++14 -fno-exceptions -O0 %s -S -emit-llvm -o - | %opt - %OPloadEnzyme %enzyme -S | %lli - | |
| // RUN: %clang++ -std=c++14 -fno-exceptions -O1 %s -S -emit-llvm -o - | %opt - %OPloadEnzyme %enzyme -S | %lli - | |
| // RUN: %clang++ -std=c++14 -fno-exceptions -O2 %s -S -emit-llvm -o - | %opt - %OPloadEnzyme %enzyme -S | %lli - | |
| // RUN: %clang++ -std=c++14 -fno-exceptions -O3 %s -S -emit-llvm -o - | %opt - %OPloadEnzyme %enzyme -S | %lli - | |
| // RUN: %clang++ -std=c++14 -fno-exceptions -O0 %s -S -emit-llvm -o - | %opt - %OPloadEnzyme %enzyme -enzyme-inline=1 -S | %lli - | |
| // RUN: %clang++ -std=c++14 -fno-exceptions -O1 %s -S -emit-llvm -o - | %opt - %OPloadEnzyme %enzyme -enzyme-inline=1 -S | %lli - | |
| // RUN: %clang++ -std=c++14 -fno-exceptions -O2 %s -S -emit-llvm -o - | %opt - %OPloadEnzyme %enzyme -enzyme-inline=1 -S | %lli - | |
| // RUN: %clang++ -std=c++14 -fno-exceptions -O3 %s -S -emit-llvm -o - | %opt - %OPloadEnzyme %enzyme -enzyme-inline=1 -S | %lli - | |
| #include <cmath> | |
| #include "../test_utils.h" | |
| template <typename T, int... n> | |
| struct tensor; | |
| template <typename T, int n> | |
| struct tensor<T, n> { | |
| T& operator[](int i) { return value[0]; }; | |
| T value[n]; | |
| }; | |
| template <typename T, int first, int... rest> | |
| struct tensor<T, first, rest...> { | |
| tensor<T, rest...>& operator[](int i) { return value[0]; }; | |
| tensor<T, rest...> value[first]; | |
| }; | |
| template<typename return_type, typename... Args> | |
| return_type __enzyme_autodiff(Args...); | |
| template<typename return_type, typename... Args> | |
| return_type __enzyme_fwddiff(Args...); | |
| extern "C" { | |
| __attribute__((noinline)) | |
| constexpr double ptr(double* A) { | |
| return A[0]; | |
| } | |
| } | |
| template <int n> | |
| __attribute__((noinline)) | |
| constexpr tensor<double, 1, 1> pdev(const tensor<double, 1, 1>& A) { | |
| auto devA = A; | |
| auto trA = ptr((double*)&A); | |
| devA[0][0] -= trA; | |
| devA[0][0] -= trA; | |
| devA[0][0] -= trA; | |
| return devA; | |
| } | |
| extern "C" { | |
| double mystress_calculation(void* __restrict__ D, const tensor<double, 1, 1> & __restrict__ du_dx) { | |
| auto devB = pdev<2>(du_dx); | |
| return 2 * devB[0][0]; | |
| } | |
| } | |
| int main(int argc, char * argv[]) { | |
| tensor<double, 1, 1> dudx = {{{0.0}}}; | |
| tensor<double, 1, 1> ddudxi = {{{0.0}}}; | |
| tensor<double, 1, 1> gradient{}; | |
| tensor<double, 1, 1> sigma{}; | |
| tensor<double, 1, 1> dir{}; | |
| dir[0][0] = 1; | |
| // Forward pass of gradient can segfault if forward and reverse preprocess | |
| // functions collide in cache. | |
| for (int i = 0; i < 2; i++) | |
| { | |
| __enzyme_autodiff<void>(mystress_calculation, | |
| &enzyme_const, nullptr, | |
| &enzyme_dup, &dudx, &gradient); | |
| } | |
| __enzyme_fwddiff<void>(mystress_calculation, | |
| &enzyme_const, nullptr, | |
| &enzyme_dup, &dudx, &ddudxi); | |
| } |