Skip to content

[ONNX] Disable type-unsafe Cast transpose fusion - #3607

Open
liquetxnx wants to merge 2 commits into
onnx:mainfrom
liquetxnx:fix/cast-transpose-canonicalization
Open

[ONNX] Disable type-unsafe Cast transpose fusion#3607
liquetxnx wants to merge 2 commits into
onnx:mainfrom
liquetxnx:fix/cast-transpose-canonicalization

Conversation

@liquetxnx

@liquetxnx liquetxnx commented Aug 13, 2026

Copy link
Copy Markdown

Summary

The canonicalize pass creates an invalid onnx.Cast.

The original Cast is valid:

%159 = "onnx.Transpose"(%158)
    <{perm = [0, 1, 3, 2]}>
    : (tensor<1x1x124x40xf16>) -> tensor<1x1x40x124xf16>

%160 = "onnx.Cast"(%159)
    <{saturate = 1 : si64, to = f32}>
    : (tensor<1x1x40x124xf16>) -> tensor<1x1x40x124xf32>

%161 = "onnx.Transpose"(%160)
    <{perm = [0, 2, 1, 3]}>
    : (tensor<1x1x40x124xf32>) -> tensor<1x40x1x124xf32>

After canonicalization, a rewritten Cast has to = f32 but an f16 result:

%cast = "onnx.Cast"(%value)
    <{saturate = 1 : si64, to = f32}>
    : (tensor<...xf16>) -> tensor<...xf16>

This causes:

'onnx.Cast' op element type does not match the 'to' attribute

Reproduction

onnx-mlir-opt input.onnx.mlir \
  --canonicalize \
  -o output.onnx.mlir

The invalid rewritten IR can be inspected with:

onnx-mlir-opt input.onnx.mlir \
  --verify-each=false \
  --canonicalize \
  -o output-unverified.onnx.mlir

Relevant data flow

The original data flow is:

Transpose
  -> Cast(f16 -> f32)
  -> Reshape
  -> Transpose

The Reshape input and result types are identical:

%178 = "onnx.Reshape"(%160, %shape)
    : (tensor<1x1x40x124xf32>, tensor<4xi64>)
      -> tensor<1x1x40x124xf32>

%179 = "onnx.Transpose"(%178)
    <{perm = [0, 2, 1, 3]}>
    : (tensor<1x1x40x124xf32>)
      -> tensor<1x40x1x124xf32>

Canonicalization can remove the identity Reshape, exposing:

Transpose -> Cast -> Transpose

Suspected cause

The likely source is the Transpose/elementwise fusion pattern in:

src/Dialect/ONNX/ONNXOps/Canonicalize.td

The relevant two-argument pattern reconstructs the elementwise operation using (about 680 lines):

(returnType $v)

This works for type-preserving operations such as Relu, but not for
ONNXCastOp.

When $v is tensor<...xf16>, the rewritten Cast receives an f16 result
type even though its to attribute is f32.

Expected behavior

The rewritten Cast should preserve the Cast result element type:

%cast = "onnx.Cast"(%value)
    <{saturate = 1 : si64, to = f32}>
    : (tensor<...xf16>) -> tensor<...xf32>

Suggested fix

  • exclude ONNXCastOp from this generic type-preserving fusion pattern

Signed-off-by: Eunsang Son <liquetxnx22@gmail.com>
Add a Transpose-Cast-Transpose ONNX MLIR reproducer and preserve the canonicalization and LLVM lowering results.

Before the fix, FuseTransposeAndCastPattern creates a Cast with to=i64 but an f32 result type, causing verification and LLVM lowering to fail. After the fix, the valid operation chain is preserved and lowers to fptosi.

Signed-off-by: Eunsang Son <liquetxnx22@gmail.com>
@jenkins-droid

Copy link
Copy Markdown
Collaborator

Can one of the admins verify this patch?

@AlexandreEichenberger

Copy link
Copy Markdown
Collaborator

@jenkins-droid test this please

@AlexandreEichenberger

Copy link
Copy Markdown
Collaborator

@jenkin-droid test this please

@gongsu832

Copy link
Copy Markdown
Collaborator

@jenkins-droid test this please

1 similar comment
@AlexandreEichenberger

Copy link
Copy Markdown
Collaborator

@jenkins-droid test this please

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants