Skip to content

Commit 2996fa2

Browse files
fatfat123-archvgvassilev
authored andcommitted
Fix reverse-mode scheduling for integral-return helper calls (issue #1793)
- mark nested reverse-mode call requests as non-differentiable when the callee returns an integral/enumeration type and has no memory-type parameters - avoid scheduling unnecessary pullbacks for helper index functions like the CMS pattern - add regression - all tests run green locally Fixes #1793
1 parent 01d1336 commit 2996fa2

2 files changed

Lines changed: 47 additions & 0 deletions

File tree

lib/Differentiator/DiffPlanner.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1191,6 +1191,19 @@ static QualType GetDerivedFunctionType(const CallExpr* CE) {
11911191
if (!utils::hasMemoryTypeParams(FD) && hasPointerOrRefReturn &&
11921192
m_TopMostReq->Mode == DiffMode::reverse)
11931193
nonDiff = true;
1194+
// Skip reverse-mode scheduling for integral-return helper calls that
1195+
// cannot accumulate through memory arguments. Keep this narrow to avoid
1196+
// suppressing diagnostics on variadic/non-helper calls.
1197+
const bool HasPointerOrReferenceParam = std::any_of(
1198+
FD->parameters().begin(), FD->parameters().end(),
1199+
[](const ParmVarDecl* PVD) {
1200+
QualType ParamType = PVD->getType();
1201+
return ParamType->isPointerType() || ParamType->isReferenceType();
1202+
});
1203+
if (m_TopMostReq->Mode == DiffMode::reverse && !FD->isVariadic() &&
1204+
HasPointerOrReferenceParam && !utils::hasMemoryTypeParams(FD) &&
1205+
returnType->isIntegralOrEnumerationType())
1206+
nonDiff = true;
11941207

11951208
if (nonDiff && m_TopMostReq->Mode != DiffMode::reverse)
11961209
return true;

test/Regressions/issue-1793.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// RUN: %cladclang -I%S/../../include %s 2>&1 | %filecheck %s
2+
3+
#include <algorithm>
4+
#include <cstddef>
5+
6+
#include "clad/Differentiator/Differentiator.h"
7+
8+
unsigned int rawBinNumber(double x, const double* boundaries,
9+
std::size_t nBoundaries) {
10+
const double* end = boundaries + nBoundaries;
11+
const double* it = std::lower_bound(boundaries, end, x);
12+
while (boundaries != it && (end == it || end == it + 1 || x < *it))
13+
--it;
14+
return it - boundaries;
15+
}
16+
17+
double roo_codegen_0(double* params, const double* obs, const double* xlArr) {
18+
double out = 0.;
19+
double t23[5]{1. + params[0], 1. + params[1], 1. + params[2],
20+
1. + params[3], 1. + params[4]};
21+
for (int i = 0; i < 5; ++i) {
22+
const double t215 = t23[rawBinNumber(obs[i], xlArr, 6)];
23+
out += t215;
24+
}
25+
return out;
26+
}
27+
28+
int main() {
29+
auto grad = clad::gradient(roo_codegen_0, "params");
30+
(void)grad;
31+
}
32+
33+
// CHECK: void roo_codegen_0_grad_0(double *params, const double *obs, const double *xlArr, double *_d_params) {
34+
// CHECK-NOT: rawBinNumber_pullback

0 commit comments

Comments
 (0)