Repository: pytorch
Issue: Skip empty frames recursively when top-level is empty
Labels: triaged,oncall: pt2,module: dynamo

### 🐛 Describe the bug

```python
import torch

def k(x):
    return x

def g(x):
    return k(x)

def f(x):
    return g(x)
a = torch.ones(2, 2)
c = torch.compile(f, fullgraph=True)(a)
```

The above compile 3 times, f, g, and k with following log:
```
I0107 16:55:09.455000 1702873 torch/_dynamo/utils.py:1403] [0/0] ChromiumEventLogger initialized with id 50c41bbc-3619-4642-a30a-ca5562f3b129
V0107 16:55:09.456000 1702873 torch/_dynamo/convert_frame.py:941] [0/0] torchdynamo start compiling f /data/users/yidi/pytorch/test_while_loop.py:9, stack (elided 4 frames):
V0107 16:55:09.456000 1702873 torch/_dynamo/convert_frame.py:941] [0/0]   File "/data/users/yidi/pytorch/test_while_loop.py", line 12, in <module>
V0107 16:55:09.456000 1702873 torch/_dynamo/convert_frame.py:941] [0/0]     c = torch.compile(f, fullgraph=True)(a)
V0107 16:55:09.456000 1702873 torch/_dynamo/convert_frame.py:941] [0/0] 
I0107 16:55:10.342000 1702873 torch/_dynamo/symbolic_convert.py:2744] [0/0] Step 1: torchdynamo start tracing f /data/users/yidi/pytorch/test_while_loop.py:9
I0107 16:55:10.343000 1702873 torch/fx/experimental/symbolic_shapes.py:3221] [0/0] create_env
V0107 16:55:10.347000 1702873 torch/_dynamo/symbolic_convert.py:956] [0/0] [__trace_source] TRACE starts_line /data/users/yidi/pytorch/test_while_loop.py:10 in f (f)
V0107 16:55:10.347000 1702873 torch/_dynamo/symbolic_convert.py:956] [0/0] [__trace_source]         return g(x)
V0107 16:55:10.348000 1702873 torch/_dynamo/symbolic_convert.py:979] [0/0] [__trace_bytecode] TRACE LOAD_GLOBAL g []
V0107 16:55:10.351000 1702873 torch/_dynamo/symbolic_convert.py:979] [0/0] [__trace_bytecode] TRACE LOAD_FAST x [UserFunctionVariable()]
V0107 16:55:10.351000 1702873 torch/_dynamo/symbolic_convert.py:979] [0/0] [__trace_bytecode] TRACE CALL_FUNCTION 1 [UserFunctionVariable(), LazyVariableTracker()]
V0107 16:55:10.351000 1702873 torch/_dynamo/symbolic_convert.py:3204] [0/0] INLINING <code object g at 0x7f4599c97260, file "/data/users/yidi/pytorch/test_while_loop.py", line 6>, inlined according trace_rules.lookup inlined by default
V0107 16:55:10.352000 1702873 torch/_dynamo/variables/builder.py:2869] [0/0] wrap_to_fake L['x'] (2, 2) StatefulSymbolicContext(dynamic_sizes=[<DimDynamic.STATIC: 2>, <DimDynamic.STATIC: 2>], dynamic_strides=[<DimDynamic.INFER_STRIDE: 4>, <DimDynamic.INFER_STRIDE: 4>], constraint_sizes=[None, None], constraint_strides=[None, None], view_base_context=None, tensor_source=LocalSource(local_name='x', is_input=True, is_derefed_cell_contents=False), shape_env_to_source_to_symbol_cache={}) <class 'torch.Tensor'>
V0107 16:55:10.354000 1702873 torch/_dynamo/output_graph.py:2201] [0/0] create_graph_input L_x_ L['x'] FakeTensor(..., size=(2, 2)) at debug_level 0 before=False
V0107 16:55:10.355000 1702873 torch/_dynamo/symbolic_convert.py:956] [0/0] [__trace_source] TRACE starts_line /data/users/yidi/pytorch/test_while_loop.py:7 in g (g) (inline depth: 1)
V0107 16:55:10.355000 1702873 torch/_dynamo/symbolic_convert.py:956] [0/0] [__trace_source]         return k(x)
V0107 16:55:10.355000 1702873 torch/_dynamo/symbolic_convert.py:979] [0/0] [__trace_bytecode] TRACE LOAD_GLOBAL k []
V0107 16:55:10.355000 1702873 torch/_dynamo/symbolic_convert.py:979] [0/0] [__trace_bytecode] TRACE LOAD_FAST x [UserFunctionVariable()]
V0107 16:55:10.355000 1702873 torch/_dynamo/symbolic_convert.py:979] [0/0] [__trace_bytecode] TRACE CALL_FUNCTION 1 [UserFunctionVariable(), TensorVariable()]
V0107 16:55:10.356000 1702873 torch/_dynamo/symbolic_convert.py:3204] [0/0] INLINING <code object k at 0x7f4599d3b3c0, file "/data/users/yidi/pytorch/test_while_loop.py", line 3>, inlined according trace_rules.lookup inlined by default
V0107 16:55:10.356000 1702873 torch/_dynamo/symbolic_convert.py:956] [0/0] [__trace_source] TRACE starts_line /data/users/yidi/pytorch/test_while_loop.py:4 in k (k) (inline depth: 2)
V0107 16:55:10.356000 1702873 torch/_dynamo/symbolic_convert.py:956] [0/0] [__trace_source]         return x
V0107 16:55:10.356000 1702873 torch/_dynamo/symbolic_convert.py:979] [0/0] [__trace_bytecode] TRACE LOAD_FAST x []
V0107 16:55:10.356000 1702873 torch/_dynamo/symbolic_convert.py:979] [0/0] [__trace_bytecode] TRACE RETURN_VALUE None [TensorVariable()]
V0107 16:55:10.356000 1702873 torch/_dynamo/symbolic_convert.py:3272] [0/0] DONE INLINING <code object k at 0x7f4599d3b3c0, file "/data/users/yidi/pytorch/test_while_loop.py", line 3>
V0107 16:55:10.357000 1702873 torch/_dynamo/symbolic_convert.py:979] [0/0] [__trace_bytecode] TRACE RETURN_VALUE None [TensorVariable()]
V0107 16:55:10.357000 1702873 torch/_dynamo/symbolic_convert.py:3272] [0/0] DONE INLINING <code object g at 0x7f4599c97260, file "/data/users/yidi/pytorch/test_while_loop.py", line 6>
V0107 16:55:10.357000 1702873 torch/_dynamo/symbolic_convert.py:979] [0/0] [__trace_bytecode] TRACE RETURN_VALUE None [TensorVariable()]
V0107 16:55:10.357000 1702873 torch/_dynamo/convert_frame.py:778] [0/0] Skipping frame because no content in function call f                     /data/users/yidi/pytorch/test_while_loop.py 9
V0107 16:55:10.357000 1702873 torch/_dynamo/convert_frame.py:787] [0/0] No graph captured with one_graph=True
I0107 16:55:10.358000 1702873 torch/_dynamo/pgo.py:639] [0/0] put_code_state: no cache key, skipping
I0107 16:55:10.358000 1702873 torch/_dynamo/convert_frame.py:1059] [0/0] run_gc_after_compile: running gc
V0107 16:55:10.365000 1702873 torch/_dynamo/convert_frame.py:941] [1/0] torchdynamo start compiling g /data/users/yidi/pytorch/test_while_loop.py:6, stack (elided 4 frames):
V0107 16:55:10.365000 1702873 torch/_dynamo/convert_frame.py:941] [1/0]   File "/data/users/yidi/pytorch/test_while_loop.py", line 12, in <module>
V0107 16:55:10.365000 1702873 torch/_dynamo/convert_frame.py:941] [1/0]     c = torch.compile(f, fullgraph=True)(a)
V0107 16:55:10.365000 1702873 torch/_dynamo/convert_frame.py:941] [1/0]   File "/data/users/yidi/pytorch/torch/_dynamo/eval_frame.py", line 576, in _fn
V0107 16:55:10.365000 1702873 torch/_dynamo/convert_frame.py:941] [1/0]     return fn(*args, **kwargs)
V0107 16:55:10.365000 1702873 torch/_dynamo/convert_frame.py:941] [1/0] 
I0107 16:55:10.365000 1702873 torch/_dynamo/symbolic_convert.py:2744] [1/0] Step 1: torchdynamo start tracing g /data/users/yidi/pytorch/test_while_loop.py:6
I0107 16:55:10.365000 1702873 torch/fx/experimental/symbolic_shapes.py:3221] [1/0] create_env
V0107 16:55:10.366000 1702873 torch/_dynamo/symbolic_convert.py:956] [1/0] [__trace_source] TRACE starts_line /data/users/yidi/pytorch/test_while_loop.py:7 in g (g)
V0107 16:55:10.366000 1702873 torch/_dynamo/symbolic_convert.py:956] [1/0] [__trace_source]         return k(x)
V0107 16:55:10.366000 1702873 torch/_dynamo/symbolic_convert.py:979] [1/0] [__trace_bytecode] TRACE LOAD_GLOBAL k []
V0107 16:55:10.367000 1702873 torch/_dynamo/symbolic_convert.py:979] [1/0] [__trace_bytecode] TRACE LOAD_FAST x [UserFunctionVariable()]
V0107 16:55:10.367000 1702873 torch/_dynamo/symbolic_convert.py:979] [1/0] [__trace_bytecode] TRACE CALL_FUNCTION 1 [UserFunctionVariable(), LazyVariableTracker()]
V0107 16:55:10.367000 1702873 torch/_dynamo/symbolic_convert.py:3204] [1/0] INLINING <code object k at 0x7f4599d3b3c0, file "/data/users/yidi/pytorch/test_while_loop.py", line 3>, inlined according trace_rules.lookup inlined by default
V0107 16:55:10.367000 1702873 torch/_dynamo/variables/builder.py:2869] [1/0] wrap_to_fake L['x'] (2, 2) StatefulSymbolicContext(dynamic_sizes=[<DimDynamic.STATIC: 2>, <DimDynamic.STATIC: 2>], dynamic_strides=[<DimDynamic.INFER_STRIDE: 4>, <DimDynamic.INFER_STRIDE: 4>], constraint_sizes=[None, None], constraint_strides=[None, None], view_base_context=None, tensor_source=LocalSource(local_name='x', is_input=True, is_derefed_cell_contents=False), shape_env_to_source_to_symbol_cache={}) <class 'torch.Tensor'>
V0107 16:55:10.368000 1702873 torch/_dynamo/output_graph.py:2201] [1/0] create_graph_input L_x_ L['x'] FakeTensor(..., size=(2, 2)) at debug_level 0 before=False
V0107 16:55:10.369000 1702873 torch/_dynamo/symbolic_convert.py:956] [1/0] [__trace_source] TRACE starts_line /data/users/yidi/pytorch/test_while_loop.py:4 in k (k) (inline depth: 1)
V0107 16:55:10.369000 1702873 torch/_dynamo/symbolic_convert.py:956] [1/0] [__trace_source]         return x
V0107 16:55:10.369000 1702873 torch/_dynamo/symbolic_convert.py:979] [1/0] [__trace_bytecode] TRACE LOAD_FAST x []
V0107 16:55:10.369000 1702873 torch/_dynamo/symbolic_convert.py:979] [1/0] [__trace_bytecode] TRACE RETURN_VALUE None [TensorVariable()]
V0107 16:55:10.369000 1702873 torch/_dynamo/symbolic_convert.py:3272] [1/0] DONE INLINING <code object k at 0x7f4599d3b3c0, file "/data/users/yidi/pytorch/test_while_loop.py", line 3>
V0107 16:55:10.369000 1702873 torch/_dynamo/symbolic_convert.py:979] [1/0] [__trace_bytecode] TRACE RETURN_VALUE None [TensorVariable()]
V0107 16:55:10.370000 1702873 torch/_dynamo/convert_frame.py:778] [1/0] Skipping frame because no content in function call g                     /data/users/yidi/pytorch/test_while_loop.py 6
V0107 16:55:10.370000 1702873 torch/_dynamo/convert_frame.py:787] [1/0] No graph captured with one_graph=True
I0107 16:55:10.370000 1702873 torch/_dynamo/pgo.py:639] [1/0] put_code_state: no cache key, skipping
I0107 16:55:10.370000 1702873 torch/_dynamo/convert_frame.py:1059] [1/0] run_gc_after_compile: running gc
V0107 16:55:10.374000 1702873 torch/_dynamo/convert_frame.py:941] [2/0] torchdynamo start compiling k /data/users/yidi/pytorch/test_while_loop.py:3, stack (elided 4 frames):
V0107 16:55:10.374000 1702873 torch/_dynamo/convert_frame.py:941] [2/0]   File "/data/users/yidi/pytorch/test_while_loop.py", line 12, in <module>
V0107 16:55:10.374000 1702873 torch/_dynamo/convert_frame.py:941] [2/0]     c = torch.compile(f, fullgraph=True)(a)
V0107 16:55:10.374000 1702873 torch/_dynamo/convert_frame.py:941] [2/0]   File "/data/users/yidi/pytorch/torch/_dynamo/eval_frame.py", line 576, in _fn
V0107 16:55:10.374000 1702873 torch/_dynamo/convert_frame.py:941] [2/0]     return fn(*args, **kwargs)
V0107 16:55:10.374000 1702873 torch/_dynamo/convert_frame.py:941] [2/0]   File "/data/users/yidi/pytorch/test_while_loop.py", line 10, in f
V0107 16:55:10.374000 1702873 torch/_dynamo/convert_frame.py:941] [2/0]     return g(x)
V0107 16:55:10.374000 1702873 torch/_dynamo/convert_frame.py:941] [2/0] 
I0107 16:55:10.374000 1702873 torch/_dynamo/symbolic_convert.py:2744] [2/0] Step 1: torchdynamo start tracing k /data/users/yidi/pytorch/test_while_loop.py:3
I0107 16:55:10.375000 1702873 torch/fx/experimental/symbolic_shapes.py:3221] [2/0] create_env
V0107 16:55:10.375000 1702873 torch/_dynamo/symbolic_convert.py:956] [2/0] [__trace_source] TRACE starts_line /data/users/yidi/pytorch/test_while_loop.py:4 in k (k)
V0107 16:55:10.375000 1702873 torch/_dynamo/symbolic_convert.py:956] [2/0] [__trace_source]         return x
V0107 16:55:10.375000 1702873 torch/_dynamo/symbolic_convert.py:979] [2/0] [__trace_bytecode] TRACE LOAD_FAST x []
V0107 16:55:10.375000 1702873 torch/_dynamo/symbolic_convert.py:979] [2/0] [__trace_bytecode] TRACE RETURN_VALUE None [LazyVariableTracker()]
V0107 16:55:10.376000 1702873 torch/_dynamo/variables/builder.py:2869] [2/0] wrap_to_fake L['x'] (2, 2) StatefulSymbolicContext(dynamic_sizes=[<DimDynamic.STATIC: 2>, <DimDynamic.STATIC: 2>], dynamic_strides=[<DimDynamic.INFER_STRIDE: 4>, <DimDynamic.INFER_STRIDE: 4>], constraint_sizes=[None, None], constraint_strides=[None, None], view_base_context=None, tensor_source=LocalSource(local_name='x', is_input=True, is_derefed_cell_contents=False), shape_env_to_source_to_symbol_cache={}) <class 'torch.Tensor'>
V0107 16:55:10.376000 1702873 torch/_dynamo/output_graph.py:2201] [2/0] create_graph_input L_x_ L['x'] FakeTensor(..., size=(2, 2)) at debug_level 0 before=False
V0107 16:55:10.377000 1702873 torch/_dynamo/convert_frame.py:778] [2/0] Skipping frame because no content in function call k                     /data/users/yidi/pytorch/test_while_loop.py 3
V0107 16:55:10.377000 1702873 torch/_dynamo/convert_frame.py:787] [2/0] No graph captured with one_graph=True
I0107 16:55:10.377000 1702873 torch/_dynamo/pgo.py:639] [2/0] put_code_state: no cache key, skipping
I0107 16:55:10.377000 1702873 torch/_dynamo/convert_frame.py:1059] [2/0] run_gc_after_compile: running gc
I0107 16:55:12.533000 1703243 torch/_dynamo/eval_frame.py:398] TorchDynamo attempted to trace the following frames: [
I0107 16:55:12.533000 1703243 torch/_dynamo/eval_frame.py:398] 
I0107 16:55:12.533000 1703243 torch/_dynamo/eval_frame.py:398] ]
I0107 16:55:12.538000 1703243 torch/_dynamo/utils.py:636] TorchDynamo compilation metrics:
I0107 16:55:12.538000 1703243 torch/_dynamo/utils.py:636] Function    Runtimes (s)
I0107 16:55:12.538000 1703243 torch/_dynamo/utils.py:636] ----------  --------------
V0107 16:55:12.538000 1703243 torch/fx/experimental/symbolic_shapes.py:172] lru_cache_stats constrain_symbol_range: CacheInfo(hits=0, misses=0, maxsize=None, currsize=0)
V0107 16:55:12.539000 1703243 torch/fx/experimental/symbolic_shapes.py:172] lru_cache_stats defer_runtime_assert: CacheInfo(hits=0, misses=0, maxsize=256, currsize=0)
V0107 16:55:12.539000 1703243 torch/fx/experimental/symbolic_shapes.py:172] lru_cache_stats evaluate_expr: CacheInfo(hits=0, misses=0, maxsize=256, currsize=0)
V0107 16:55:12.539000 1703243 torch/fx/experimental/symbolic_shapes.py:172] lru_cache_stats _simplify_floor_div: CacheInfo(hits=0, misses=0, maxsize=None, currsize=0)
V0107 16:55:12.539000 1703243 torch/fx/experimental/symbolic_shapes.py:172] lru_cache_stats _maybe_guard_rel: CacheInfo(hits=0, misses=0, maxsize=256, currsize=0)
V0107 16:55:12.539000 1703243 torch/fx/experimental/symbolic_shapes.py:172] lru_cache_stats _find: CacheInfo(hits=0, misses=0, maxsize=None, currsize=0)
V0107 16:55:12.539000 1703243 torch/fx/experimental/symbolic_shapes.py:172] lru_cache_stats has_hint: CacheInfo(hits=0, misses=0, maxsize=256, currsize=0)
V0107 16:55:12.539000 1703243 torch/fx/experimental/symbolic_shapes.py:172] lru_cache_stats size_hint: CacheInfo(hits=0, misses=0, maxsize=256, currsize=0)
V0107 16:55:12.539000 1703243 torch/fx/experimental/symbolic_shapes.py:172] lru_cache_stats simplify: CacheInfo(hits=0, misses=0, maxsize=None, currsize=0)
V0107 16:55:12.539000 1703243 torch/fx/experimental/symbolic_shapes.py:172] lru_cache_stats _update_divisible: CacheInfo(hits=0, misses=0, maxsize=None, currsize=0)
V0107 16:55:12.540000 1703243 torch/fx/experimental/symbolic_shapes.py:172] lru_cache_stats replace: CacheInfo(hits=0, misses=0, maxsize=None, currsize=0)
V0107 16:55:12.540000 1703243 torch/fx/experimental/symbolic_shapes.py:172] lru_cache_stats _maybe_evaluate_static: CacheInfo(hits=0, misses=0, maxsize=None, currsize=0)
V0107 16:55:12.540000 1703243 torch/fx/experimental/symbolic_shapes.py:172] lru_cache_stats get_implications: CacheInfo(hits=0, misses=0, maxsize=None, currsize=0)
V0107 16:55:12.540000 1703243 torch/fx/experimental/symbolic_shapes.py:172] lru_cache_stats get_axioms: CacheInfo(hits=0, misses=0, maxsize=None, currsize=0)
V0107 16:55:12.540000 1703243 torch/fx/experimental/symbolic_shapes.py:172] lru_cache_stats _maybe_evaluate_static_worker: CacheInfo(hits=0, misses=0, maxsize=None, currsize=0)
V0107 16:55:12.540000 1703243 torch/fx/experimental/symbolic_shapes.py:172] lru_cache_stats safe_expand: CacheInfo(hits=0, misses=0, maxsize=256, currsize=0)
V0107 16:55:12.540000 1703243 torch/fx/experimental/symbolic_shapes.py:172] lru_cache_stats uninteresting_files: CacheInfo(hits=0, misses=0, maxsize=None, currsize=0)
I0107 16:55:13.045000 1702873 torch/_dynamo/eval_frame.py:398] TorchDynamo attempted to trace the following frames: [
I0107 16:55:13.045000 1702873 torch/_dynamo/eval_frame.py:398]   * f /data/users/yidi/pytorch/test_while_loop.py:9
I0107 16:55:13.045000 1702873 torch/_dynamo/eval_frame.py:398]   * g /data/users/yidi/pytorch/test_while_loop.py:6
I0107 16:55:13.045000 1702873 torch/_dynamo/eval_frame.py:398]   * k /data/users/yidi/pytorch/test_while_loop.py:3
I0107 16:55:13.045000 1702873 torch/_dynamo/eval_frame.py:398] ]
I0107 16:55:13.050000 1702873 torch/_dynamo/utils.py:636] TorchDynamo compilation metrics:
I0107 16:55:13.050000 1702873 torch/_dynamo/utils.py:636] Function                  Runtimes (s)
I0107 16:55:13.050000 1702873 torch/_dynamo/utils.py:636] ----------------------  --------------
I0107 16:55:13.050000 1702873 torch/_dynamo/utils.py:636] _compile.compile_inner          0.9094
I0107 16:55:13.050000 1702873 torch/_dynamo/utils.py:636] gc                              0.0024
```
Ideally, we should be able to skip compilation of function calls to g and k.

### Versions

main

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