pytorch/torch/_inductor/fx_passes
Yuanyuan Chen 030de07aff [2/N] Use 'is' in callable comparisons (#166685)
It is generally advised to use `is/is not` for comparisons against torch functions.

Pull Request resolved: https://github.com/pytorch/pytorch/pull/166685
Approved by: https://github.com/xmfan, https://github.com/mlazos
2025-10-31 08:08:07 +00:00
..
serialized_patterns Add SDPA patterns for T5 variants when batch size is 1 (#163252) 2025-09-26 08:50:06 +00:00
__init__.py
b2b_gemm.py Use 'is' in callable comparisons (#166624) 2025-10-30 19:00:09 +00:00
binary_folding.py [2/N] Use 'is' in callable comparisons (#166685) 2025-10-31 08:08:07 +00:00
bucketing.py [2/N] Use 'is' in callable comparisons (#166685) 2025-10-31 08:08:07 +00:00
control_dependencies.py Add hop for additional control dependencies (#164568) 2025-10-06 15:47:55 +00:00
ddp_fusion.py [2/N] Use 'is' in callable comparisons (#166685) 2025-10-31 08:08:07 +00:00
decompose_mem_bound_mm.py Fix pyrefly ignore syntax in _inductor (#166247) 2025-10-27 02:48:42 +00:00
dedupe_symint_uses.py Use union syntax in torch/_inductor runtime and fx_passes (#165652) 2025-10-16 20:51:59 +00:00
efficient_conv_bn_eval.py Fix pyrefly ignore syntax in _inductor (#166247) 2025-10-27 02:48:42 +00:00
freezing_patterns.py [2/N] Use 'is' in callable comparisons (#166685) 2025-10-31 08:08:07 +00:00
fsdp.py [2/N] Use 'is' in callable comparisons (#166685) 2025-10-31 08:08:07 +00:00
fuse_attention.py Add SDPA patterns for T5 variants when batch size is 1 (#163252) 2025-09-26 08:50:06 +00:00
group_batch_fusion.py [2/N] Use 'is' in callable comparisons (#166685) 2025-10-31 08:08:07 +00:00
joint_graph.py [2/N] Use 'is' in callable comparisons (#166685) 2025-10-31 08:08:07 +00:00
memory_estimator.py Use union syntax in torch/_inductor runtime and fx_passes (#165652) 2025-10-16 20:51:59 +00:00
micro_pipeline_tp.py [2/N] Use 'is' in callable comparisons (#166685) 2025-10-31 08:08:07 +00:00
misc_patterns.py Fix pyrefly ignore syntax in _inductor (#166247) 2025-10-27 02:48:42 +00:00
mkldnn_fusion.py [2/N] Use 'is' in callable comparisons (#166685) 2025-10-31 08:08:07 +00:00
numeric_utils.py Enable all flake8-logging-format rules (#164655) 2025-10-19 00:59:28 +00:00
overlap_preserving_bucketer.py bucket all reduce (#166528) 2025-10-30 17:12:34 +00:00
overlap_scheduling.py use multi-dtype bucketing (#166527) 2025-10-30 16:54:49 +00:00
pad_mm.py [2/N] Use 'is' in callable comparisons (#166685) 2025-10-31 08:08:07 +00:00
post_grad.py [2/N] Use 'is' in callable comparisons (#166685) 2025-10-31 08:08:07 +00:00
pre_grad.py Use 'is' in callable comparisons (#166624) 2025-10-30 19:00:09 +00:00
quantization.py [2/N] Use 'is' in callable comparisons (#166685) 2025-10-31 08:08:07 +00:00
README.md
reinplace.py [2/N] Use 'is' in callable comparisons (#166685) 2025-10-31 08:08:07 +00:00
replace_random.py Fix pyrefly ignore syntax in _inductor (#166247) 2025-10-27 02:48:42 +00:00
split_cat.py [2/N] Use 'is' in callable comparisons (#166685) 2025-10-31 08:08:07 +00:00

Implicit Invariants for writing FX Graph Passes

Fake Tensor metadata on node

Each FX node has metadata on it, and in particular, stores a faketensor representing the metadata of that node node.meta['val']. This FakeTensor has properties like 1. shape, 2. stride, and 3. aliasing information. However, various passes may change the faketensor values, and so we need to maintain consistency.

The current way we do this is through FakeTensorUpdater (in _inductor/fx_utils.py). Read it for more details, and run it if your pass needs accurate faketensor metadata.

Mutations throughout the stack

The invariant about mutation we have is:

After AOTDispatch tracing and before Inductor, we have no mutation in our graph, except for a copy_ epilogue at the end of the graph.

For example, passes operating on the joint_graph and post_grad graph do not need to worry about mutation at all.

However, we do still have aliasing in the graph. This does not matter most of the time, but it does mean that our passes are not allowed to cause any additional inputs/outputs to alias if they did not alias in the original graph.

For example

def f(x: Tensor):
    return x.clone()

cannot be turned into a no-op, as this would change the semantics of the compiled graph.

In addition, AOTDispatch can introduce a copy_ epilogue into the graph. For example, we may have a graph like

def f(x: Tensor):
    y = x.clone()
    x.copy_(y)
    return y

In this case, we are also not allowed to eliminate x.clone(). Luckily, the condition for when this can cause problems is the same as with aliasing, which is that our passes are not allowed to cause the input and output to alias if they did not alias in the original graph. To check whether the inputs and outputs have any aliasing, it suffices to check whether the storages of the input and the storages of the output have any overlap. See remove_noop_ops for an example of how to do this.

Additionally, we do have one pass that does introduce mutation - reinplace_inplaceable_ops. This pass must run just before Inductor lowering, as otherwise this breaks our invariant.