I'm trying to differentiate the following C++ code:
#include <cmath>
#include <iostream>
double add_angles(double a, double b)
{
double cos_apb = std::cos(a) * std::cos(b) - std::sin(a) * std::sin(b);
double sin_apb = std::sin(a) * std::cos(b) + std::cos(a) * std::sin(b);
return std::atan2(sin_apb, cos_apb);
}
double sub_angles(double a, double b)
{
double cos_amb = std::cos(a) * std::cos(b) + std::sin(a) * std::sin(b);
double sin_amb = std::sin(a) * std::cos(b) - std::cos(a) * std::sin(b);
return std::atan2(sin_amb, cos_amb);
}
double ang_dist(double theta1, double theta2)
{
return std::abs(sub_angles(theta1, theta2));
}
double lens_eq_binary_real(double z_real, double z_imag, double a, double e1)
{
// e1*(a - re(z))/((a - re(z))**2 + im(z)**2) + (a + re(z))*(e1 - 1.0)/((a + re(z))**2 + im(z)**2) + re(z)
return e1 * (a - z_real) / ((a - z_real) * (a - z_real) + z_imag * z_imag) + (a + z_real) * (e1 - 1.0) / ((a + z_real) * (a + z_real) + z_imag * z_imag) + z_real;
}
double lens_eq_binary_imag(double z_real, double z_imag, double a, double e1)
{
// -e1*im(z)/((a - re(z))**2 + im(z)**2) + (e1 - 1.0)*im(z)/((a + re(z))**2 + im(z)**2) + im(z)
return -e1 * z_imag / ((a - z_real) * (a - z_real) + z_imag * z_imag) + (e1 - 1.0) * z_imag / ((a + z_real) * (a + z_real) + z_imag * z_imag) + z_imag;
}
double linear_limbdark(double r, double I0, double c)
{
return I0 * (1.0 - c * (1.0 - std::sqrt(1.0 - r * r)));
}
void evaluate_integrand(
const double rmin, const double theta_min, const double dr, const double dtheta, const int nr,
const int ntheta, const double rho, const double a1, const double a, const double e1, const double w_cent_real,
const double w_cent_imag, double *integrand)
{
for (int tid = 0; tid < nr * ntheta; tid++)
{
int i = tid / ntheta;
int j = tid % ntheta;
double r = rmin + i * dr + 0.5 * dr;
double theta = add_angles(theta_min, j * dtheta + 0.5 * dtheta);
double w_real = lens_eq_binary_real(r * std::cos(theta), r * std::sin(theta), a, e1);
double w_imag = lens_eq_binary_imag(r * std::cos(theta), r * std::sin(theta), a, e1);
// Check if point falls inside the source
double xs = w_real - w_cent_real;
double ys = w_imag - w_cent_imag;
double rs = std::sqrt(xs * xs + ys * ys);
if (rs < rho)
{
integrand[tid] = r * linear_limbdark(rs, 1.0, a1);
}
else
{
integrand[tid] = 0.0;
}
}
}
double sum_integrand(const int nr, const int ntheta,
double rmin, double theta_min, double dr, double dtheta,
double rho, double a1, double a, double e1, double w_cent_real, double w_cent_imag)
{
int N = nr * ntheta;
// Initialize array of size (nr, ntheta)
double *integrand = new double[N];
evaluate_integrand(rmin, theta_min, dr, dtheta, nr, ntheta, rho, a1, a, e1,
w_cent_real, w_cent_imag, integrand);
// Sum the columns of integrand matrix
double *integrand_sum = new double[ntheta];
for (int j = 0; j < ntheta; j++)
{
double sum = 0.0;
for (int i = 0; i < nr; i++)
{
sum += integrand[i * ntheta + j];
}
integrand_sum[j] = sum;
}
// Sum the rows
double sum = 0.0;
for (int i = 0; i < ntheta; i++)
{
sum += integrand_sum[i];
}
// Free memory
delete[] integrand_sum;
delete[] integrand;
return sum;
}
extern double __enzyme_autodiff(void *, double, double, double, double, double, double,
double, double, double, double, double, double);
double integrate_image(
double rmin, double rmax, double theta_min, double theta_max, double dr, double dtheta,
double rho, double a1, double a, double e1,
double w_cent_real, double w_cent_imag)
{
double grid_ratio = 4.;
double f = 0.8;
double eps_max = 1e-04;
// Return 0. if the bounding box is empty
if (rmax - rmin == 0. || theta_max - theta_min == 0.)
{
double result = 0.0;
return result;
}
else
{
double eps = 1.;
double I_previous = 0.;
double I_estimate;
while (eps > eps_max)
{
int nr = std::ceil((rmax - rmin) / dr);
int ntheta = std::ceil(ang_dist(theta_min, theta_max) / dtheta);
int N = nr * ntheta;
// Because of memory limitations, we need to compute the integral in chunks
double sum = 0.0;
int n_chunks = std::max<int>(int((N / 2.e06)), 1);
// Iterate over chunks of the grid (split across radius r) and add to the sum
double _rmin = rmin;
int chunk_size = int(std::ceil(nr / n_chunks));
int nr_chunk = chunk_size;
for (int i = 0; i < n_chunks; i++)
{
_rmin = rmin + i * chunk_size * dr;
if (i == (n_chunks - 1))
{
nr_chunk = nr - i * chunk_size;
}
sum += sum_integrand(nr_chunk, ntheta, _rmin, theta_min, dr, dtheta, rho, a1, a, e1, w_cent_real, w_cent_imag);
}
I_estimate = sum * dr * dtheta;
// print I_estimate
eps = std::abs((I_estimate - I_previous) / I_previous);
I_previous = I_estimate;
// Update the step size
dr *= f;
dtheta = grid_ratio * dr;
}
return I_estimate;
}
}
int main()
{
double rmin = 1.2460687963709596;
double rmax = 1.3807432495443732;
double theta_min = -0.6736152464838706;
double theta_max = 0.6736152464838707;
double dr = 0.0005;
double dtheta = 0.002;
double rho = 0.01;
double a1 = 0.2;
double a = 0.45;
double e1 = 0.8;
double w_cent_real = 0.3955;
double w_cent_imag = 0.;
double I = integrate_image(rmin, rmax, theta_min, theta_max, dr, dtheta, rho, a1, a, e1, w_cent_real, w_cent_imag);
std::cout << "I = " << I << std::endl;
__enzyme_autodiff((void *)integrate_image, rmin, rmax, theta_min, theta_max, dr, dtheta, rho, a1, a, e1, w_cent_real, w_cent_imag);
}
I first cloned the llvm-project
repo and followed the instructions in the docs to build llvm from source. I then installed the latest Enzyme version. I made sure that clang++
points to llvm-project/build/bin/clang++
and opt
to llvm-project/build/bin/opt
. I run clang++ test.cc -S -emit-llvm -o input.ll -O2 -fno-vectorize -fno-slp-vectorize -fno-unroll-loops -std=c++14
followed by opt -enable-new-pm=0 input.ll -load=/home/fb90/bin/Enzyme/enzyme/build/Enzyme/LLVMEnzyme-15.so -enzyme -o output.ll -S
which results in the following error:
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0. Program arguments: /home/fb90/bin/llvm-project/build/bin/opt -enable-new-pm=0 input.ll -load=/home/fb90/bin/Enzyme/enzyme/build/Enzyme/LLVMEnzyme-15.so -enzyme -o output.ll -S
1. Running pass 'Enzyme Pass' on module 'input.ll'.
#0 0x000055cb2a01c760 PrintStackTraceSignalHandler(void*) Signals.cpp:0:0
#1 0x000055cb2a01a00e SignalHandler(int) Signals.cpp:0:0
#2 0x00002b83287ae630 __restore_rt sigaction.c:0:0
#3 0x00002b8329a57c24 llvm::Value::getType() const (/home/fb90/bin/Enzyme/enzyme/build/Enzyme/LLVMEnzyme-15.so+0x5c0c24)
#4 0x00002b8329cad9fd GradientUtils::unwrapM(llvm::Value*, llvm::IRBuilder<llvm::ConstantFolder, llvm::IRBuilderDefaultInserter>&, llvm::ValueMap<llvm::Value const*, llvm::WeakTrackingVH, llvm::ValueMapConfig<llvm::Value const*, llvm::sys::SmartMutex<false> > > const&, UnwrapMode, llvm::BasicBlock*, bool) (/home/fb90/bin/Enzyme/enzyme/build/Enzyme/LLVMEnzyme-15.so+0x8169fd)
#5 0x00002b8329cb4c8e GradientUtils::unwrapM(llvm::Value*, llvm::IRBuilder<llvm::ConstantFolder, llvm::IRBuilderDefaultInserter>&, llvm::ValueMap<llvm::Value const*, llvm::WeakTrackingVH, llvm::ValueMapConfig<llvm::Value const*, llvm::sys::SmartMutex<false> > > const&, UnwrapMode, llvm::BasicBlock*, bool) (/home/fb90/bin/Enzyme/enzyme/build/Enzyme/LLVMEnzyme-15.so+0x81dc8e)
#6 0x00002b8329cc3750 GradientUtils::unwrapM(llvm::Value*, llvm::IRBuilder<llvm::ConstantFolder, llvm::IRBuilderDefaultInserter>&, llvm::ValueMap<llvm::Value const*, llvm::WeakTrackingVH, llvm::ValueMapConfig<llvm::Value const*, llvm::sys::SmartMutex<false> > > const&, UnwrapMode, llvm::BasicBlock*, bool) (/home/fb90/bin/Enzyme/enzyme/build/Enzyme/LLVMEnzyme-15.so+0x82c750)
#7 0x00002b8329cb4c8e GradientUtils::unwrapM(llvm::Value*, llvm::IRBuilder<llvm::ConstantFolder, llvm::IRBuilderDefaultInserter>&, llvm::ValueMap<llvm::Value const*, llvm::WeakTrackingVH, llvm::ValueMapConfig<llvm::Value const*, llvm::sys::SmartMutex<false> > > const&, UnwrapMode, llvm::BasicBlock*, bool) (/home/fb90/bin/Enzyme/enzyme/build/Enzyme/LLVMEnzyme-15.so+0x81dc8e)
#8 0x00002b8329cb4c8e GradientUtils::unwrapM(llvm::Value*, llvm::IRBuilder<llvm::ConstantFolder, llvm::IRBuilderDefaultInserter>&, llvm::ValueMap<llvm::Value const*, llvm::WeakTrackingVH, llvm::ValueMapConfig<llvm::Value const*, llvm::sys::SmartMutex<false> > > const&, UnwrapMode, llvm::BasicBlock*, bool) (/home/fb90/bin/Enzyme/enzyme/build/Enzyme/LLVMEnzyme-15.so+0x81dc8e)
#9 0x00002b8329cc3750 GradientUtils::unwrapM(llvm::Value*, llvm::IRBuilder<llvm::ConstantFolder, llvm::IRBuilderDefaultInserter>&, llvm::ValueMap<llvm::Value const*, llvm::WeakTrackingVH, llvm::ValueMapConfig<llvm::Value const*, llvm::sys::SmartMutex<false> > > const&, UnwrapMode, llvm::BasicBlock*, bool) (/home/fb90/bin/Enzyme/enzyme/build/Enzyme/LLVMEnzyme-15.so+0x82c750)
#10 0x00002b8329cb52e6 GradientUtils::unwrapM(llvm::Value*, llvm::IRBuilder<llvm::ConstantFolder, llvm::IRBuilderDefaultInserter>&, llvm::ValueMap<llvm::Value const*, llvm::WeakTrackingVH, llvm::ValueMapConfig<llvm::Value const*, llvm::sys::SmartMutex<false> > > const&, UnwrapMode, llvm::BasicBlock*, bool) (/home/fb90/bin/Enzyme/enzyme/build/Enzyme/LLVMEnzyme-15.so+0x81e2e6)
#11 0x00002b8329cbbc23 GradientUtils::unwrapM(llvm::Value*, llvm::IRBuilder<llvm::ConstantFolder, llvm::IRBuilderDefaultInserter>&, llvm::ValueMap<llvm::Value const*, llvm::WeakTrackingVH, llvm::ValueMapConfig<llvm::Value const*, llvm::sys::SmartMutex<false> > > const&, UnwrapMode, llvm::BasicBlock*, bool) (/home/fb90/bin/Enzyme/enzyme/build/Enzyme/LLVMEnzyme-15.so+0x824c23)
#12 0x00002b8329caf7e0 GradientUtils::unwrapM(llvm::Value*, llvm::IRBuilder<llvm::ConstantFolder, llvm::IRBuilderDefaultInserter>&, llvm::ValueMap<llvm::Value const*, llvm::WeakTrackingVH, llvm::ValueMapConfig<llvm::Value const*, llvm::sys::SmartMutex<false> > > const&, UnwrapMode, llvm::BasicBlock*, bool) (/home/fb90/bin/Enzyme/enzyme/build/Enzyme/LLVMEnzyme-15.so+0x8187e0)
#13 0x00002b8329cb4c8e GradientUtils::unwrapM(llvm::Value*, llvm::IRBuilder<llvm::ConstantFolder, llvm::IRBuilderDefaultInserter>&, llvm::ValueMap<llvm::Value const*, llvm::WeakTrackingVH, llvm::ValueMapConfig<llvm::Value const*, llvm::sys::SmartMutex<false> > > const&, UnwrapMode, llvm::BasicBlock*, bool) (/home/fb90/bin/Enzyme/enzyme/build/Enzyme/LLVMEnzyme-15.so+0x81dc8e)
#14 0x00002b8329caf7e0 GradientUtils::unwrapM(llvm::Value*, llvm::IRBuilder<llvm::ConstantFolder, llvm::IRBuilderDefaultInserter>&, llvm::ValueMap<llvm::Value const*, llvm::WeakTrackingVH, llvm::ValueMapConfig<llvm::Value const*, llvm::sys::SmartMutex<false> > > const&, UnwrapMode, llvm::BasicBlock*, bool) (/home/fb90/bin/Enzyme/enzyme/build/Enzyme/LLVMEnzyme-15.so+0x8187e0)
#15 0x00002b8329cb4c8e GradientUtils::unwrapM(llvm::Value*, llvm::IRBuilder<llvm::ConstantFolder, llvm::IRBuilderDefaultInserter>&, llvm::ValueMap<llvm::Value const*, llvm::WeakTrackingVH, llvm::ValueMapConfig<llvm::Value const*, llvm::sys::SmartMutex<false> > > const&, UnwrapMode, llvm::BasicBlock*, bool) (/home/fb90/bin/Enzyme/enzyme/build/Enzyme/LLVMEnzyme-15.so+0x81dc8e)
#16 0x00002b8329caf7e0 GradientUtils::unwrapM(llvm::Value*, llvm::IRBuilder<llvm::ConstantFolder, llvm::IRBuilderDefaultInserter>&, llvm::ValueMap<llvm::Value const*, llvm::WeakTrackingVH, llvm::ValueMapConfig<llvm::Value const*, llvm::sys::SmartMutex<false> > > const&, UnwrapMode, llvm::BasicBlock*, bool) (/home/fb90/bin/Enzyme/enzyme/build/Enzyme/LLVMEnzyme-15.so+0x8187e0)
#17 0x00002b8329cbbc23 GradientUtils::unwrapM(llvm::Value*, llvm::IRBuilder<llvm::ConstantFolder, llvm::IRBuilderDefaultInserter>&, llvm::ValueMap<llvm::Value const*, llvm::WeakTrackingVH, llvm::ValueMapConfig<llvm::Value const*, llvm::sys::SmartMutex<false> > > const&, UnwrapMode, llvm::BasicBlock*, bool) (/home/fb90/bin/Enzyme/enzyme/build/Enzyme/LLVMEnzyme-15.so+0x824c23)
#18 0x00002b8329cb4c8e GradientUtils::unwrapM(llvm::Value*, llvm::IRBuilder<llvm::ConstantFolder, llvm::IRBuilderDefaultInserter>&, llvm::ValueMap<llvm::Value const*, llvm::WeakTrackingVH, llvm::ValueMapConfig<llvm::Value const*, llvm::sys::SmartMutex<false> > > const&, UnwrapMode, llvm::BasicBlock*, bool) (/home/fb90/bin/Enzyme/enzyme/build/Enzyme/LLVMEnzyme-15.so+0x81dc8e)
#19 0x00002b8329caf7e0 GradientUtils::unwrapM(llvm::Value*, llvm::IRBuilder<llvm::ConstantFolder, llvm::IRBuilderDefaultInserter>&, llvm::ValueMap<llvm::Value const*, llvm::WeakTrackingVH, llvm::ValueMapConfig<llvm::Value const*, llvm::sys::SmartMutex<false> > > const&, UnwrapMode, llvm::BasicBlock*, bool) (/home/fb90/bin/Enzyme/enzyme/build/Enzyme/LLVMEnzyme-15.so+0x8187e0)
#20 0x00002b8329ab7107 CacheUtility::getSubLimits(bool, llvm::IRBuilder<llvm::ConstantFolder, llvm::IRBuilderDefaultInserter>*, CacheUtility::LimitContext, llvm::Value*) (/home/fb90/bin/Enzyme/enzyme/build/Enzyme/LLVMEnzyme-15.so+0x620107)
#21 0x00002b8329ab850a CacheUtility::getCachePointer(bool, llvm::IRBuilder<llvm::ConstantFolder, llvm::IRBuilderDefaultInserter>&, CacheUtility::LimitContext, llvm::Value*, bool, bool, llvm::ValueMap<llvm::Value const*, llvm::WeakTrackingVH, llvm::ValueMapConfig<llvm::Value const*, llvm::sys::SmartMutex<false> > > const&, llvm::Value*) (/home/fb90/bin/Enzyme/enzyme/build/Enzyme/LLVMEnzyme-15.so+0x62150a)
#22 0x00002b8329ab90b9 CacheUtility::lookupValueFromCache(bool, llvm::IRBuilder<llvm::ConstantFolder, llvm::IRBuilderDefaultInserter>&, CacheUtility::LimitContext, llvm::Value*, bool, llvm::ValueMap<llvm::Value const*, llvm::WeakTrackingVH, llvm::ValueMapConfig<llvm::Value const*, llvm::sys::SmartMutex<false> > > const&, llvm::Value*, llvm::Value*) (/home/fb90/bin/Enzyme/enzyme/build/Enzyme/LLVMEnzyme-15.so+0x6220b9)
#23 0x00002b8329ce3c28 GradientUtils::lookupM(llvm::Value*, llvm::IRBuilder<llvm::ConstantFolder, llvm::IRBuilderDefaultInserter>&, llvm::ValueMap<llvm::Value const*, llvm::WeakTrackingVH, llvm::ValueMapConfig<llvm::Value const*, llvm::sys::SmartMutex<false> > > const&, bool) (/home/fb90/bin/Enzyme/enzyme/build/Enzyme/LLVMEnzyme-15.so+0x84cc28)
#24 0x00002b8329c00fd1 AdjointGenerator<AugmentedReturn const*>::lookup(llvm::Value*, llvm::IRBuilder<llvm::ConstantFolder, llvm::IRBuilderDefaultInserter>&) (/home/fb90/bin/Enzyme/enzyme/build/Enzyme/LLVMEnzyme-15.so+0x769fd1)
#25 0x00002b8329bb9c87 AdjointGenerator<AugmentedReturn const*>::visitCallInst(llvm::CallInst&) (/home/fb90/bin/Enzyme/enzyme/build/Enzyme/LLVMEnzyme-15.so+0x722c87)
#26 0x00002b8329ba3ee2 llvm::InstVisitor<AdjointGenerator<AugmentedReturn const*>, void>::delegateCallInst(llvm::CallInst&) (/home/fb90/bin/Enzyme/enzyme/build/Enzyme/LLVMEnzyme-15.so+0x70cee2)
#27 0x00002b8329b77217 llvm::InstVisitor<AdjointGenerator<AugmentedReturn const*>, void>::visitCall(llvm::CallInst&) (/home/fb90/bin/Enzyme/enzyme/build/Enzyme/LLVMEnzyme-15.so+0x6e0217)
#28 0x00002b8329b62fe0 llvm::InstVisitor<AdjointGenerator<AugmentedReturn const*>, void>::visit(llvm::Instruction&) (/home/fb90/bin/Enzyme/enzyme/build/Enzyme/LLVMEnzyme-15.so+0x6cbfe0)
#29 0x00002b8329b5367f llvm::InstVisitor<AdjointGenerator<AugmentedReturn const*>, void>::visit(llvm::Instruction*) (/home/fb90/bin/Enzyme/enzyme/build/Enzyme/LLVMEnzyme-15.so+0x6bc67f)
#30 0x00002b8329b28d40 EnzymeLogic::CreatePrimalAndGradient(ReverseCacheKey const&&, TypeAnalysis&, AugmentedReturn const*, bool) (/home/fb90/bin/Enzyme/enzyme/build/Enzyme/LLVMEnzyme-15.so+0x691d40)
#31 0x00002b8329ae2edd (anonymous namespace)::Enzyme::HandleAutoDiff(llvm::CallInst*, llvm::TargetLibraryInfo&, DerivativeMode, bool) Enzyme.cpp:0:0
#32 0x00002b8329ae879c (anonymous namespace)::Enzyme::lowerEnzymeCalls(llvm::Function&, bool&, std::set<llvm::Function*, std::less<llvm::Function*>, std::allocator<llvm::Function*> >&) Enzyme.cpp:0:0
#33 0x00002b8329ae9a99 (anonymous namespace)::Enzyme::runOnModule(llvm::Module&) Enzyme.cpp:0:0
#34 0x000055cb29673e72 llvm::legacy::PassManagerImpl::run(llvm::Module&) (/home/fb90/bin/llvm-project/build/bin/opt+0x140ee72)
#35 0x000055cb287a0bd2 main (/home/fb90/bin/llvm-project/build/bin/opt+0x53bbd2)
#36 0x00002b83290eb555 __libc_start_main (/lib64/libc.so.6+0x22555)
#37 0x000055cb288100d5 _start (/home/fb90/bin/llvm-project/build/bin/opt+0x5ab0d5)
Segmentation fault (core dumped)
Is anyone else able to reproduce this issue?
bug