<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/128843>128843</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
GlobalISel inserts illegal COPY operation
</td>
</tr>
<tr>
<th>Labels</th>
<td>
backend:AArch64,
llvm:globalisel
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
sdesmalen-arm
</td>
</tr>
</table>
<pre>
### Reproducer:
```
; compile with `llc -mattr=+fullfp16 -O0`
define i32 @reproducer() {
%retval = call i32 @llvm.aarch64.neon.fcvtzs.i32.f16(half 0xH4566)
ret i32 %retval
}
```
This runs into a llvm_unreachable:
```
H0 = COPY W0
unimplemented reg-to-reg copy
UNREACHABLE executed at llvm/lib/Target/AArch64/AArch64InstrInfo.cpp:5250
```
This issue may be related to #79822.
### My Analysis:
GlobalISel seems to assume that everything goes by default into a GPR, because after RegBankSelect the IR looks like this:
```
bb.1 (%ir-block.0):
%1:fpr(s16) = G_FCONSTANT half 0xH4566
%2:gpr(s16) = COPY %1:fpr(s16)
%0:gpr(s32) = G_INTRINSIC intrinsic(@llvm.aarch64.neon.fcvtzs), %2:gpr(s16)
```
(1) During the 'instruction selection' step for `G_INTRINSIC` it inserts a COPY to move `%2` from a GPR -> FPR. This results in:
```
bb.1 (%ir-block.0):
%1:fpr(s16) = G_FCONSTANT half 0xH4566
%2:gpr(s16) = COPY %1:fpr(s16)
%3:fpr(s16) = COPY %2:gpr(s16) // COPY inserted by lowering of G_INTRINSIC
%0:gpr(s32) = FCVTZSUWHr %3
```
(2) During the 'instruction selection' step for `%2:gpr(s16) = COPY %1:fpr(s16)` it:
* Legalises the operation, e.g. if the size doesn't match, it either copies the sub-register or it inserts it into a larger register using SUBREG_TO_REG.
* Legalises the type (selects the appropriate register class for the result)
After this, the IR looks like:
```
%6:fpr(s16) = G_FCONSTANT half 0xH4566
%4:fpr32 = SUBREG_TO_REG 0, %6:fpr16, %subreg.hsub
%2:gpr32all = COPY %4:fpr32 // type is promoted, and SUBREG_TO_REG is inserted
%3:fpr16 = COPY %2:gpr32all
%0:gpr32 = FCVTZSUWHr %3:fpr16
```
Because the GlobalISel instruction selector has explicit code not to revisit the `%3:fpr16 = COPY %2:gpr32all`, the COPY remains in place.
```
// Snippet from InstructionSelect::selectMachineFunction
for (auto End = MBB->rend(); MIIMaintainer.MII != End;) {
MachineInstr &MI = *MIIMaintainer.MII;
// Increment early to skip instructions inserted by select().
++MIIMaintainer.MII;
```
I think this COPY should instead have been turned into an FMOV by SelectionDAG, rather than leaving it a COPY and hoping the target will implement it. My understanding is that `copyPhysReg` should only implement copies where the sizes match.
I don't understand GlobalISel enough to make a judgement call on how to fix this though, @aemerson any ideas?
</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJzMV01z4zgO_TX0BRWVTFm2c_BBduK0qyZJl5Oeqd1LFyVBEicUqSIpJ55fv0VSsp2P3tqd07h86LYE4AF4eECYMbyWiCuSrkl6M2G9bZRemRJNywTKK6bbSa7K44rQJHxhj51WZV-gJklG4ozM4-EbZyRZQ6HajguEV24bIPNYiAKuWmatJskNoeuqF6LqpnO4ehyt4qzEiksEnlAgs1ifQ9AloddAFmsSZwCEphrtgQkgyQ0UTIjRRIhDGzGmi2Y-iyQqGVXFwf5lIp7QqJrOCV02TFQQv32bpfM5odfeoUYbPIyOHZzFzce04uy54QZ0Lw1waRUwcAF_9lIjKxqWCxyK8d7wW-yBbh6__wv-cD_0kredwBalxRI01ldWXWmsoVDdMdj_eNjfZptv2fq3W8A3LHr3JrM-IKFbwXNCt89M12gJ3WaZT_n8r500Vu9kpaKi60iSpTSNf5EON6ZHaNkRcgSNgrlIVgGhyeJ6SWk0JHRq_f0RMsnE0XBzSvdOqJyJ3RMKMIitcQ6YMX2LYBtmAQ-oj7bhsoZaoYH8CCVWrBd2rOTd9z2hG8ixYL1BYJVFDXus10y-PKHAwoJtEHZ7EEq9GBD8xfk-YbjILM-jKXjOpFxf5UIVL1Hseu3f9PyZkiSrOkcs41hx7Rt093O7eXx4es4enuEdTQYjSpKs_mjku_qFx9EoPhsl9Bxp9_C83z087TYuf82l4YVD_GsKO5d08xWMz30ldDl1oW567Sru6kbogjtO9IXlSoLxFeVKEroAY7GDSmk3pxfIyDwG7vpjUFsDLKRqFbTqgO5dj2UeQ6VVGzoIVyS5he33fQRhVND0wrpp-Yd2CfzHmRKaJl-FGy0_uQ2WdEvoNrwUCoWlI7dQr-hrr6rLZv9XUmw3vz__--nHH990APNVW-nfbOv_zV7f-6FpNIPfsGaCGzQ-qupQsxBmAxjVEfDKPzD8L4RSoXEALLTMFo17h1tAbhvUTuH44MX0uRM9btykK33JNX6SBeEkTsPpvd641J9-rPe3dz-fH3_ub--iLzHaY-fKswwlCb-xrtOq05xZPHssBDPG18m9Ehg7TFWcZV6GvMzQzWcB-sxq39753-HtLBi5NZTcvM8Q4mH0B8fOqf-_6XONddSYPh84PHQ5oW4rXnb47H78DNz1heIGOq1aZbF0rpksPyBwi2Lg9wg4GcF8NScewAe6D6l95PmY0ie-r4dd4Mp-sWA-E15paJgBfOsEL7iFQpUIUlknVhoP3PCwPMIg_A-45_HYbv9YY8u4X_rQCVZg9BFrqOST5F2HNujh7owyrC_HlSQLgO9Z0XCJ216GafXp-lGlS9ZbBbey9Oju12snqRplGY4gd1vd73b3jEvLuEQd3e92QOjUvX0rS5KsL0-lIZAHA4TO73feLaHZJyfOMvTLJ7OThfYXCiDT4uhKaV54d1l9807yQmYBZTR4WhO6_kWgD73euSGTL37UQtFNo3pR-njISmjYASFHlGB7LbEcBELC9v7xdxf_adS-m-zOdU8zLzi2YRIEsoPTDW7HNeYY3qhu1FHrLyl45e6WHG8z4DZy104vS9TGMll6HyacNGQeu3Pte3M0e6ydYA6IlRTHCyeD4r02qPEkkiZoYzQmX6qgmOdQl4xHqfq68auXvSAw-LMv68G7m3MloVGv7nnF30IJbeNMvEzMYoYtaqMkMHkEXiIzJNlOylVSXifXbIKr6WIWp-lyMU8mzSrGdDkt6aJgNMkrxOlyzqZpOaMlncbTIp3wFY1pGlM6j5cJnSXR9RLZbFGw6TKdpgmdkVnsJkZE_phRup74I3M1pcvlLJkIlqMw_q8NSnNWvDh2J9npiKWEbgil_tRNstrXgRsU7kl6M9Er9-Qq72vj7iVurDkHstwKXL1Xi7BShHD7IXT_tMAmvRarxtrOn5Ge-TW3TZ9HhfJ39nBuu4CdVn96hm99NobQ7ZDQYUX_EwAA__93wvx-">