One step in a backward walk through the graph. Used with walk_back() to define pattern chains. Supports both exact op matching and predicate-based matching. Attributes: op: Specific op to match (e.g., torch.ops.aten.rsqrt.default) predicate: Alternative to op - a f
| 103 | |
| 104 | @dataclass |
| 105 | class OpStep: |
| 106 | """ |
| 107 | One step in a backward walk through the graph. |
| 108 | |
| 109 | Used with walk_back() to define pattern chains. Supports both exact op |
| 110 | matching and predicate-based matching. |
| 111 | |
| 112 | Attributes: |
| 113 | op: Specific op to match (e.g., torch.ops.aten.rsqrt.default) |
| 114 | predicate: Alternative to op - a function that returns True for matching nodes |
| 115 | optional: If True, skip this step if it doesn't match |
| 116 | repeat: If True, match this step 0 or more times (like regex *) |
| 117 | require_single_user: If True (default), only match nodes with exactly one user |
| 118 | nargs: Number of args required. Can be: |
| 119 | - int: minimum number of args (default 1, since we advance via args[0]) |
| 120 | - tuple (min, max): range of args required (inclusive) |
| 121 | kwargs: Set of kwargs we handle (node's kwargs must be subset of this) |
| 122 | arg_index: Which arg to follow when advancing (default 0) |
| 123 | |
| 124 | Examples: |
| 125 | # Match specific op |
| 126 | OpStep(op=torch.ops.aten.rsqrt.default) |
| 127 | |
| 128 | # Match with predicate (for matching families of ops) |
| 129 | OpStep(predicate=lambda n: match_target(n, torch.ops.aten.select.int)) |
| 130 | |
| 131 | # Match chain of same op type (0 or more) |
| 132 | OpStep(op=torch.ops.aten.select.int, repeat=True) |
| 133 | |
| 134 | # Optional dtype conversion |
| 135 | OpStep(op=torch.ops.aten._to_copy.default, optional=True) |
| 136 | |
| 137 | # Require between 2 and 4 args |
| 138 | OpStep(op=torch.ops.aten.some_op.default, nargs=(2, 4)) |
| 139 | |
| 140 | # Declare that we handle 'dtype' kwarg |
| 141 | OpStep(op=torch.ops.aten._to_copy.default, kwargs={"dtype"}) |
| 142 | |
| 143 | # Follow second arg (e.g., mul(x, rsqrt(y)) -> follow rsqrt in args[1]) |
| 144 | OpStep(op=torch.ops.aten.mul.Tensor, arg_index=1) |
| 145 | """ |
| 146 | |
| 147 | op: Any = None |
| 148 | predicate: Optional[Callable[[Node], bool]] = None |
| 149 | optional: bool = False |
| 150 | repeat: bool = False |
| 151 | require_single_user: bool = True |
| 152 | nargs: Union[int, Tuple[int, int]] = 1 |
| 153 | kwargs: Set[str] = field(default_factory=set) # Empty = no kwargs allowed |
| 154 | arg_index: int = 0 |
| 155 | |
| 156 | def matches(self, node: Node) -> bool: |
| 157 | """Check if this step fully matches the given node.""" |
| 158 | # Check op or predicate |
| 159 | if self.op is not None: |
| 160 | if not match_target(node, self.op): |
| 161 | return False |
| 162 | elif self.predicate is not None: |
no outgoing calls