From 71029dc9874d83eafaa1cf22c8fa036fac5aa6a6 Mon Sep 17 00:00:00 2001 From: Winston Kuo Date: Thu, 30 Jul 2026 10:41:04 +0800 Subject: [PATCH] Fix q dq ops target --- backends/qualcomm/_passes/insert_io_qdq.py | 4 +-- .../lpai_partition_fallback_support.py | 27 ++++++++++++------- backends/qualcomm/_passes/utils.py | 8 +++++- backends/qualcomm/builders/node_visitor.py | 14 +++++++--- 4 files changed, 37 insertions(+), 16 deletions(-) diff --git a/backends/qualcomm/_passes/insert_io_qdq.py b/backends/qualcomm/_passes/insert_io_qdq.py index 9a234554452..c565674df47 100644 --- a/backends/qualcomm/_passes/insert_io_qdq.py +++ b/backends/qualcomm/_passes/insert_io_qdq.py @@ -10,7 +10,7 @@ insert_quant_node, ) -from executorch.backends.qualcomm.builders.node_visitor import q_dq_map, q_ops +from executorch.backends.qualcomm.builders.node_visitor import q_ops, to_dq_op from executorch.backends.qualcomm.builders.utils import ( is_mutable_buffer_input, @@ -76,7 +76,7 @@ def _insert(self, graph_module: torch.fx.GraphModule) -> torch.fx.GraphModule: graph_module=graph_module, input_node=n, output_node=user, - target=q_dq_map[n.meta[QCOM_QUANT_ATTRS][QCOM_ENCODING]], + target=to_dq_op(n.meta[QCOM_QUANT_ATTRS][QCOM_ENCODING]), ) def call(self, graph_module: torch.fx.GraphModule): diff --git a/backends/qualcomm/_passes/lpai_partition_fallback_support.py b/backends/qualcomm/_passes/lpai_partition_fallback_support.py index 02c17f92c20..5983c145749 100644 --- a/backends/qualcomm/_passes/lpai_partition_fallback_support.py +++ b/backends/qualcomm/_passes/lpai_partition_fallback_support.py @@ -11,7 +11,12 @@ insert_dequant_node, insert_quant_node, ) -from executorch.backends.qualcomm.builders.node_visitor import dq_ops, q_dq_map, q_ops +from executorch.backends.qualcomm.builders.node_visitor import ( + dq_ops, + q_ops, + to_dq_op, + to_q_op, +) from executorch.backends.qualcomm.builders.utils import is_graph_input, is_graph_output @@ -108,7 +113,7 @@ def preserve_io_qdq(self, graph_module: torch.fx.GraphModule) -> None: graph_module=graph_module, input_node=n, output_node=user, - target=n.meta[QCOM_QUANT_ATTRS][QCOM_ENCODING], + target=to_q_op(n.meta[QCOM_QUANT_ATTRS][QCOM_ENCODING]), pop_quant_attrs=False, ) q_node.meta[QCOM_FALLBACK_NODE] = True @@ -116,7 +121,7 @@ def preserve_io_qdq(self, graph_module: torch.fx.GraphModule) -> None: graph_module=graph_module, input_node=q_node, output_node=user, - target=q_dq_map[q_node.target], + target=to_dq_op(q_node.target), ) dq_node.meta[QCOM_BYPASS_NODE] = True elif ( @@ -131,7 +136,9 @@ def preserve_io_qdq(self, graph_module: torch.fx.GraphModule) -> None: graph_module=graph_module, input_node=output_node, output_node=getitem_node, - target=output_node.meta[QCOM_QUANT_ATTRS][QCOM_ENCODING], + target=to_q_op( + output_node.meta[QCOM_QUANT_ATTRS][QCOM_ENCODING] + ), pop_quant_attrs=False, ) q_node.meta[QCOM_BYPASS_NODE] = True @@ -139,7 +146,7 @@ def preserve_io_qdq(self, graph_module: torch.fx.GraphModule) -> None: graph_module=graph_module, input_node=q_node, output_node=getitem_node, - target=q_dq_map[q_node.target], + target=to_dq_op(q_node.target), ) dq_node.meta[QCOM_FALLBACK_NODE] = True @@ -191,7 +198,7 @@ def insert_partition_qdq( graph_module=graph_module, input_node=input_node, output_node=node, - target=input_node.meta[QCOM_QUANT_ATTRS][QCOM_ENCODING], + target=to_q_op(input_node.meta[QCOM_QUANT_ATTRS][QCOM_ENCODING]), pop_quant_attrs=False, ) for input_node in input_nodes @@ -203,7 +210,7 @@ def insert_partition_qdq( graph_module=graph_module, input_node=input_q_node, output_node=node, - target=q_dq_map[input_q_node.target], + target=to_dq_op(input_q_node.target), ) for input_q_node in input_q_nodes ] @@ -232,7 +239,7 @@ def insert_partition_qdq( graph_module=graph_module, input_node=output_node, output_node=output_user_node, - target=output_node.meta[QCOM_QUANT_ATTRS][QCOM_ENCODING], + target=to_q_op(output_node.meta[QCOM_QUANT_ATTRS][QCOM_ENCODING]), pop_quant_attrs=False, ) output_q_node.meta[QCOM_FALLBACK_NODE] = True @@ -240,9 +247,9 @@ def insert_partition_qdq( graph_module=graph_module, input_node=output_q_node, output_node=output_user_node, - target=q_dq_map[ + target=to_dq_op( output_q_node.meta[QCOM_QUANT_ATTRS][QCOM_ENCODING] - ], + ), ) output_dq_node.meta[QCOM_BYPASS_NODE] = True graph_module.graph.eliminate_dead_code() diff --git a/backends/qualcomm/_passes/utils.py b/backends/qualcomm/_passes/utils.py index 2a580ab11a4..53cd1760f99 100755 --- a/backends/qualcomm/_passes/utils.py +++ b/backends/qualcomm/_passes/utils.py @@ -7,7 +7,7 @@ from typing import Callable, Dict, List import torch -from executorch.backends.qualcomm.builders.node_visitor import q_ops +from executorch.backends.qualcomm.builders.node_visitor import dq_ops, q_ops from executorch.backends.qualcomm.builders.utils import get_parameter from executorch.backends.qualcomm.utils.constants import ( QCOM_DTYPE, @@ -81,6 +81,9 @@ def insert_quant_node( quant_attrs: Dict = None, pop_quant_attrs: bool = True, ) -> torch.fx.Node: + assert ( + target in q_ops + ), f"insert_quant_node expects a quantize target, got: {target}" with graph_module.graph.inserting_after(input_node): inserted_node = _create_q_or_dq_node( graph_module=graph_module, @@ -101,6 +104,9 @@ def insert_dequant_node( output_node: torch.fx.node, target: torch.fx.node.Target, ) -> None: + assert ( + target in dq_ops + ), f"insert_dequant_node expects a dequantize target, got: {target}" with graph_module.graph.inserting_after(input_node): inserted_node = _create_q_or_dq_node( graph_module=graph_module, node=input_node, target=target diff --git a/backends/qualcomm/builders/node_visitor.py b/backends/qualcomm/builders/node_visitor.py index 60785901c8d..1b6c37305a7 100644 --- a/backends/qualcomm/builders/node_visitor.py +++ b/backends/qualcomm/builders/node_visitor.py @@ -101,13 +101,21 @@ q_dq_map = { exir_ops.edge.quantized_decomposed.quantize_per_tensor.default: exir_ops.edge.quantized_decomposed.dequantize_per_tensor.default, exir_ops.edge.quantized_decomposed.quantize_per_tensor.tensor: exir_ops.edge.quantized_decomposed.dequantize_per_tensor.tensor, - exir_ops.edge.quantized_decomposed.dequantize_per_tensor.default: exir_ops.edge.quantized_decomposed.dequantize_per_tensor.default, - exir_ops.edge.quantized_decomposed.dequantize_per_tensor.tensor: exir_ops.edge.quantized_decomposed.dequantize_per_tensor.tensor, exir_ops.edge.quantized_decomposed.quantize_per_channel.default: exir_ops.edge.quantized_decomposed.dequantize_per_channel.default, - exir_ops.edge.quantized_decomposed.dequantize_per_channel.default: exir_ops.edge.quantized_decomposed.dequantize_per_channel.default, + exir_ops.edge.quantized_decomposed.dequantize_per_tensor.default: exir_ops.edge.quantized_decomposed.quantize_per_tensor.default, + exir_ops.edge.quantized_decomposed.dequantize_per_tensor.tensor: exir_ops.edge.quantized_decomposed.quantize_per_tensor.tensor, + exir_ops.edge.quantized_decomposed.dequantize_per_channel.default: exir_ops.edge.quantized_decomposed.quantize_per_channel.default, } +def to_q_op(target): + return target if target in q_ops else q_dq_map[target] + + +def to_dq_op(target): + return target if target in dq_ops else q_dq_map[target] + + class NodeVisitor: """ Node visitor pattern for visiting nodes in an edge IR graph