<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/76000>76000</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
[LLVM][InstCombine Pass][BF16] Bfloat Computation Can't do Instruction Combine
</td>
</tr>
<tr>
<th>Labels</th>
<td>
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
circYuan
</td>
</tr>
</table>
<pre>
Hi LLVM community,
There is an issue for bfloat type in the instcombine pass. The link is the smallest testcase:
https://godbolt.org/z/K57hG6jrK
I think the function `foo` which uses `double / (double) bfloat` can be also optimized to `bfloat / bfloat`, just like the function `hfoo` do.
And the root cause is in the `llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp`
https://github.com/llvm/llvm-project/blob/a8081ed8ff0fd11fb8d5f4c83df49da909e49612/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp#L1527-L1533
This function casts the FPConstant to the smallest fp type that can represent. The trivial way to make bfloat type work is also adding the bfloat relative code in this function, but there is a main concern: The implementation order of `bfloat and half` would make some use cases weird. Considering a FPConstant that `bfloat` can represent but `half` can't represent, and once I correct the code to
```
1 static Type *shrinkFPConstant(ConstantFP *CFP) {
2 if (CFP->getType() == Type::getPPC_FP128Ty(CFP->getContext()))
3 return nullptr; // No constant folding of this.
4 // See if the value can be truncated to half and then reextended.
5 if (fitsInFPType(CFP, APFloat::BFloat()))
6 return Type::getBFlaotTy(CFP->getContext());
7 if (fitsInFPType(CFP, APFloat::IEEEhalf()))
8 return Type::getHalfTy(CFP->getContext());
9 // See if the value can be truncated to float and then reextended.
```
I think there will be a case that `double / (doube) half` becomes `Inf / half` since the function told that the smallest type can represent is `bfloat` but it actully would be transfer to `half`, we can reference the following code to see the reason:
https://github.com/llvm/llvm-project/blob/a8081ed8ff0fd11fb8d5f4c83df49da909e49612/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp#L1719-L1731
**One solution is that I think we can add the fptrunc result type to function `shrinkFPConstant`, and make it double check the return type and the smallest type are the same type.**
```
1 static Type *shrinkFPConstant(ConstantFP *CFP, const Type * DstType) {
2 if (CFP->getType() == Type::getPPC_FP128Ty(CFP->getContext()))
3 return nullptr; // No constant folding of this.
4 // See if the value can be truncated to half and then reextended.
5 if (fitsInFPType(CFP, APFloat::BFloat()) && DstType->isBFloat())
6 return Type::getBFlaotTy(CFP->getContext());
7 if (fitsInFPType(CFP, APFloat::IEEEhalf()) && DstType->isHalf())
8 return Type::getHalfTy(CFP->getContext());
9 // See if the value can be truncated to float and then reextended.
```
But I think we can do more discuss, since it is just a case by case solution.
Thanks!
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzcV99v2zYQ_mvol0MMifIP-cEPsROtQbPNwIIBexoo8hSxoUiDpJKmf_3AH3bsukXRYQO6BUZs2XfHu----05izslHjbgm8w2Z30zY6Htj11xa_sfI9KQ14nX9TsL9_e8_AzfDMGrpXwndkuKGFNcPPVoE6YBpkM6NCJ2x0HbKMA_-dY8gNfg-vDnPzdBKjbBnzk3hoUdQUj8F72DhBqYUOg8enefMIamu0yG993sXrmhDaPNoRGuUnxr7SGjzidDm_XzZ_7T4YN8n8_T_DnwfoofQ3ai5l0YDWRSdMWRRwEsveQ-jQxe-FGZsFQKhDRBapytCV7mQYM-ZhhaBKWfA7L0c5CcU4E3wzuUG76MDoVv4MDoPSj7hRRJ9zkKYacr2WotoZI3xwNnoIqgZO7IolHoeCG2UbAltHizTrjN2cIQ2d9r5bQL2_GrLnHdTvt-HbL6Eo_T92E65iYFzfPU8XO2t-YDcE9q0yoTzWF3UJYq664pOlGXX1mLezXhdiW62EmxVrHC2WpT0JM7fypNW9-WcLq_uy3lVnfbyoZfuDT8eHCIwzW5rtPNM-9CJMxJ1-0Q_3zMfm2dxb9Gh9ol53spnyRS8sNfgO7AnPKPti7GRmbHhTAipH-MB2caiYl4-I3AjMsdPUgzNb0cfHPJ0wMCkBm40R6tJdR1zkMNe4YDas1iXsQItmO6EUkwL6JnqImPNqERK1JkBA3cDFOjgBaUVUwhYSIE2pMrOsAkYHIMe2HwEJKYaSJkP4kwTuvRvBqGckEnIHu6AG2uRx-pS-d7kZi2K_IqXJbhQGYeHACih1663Uj-9JUZoffjY7ILBttmFqSPLTYpAQXZhILfN7opUt4_oQyhC62hV3ZDqJgYPnK6uH9Hvdts_m11J64fXM7et0R4_-uSZXpCOqMCiH60GPSq195ZUG4A0IPCLCR1LGHZGRQ6YLrZ6mt1nAEfz3xBDvgGWZ6ZGPGiGt6PmzCe5CCBHMH2PoQf40aMWKA4B5yFgqrqT3t3pZpdrjuBs4XrXxC7Gkjfp82VZC4h_ubYzjDaNYsZ_C6Aqt2D5Xfnc3d7eRhpdZlR_PaN3THXfzifHWX0v4m-T9BXIP6PtyeKwCC9SqSj8cdaOo3S5MOK-OIxQi9wMabXc6S6aHX5yMkzR2ULwRokU-XwPhrE5n1Tpzuc4TK70wLgflXrNEhEBCMqLNi-ofHZo18shZIcWj5kYpcxLoHeeZ3CYfrHInNFf28Q_5AZZlqur-3JZlacbhNDw-lUH7VRjRD3edjAPh35nZJhIm7jbRxaBRTeq3IzAppMtfqFnCeJAtSjT0kPmCe-RP2VAI_9juMzJzzrObILesQHjN9OU_D-psdskbEcvuHFZWs_U9zj6_6oAn-rC_0GFgdAFoYsDpgEB6S5sfiiZ_mLK784t_lsqvhkvJlsYGIxFENLx0bmAShJjGYU13q1nmW9f0_tBLKaH-1Cmnxyh5USsK7GqVmyC63JZVMWsqmg96dc4K-hiNS84nbUVn3O-WC3rthS0LStRIk7kmha0Kiktiqqa03oq6hVdLCtez2cd75aCzAocmFTTIIThIWcSn6vWy0VRFBPFWlTu8LBm11Fu2_HRkVmhZJDBo5uXXsXHuvDoRuY3ZL450UzYMefSt5umXJD5DWwSxlsz7Md8S7rNt4LCQPC1Y9K-HGMyWrX-7pUQywl6Hiv6KwAA__9xc47U">