[QNN EP] Fix Clip op with min or max from QDQ#26601
[QNN EP] Fix Clip op with min or max from QDQ#26601adrianlizarraga merged 1 commit intomicrosoft:mainfrom
Conversation
Add few more test cases
|
@deval-patel and @chilo-ms |
|
@chilo-ms - Could you please run CI and review/merge this change? |
There was a problem hiding this comment.
Pull request overview
This PR fixes an issue with QNN EP's handling of the Clip operator when min/max values are provided through Q/DQ nodes. Previously, Clip was incorrectly handled by the UnaryNodeGroupSelector, which couldn't properly recognize patterns where min/max inputs come from quantized sources.
Key changes:
- Implemented a custom
ClipNodeGroupSelectorto properly handle Clip operations with 1-3 DQ inputs - Added dequantization logic in QNN EP's Clip op builder to convert quantized min/max values to floats
- Fixed spelling error in function name (
ExplictOpCheck→ExplicitOpCheck)
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| clip_op_test.cc | Added three test cases validating Clip with quantized min-only, max-only, and min+max inputs |
| qdq_transformer_test.cc | Added tests verifying ClipNodeGroupSelector properly identifies QDQ patterns for Clip operations |
| clip_op_builder.cc | Added dequantization logic for quantized min/max inputs and fixed function name typo |
| utils.cc | Removed Clip from unary ops map, created dedicated Clip ops map, and registered ClipNodeGroupSelector |
| qdq_selectors.h | Declared ClipNodeGroupSelector class |
| qdq_selectors.cc | Implemented ClipNodeGroupSelector::Check method to validate 1-3 DQ input patterns |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
/azp run Linux QNN CI Pipeline, Win_TRT_Minimal_CUDA_Test_CI, Windows ARM64 QNN CI Pipeline, Windows GPU CUDA CI Pipeline, Windows GPU DML CI Pipeline, Windows GPU Doc Gen CI Pipeline, Windows GPU TensorRT CI Pipeline, Windows OpenVINO CI Pipeline, Windows x64 QNN CI Pipeline |
|
Azure Pipelines successfully started running 4 pipeline(s). |
|
/asp run Windows GPU CUDA CI Pipeline, Windows GPU DML CI Pipeline, Windows GPU TensorRT CI Pipeline, Windows OpenVINO CI Pipeline, Windows x64 QNN CI Pipeline |
|
Please, address or comment on the Copilot comments |
Done. But it's no harm to apply suggested change so lemme know if you feel strong about it. |
|
/azp run Linux QNN CI Pipeline, Win_TRT_Minimal_CUDA_Test_CI, Windows ARM64 QNN CI Pipeline, Windows GPU CUDA CI Pipeline, Windows GPU DML CI Pipeline, Windows GPU Doc Gen CI Pipeline, Windows GPU TensorRT CI Pipeline, Windows OpenVINO CI Pipeline, Windows x64 QNN CI Pipeline |
|
Azure Pipelines successfully started running 4 pipeline(s). |
|
/azp run "Linux QNN CI Pipeline", "Win_TRT_Minimal_CUDA_Test_CI", "Windows ARM64 QNN CI Pipeline", "Windows GPU CUDA CI Pipeline", "Windows GPU DML CI Pipeline", "Windows GPU Doc Gen CI Pipeline", "Windows GPU TensorRT CI Pipeline", "Windows OpenVINO CI Pipeline", "Windows x64 QNN CI Pipeline" |
|
No pipelines are associated with this pull request. |
onnxruntime/core/optimizer/qdq_transformer/selectors_actions/qdq_selectors.cc
Show resolved
Hide resolved
|
Closing and reopening to get CI checks to run |
## Motivation QDQ node group selection logic currently navigate `Clip` op to `UnaryNodeGroupSelector`. This isn't properly handling the use case where `Clip` op has `min/max` provided from Q/DQ ops (still constant initializers). <img width="255" height="378" alt="image-2025-11-18-11-49-19-156" src="https://github.com/user-attachments/assets/ec6250ee-68f3-40fa-8f60-93b1a400d5a0" /> ## Changes: - Implement custom NodeGroupSelector so that `Clip` op is properly tagged for backend to consume. - Fix QNN EP `Clip` min/max parsing and perform de-quantize when needed. - Unit tests for both changes.
Motivation
QDQ node group selection logic currently navigate
Clipop toUnaryNodeGroupSelector. This isn't properly handling the use case whereClipop hasmin/maxprovided from Q/DQ ops (still constant initializers).Changes:
Clipop is properly tagged for backend to consume.Clipmin/max parsing and perform de-quantize when needed.