Skip to content

Commit c2e2d9a

Browse files
committed
Convert to a static cast and add a more targeted test case
1 parent 767c5ef commit c2e2d9a

2 files changed

Lines changed: 57 additions & 6 deletions

File tree

enzyme/Enzyme/MLIR/Interfaces/GradientUtils.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -225,13 +225,16 @@ void mlir::enzyme::MGradientUtils::setDiffe(mlir::Value val, mlir::Value toset,
225225
}
226226
assert(!isConstantValue(val));
227227

228-
bool isMutable = false;
229-
if (auto iface = dyn_cast<AutoDiffTypeInterface>(val.getType()))
230-
isMutable = iface.isMutable();
231-
228+
// Reverse mode also uses invertedPointers for mutable values. For allocation
229+
// results, forceAugmentedReturns() installs a placeholder shadow; the
230+
// allocation derivative later calls setDiffe with the real shadow, so replace
231+
// it here.
232+
bool isMutable = cast<AutoDiffTypeInterface>(val.getType()).isMutable();
232233
if (mode == DerivativeMode::ForwardMode ||
233234
mode == DerivativeMode::ForwardModeSplit || isMutable) {
234235
if (isMutable) {
236+
// Mutable arguments may already be mapped to a real user-provided shadow
237+
// rather than a placeholder. Only replace placeholders here.
235238
auto existing = invertedPointers.lookupOrNull(val);
236239
if (existing && !existing.getDefiningOp<enzyme::PlaceholderOp>())
237240
return;

enzyme/test/MLIR/ReverseMode/alloca.mlir

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %eopt --enzyme %s | FileCheck %s
1+
// RUN: %eopt --enzyme %s | FileCheck --implicit-check-not=enzyme.placeholder %s
22

33
func.func @foo_flat(%x : f64) -> f64 {
44
%buf = memref.alloca() : memref<f64>
@@ -59,4 +59,52 @@ func.func @dfoo_flat(%x: f64, %dout : f64) -> f64 {
5959
// CHECK: %{{.+}} = "enzyme.get"(%[[GX]]) : (!enzyme.Gradient<f64>) -> f64
6060
// CHECK: return %{{.+}} : f64
6161

62-
// CHECK-NOT: enzyme.placeholder
62+
63+
// -----
64+
65+
func.func @load_arg(%mem: memref<f64>) -> f64 {
66+
%buf = memref.alloca() : memref<f64>
67+
%x = memref.load %mem[] : memref<f64>
68+
memref.store %x, %buf[] : memref<f64>
69+
%y = memref.load %buf[] : memref<f64>
70+
return %y : f64
71+
}
72+
73+
func.func @dload_arg(%mem: memref<f64>, %dmem: memref<f64>, %dout : f64) {
74+
enzyme.autodiff @load_arg(%mem, %dmem, %dout) {
75+
activity = [#enzyme<activity enzyme_dup>],
76+
ret_activity = [#enzyme<activity enzyme_activenoneed>]
77+
} : (memref<f64>, memref<f64>, f64) -> ()
78+
return
79+
}
80+
81+
// CHECK-LABEL: func.func private @diffeload_arg(
82+
// CHECK-SAME: %[[MEM:[^,]+]]: memref<f64>,
83+
// CHECK-SAME: %[[DMEM:[^,]+]]: memref<f64>,
84+
// CHECK-SAME: %[[DOUT:[^)]+]]: f64) {
85+
// CHECK: %[[DBUF:.+]] = memref.alloca() : memref<f64>
86+
// CHECK: linalg.fill ins(%{{.+}} : f64) outs(%[[DBUF]] : memref<f64>)
87+
// CHECK: %[[BUF:.+]] = memref.alloca() : memref<f64>
88+
// CHECK: "enzyme.push"(%{{.+}}, %[[DMEM]]) : (!enzyme.Cache<memref<f64>>, memref<f64>) -> ()
89+
// CHECK: memref.load %[[MEM]][] : memref<f64>
90+
// CHECK: "enzyme.push"(%{{.+}}, %[[DBUF]]) : (!enzyme.Cache<memref<f64>>, memref<f64>) -> ()
91+
// CHECK: memref.store %{{.+}}, %[[BUF]][] : memref<f64>
92+
// CHECK: "enzyme.push"(%{{.+}}, %[[DBUF]]) : (!enzyme.Cache<memref<f64>>, memref<f64>) -> ()
93+
// CHECK: memref.load %[[BUF]][] : memref<f64>
94+
// CHECK: arith.addf %{{.+}}, %[[DOUT]] : f64
95+
// CHECK: %[[POPL:.+]] = "enzyme.pop"(%{{.+}}) : (!enzyme.Cache<memref<f64>>) -> memref<f64>
96+
// CHECK: memref.load %[[POPL]][] : memref<f64>
97+
// CHECK: arith.addf
98+
// CHECK: memref.store %{{.+}}, %[[POPL]][] : memref<f64>
99+
// CHECK: %[[POPS:.+]] = "enzyme.pop"(%{{.+}}) : (!enzyme.Cache<memref<f64>>) -> memref<f64>
100+
// CHECK: memref.load %[[POPS]][] : memref<f64>
101+
// CHECK: "enzyme.get"
102+
// CHECK: arith.addf
103+
// CHECK: "enzyme.set"
104+
// CHECK: memref.store %{{.+}}, %[[POPS]][] : memref<f64>
105+
// CHECK: "enzyme.get"
106+
// CHECK: %[[POPD:.+]] = "enzyme.pop"(%{{.+}}) : (!enzyme.Cache<memref<f64>>) -> memref<f64>
107+
// CHECK: memref.load %[[POPD]][] : memref<f64>
108+
// CHECK: arith.addf
109+
// CHECK: memref.store %{{.+}}, %[[POPD]][] : memref<f64>
110+
// CHECK: return

0 commit comments

Comments
 (0)