Open
Description
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