Repository: pytorch
Issue: [Dynamo]Illegal getattr invocation requires_grad in strict mode
Labels: triaged,oncall: pt2,module: dynamo,module: higher order operators,module: pt2-dispatcher,dynamo-autograd-function

### 🐛 Describe the bug

Hello, we got `torch._dynamo.exc.Unsupported: Illegal getattr invocation requires_grad in strict mode` when trying to check the `requires_grad` attr of a tensor in backward. Can we make it read-able and restrict write?

### Error logs

```
Traceback (most recent call last):
  File "dynamo_read_require_grad.py", line 42, in <module>
    main()
  File "dynamo_read_require_grad.py", line 36, in main
    r = custom_function(a)
  File "/Users/chenxiny/miniforge3/envs/torch-metal/lib/python3.8/site-packages/torch/_dynamo/eval_frame.py", line 462, in _fn
    return fn(*args, **kwargs)
  File "/Users/chenxiny/miniforge3/envs/torch-metal/lib/python3.8/site-packages/torch/_dynamo/convert_frame.py", line 1182, in __call__
    return self._torchdynamo_orig_callable(
  File "/Users/chenxiny/miniforge3/envs/torch-metal/lib/python3.8/site-packages/torch/_dynamo/convert_frame.py", line 506, in __call__
    return _compile(
  File "/Users/chenxiny/miniforge3/envs/torch-metal/lib/python3.8/contextlib.py", line 75, in inner
    return func(*args, **kwds)
  File "/Users/chenxiny/miniforge3/envs/torch-metal/lib/python3.8/site-packages/torch/_dynamo/convert_frame.py", line 862, in _compile
    guarded_code = compile_inner(code, one_graph, hooks, transform)
  File "/Users/chenxiny/miniforge3/envs/torch-metal/lib/python3.8/site-packages/torch/_dynamo/utils.py", line 272, in time_wrapper
    r = func(*args, **kwargs)
  File "/Users/chenxiny/miniforge3/envs/torch-metal/lib/python3.8/site-packages/torch/_utils_internal.py", line 85, in wrapper_function
    return StrobelightCompileTimeProfiler.profile_compile_time(
  File "/Users/chenxiny/miniforge3/envs/torch-metal/lib/python3.8/site-packages/torch/_strobelight/compile_time_profiler.py", line 129, in profile_compile_time
    return func(*args, **kwargs)
  File "/Users/chenxiny/miniforge3/envs/torch-metal/lib/python3.8/site-packages/torch/_dynamo/convert_frame.py", line 680, in compile_inner
    out_code = transform_code_object(code, transform)
  File "/Users/chenxiny/miniforge3/envs/torch-metal/lib/python3.8/site-packages/torch/_dynamo/bytecode_transformation.py", line 1322, in transform_code_object
    transformations(instructions, code_options)
  File "/Users/chenxiny/miniforge3/envs/torch-metal/lib/python3.8/site-packages/torch/_dynamo/convert_frame.py", line 201, in _fn
    return fn(*args, **kwargs)
  File "/Users/chenxiny/miniforge3/envs/torch-metal/lib/python3.8/site-packages/torch/_dynamo/convert_frame.py", line 622, in transform
    tracer.run()
  File "/Users/chenxiny/miniforge3/envs/torch-metal/lib/python3.8/site-packages/torch/_dynamo/symbolic_convert.py", line 2657, in run
    super().run()
  File "/Users/chenxiny/miniforge3/envs/torch-metal/lib/python3.8/site-packages/torch/_dynamo/symbolic_convert.py", line 925, in run
    while self.step():
  File "/Users/chenxiny/miniforge3/envs/torch-metal/lib/python3.8/site-packages/torch/_dynamo/symbolic_convert.py", line 837, in step
    self.dispatch_table[inst.opcode](self, inst)
  File "/Users/chenxiny/miniforge3/envs/torch-metal/lib/python3.8/site-packages/torch/_dynamo/symbolic_convert.py", line 529, in wrapper
    return inner_fn(self, inst)
  File "/Users/chenxiny/miniforge3/envs/torch-metal/lib/python3.8/site-packages/torch/_dynamo/symbolic_convert.py", line 1532, in CALL_FUNCTION
    self.call_function(fn, args, {})
  File "/Users/chenxiny/miniforge3/envs/torch-metal/lib/python3.8/site-packages/torch/_dynamo/symbolic_convert.py", line 775, in call_function
    self.push(fn.call_function(self, args, kwargs))  # type: ignore[arg-type]
  File "/Users/chenxiny/miniforge3/envs/torch-metal/lib/python3.8/site-packages/torch/_dynamo/variables/misc.py", line 757, in call_function
    return self.obj.call_method(tx, self.name, args, kwargs)
  File "/Users/chenxiny/miniforge3/envs/torch-metal/lib/python3.8/site-packages/torch/_dynamo/variables/misc.py", line 514, in call_method
    return self.call_apply(tx, args, kwargs)
  File "/Users/chenxiny/miniforge3/envs/torch-metal/lib/python3.8/site-packages/torch/_dynamo/variables/misc.py", line 434, in call_apply
    val = AutogradFunctionApplyVariable(
  File "/Users/chenxiny/miniforge3/envs/torch-metal/lib/python3.8/site-packages/torch/_dynamo/variables/higher_order_ops.py", line 1862, in call_function
    (bwd_out, _), bwd_graph, bwd_freevars = speculate_subgraph(
  File "/Users/chenxiny/miniforge3/envs/torch-metal/lib/python3.8/site-packages/torch/_dynamo/variables/higher_order_ops.py", line 528, in speculate_subgraph
    raise ex
  File "/Users/chenxiny/miniforge3/envs/torch-metal/lib/python3.8/site-packages/torch/_dynamo/variables/higher_order_ops.py", line 457, in speculate_subgraph
    output = f.call_function(tx, args, sub_kwargs)
  File "/Users/chenxiny/miniforge3/envs/torch-metal/lib/python3.8/site-packages/torch/_dynamo/variables/functions.py", line 309, in call_function
    return super().call_function(tx, args, kwargs)
  File "/Users/chenxiny/miniforge3/envs/torch-metal/lib/python3.8/site-packages/torch/_dynamo/variables/functions.py", line 106, in call_function
    return tx.inline_user_function_return(self, [*self.self_args(), *args], kwargs)
  File "/Users/chenxiny/miniforge3/envs/torch-metal/lib/python3.8/site-packages/torch/_dynamo/symbolic_convert.py", line 781, in inline_user_function_return
    return InliningInstructionTranslator.inline_call(self, fn, args, kwargs)
  File "/Users/chenxiny/miniforge3/envs/torch-metal/lib/python3.8/site-packages/torch/_dynamo/symbolic_convert.py", line 2872, in inline_call
    return cls.inline_call_(parent, func, args, kwargs)
  File "/Users/chenxiny/miniforge3/envs/torch-metal/lib/python3.8/site-packages/torch/_dynamo/symbolic_convert.py", line 2988, in inline_call_
    tracer.run()
  File "/Users/chenxiny/miniforge3/envs/torch-metal/lib/python3.8/site-packages/torch/_dynamo/symbolic_convert.py", line 925, in run
    while self.step():
  File "/Users/chenxiny/miniforge3/envs/torch-metal/lib/python3.8/site-packages/torch/_dynamo/symbolic_convert.py", line 837, in step
    self.dispatch_table[inst.opcode](self, inst)
  File "/Users/chenxiny/miniforge3/envs/torch-metal/lib/python3.8/site-packages/torch/_dynamo/symbolic_convert.py", line 1657, in LOAD_ATTR
    self._load_attr(inst)
  File "/Users/chenxiny/miniforge3/envs/torch-metal/lib/python3.8/site-packages/torch/_dynamo/symbolic_convert.py", line 1647, in _load_attr
    result = BuiltinVariable(getattr).call_function(
  File "/Users/chenxiny/miniforge3/envs/torch-metal/lib/python3.8/site-packages/torch/_dynamo/variables/builtin.py", line 978, in call_function
    return handler(tx, args, kwargs)
  File "/Users/chenxiny/miniforge3/envs/torch-metal/lib/python3.8/site-packages/torch/_dynamo/variables/builtin.py", line 859, in builtin_dipatch
    rv = fn(tx, args, kwargs)
  File "/Users/chenxiny/miniforge3/envs/torch-metal/lib/python3.8/site-packages/torch/_dynamo/variables/builtin.py", line 777, in call_self_handler
    result = self_handler(tx, *args, **kwargs)
  File "/Users/chenxiny/miniforge3/envs/torch-metal/lib/python3.8/site-packages/torch/_dynamo/variables/builtin.py", line 1683, in call_getattr
    return obj.var_getattr(tx, name)
  File "/Users/chenxiny/miniforge3/envs/torch-metal/lib/python3.8/site-packages/torch/_dynamo/variables/tensor.py", line 366, in var_getattr
    unimplemented(f"Illegal getattr invocation {name} in strict mode")
  File "/Users/chenxiny/miniforge3/envs/torch-metal/lib/python3.8/site-packages/torch/_dynamo/exc.py", line 271, in unimplemented
    raise Unsupported(msg, case_name=case_name)
torch._dynamo.exc.Unsupported: Illegal getattr invocation requires_grad in strict mode

from user code:
   File "dynamo_read_require_grad.py", line 30, in custom_function
    x = CustomOp.apply(x)
  File "dynamo_read_require_grad.py", line 19, in backward
    if outputs.requires_grad:

Set TORCH_LOGS="+dynamo" and TORCHDYNAMO_VERBOSE=1 for more information


You can suppress this exception and fall back to eager by setting:
    import torch._dynamo
    torch._dynamo.config.suppress_errors = True
```

### Minified repro

```
import torch


class CustomOp(torch.autograd.Function):
	@staticmethod
	def forward(ctx, i):
		result = i + i
		ctx.save_for_backward = i
		return result

	@staticmethod
	def backward(ctx, grad_output):
		input = ctx.save_for_backward
		detached_inputs = input.detach()
		with torch.enable_grad():
			outputs = detached_inputs * detached_inputs
		output_tensors = []
		grad_tensors = []
		if outputs.requires_grad:
			output_tensors.append(outputs)
			grad_tensors.append(grad_output)
		
		torch.autograd.backward(output_tensors, grad_tensors)

		return detached_inputs.grad()


@torch.compile(backend='inductor', fullgraph=True)
def custom_function(x):
	x = CustomOp.apply(x)
	return x


def main():
	a = torch.tensor([1., 2.]).requires_grad_(True)
	r = custom_function(a)
	l = torch.sum(r)
	l.backward(torch.tensor(1.))


if __name__ == "__main__":
	main()


```

### Versions

```
PyTorch version: 2.5.0.dev20240729
Is debug build: False
CUDA used to build PyTorch: None
ROCM used to build PyTorch: N/A

OS: macOS 14.3.1 (arm64)
GCC version: Could not collect
Clang version: 15.0.0 (clang-1500.3.9.4)
CMake version: version 3.30.0
Libc version: N/A

Python version: 3.8.18 (default, Sep 11 2023, 08:17:16)  [Clang 14.0.6 ] (64-bit runtime)
Python platform: macOS-14.3.1-arm64-arm-64bit
Is CUDA available: False
CUDA runtime version: No CUDA
CUDA_MODULE_LOADING set to: N/A
GPU models and configuration: No CUDA
Nvidia driver version: No CUDA
cuDNN version: No CUDA
HIP runtime version: N/A
MIOpen runtime version: N/A
Is XNNPACK available: True

CPU:
Apple M1 Pro

Versions of relevant libraries:
[pip3] numpy==1.24.3
[pip3] onnx==1.16.1
[pip3] onnx2torch==1.5.14
[pip3] optree==0.11.0
[pip3] pytorch-lightning==1.7.7
[pip3] torch==2.5.0a0+git1f961ad
[pip3] torchaudio==2.4.0.dev20240729
[pip3] torchmetrics==0.10.0
[pip3] torchvision==0.12.0
[conda] numpy                     1.22.3                   pypi_0    pypi
[conda] numpy-base                1.24.3           py38h90707a3_0
[conda] onnx2torch                1.5.14                   pypi_0    pypi
[conda] optree                    0.11.0                   pypi_0    pypi
[conda] pytorch-lightning         1.7.7                    pypi_0    pypi
[conda] torch                     1.12.0.dev20220518          pypi_0    pypi
[conda] torchaudio                2.4.0.dev20240729          pypi_0    pypi
[conda] torchmetrics              0.10.0                   pypi_0    pypi
[conda] torchvision               0.12.0                   pypi_0    pypi
```

cc @ezyang @chauhang @penguinwu @voznesenskym @EikanWang @jgong5 @Guobing-Chen @XiaobingSuper @zhuhaozhe @blzheng @wenzhe-nrv @jiayisunx @chenyang78 @kadeng @amjames @zou3519 @ydwu4 @bdhirsh