blob: 7f9f0abe912a5e897a719ad2a1c522a43f5f1998 [file] [edit]
// RUN: %eopt --pass-pipeline="builtin.module(enzyme{dataflow=true},canonicalize)" %s | FileCheck %s
// Differentiating a function that itself contains an enzyme.fwddiff runs the
// dataflow activity analysis on the first-order function the inner op
// generated -- after an enclosing analysis has already stamped it with a
// pointer summary. The summary serves callers; the function's own per-value
// maps must still be computed, or every value inside looks inactive and the
// second derivative of anything is zero.
module {
func.func @square(%x: f64) -> f64 {
%r = arith.mulf %x, %x : f64
return %r : f64
}
func.func @dsquare(%x: f64, %dx: f64) -> f64 {
%r = enzyme.fwddiff @square(%x, %dx) { activity=[#enzyme<activity enzyme_dup>], ret_activity=[#enzyme<activity enzyme_dupnoneed>] } : (f64, f64) -> f64
return %r : f64
}
func.func @ddsquare(%x: f64, %dx: f64, %sx: f64, %sdx: f64) -> f64 {
%r = enzyme.fwddiff @dsquare(%x, %dx, %sx, %sdx) { activity=[#enzyme<activity enzyme_dup>, #enzyme<activity enzyme_dup>], ret_activity=[#enzyme<activity enzyme_dupnoneed>] } : (f64, f64, f64, f64) -> f64
return %r : f64
}
}
// The second derivative of x*x in direction (sx, sdx) is 2 (sx dx + x sdx);
// with everything active the generated second-order function must read all
// four inputs, not collapse to a constant zero.
// CHECK-LABEL: func.func private @fwddiffefwddiffesquare
// CHECK-NOT: arith.constant 0.000000e+00
// CHECK: arith.mulf %arg3, %arg0
// CHECK: arith.mulf %arg1, %arg2
// CHECK: return