Walk backwards through a chain of ops, matching against a pattern. Starting from *node*, try to match each step against the current node. At every matched step the walk advances to ``cur.args[step.arg_index]``. Optional steps are silently skipped when they don't match. Repeat steps
( # noqa: C901
node: Node,
steps: List[OpStep],
debug: bool = False,
)
| 194 | |
| 195 | |
| 196 | def walk_back( # noqa: C901 |
| 197 | node: Node, |
| 198 | steps: List[OpStep], |
| 199 | debug: bool = False, |
| 200 | ) -> Optional[Tuple[Node, List[WalkBackEntry]]]: |
| 201 | """ |
| 202 | Walk backwards through a chain of ops, matching against a pattern. |
| 203 | |
| 204 | Starting from *node*, try to match each step against the current node. |
| 205 | At every matched step the walk advances to ``cur.args[step.arg_index]``. |
| 206 | Optional steps are silently skipped when they don't match. Repeat steps |
| 207 | match 0 or more times. |
| 208 | |
| 209 | Args: |
| 210 | node: Starting node |
| 211 | steps: List of OpStep to match in order |
| 212 | |
| 213 | Returns: |
| 214 | ``(base_node, entries)`` if the full chain matches, else ``None``. |
| 215 | *base_node* is the input to the first (deepest) op in the chain. |
| 216 | *entries* is a list with one entry per OpStep: |
| 217 | - Node: matched node (for regular steps) |
| 218 | - None: optional step that didn't match |
| 219 | - List[Node]: repeat step (0 or more matches) |
| 220 | |
| 221 | Examples: |
| 222 | # Match: rsqrt(add(mean(pow(x, 2)), eps)) |
| 223 | result = walk_back(rsqrt_node, [ |
| 224 | OpStep(op=torch.ops.aten.rsqrt.default), |
| 225 | OpStep(op=torch.ops.aten.add.Tensor), |
| 226 | OpStep(op=torch.ops.aten.mean.dim), |
| 227 | OpStep(op=torch.ops.aten.pow.Tensor_Scalar), |
| 228 | ]) |
| 229 | if result: |
| 230 | base, entries = result |
| 231 | rsqrt, add, mean, pow = entries # Each is a Node |
| 232 | |
| 233 | # Match chain of select ops (like tensor[0][0]) |
| 234 | result = walk_back(node, [ |
| 235 | OpStep(op=torch.ops.aten.select.int, repeat=True), |
| 236 | ]) |
| 237 | if result: |
| 238 | base, entries = result |
| 239 | select_nodes = entries[0] # List[Node], may be empty |
| 240 | |
| 241 | # Skip optional _to_copy, then match rsqrt |
| 242 | result = walk_back(node, [ |
| 243 | OpStep(op=torch.ops.aten._to_copy.default, optional=True), |
| 244 | OpStep(op=torch.ops.aten.rsqrt.default), |
| 245 | ]) |
| 246 | if result: |
| 247 | base, entries = result |
| 248 | to_copy, rsqrt = entries # to_copy may be None |
| 249 | """ |
| 250 | entries: List[WalkBackEntry] = [] |
| 251 | cur = node |
| 252 | |
| 253 | for i, step in enumerate(steps): |