Skip to content

[mlir][arith] wrong canonicalization pattern on index_castui causing miscompilation #90238

Open
@pingshiyu

Description

@pingshiyu

For the following program,

module {
    func.func @main() {
        %c = arith.constant 100 : i64
        %0 = call @c0() : () -> i64
        %1 = arith.muli %c, %0 : i64 // 100^2
        %2 = arith.index_castui %1 : i64 to index // 100^2 
        %3 = arith.index_castui %2 : index to i8 // should be within [-128, 128)
        %4 = arith.index_castui %3 : i8 to index // should be within [-128, 128)
        vector.print str "%c="
        vector.print %c : i64
        vector.print str "%0="
        vector.print %0 : i64
        vector.print str "%1="
        vector.print %1 : i64
        vector.print str "%2="
        vector.print %2 : index
        vector.print str "%3="
        vector.print %3 : i8
        vector.print str "%4="
        vector.print %4 : index
        return
    }
    func.func @c0() -> i64 {
        %cl = arith.constant 100 : i64
        return %cl : i64
    }
}

Canonicalization removes the third cast (%4), rewriting it into:

    ...
    %1 = arith.muli %0, %c100_i64 : i64
    %2 = arith.index_castui %1 : i64 to index
    %3 = arith.index_castui %2 : index to i8
    ...
    // effectively %4 = %2
    vector.print str "%4="
    vector.print %2 : index

This is incorrect here as %4 is a truncation of %2, i.e. %4 /= %2.

The bug is shown when compiling and executing the above using

mlir-opt --canonicalize --test-lower-to-llvm | mlir-cpu-runner -e main --shared-libs ~/lib/mlir/libmlir_c_runner_utils.so --entry-point-result void

Here %4 is expected to be within the range of i8 ([-128, 128)), but instead, the execution prints 10000.

Replication: https://godbolt.org/z/jnx7ns3oE

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions