From 7f64b2a9e3eb7aea13de550bd24c1aea7787c94b Mon Sep 17 00:00:00 2001 From: Sai Praveen Bangaru <31557731+saipraveenb25@users.noreply.github.com> Date: Wed, 4 Jan 2023 23:40:13 +0530 Subject: Multi-block reverse-mode autodiff (#2576) * Initial multi-block implementation * Implemented multi-block reverse-mode (without loops) * Added logic to remove block-level decorations to avoid confusing IR simplification passes * Fixed issues with block-level decorations during IR simplification by removing them prior to simplification. Co-authored-by: Yong He --- source/slang/slang-ir-autodiff.cpp | 51 +++++++++++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) (limited to 'source/slang/slang-ir-autodiff.cpp') diff --git a/source/slang/slang-ir-autodiff.cpp b/source/slang/slang-ir-autodiff.cpp index f0ec1542e..40c24d11d 100644 --- a/source/slang/slang-ir-autodiff.cpp +++ b/source/slang/slang-ir-autodiff.cpp @@ -421,6 +421,32 @@ void stripAutoDiffDecorations(IRModule* module) stripAutoDiffDecorationsFromChildren(module->getModuleInst()); } + +void stripBlockTypeDecorations(IRFunc* func) +{ + for (auto child : func->getChildren()) + { + if (auto block = as(child)) + { + for (auto decor = block->getFirstDecoration(); decor; ) + { + auto next = decor->getNextDecoration(); + switch (decor->getOp()) + { + case kIROp_DifferentialInstDecoration: + case kIROp_MixedDifferentialInstDecoration: + decor->removeAndDeallocate(); + break; + default: + break; + } + decor = next; + } + } + } +} + + struct StripNoDiffTypeAttributePass : InstPassBase { StripNoDiffTypeAttributePass(IRModule* module) : @@ -484,7 +510,7 @@ struct AutoDiffPass : public InstPassBase { bool changed = false; List autoDiffWorkList; - // Collect all `ForwardDifferentiate` insts from the module. + // Collect all `ForwardDifferentiate`/`BackwardDifferentiate` insts from the module. autoDiffWorkList.clear(); processAllInsts([&](IRInst* inst) { @@ -541,6 +567,7 @@ struct AutoDiffPass : public InstPassBase // Run transcription logic to generate the body of forward/backward derivatives functions. // While doing so, we may discover new functions to differentiate, so we keep running until // the worklist goes dry. + List autodiffCleanupList; while (autodiffContext->followUpFunctionsToTranscribe.getCount() != 0) { changed = true; @@ -549,6 +576,14 @@ struct AutoDiffPass : public InstPassBase { auto diffFunc = as(task.resultFunc); SLANG_ASSERT(diffFunc); + + // We're running in to some situations where the follow-up task + // has already been completed (diffFunc has been generated, processed, + // and deallocated). Skip over these for now. + // + if (!diffFunc->getDataType()) + continue; + auto primalFunc = as(task.originalFunc); SLANG_ASSERT(primalFunc); switch (task.type) @@ -562,12 +597,26 @@ struct AutoDiffPass : public InstPassBase default: break; } + + autodiffCleanupList.add(diffFunc); } } + + // Get rid of block-level decorations that are used to keep track of + // different block types. These don't work well with the IR simplification + // passes since they don't expect decorations in blocks. + // + for (auto diffFunc : autodiffCleanupList) + stripBlockTypeDecorations(diffFunc); + + autodiffCleanupList.clear(); + if (!changed) break; hasChanges |= changed; } + + return hasChanges; } -- cgit v1.2.3