<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/126889>126889</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
Zero-Extend is dropped in DAG->DAG pass
</td>
</tr>
<tr>
<th>Labels</th>
<td>
new issue
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
wthaller-blackshark
</td>
</tr>
</table>
<pre>
Observed with llc 18.1.0, 18.1.3, 19.1.0 and with whatever `trunk` is on godbolt as of Feb 12,2025.
Not observed with llc 17.1.0.
The "X86 DAG->DAG Instruction Selection" pass drops `zext` in a situation where it is needed.
I have code that loads an i8 from a pointer (function `bad` below), passes that to a function (`helper`) that takes an i8, and then performs `1.0 / (uint64_t(1) << x)`.
The DAG->DAG instruction selection pass on the first function changes the 8-bit load to a 32-bit load, and the DAG->DAG instruction selection pass on the called function optimizes the instruction sequence for the above expression but chooses not to do a zero extend.
If I put the same code into a single function (function `good`), the load is compiled as a `movzx`.
```
target triple = "x86_64-pc-linux-gnu"
define double @bad(ptr %0) {
%2 = getelementptr i8, ptr %0, i64 16
%3 = load i8, ptr %2, align 8
%result = tail call fastcc double @helper(i8 %3)
ret double %result
}
define double @helper(i8 %0){
%2 = zext i8 %0 to i64
%3 = shl nuw i64 1, %2
%4 = uitofp i64 %3 to double
%5 = fdiv double 1.000000e+00, %4
ret double %5
}
define double @good(ptr %0) {
%2 = getelementptr i8, ptr %0, i64 16
%3 = load i8, ptr %2, align 8
%4 = zext i8 %3 to i64
%5 = shl nuw i64 1, %4
%6 = uitofp i64 %5 to double
%result = fdiv double 1.000000e+00, %6
ret double %result
}
```
Output (directives removed for clarity):
```
bad: # @bad
mov edi, dword ptr [rdi + 16]
jmp helper@PLT # TAILCALL
helper: # @helper
shl rdi, 52
movabs rax, 4607182418800017408
sub rax, rdi
movq xmm0, rax
ret
good: # @good
movzx eax, byte ptr [rdi + 16]
xor rax, 1023
shl rax, 52
movq xmm0, rax
ret
```
Note the difference between the `movzx` in `good` and the `mov` in `bad`.
</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJzEVk1v2zgQ_TX0ZWCDoj4sH3xQkroIELQLbA-LvRSUNLLYSKRKUrabX78YSo4dt912TysYkCzOPL73ZihSOqf2GnHL0juWPizk6Ftjt0ffyq5Duyw7WT27VtrnRWnqb9uPpUN7wBqOyrfQdRVE-SpacSbup6c4PG3oHUg9xx1b6fGAFljGvR31M8s4KAdGw97Upek8SAemgR2WEAkm7gUX6Yrx4oPxYL6fc034NM548alFYEL8lWfwULxfsvjdQ_EeHrXzdqy8Mhr-xA7DExMCBukc1NYMjti84MkHMhokOOVHGTKOLVoE5YmkRqyxnid7hFYeECpTI_hWeuiMrB1IDSqHxpoeJAxGaU9iRd6MeqLAMl7KmmYqsTNHJjbkE3FBNwF5AxIu8SJnGW-xG9CyjDOxmaPkM87TEQA57FvUMKBtjO2DJrKeiR1hjEr7LPnsmcgjwmDxPYvv4UTzZ8FAcu_KNnVlmzvbNnlmNE0FjbLOX4hWrdT7oAEhX5ZqcmRSE4vXF1dk_9t0FfVhfZnPDF716mWe8W3-1xF1hdAYGwZlaQ4IeBosOkcR5eihao0hz7UJltfE8wWtATx51K9lbuARhtEHHCf7ueJKB11O6X2Hb4p1Xei9MfVUM1JNCMES5aAy_aBIjnQgKbQ3h5fTXAn6ZXz-8cJLu0cP3qqhQ2DxAzX5Kc8-Z8lyqJad0uNpudcjE2JKrrFRGqE2Y0kJSWg4kQ-eOjENLQRsfcd4AfRCBMw9euywR-0pbmqqS8Y9qCyBKDvnxCFnUnMdKkJ5O7XXkJ9jLbqx8yHBS9WFQkIjna-qK45zh4tc5WECMo0ALPrXqDMWyVw__ETsDVBw_1YsLXaYx6n4KkveKnNtB3o8TqpJU9DGC7onIWJU3jRDCAhZoYWIwxkoDWFNrQ5nctGKhwuZuON8Rk1-oDL9V4Ghq_6_cia3DsY3DqY_dfA1JPuBhen3Fl51zi99zH6jW64WFePFx9HTwmYir5WlD84BHVjsDe0w9OmoOmmV_0YNFN8uSlpScQG_cTERn9cgL6A3h_AWa0XE66Ox9eR2emdrBUzcUV3ShyBnur70Q7jPnZ3wP54-BdhPxePTffH0xHgxj_0GpZnPnMCLUCm67ERp6vP56s1Blg7AyhONJRlfR7lIojznnEfrhOdXwW4sz4GE9QblK91PfR_KRUGXUYtUotDVcXGmF_6-QXg5kW0TfPnN469cOxl7ZhNxEV_zPAueRm8F_4jqxPGmgT4Yj-GrXqumQRu2nBL9EXHasa4-63SsuGwIrxvgFHEZn04Gq0W9jetNvJEL3EbreBOneRyni3abxWlcRjFfZzKXyDHOIywzkZdr3iSbulyoLZ2XuIhEFPE0Tld5vC7XWG0260xuSsFZwrGXqlt13aFfGbtfKOdG3EYiy_PNopMldi6cAYXQeIQwSjtL-rCwW0paluPesYR3ynl3gfHKd7j9G61ZvgsbKG1zdLoasCZ1V3s97eqL0Xbb1vvB0doSOyZ2e-XbsVxVpmdiR7jzbTlY8wUrz8QusHFM7Ga6h634JwAA__-hQh3U">