mirror of https://github.com/llvm/torch-mlir
74 lines
3.9 KiB
TableGen
74 lines
3.9 KiB
TableGen
//===-- Passes.td - Pass definition file -------------------*- tablegen -*-===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef NPCOMP_TORCH_PASSES
|
|
#define NPCOMP_TORCH_PASSES
|
|
|
|
include "mlir/Pass/PassBase.td"
|
|
|
|
def GlobalizeObjectGraph : Pass<"torch-globalize-object-graph", "ModuleOp"> {
|
|
let summary = "Converts TorchScript object graphs to a globalized form";
|
|
let constructor = "mlir::NPCOMP::Torch::createGlobalizeObjectGraphPass()";
|
|
let description = [{
|
|
This pass converts a subset of possible TorchScript modules into a
|
|
more restrictive lower-level form that strips away the need to be
|
|
concerned with instances of !torch.nn.Module<...> type. Specifically,
|
|
the object graph is flattened into a set of discrete globals
|
|
(`torch.global_slot`) that hold the program state.
|
|
|
|
The overarching goal is for a strict correspondence between the original
|
|
`torch.nn.Module` (call it `root`) that the user `torch.jit.script`'ed, and
|
|
the public interface of the resulting MLIR module. Specifically:
|
|
- The call `root.encoder.forward(...)` in Python corresponds to invoking
|
|
the `func @encoder.forward` on the resulting MLIR module.
|
|
- The data member access `root.decoder.ids_to_strings_table` in Python
|
|
corresponds to accessing the
|
|
`torch.global_slot @decoder.ids_to_strings_table` on the resulting
|
|
MLIR module.
|
|
In effect, the entire MLIR module corresponds to an instance of the `root`
|
|
object. This matches with the intuitive behavior desired for deployment:
|
|
When the MLIR module (or, more likely, a compiled artifact derived from it)
|
|
is loaded in a deployed environment, it is equivalent to recreating the
|
|
original `root` object.
|
|
|
|
This pass performs a complete change of the externally visible calling
|
|
convention of the MLIR module for a graph of objects and methods to a
|
|
fixed set of globals and functions.
|
|
|
|
Of course, only a subset of programs can be transformed, and this pass fails
|
|
with an error if the conditions are violated.
|
|
|
|
Specifically, the restrictions are:
|
|
- There must be a unique torch.nn_module that is not the value of a slot
|
|
of any other torch.nn_module
|
|
- Rationale: Allows us to have a notion of a unique "root" op, which is
|
|
used to define linkage. This also matches how TorchScript imports in
|
|
practice (`torch.jit.script` imports a single root object).
|
|
- There must be exactly one instance of each torch.class_type. Equivalently,
|
|
Every torch.nn_module must have a distinct type.
|
|
- Rationale: This guarantee precludes things like selecting between
|
|
multiple modules dynamically at runtime, which would require indirecting
|
|
between the separate storage of each instance.
|
|
- All torch.nn_module's must be reachable by a unique path from the root
|
|
- Rationale: Eliminates possibility of potentially exponential number of
|
|
paths. Or worse, infinite number of paths when considering cyclic
|
|
object graphs. Also as of Feb 2021, TorchScript won't import into
|
|
this form (it has a bug related to the identity of submodules).
|
|
- Two slots cannot have initial values that alias each other.
|
|
- Rationale: This makes the representation of initial values simpler. Also
|
|
as of Feb 2021, TorchScript won't import into this form except
|
|
potentially for Tensors (it has a bug related to the identity of
|
|
objects). And for tensors, the npcomp IValue importer only supports a
|
|
very restricted form of aliasing anyway for other reasons. We are
|
|
waiting for signals that more general handling of object aliasing is
|
|
important to devote the effort to it.
|
|
}];
|
|
}
|
|
|
|
#endif // NPCOMP_TORCH_PASSES
|