<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/151795>151795</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
[MLIR]Inconsistent Output Between `-convert-math-to-llvm` and `-convert-math-to-spirv`
</td>
</tr>
<tr>
<th>Labels</th>
<td>
mlir
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
sweead
</td>
</tr>
</table>
<pre>
test commit: [8934a6e](https://github.com/llvm/llvm-project/commit/8934a6e13bd8d2a0ad2609bd62832ca700dab3a7)
## Description:
When converting MLIR code with math operations, different backends (llvm vs spirv) produce inconsistent outputs for the same code
## Steps to Reproduce:
### MLIR program (test.mlir):
```
module {
llvm.func @malloc(i64) -> !llvm.ptr
llvm.mlir.global private constant @__constant_10x1x1xf32(dense<72.4199981> : tensor<10x1x1xf32>) {addr_space = 0 : i32, alignment = 64 : i64} : !llvm.array<10 x array<1 x array<1 x f32>>>
llvm.func @printMemrefF32(i64, !llvm.ptr) attributes {sym_visibility = "private"}
llvm.func @main() {
%0 = llvm.mlir.constant(1 : index) : i64
%1 = llvm.mlir.constant(10 : index) : i64
%2 = llvm.mlir.constant(0 : index) : i64
%3 = llvm.mlir.constant(10 : index) : i64
%4 = llvm.mlir.constant(1 : index) : i64
%5 = llvm.mlir.constant(1 : index) : i64
%6 = llvm.mlir.constant(1 : index) : i64
%7 = llvm.mlir.zero : !llvm.ptr
%8 = llvm.getelementptr %7[%3] : (!llvm.ptr, i64) -> !llvm.ptr, f32
%9 = llvm.ptrtoint %8 : !llvm.ptr to i64
%10 = llvm.mlir.addressof @__constant_10x1x1xf32 : !llvm.ptr
%11 = llvm.getelementptr %10[0, 0, 0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<10 x array<1 x array<1 x f32>>>
%12 = llvm.mlir.constant(3735928559 : index) : i64
%13 = llvm.inttoptr %12 : i64 to !llvm.ptr
%14 = llvm.mlir.poison : !llvm.struct<(ptr, ptr, i64, array<3 x i64>, array<3 x i64>)>
%15 = llvm.insertvalue %13, %14[0] : !llvm.struct<(ptr, ptr, i64, array<3 x i64>, array<3 x i64>)>
%16 = llvm.insertvalue %11, %15[1] : !llvm.struct<(ptr, ptr, i64, array<3 x i64>, array<3 x i64>)>
%17 = llvm.mlir.constant(0 : index) : i64
%18 = llvm.insertvalue %17, %16[2] : !llvm.struct<(ptr, ptr, i64, array<3 x i64>, array<3 x i64>)>
%19 = llvm.insertvalue %3, %18[3, 0] : !llvm.struct<(ptr, ptr, i64, array<3 x i64>, array<3 x i64>)>
%20 = llvm.insertvalue %4, %19[3, 1] : !llvm.struct<(ptr, ptr, i64, array<3 x i64>, array<3 x i64>)>
%21 = llvm.insertvalue %5, %20[3, 2] : !llvm.struct<(ptr, ptr, i64, array<3 x i64>, array<3 x i64>)>
%22 = llvm.insertvalue %4, %21[4, 0] : !llvm.struct<(ptr, ptr, i64, array<3 x i64>, array<3 x i64>)>
%23 = llvm.insertvalue %5, %22[4, 1] : !llvm.struct<(ptr, ptr, i64, array<3 x i64>, array<3 x i64>)>
%24 = llvm.insertvalue %6, %23[4, 2] : !llvm.struct<(ptr, ptr, i64, array<3 x i64>, array<3 x i64>)>
%25 = llvm.mlir.constant(10 : index) : i64
%26 = llvm.mlir.constant(1 : index) : i64
%27 = llvm.mlir.constant(1 : index) : i64
%28 = llvm.mlir.constant(1 : index) : i64
%29 = llvm.mlir.zero : !llvm.ptr
%30 = llvm.getelementptr %29[%25] : (!llvm.ptr, i64) -> !llvm.ptr, f32
%31 = llvm.ptrtoint %30 : !llvm.ptr to i64
%32 = llvm.mlir.constant(64 : index) : i64
%33 = llvm.add %31, %32 : i64
%34 = llvm.call @malloc(%33) : (i64) -> !llvm.ptr
%35 = llvm.ptrtoint %34 : !llvm.ptr to i64
%36 = llvm.mlir.constant(1 : index) : i64
%37 = llvm.sub %32, %36 : i64
%38 = llvm.add %35, %37 : i64
%39 = llvm.urem %38, %32 : i64
%40 = llvm.sub %38, %39 : i64
%41 = llvm.inttoptr %40 : i64 to !llvm.ptr
%42 = llvm.mlir.poison : !llvm.struct<(ptr, ptr, i64, array<3 x i64>, array<3 x i64>)>
%43 = llvm.insertvalue %34, %42[0] : !llvm.struct<(ptr, ptr, i64, array<3 x i64>, array<3 x i64>)>
%44 = llvm.insertvalue %41, %43[1] : !llvm.struct<(ptr, ptr, i64, array<3 x i64>, array<3 x i64>)>
%45 = llvm.mlir.constant(0 : index) : i64
%46 = llvm.insertvalue %45, %44[2] : !llvm.struct<(ptr, ptr, i64, array<3 x i64>, array<3 x i64>)>
%47 = llvm.insertvalue %25, %46[3, 0] : !llvm.struct<(ptr, ptr, i64, array<3 x i64>, array<3 x i64>)>
%48 = llvm.insertvalue %26, %47[3, 1] : !llvm.struct<(ptr, ptr, i64, array<3 x i64>, array<3 x i64>)>
%49 = llvm.insertvalue %27, %48[3, 2] : !llvm.struct<(ptr, ptr, i64, array<3 x i64>, array<3 x i64>)>
%50 = llvm.insertvalue %26, %49[4, 0] : !llvm.struct<(ptr, ptr, i64, array<3 x i64>, array<3 x i64>)>
%51 = llvm.insertvalue %27, %50[4, 1] : !llvm.struct<(ptr, ptr, i64, array<3 x i64>, array<3 x i64>)>
%52 = llvm.insertvalue %28, %51[4, 2] : !llvm.struct<(ptr, ptr, i64, array<3 x i64>, array<3 x i64>)>
llvm.br ^bb1(%2 : i64)
^bb1(%53: i64): // 2 preds: ^bb0, ^bb8
%54 = llvm.icmp "slt" %53, %1 : i64
llvm.cond_br %54, ^bb2, ^bb9
^bb2: // pred: ^bb1
llvm.br ^bb3(%2 : i64)
^bb3(%55: i64): // 2 preds: ^bb2, ^bb7
%56 = llvm.icmp "slt" %55, %0 : i64
llvm.cond_br %56, ^bb4, ^bb8
^bb4: // pred: ^bb3
llvm.br ^bb5(%2 : i64)
^bb5(%57: i64): // 2 preds: ^bb4, ^bb6
%58 = llvm.icmp "slt" %57, %0 : i64
llvm.cond_br %58, ^bb6, ^bb7
^bb6: // pred: ^bb5
%59 = llvm.extractvalue %24[1] : !llvm.struct<(ptr, ptr, i64, array<3 x i64>, array<3 x i64>)>
%60 = llvm.add %53, %55 overflow<nsw, nuw> : i64
%61 = llvm.add %60, %57 overflow<nsw, nuw> : i64
%62 = llvm.getelementptr inbounds|nuw %59[%61] : (!llvm.ptr, i64) -> !llvm.ptr, f32
%63 = llvm.load %62 : !llvm.ptr -> f32
%64 = math.tanh %63 : f32
%65 = llvm.extractvalue %52[1] : !llvm.struct<(ptr, ptr, i64, array<3 x i64>, array<3 x i64>)>
%66 = llvm.add %53, %55 overflow<nsw, nuw> : i64
%67 = llvm.add %66, %57 overflow<nsw, nuw> : i64
%68 = llvm.getelementptr inbounds|nuw %65[%67] : (!llvm.ptr, i64) -> !llvm.ptr, f32
llvm.store %64, %68 : f32, !llvm.ptr
%69 = llvm.add %57, %0 : i64
llvm.br ^bb5(%69 : i64)
^bb7: // pred: ^bb5
%70 = llvm.add %55, %0 : i64
llvm.br ^bb3(%70 : i64)
^bb8: // pred: ^bb3
%71 = llvm.add %53, %0 : i64
llvm.br ^bb1(%71 : i64)
^bb9: // pred: ^bb1
%72 = llvm.mlir.constant(1 : index) : i64
%73 = llvm.alloca %72 x !llvm.struct<(ptr, ptr, i64, array<3 x i64>, array<3 x i64>)> : (i64) -> !llvm.ptr
llvm.store %52, %73 : !llvm.struct<(ptr, ptr, i64, array<3 x i64>, array<3 x i64>)>, !llvm.ptr
%74 = llvm.mlir.constant(3 : index) : i64
%75 = llvm.mlir.poison : !llvm.struct<(i64, ptr)>
%76 = llvm.insertvalue %74, %75[0] : !llvm.struct<(i64, ptr)>
%77 = llvm.insertvalue %73, %76[1] : !llvm.struct<(i64, ptr)>
%78 = llvm.extractvalue %77[0] : !llvm.struct<(i64, ptr)>
%79 = llvm.extractvalue %77[1] : !llvm.struct<(i64, ptr)>
llvm.call @printMemrefF32(%78, %79) : (i64, !llvm.ptr) -> ()
llvm.return
}
}
```
#### Use -convert-math-to-llvm :
```
/home/workdir/llvm-project/build/bin/mlir-opt test.mlir -convert-math-to-llvm \
| /home/workdir/llvm-project/build/bin/mlir-runner -e main -entry-point-result=void -shared-libs=/home/workdir/llvm-project/build/lib/libmlir_runner_utils.so
```
#### Output:
```
[[[1]],[[1]],[[1]],[[1]],[[1]],[[1]],[[1]],[[1]],[[1]],[[1]]]
```
### 2. Use -convert-math-to-spirv:
```
/home/workdir/llvm-project/build/bin/mlir-opt test.mlir -convert-math-to-spirv \
-one-shot-bufferize="bufferize-function-boundaries=1" -convert-spirv-to-llvm\
| /home/workdir/llvm-project/build/bin/mlir-runner -e main -entry-point-result=void -shared-libs=/home/workdir/llvm-project/build/lib/libmlir_runner_utils.so
```
#### Output:
```
[[[-nan]], [[-nan]], [[-nan]], [[-nan]], [[-nan]], [[-nan]], [[-nan]], [[-nan]], [[-nan]], [[-nan]]]
```
</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJzkWt2O4yoSfhr6BqWFwfjnIhedZCKNdEYrzWq1ly1skw57HLAAp3vO06_AP-0ktjPT0aR3daQocQxUfV9VUS4wzBjxIjlfAroCdPPAartXemleOWfFQ6aKH0vLjYW5OhyEBeQJArpKUhKyiAO6ATjZW1sZQJ4A3gK8fRF2X2ePuToAvC3LY_ezqLT6D88twNtWFN62YgKSFUmBGWIFjlCaFRFOCM5ZjFDBMsJigFOAntwHE4AJ3HCTa1FZoaTT65v-vecS5koeubZCvsBvf3z9DnNVcPgq7B4emN1DVXHN3CgD8BoWYrfjmksLM5b_yWVhIMCJwwqPBppK6CPAKay0KuqcQyFzJY0w1o1Qta1qa-BOaWj3HBp24F5bi7OH-k_LKwOtgt95K6hH3PRwnTzWSqsXzQ4OgzP446EU2hHvu0eo_aCngyrqkkMQrwB6gtBhftzVMocgRAdWlioHOBFR6PAvAPkCAQ58p8pqN8JfOwWPL6XKWAkrLY7MOgrSWCatE_T83P17DtBb8Ba87QgGOCm4NByQdYwfwyBN0yTwGsgTtFwapQFZD_qTLw4EiFesKPSzqVjOISAbiPwI4SSuISvFizw4w7qmKGzaohDEG3_ZwWdasx9ePnyD_Z-z61Zr87kwT6WFtN_4QfPd1tPxZlqfWAinkFmrRVZbbhx28-PwfBRGZKIU9ocHCTBujQYwBvFmzBFCApy09F07wBT5we_270wMcBI0rGXB3_yY1gROLnRDg5mh6MpYPD322lByg9rw42zpx4dGHx8anw39i2t1EoHtBAKYJu9dX7jlJXfxW1ntxbhkiikBtIvf5CS-1nBqcuK1j98eUPqupbLaKuHmSKP8BJRLMafRch5pbv5xY9Rucm6PEW2FBTNkAwToCjnkw68J5uOUb5rfDsJMfJOY0BQnlKbX5tcg0oW0VnX8cNfXGXncPueBXilhlDwxqLG6zi0ga4CTlvYwFtY9RwLf_C2XOcfvpl1ma5TTIW7DtT2ysuYNpca6NAi9j-jmd0KCA0zRNKagw0QBXQV3xHQ-uX8hCQbJNJ-44xMBusJ35JNOYurdngC6ImcT8nfjwmgSV9jhSjtcd_Q_DiZx0RYXRh2uO_oR46v2wgGgq_DefiTX7YU7XPf0YziJK-pwkQ7XPf04V7JcLdBuKFrwTGK7Oja5YWz6k9VSW0iimSICp03JhOntNRMJxosmgq5WTWSmkOiWJdOV8mDCsKJooLQRSfBI_0Eg56wsT1ZvXl6nZn4157rSCcrhdco3RB4ZRJ6ps4Zoxzga6Z9cWqjLJV7Wef9BhNWaHxoZMyYN0SWgvv_YAiUYr_lCdLXmC89D5Z41Xzidm0n30AjxfWu-cDovh900CMl9a75wJidfXbxO17BhF7RheN-aL4wnMeEeU_QJRV84XSDj7qkcxp9Q9YXTVTLuKvcw-YSyj06Xye8WSz-h7qPTdXJvMYo-ofCj04Uy7pI8De5d-XnZmYaAfsmyoHlyvz-Z_M41PGmkZNBIXKPfOIcYVpoXptli_5JlfiPFXyUDGwyTbH6oIMDYlBa4RYQX3S6wztJZU2MoWTxnuhHTC8f91QAqbgzncTlUPahgjDWZY902UvpzrN_hxAPW0SzrLvOha6yjXnh4Ztz25gDYCW0yRpvO0W4bafxztN_xRAPaySzteIz2BedkIPnUtO3NKc50AGSQRPmb1SwfTL3wvo_0CF3UkH3YUwrVketdqV4BWUvz6u7L-rV7QdHayEkJLqREqJMS_5SUFg6eWtUImalaFgbEa1m_NmZsFjlRcPsiJxpUgKViRY_ltNr3ck4HNhnkwOz-0TK574U9nfWj0z6n-M4-j272eSsovnR79CG3T27_X7o9oq3b4xvd3lpZ6Wazoyv0o6T33tmLrHe46aUBR9PHRI6L0tEkF_9M8ohHJuxsxj57rMRoVHdyNVm7sZfTvA-cWd3tszoORnWnk7qDNr_EMxsJV19CDfcRylLlrJX49vum2tVNhovwo91CPya_dc07FdLxzMtFcs3C58vCK2v3FnnzButkIR5PLxLjbn7G9NpC_Fz-IPXF0yu-uIvkOLqWjucUJNN5Po5vQT5TNHjBH0J8slt28TLf8-mskp5vn1285W8DPekmdytec1tr6Weyf7Hffg8OYAyPbwBM4L8Mh4v29MnCPVoXVi2cLNie3xiOxdu9OnCAt69K_1kIfXlCJqtFWbhfIQHeughdqMrC_lzIhC4I6LpB7Zh-RIuupeQaLjg8MCHhgkurfywqJaRdaG7q0gKyOSpRwIXZM82LRSkyA8jmF9SVImu-ncbnRuNzbUVpHo26sNXAyP_wh25GDEpXzccFlD-TtP7f-k8vwqfnhB_HY6c5fnSf2PG62thZKMkXZq_sIqt3O67FX9x7F_d_F7ta5lYoufB1DtOCuwAI3KqkF-1FdnH594xK2IflQjLZRwb8v7t3Gb3o6aFYkiIlKXvgyyCmYYDSACUP-2XKiixhcUoCvEtohoI8DYJiF6V8h6MkjB7EEiNMUYIwCkkQJo95gTEOExpEiCY03IEQ8QMT5aNPxUq_PAhjar4MaBCn9KFkGS-NP62IcXNGDgO6edBL79isfjEgRKUw1rxLsMKW_oTjtz--fgd083V4lq9xIFxx-8q5hCBCo9kVRAgyWYy2N7M1Qg-1Lpe_fB7S8zMAb1uKxyX-bwAAAP__olVOng">