llvm / llvm/llvm-project

[InstCombine] missed signbit comparisons -> copysign

Closed
#213,244 1 comment 0 reactions 1 assignee Claimed by @tejasgaikwad04 View on GitHub
llvm:instcombine missed-optimization
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

found from https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109843

https://github.com/gcc-mirror/gcc/commit/1c8ca0108746d3a7452134f9d1c2e5d89857fed7

>MATCH: fold signbit comparison and conditional negate to copysign [PR109843]
Fold (signbit (x) cmp1 0) cmp (signbit (y) cmp2 0) ? y : -y
to copysign (y, +-x). The result keeps the magnitude of Y and takes its
sign from X (or -X). Emitted as IFN_COPYSIGN when the target supports it.

```c
#include

/* Transforms to copysign (y, x) */

float copysign1 (float x, float y)
{
bool t = __builtin_signbit (x) == 0;
bool t1 = __builtin_signbit (y) == 0;
return (t == t1) ? y : -y;
}

float copysign2 (float x, float y)
{
bool t = __builtin_signbit (x) != 0;
bool t1 = __builtin_signbit (y) != 0;
return (t == t1) ? y : -y;
}

float copysign3 (float x, float y)
{
bool t = __builtin_signbit (x) != 0;
bool t1 = __builtin_signbit (y) == 0;
return (t != t1) ? y : -y;
}

float copysign4 (float x, float y)
{
bool t = __builtin_signbit (x) == 0;
bool t1 = __builtin_signbit (y) != 0;
return (t != t1) ? y : -y;
}

float copysign5 (float x, float y)
{
bool t = __builtin_signbit (y) == 0;
bool t1 = __builtin_signbit (x) == 0;
return (t == t1) ? y : -y;
}

/* Transforms to copysign (y, -x) */

float copysign6 (float x, float y)
{
bool t = __builtin_signbit (x) == 0;
bool t1 = __builtin_signbit (y) == 0;
return (t != t1) ? y : -y;
}

float copysign7 (float x, float y)
{
bool t = __builtin_signbit (x) != 0;
bool t1 = __builtin_signbit (y) == 0;
return (t == t1) ? y : -y;
}

float copysign8 (float x, float y)
{
bool t = __builtin_signbit (x) == 0;
bool t1 = __builtin_signbit (y) != 0;
return (t == t1) ? y : -y;
}

float copysign9 (float x, float y)
{
bool t = __builtin_signbit (x) != 0;
bool t1 = __builtin_signbit (y) != 0;
return (t != t1) ? y : -y;
}
```
gcc:
```asm
"copysign1":
vmovaps xmm2, xmm0
vmovaps xmm3, xmm1
vpternlogd xmm3, xmm2, DWORD PTR .LC2[rip]{1to4}, 228
vmovaps xmm0, xmm3
ret
"copysign2":
vmovaps xmm2, xmm0
vmovaps xmm3, xmm1
vpternlogd xmm3, xmm2, DWORD PTR .LC2[rip]{1to4}, 228
vmovaps xmm0, xmm3
ret
"copysign3":
vmovaps xmm2, xmm0
vmovaps xmm3, xmm1
vpternlogd xmm3, xmm2, DWORD PTR .LC2[rip]{1to4}, 228
vmovaps xmm0, xmm3
ret
"copysign4":
vmovaps xmm2, xmm0
vmovaps xmm3, xmm1
vpternlogd xmm3, xmm2, DWORD PTR .LC2[rip]{1to4}, 228
vmovaps xmm0, xmm3
ret
"copysign5":
vmovaps xmm2, xmm0
vmovaps xmm3, xmm1
vpternlogd xmm3, xmm2, DWORD PTR .LC2[rip]{1to4}, 228
vmovaps xmm0, xmm3
ret
"copysign6":
vxorps xmm2, xmm0, XMMWORD PTR .LC3[rip]
vmovaps xmm3, xmm1
vpternlogd xmm3, xmm2, DWORD PTR .LC2[rip]{1to4}, 228
vmovaps xmm0, xmm3
ret
"copysign7":
vxorps xmm2, xmm0, XMMWORD PTR .LC3[rip]
vmovaps xmm3, xmm1
vpternlogd xmm3, xmm2, DWORD PTR .LC2[rip]{1to4}, 228
vmovaps xmm0, xmm3
ret
"copysign8":
vxorps xmm2, xmm0, XMMWORD PTR .LC3[rip]
vmovaps xmm3, xmm1
vpternlogd xmm3, xmm2, DWORD PTR .LC2[rip]{1to4}, 228
vmovaps xmm0, xmm3
ret
"copysign9":
vxorps xmm2, xmm0, XMMWORD PTR .LC3[rip]
vmovaps xmm3, xmm1
vpternlogd xmm3, xmm2, DWORD PTR .LC2[rip]{1to4}, 228
vmovaps xmm0, xmm3
ret
.LC2:
.long 2147483647
.LC3:
.long -2147483648
.long 0
.long 0
.long 0
```
clang:
```asm
.LCPI0_0:
.long 0x80000000
copysign1:
vmovd eax, xmm0
vmovd ecx, xmm1
vpxord xmm0, xmm1, dword ptr [rip + .LCPI0_0]{1to4}
xor eax, ecx
sets al
kmovd k1, eax
vmovss xmm1 {k1}, xmm1, xmm0
vmovaps xmm0, xmm1
ret

.LCPI1_0:
.long 0x80000000
copysign2:
vmovd eax, xmm0
vmovd ecx, xmm1
vpxord xmm0, xmm1, dword ptr [rip + .LCPI1_0]{1to4}
xor eax, ecx
sets al
kmovd k1, eax
vmovss xmm1 {k1}, xmm1, xmm0
vmovaps xmm0, xmm1
ret

.LCPI2_0:
.long 0x80000000
copysign3:
vmovd eax, xmm0
vmovd ecx, xmm1
xor eax, ecx
sets al
vpxord xmm0, xmm1, dword ptr [rip + .LCPI2_0]{1to4}
kmovd k1, eax
vmovss xmm1 {k1}, xmm1, xmm0
vmovaps xmm0, xmm1
ret

.LCPI3_0:
.long 0x80000000
copysign4:
vmovd eax, xmm0
vmovd ecx, xmm1
xor eax, ecx
sets al
vpxord xmm0, xmm1, dword ptr [rip + .LCPI3_0]{1to4}
kmovd k1, eax
vmovss xmm1 {k1}, xmm1, xmm0
vmovaps xmm0, xmm1
ret

.LCPI4_0:
.long 0x80000000
copysign5:
vmovd eax, xmm1
vmovd ecx, xmm0
vpxord xmm0, xmm1, dword ptr [rip + .LCPI4_0]{1to4}
xor eax, ecx
sets al
kmovd k1, eax
vmovss xmm1 {k1}, xmm1, xmm0
vmovaps xmm0, xmm1
ret

.LCPI5_0:
.long 0x80000000
copysign6:
vmovd eax, xmm0
vmovd ecx, xmm1
vpxord xmm0, xmm1, dword ptr [rip + .LCPI5_0]{1to4}
xor eax, ecx
sets al
kmovd k1, eax
vmovss xmm0 {k1}, xmm0, xmm1
ret

.LCPI6_0:
.long 0x80000000
copysign7:
vmovd eax, xmm0
vmovd ecx, xmm1
xor eax, ecx
sets al
vpxord xmm0, xmm1, dword ptr [rip + .LCPI6_0]{1to4}
kmovd k1, eax
vmovss xmm0 {k1}, xmm0, xmm1
ret

.LCPI7_0:
.long 0x80000000
copysign8:
vmovd eax, xmm0
vmovd ecx, xmm1
xor eax, ecx
sets al
vpxord xmm0, xmm1, dword ptr [rip + .LCPI7_0]{1to4}
kmovd k1, eax
vmovss xmm0 {k1}, xmm0, xmm1
ret

.LCPI8_0:
.long 0x80000000
copysign9:
vmovd eax, xmm0
vmovd ecx, xmm1
vpxord xmm0, xmm1, dword ptr [rip + .LCPI8_0]{1to4}
xor eax, ecx
sets al
kmovd k1, eax
vmovss xmm0 {k1}, xmm0, xmm1
ret
```
https://godbolt.org/z/PEK59azfP

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.