SIGN IN SIGN UP

Fix create_constant_placeholder crashing when torch.fx renames the requested placeholder (#21542)

Fixes #14055
Fixes #21541

## Problem

Found while verifying #21489: the textbook CNN used there, one top-level
`nn.Sequential` of conv, batchnorm, relu and maxpool, gets past the
pooling check it used to crash on and now dies one pass later, in
`FuseBatchNormPass`.

`create_constant_placeholder` records the name it requested, not the
name torch.fx assigned:

```python
node = graph.create_node(op="placeholder", name=name, target=name)
...
node_names = [n.name for n in graph.nodes if n.op == "placeholder"]
node_index = node_names.index(name)   # ValueError after any rename
...
arg_spec = TensorArgument(name)
```

torch.fx renames the node whenever the requested name is not a valid
identifier or collides with an existing node. Two plain models trigger
this today. A top-level `nn.Sequential` names its parameters `0.weight`,
so `FuseBatchNormPass` requests `0_weight_fused_bn`, fx assigns
`_0_weight_fused_bn`, and lowering to XNNPACK dies with `ValueError:
'0_weight_fused_bn' is not in list`. torchvision regnet under Vulkan
hits the same lines through its hyphenated module names (#14055). The
identical models behind a named attribute lower fine, which is why
existing coverage never reached this path.

Two further defects sit behind the crash. A placeholder's `target` is
emitted verbatim as a function parameter name on recompile, so fixing
only the lookup produces `def forward(self, 0_weight_fused_bn, ...)`, a
SyntaxError. And the shared-weight dedup from #18031 matched on `target
== name`, so after a rename it misses and creates a duplicate
placeholder.

## Fix

One name everywhere: `node.name`, `node.target`, the state_dict key and
the graph signature all follow the name fx assigned. The requested name
is kept in `node.meta` and used for the dedup, so the #18031 contract is
preserved: a second request for the same name returns the existing node,
now also when fx renamed it. Keying the state_dict by the assigned name
inherits the fx namespace uniqueness guarantee, so a colliding request
can never overwrite an existing parameter.

For any requested name that is a valid identifier with no collision, the
assigned name equals the requested name and behavior is unchanged.

## Effect

Same script on either side of the change, executed on executor_runner
built from this branch. maxdiff is deviation from eager.

```
                                     BEFORE                        AFTER
nn.Sequential(conv, bn, relu)        ValueError at utils.py:151    delegated, maxdiff 4.0e-07
two-block Sequential CNN             ValueError at utils.py:151    delegated, maxdiff 4.8e-07
same models behind an attribute      lower and run                 unchanged, maxdiff <= 5.5e-07
```

## Testing

Two helper tests in `test_create_delete_constant_placeholder.py`: a
digit-leading request checks node, signature, state_dict and a recompile
round trip; a dedup test checks that requesting the same name twice
returns the existing node for a clean, a digit-leading and a hyphenated
name. One pass test in `test_batch_norm_fusion.py` fuses a top-level
Sequential end to end. `test_conv_bn` in
`runtime/test/test_runtime_xnnpack.py`, skipped on this bug, is
re-enabled (linux-gated, runs in CI).

Verified failing-first by reverting only `backends/transforms/utils.py`:
exactly the three new tests fail, all with `ValueError` at
`utils.py:151`.

```
backends/transforms/test + backends/xnnpack/test/passes + runtime/test/test_runtime_xnnpack.py
  main    : 165 passed, 57 skipped
  this PR : 168 passed, 57 skipped
```

lintrunner reports no issues on all changed files.

The helper is shared by the Arm, Vulkan and XNNPACK backends. Callers
passing valid unique names get identical behavior; renamed cases
previously crashed, so no caller can depend on the old behavior.

cc @GregoryComer @digantdesai @cbilgin @JakeStevens
S
shresth rana committed
8812915cb19620e1ae7012365721bce090b88fee
Parent: 4b4df96
Committed by GitHub <noreply@github.com> on 8/4/2026, 11:03:12 AM