Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 38 additions & 2 deletions backends/cadence/aot/tests/test_quantizer_ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@
from typing import Callable

import torch
from executorch.backends.cadence.aot.graph_builder import GraphBuilder
from executorch.backends.cadence.aot.graph_builder import (
GraphBuilder,
single_op_builder,
Copy link

Copilot AI Dec 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The import of single_op_builder is only used once in the _build_layer_norm_graph method. If the method is refactored to use GraphBuilder (consistent with all other test methods in this class), this import would no longer be needed and could be removed.

Copilot uses AI. Check for mistakes.
)
from executorch.backends.cadence.aot.quantizer import quantizer as quantizer_module
from executorch.backends.cadence.aot.quantizer.patterns import AddmmPattern
from executorch.backends.cadence.aot.quantizer.quantizer import (
Expand Down Expand Up @@ -56,7 +59,6 @@
CadenceW8A32MixedQuantizer, # TODO: T247438158 Add test coverage
CadenceRmsNormNopQuantizer, # No-op quantizer, doesn't annotate anything, preserves rms_norm from decomposition
CadenceWakeWordQuantizer, # TODO: T247438162 Add test coverage
CadenceWithLayerNormQuantizer, # TODO: T247438410 Add test coverage
}


Expand Down Expand Up @@ -118,6 +120,15 @@
# For softmax: only input_activation
[qconfig_A16.input_activation],
),
(
"layer_norm_A8W8",
lambda self: self._build_layer_norm_graph(),
CadenceWithLayerNormQuantizer(),
torch.ops.aten.layer_norm.default,
qconfig_A8W8.output_activation,
# For layer_norm: only input_activation (weights/bias are passed as others)
[qconfig_A8W8.input_activation],
),
]

# Derive the set of tested quantizer classes from the test cases.
Expand Down Expand Up @@ -243,6 +254,31 @@ def _build_softmax_graph(self) -> tuple[torch.fx.GraphModule, torch.fx.Node]:
self.assertEqual(len(softmax_nodes), 1, "Should find exactly one softmax node")
return gm, softmax_nodes[0]

def _build_layer_norm_graph(self) -> tuple[torch.fx.GraphModule, torch.fx.Node]:
"""Build a simple graph with a layer_norm operation."""
# Input shape: (batch, features)
x = torch.randn(1, 10)
# normalized_shape must match the last dimension(s) of input
normalized_shape = [10]
gm = single_op_builder(
placeholders=(x,),
op=torch.ops.aten.layer_norm.default,
args=(x, normalized_shape),
)

layer_norm_nodes = gm.graph.find_nodes(
op="call_function",
target=torch.ops.aten.layer_norm.default,
)
self.assertEqual(
len(layer_norm_nodes), 1, "Should find exactly one layer_norm node"
)
# Add source_fn_stack metadata required by quantizer pattern matching
layer_norm_nodes[0].meta["source_fn_stack"] = [
("layer_norm", torch.ops.aten.layer_norm.default)
]
return gm, layer_norm_nodes[0]
Comment on lines +257 to +280
Copy link

Copilot AI Dec 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The _build_layer_norm_graph method uses a different approach than the other graph builders (single_op_builder instead of GraphBuilder), and manually adds source_fn_stack metadata after graph construction. While this works, it creates an inconsistency in the codebase.

Consider refactoring to use GraphBuilder directly like the other methods for consistency. The normalized_shape parameter can be passed directly in args since GraphBuilder's call_operator handles both tensor and non-tensor arguments. This would allow adding the source_fn_stack metadata during construction rather than after the fact.

Copilot uses AI. Check for mistakes.

@parameterized.expand(QUANTIZER_ANNOTATION_TEST_CASES)
def test_quantizer_annotation(
self,
Expand Down
Loading