onnxruntime
359d9ab4 - fix(qdq): skip DQ forward propagation when DQ input is constant (#28521)

Commit
99 days ago
fix(qdq): skip DQ forward propagation when DQ input is constant (#28521) ## Summary - Guard `QDQPropagationTransformer::PropagateDQForward` against propagating a DQ whose data input is a constant (graph initializer or `Constant` op output). - Prevents a stale `QuantizeLinear` insertion that the S8-to-U8 weight transformer fails to update, which silently clamps int8 negatives to zero under `ORT_ENABLE_ALL`. - Adds a regression test in `qdq_transformer_test.cc` covering both constant-input shapes. ## Motivation Fixes #28491. Reported scenario: a model containing `Constant(int8) -> DequantizeLinear -> Reshape` produces correct outputs under `ORT_DISABLE_ALL` but wrong outputs (negatives clamped to 0) under `ORT_ENABLE_ALL`. Root cause: `PropagateDQForward` inserts a `Q -> DQ` pair after the Reshape, then `QDQS8ToU8Transformer` (or the avx2 weight transformer) flips the upstream DQ from int8 to uint8 without touching the freshly inserted `Q`. The orphaned uint8 `Q` then clamps the int8 weight's negative values to 0. Propagating a DQ whose data is a constant weight has no benefit anyway: the constant is folded, so there is no runtime tensor that downstream nodes need re-quantized. ## Changes - `onnxruntime/core/optimizer/qdq_transformer/qdq_propagation.cc`: inside `PropagateDQForward`'s per-DQ loop, after existing skip checks and before any graph mutation, `continue` if `dq_node.InputDefs()[QDQ::InputIndex::INPUT_ID]` is a graph initializer (`graph_utils::NodeArgIsConstant`) or the output of a `Constant` op node (`graph.GetProducerNode(...)->OpType() == "Constant"`). Both checks are required because `NodeArgIsConstant` only handles the initializer case. - `onnxruntime/test/optimizer/qdq_transformer_test.cc`: new test `QDQPropagation_DQForward_ConstantInput_NoPropagation` with two cases — DQ fed by an initializer, and DQ fed by an explicit `Constant` op node — asserting no `QuantizeLinear` is inserted after the downstream Reshape. `PropagateQBackward` is structurally not affected (its data input is a live activation, not a constant), so it does not need a symmetric guard. ## Test Plan - New `QDQTransformerTests.QDQPropagation_DQForward_ConstantInput_NoPropagation` (gtest) covers both code paths and would fail on `main`. - Existing `QDQPropagation_*` tests use `MakeInput` (graph inputs, not initializers) for their DQ data tensors, so the new guard does not regress them. - The reproducer from #28491 should now produce identical results between `ORT_DISABLE_ALL` and `ORT_ENABLE_ALL`. - CI will exercise `--gtest_filter=QDQTransformerTests.QDQPropagation*` under `onnxruntime_test_all`. Fixes #28491
Author
Parents
Loading