<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/61933>61933</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
Aarch64: load + sign extension of i1 values incorrectly folded into "ldrsb" by FastISel
</td>
</tr>
<tr>
<th>Labels</th>
<td>
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
piotr-coco
</td>
</tr>
</table>
<pre>
We've had an issue whereby a load followed by sign extension like this:
```
%.b = load i1, i1* @Mdropped_sbfxVmax_uint, align 4
%0 = sext i1 %.b to i32
%1 = tail call { i32, i1 } @llvm.usub.with.overflow.i32(i32 %0, i32 -2147483648)
```
gets miscompiled into:
```
adrp x8, _Mdropped_sbfxVmax_uint@PAGE
Lloh4:
add x8, x8, _Mdropped_sbfxVmax_uint@PAGEOFF
Lloh5:
ldrsb w8, [x8]
and w3, w8, #0x1
mov w8, #-2147483648 ; =0x80000000
subs w0, w3, w8
```
Note that the value being loaded is an `i1`, so `ldrsb` will not sign-extend it as it will be extending the 8th bit, not the first.
We have traced this down to `AArch64FastISel::selectLoad` and `AArch64FastISel::emitLoad`:
In `AArch64FastISel::selectLoad` the bit of code that decides whether to fold the load and sign extension under the comment `// Fold the following sign-/zero-extend into the load instruction` will allow the folding whatever the width of the value.
We then end up up in `AArch64FastISel::emitLoad` in this bit of code:
```
bool IsRet64Bit = RetVT == MVT::i64;
switch (VT.SimpleTy) {
default:
llvm_unreachable("Unexpected value type.");
case MVT::i1: // Intentional fall-through.
case MVT::i8:
Opc = GPOpcTable[WantZExt][2 * Idx + IsRet64Bit][0];
RC = (IsRet64Bit && !WantZExt) ?
&AArch64::GPR64RegClass: &AArch64::GPR32RegClass;
```
This will not do the right thing if VT.SimpleTy == MVT::i1: and !WantZExt since it will extend the wrong bit.
We patched it with this simple patch, although we're not sure what the best way to do it is. The patch has been generated against an older revision but we can see the same behaviour on LLVM HEAD.
```
+--- llvm/lib/Target/AArch64/AArch64FastISel.cpp
++++ llvm/lib/Target/AArch64/AArch64FastISel.cpp
+@@ -1811,6 +1811,8 @@ unsigned AArch64FastISel::emitLoad(MVT VT, MVT RetVT, Address Addr,
+ default:
+ llvm_unreachable("Unexpected value type.");
+ case MVT::i1: // Intentional fall-through.
++ assert(WantZExt && "Load with sign extension of an i1 will not work");
++ LLVM_FALLTHROUGH;
+ case MVT::i8:
+ Opc = GPOpcTable[WantZExt][2 * Idx + IsRet64Bit][0];
+ RC = (IsRet64Bit && !WantZExt) ?
+@@ -1961,7 +1963,8 @@ bool AArch64FastISel::selectLoad(const Instruction *I) {
+ IntExtVal = ZE;
+ else
+ RetVT = VT;
+- } else if (const auto *SE = dyn_cast<SExtInst>(I->use_begin()->getUser())) {
++ } else if (const auto *SE = dyn_cast<SExtInst>(I->use_begin()->getUser());
++ SE && VT.SimpleTy != MVT::i1) {
+ if (isTypeSupported(SE->getType(), RetVT))
+ IntExtVal = SE;
+ else
```
Attaching a test case. To trigger the miscompile we used:
`llc -march=aarch64 dropped_sbfx.ll -o - -fast-isel=true`
[dropped_sbfx.txt](https://github.com/llvm/llvm-project/files/11149277/dropped_sbfx.txt)
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJy8V1uP4jgW_jWulyOixAkhPPAAVdBdUvV2q4qulual5CQH4h0TR7bDZX_96jghULed2ZnVIgS5nPv5zmdbWCu3NeKMjRdsfHcjWldpM2ukdmZU6ELf5Lo8zX4h45M9QiVKEDVIa1uEQ4UG8xMIUFqUsNFK6QOWkJ-AjAIeHdZW6hqU_B3BVdKyeM7COxbOWRr2X38LjI-DHFh819mSEeO3_ncOLAm_lUY3DZYvNt8cn3fi-NLK2pGIUOQp6a2QmdBbsXh0IKPertMgY34lFHkhJ6SCQigFbLLwEt4psMkdeVVqvwta2-bBQboq0Hs0G6UPgRfMZMy9O68TcxjxKJkkWZwmGePTD7PcorOwk7bQu0YqLEHWTn9WEhZORWkaFk6PGfl4-aQISfhj_mXZ6TwoXSUXg2ShHAz8GTPfV6uLpfG1JVUam7NwevBW2HhxzNj47uKoJkeHmF72IjwOj9EgsNP7izaPr6oFbz4sXlB3wmMWdp_Bhm1zS0Z8zQdfHxePfv-hHcFOOHAVwl6oFiFHWW89yKj-ltDM0lBGpMpvwWq67ZJNQzhIpaDWzgN65AFdgnQgLP36tzl2QC_JLvnJXAW59OgkTXq0kca6oAvqF03RHsEZUWDppwJKfagJpCwN53NTVGmyEtbdP6GiFsRziwoL96BFSUGJuvxUEnfyLDd0777-k4Yp1Fw60BsodNmXrsRClmhp2l2FhsLcaFV6YT-rFM6beW_rkiQrhELvdlg78OVdMb6C1Vm54wuqmi8u46t_odFDkWunLz5kbZ1pCyd1PbRFkPrZkq_-oRIO973ngyxdRakMvb80wFVYA3lpG_rKzwt0VU8S8926KtGnfAa51gru7SO6NFlI5_nmEd3zmq7o5tvzunMh04TFi17PHqQrKmA8e14HT3LXKFyfGJ8SQ51Nl7gRrXKDbxoa4qqXtjYoikrkChnPGOc_azw2WDgse_S7U4MB45wYavAJhbB4FU_EYiJk36372mFNZRcKNkKpkauMbrdV8Ilu9iqq703hE__y43tTrH1c48UvUbvflkdH9DFeEInO4b48AuOLq4J1b0P6GwJ9vPXWGM-uC8tTxlNgPBoMU7ni1SWMC7XwtO9yF-6XH49p8ojbWyWs7bJ-JxDzi8Diw2avCRQDU5QdbI3cVjT8hEu5gatuvgeAL7if6ksSYGVd4MAy_VR4YBtdbwmEwTXX_UJohCsqLDsdV3Vgtd5r965bMF1FDYQDLekGO3ZrDfrp6SgArYODONGol5rMSRvAuuqtQCUs5Ig1bLFGIwhdYitoRIlNtaLZN7iXngry1sEBoRA1WPSTB1bsyEkl9lK3BnQNDw_P3-Drcn4XfMzmfDEajTzGGV8pmTO-WguzRcf46tyv4eo8wEHRNIP-8P17VpKQJSGMoiyiDQqhbtFfZ9C_bGu_oyrhP_MJz749r-F5TT2hK88NdDMvS4PW-n_Gbwff78aenv3N0e9M_PXx70sKAMJaNI7xbMDvMJec8u0Q-WaZ0Bu_mYwuw3PQ5vf3MfY-CCUvq_nDw_rr4_efX76-SuNTHjqX6X_LRWerf4WSroE0TQk8Ew-kaRpfA8mvIH-0avOs0DR495cFkpK4f7Vk-Gxqtzy6Z6F8vL8t32UCgMri22dwWbQIrFdKI0-okzuvRhQ3xCJa2srw-dPSq5Wn-qUQ1rH49ml5dBQpi5dUsRGLl63Flxy3svawndKjLbqfFk33oPu-yoWi-_84fo_Bqw956Rr9itx59Jbc37ai-3SBS7s-NfjUNo02DqmfT8s-FHpxDuX2zA_Ty9niKqDXzX36g-a-Jte5c6Lwy5QAR8xPkxTAWoMzcrvtd1OXUwuxeWuxvN76KFXAaCdMUbH4TggPWbg-ZwRKwUjDCEYbYd1IWoLynTMtXkh-vHil4bqp5FnlXOMPjp6SttJVbR4U2pN4z-Vqvxs1Rv8TC-LyjVRoGV9FUZRM-WTC-Oqd5XMVb8pZXE7jqbjBWZRmYRql4yy8qWZFEU0nmygswokoM56NU5Gn07jIeDHhCZ_eyBkPeRwmYRLF45SHQRhFUZ5MJhwxS8NNwpIQd0KqwJ8jtdne-GPzLI2mcXyjRI7Kno_dZuZzyNutpYOntM5e1Jx0Cmdzcd6XdFtiau17PpVRR_cWZF1oY7Bw6uQ3yP1xkwi5O95wTif1M7PctEbN_utS-4yo1j6pfwcAAP__3avEmg">