diff options
| author | Sai Praveen Bangaru <31557731+saipraveenb25@users.noreply.github.com> | 2022-06-23 16:02:05 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-06-23 16:02:05 -0400 |
| commit | 6cf3d496005c5635b273d9ce6c110f14541a9492 (patch) | |
| tree | 91d6480cec20ca88e85fb9b4d437e4661fba229c /source/slang/slang-ir-diff-call.cpp | |
| parent | 4aa6344f772d31c1f7b0676cbaf315104c4b30a2 (diff) | |
Added basic syntax to mark and request function derivatives, as well as the framework for passes to process them. (#2297)
* Added a decorator to mark functions for forward-mode differentiation
* Fill out support for calls to non-decl values
The existing compiler logic has a few places (semantic checking plus AST-to-IR lowering) where it assumes that function calls (`InvokeExpr`) are only ever made to expressions that resolve to a specific `Decl` (`DeclRefExpr`). This assumption allows semantic checking and lowering code to inspect things like the parameter list of an actual declaration, rather than just the type signature of the callee, and that infrastructure is used to support various features (e.g., default argument values on parameters).
The AST and IR representations themselves have no matching requirement, and the places where the more general case of call expressions would need to be supported were relatively clear in the code. This change attempts to add suitable logic into each of those places.
Note that this change does *not* surface any valid way to form input code that would cause these new code paths to be executed, so it is entirely possible that there are bugs in the logic as written here. The primary goal of this change is simply to get a sketch of the correct code checked in so that we have something to build on once we have language features that will require this support.
* fixup: warnings-as-errors
* Added parser logic for '__jvp(<fn-name>)' operator
* Fixed issue with missing overload candidate item and added basic parsing test for the __jvp syntax
* Added a blank JVP Auto-diff pass and a pass that replaces 'JVPDerivativeOf' calls with the differentiated function
* Added a couple comments
* Added parameter handling for the JVP pass
Co-authored-by: Theresa Foley <tfoley@nvidia.com>
Diffstat (limited to 'source/slang/slang-ir-diff-call.cpp')
| -rw-r--r-- | source/slang/slang-ir-diff-call.cpp | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/source/slang/slang-ir-diff-call.cpp b/source/slang/slang-ir-diff-call.cpp new file mode 100644 index 000000000..76ffe3c8b --- /dev/null +++ b/source/slang/slang-ir-diff-call.cpp @@ -0,0 +1,90 @@ +// slang-ir-diff-call.cpp +#include "slang-ir-diff-call.h" + +#include "slang-ir.h" +#include "slang-ir-insts.h" + +namespace Slang +{ + +struct DerivativeCallProcessContext +{ + // This type passes over the module and replaces + // derivative calls with the processed derivative + // function. + // + IRModule* module; + + bool processModule() + { + // Run through all the global-level instructions, + // looking for callable blocks. + for (auto inst : module->getGlobalInsts()) + { + // If the instr is a callable, get all the basic blocks + if (auto callable = as<IRGlobalValueWithCode>(inst)) + { + // Iterate over each block in the callable + for (auto block : callable->getBlocks()) + { + // Iterate over each child instruction. + auto child = block->getFirstInst(); + if (!child) continue; + + do + { + auto nextChild = child->getNextInst(); + // Look for IRJVPDerivativeOf + if (auto derivOf = as<IRJVPDerivativeOf>(child)) + { + processDerivativeOf(derivOf); + } + child = nextChild; + } + while (child); + } + } + } + return true; + } + + // Perform forward-mode automatic differentiation on + // the intstructions. + void processDerivativeOf(IRJVPDerivativeOf* derivOfInst) + { + IRFunc* jvpFunc = nullptr; + + // Resolve the derivative function. + // + // Check for the 'JVPDerivativeReference' decorator on the + // base function. + if (auto jvpRefDecorator = derivOfInst->base.get()->findDecoration<IRJVPDerivativeReferenceDecoration>()) + { + jvpFunc = jvpRefDecorator->getJVPFunc(); + } + + // Substitute all uses of the 'derivativeOf' operation + // with the resolved derivative function. + while (auto use = derivOfInst->firstUse) + { + use->set(jvpFunc); + } + + // Remove the 'derivativeOf' + derivOfInst->removeAndDeallocate(); + } +}; + +// Set up context and call main process method. +// +bool processDerivativeCalls( + IRModule* module, + IRDerivativeCallProcessOptions const&) +{ + DerivativeCallProcessContext context; + context.module = module; + + return context.processModule(); +} + +} |
