| Issue |
171671
|
| Summary |
Multiplication by zero generated for widening multiplication in loops
|
| Labels |
new issue
|
| Assignees |
|
| Reporter |
purplesyringa
|
[Godbolt](https://godbolt.org/z/445r7c4KW)
```cpp
#include <stdint.h>
static uint64_t mul(uint64_t a, uint64_t b) {
__uint128_t product = (__uint128_t)a * b;
uint64_t result;
result += __builtin_add_overflow((uint64_t)product, (uint64_t)(product >> 64), &result);
return result;
}
uint64_t pow(uint64_t x, uint64_t n) {
uint64_t res = 1;
uint64_t tmp = x;
while (n > 0) {
if (n % 2 == 1) {
res = mul(res, tmp);
}
tmp = mul(tmp, tmp);
n /= 2;
}
return res;
}
```
```asm
pow(unsigned long, unsigned long):
mov ecx, 1
test rsi, rsi
jne .LBB0_1
.LBB0_4:
mov rax, rcx
ret
.LBB0_3:
xor r8d, r8d ; r8 is cleared
imul r8, rdi ; ...and then multiplied by rdi
mov rax, rdi
mul rdi
mov rdi, rdx
add rdi, r8 ; adding 0 to rdi for no reason
add rdi, r8 ; ...and again
add rdi, rax
adc rdi, 0
shr rsi
je .LBB0_4
.LBB0_1:
test sil, 1
je .LBB0_3
mov rax, rdi
mul rcx
mov rcx, rdx
add rcx, rax
adc rcx, 0
jmp .LBB0_3
```
>From a quick check, it seems like GVN hoists `zext` from `i64` to `i128` out of the BB that performs the squaring, which prevents isel from realizing this is not a full 128x128 -> 128 multiplication, but only 64x64 -> 128.
_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs