|
17 | 17 |
|
18 | 18 | from executorch.exir.dialects.edge._ops import EdgeOpOverload |
19 | 19 | from executorch.exir.pass_base import ExportPass |
| 20 | +from torch._ops import OpOverload |
20 | 21 |
|
21 | 22 | from .arm_pass import ArmPass |
22 | 23 |
|
@@ -103,6 +104,35 @@ def __init__(self, tfa_pass=False, *args, **kwargs): |
103 | 104 | # Actual selection is done per-call in call_operator. |
104 | 105 | super().__init__(tfa_pass, _all_ops, *args, **kwargs) |
105 | 106 |
|
| 107 | + def get_replacement(self, op, args, kwargs, meta): |
| 108 | + # The base pass casts the scalar through float(), which rounds an |
| 109 | + # integer above 2**53 before it reaches an int64 tensor. |
| 110 | + if isinstance(args[1], int) and not isinstance(args[1], bool): |
| 111 | + full_op = ( |
| 112 | + torch.ops.aten.full.default |
| 113 | + if isinstance(op, OpOverload) |
| 114 | + else exir_ops.edge.aten.full.default |
| 115 | + ) |
| 116 | + tensor = args[0].to_tensor() |
| 117 | + return ExportPass.call_operator( |
| 118 | + self, |
| 119 | + self.scalar_to_tensor_ops[op], |
| 120 | + ( |
| 121 | + args[0], |
| 122 | + ExportPass.call_operator( |
| 123 | + self, |
| 124 | + full_op, |
| 125 | + ((1,), args[1]), |
| 126 | + {"dtype": tensor.dtype, "device": tensor.device}, |
| 127 | + meta, |
| 128 | + ), |
| 129 | + *args[2:], |
| 130 | + ), |
| 131 | + kwargs, |
| 132 | + meta, |
| 133 | + ) |
| 134 | + return super().get_replacement(op, args, kwargs, meta) |
| 135 | + |
106 | 136 | def should_run_pass(self, graph_module: torch.fx.GraphModule) -> bool: |
107 | 137 | for node in graph_module.graph.nodes: |
108 | 138 | if node.op == "call_function" and node.target in _all_ops: |
|
0 commit comments