blob: 2770060575ce4b06bc3ccd9029ce5a92a12b3852 [file] [log] [blame] [edit]
// RUN: %clang -O0 %s -S -emit-llvm -o - | %opt - %OPloadEnzyme %enzyme -S | %lli -
// RUN: %clang -O1 %s -S -emit-llvm -o - | %opt - %OPloadEnzyme %enzyme -S | %lli -
// RUN: %clang -O2 %s -S -emit-llvm -o - | %opt - %OPloadEnzyme %enzyme -S | %lli -
// RUN: %clang -O3 %s -S -emit-llvm -o - | %opt - %OPloadEnzyme %enzyme -S | %lli -
#include "../test_utils.h"
double sin(double);
double cos(double);
double fabs(double);
extern double __enzyme_error_estimate(void *, ...);
int errorLogCount = 0;
void enzymeLogError(double res, double err, const char *opcodeName,
const char *calleeName, const char *moduleName,
const char *functionName, const char *blockName) {
++errorLogCount;
printf("Res = %e, Error = %e, Op = %s, Callee = %s, Module = %s, Function = "
"%s, BasicBlock = %s\n",
res, err, opcodeName, calleeName, moduleName, functionName, blockName);
}
// An example from https://dl.acm.org/doi/10.1145/3371128
double fun(double x) {
double v1 = cos(x);
double v2 = 1 - v1;
double v3 = x * x;
double v4 = v2 / v3;
double v5 = sin(v4); // Inactive -- logger is not invoked.
printf("v1 = %.18e, v2 = %.18e, v3 = %.18e, v4 = %.18e, v5 = %.18e\n", v1, v2,
v3, v4, v5);
return v4;
}
int main() {
double res = fun(1e-7);
double error = __enzyme_error_estimate((void *)fun, 1e-7, 0.0);
printf("res = %.18e, abs error = %.18e, rel error = %.18e\n", res, error,
fabs(error / res));
APPROX_EQ(error, 2.2222222222e-2, 1e-4);
TEST_EQ(errorLogCount, 4);
}