blob: 80d2bc16914389604a38471b9972a1221b6381b0 [file]
/* { dg-do compile { target lp64 } } */
/* { dg-options "-mdejagnu-cpu=power9 -O2" } */
/* { dg-require-effective-target powerpc_vsx } */
#include <stdint.h>
/*
* PR target/117487
*
* On power8 with the optimization it generates:
*
* xscvdpspn 0,1
* sldi 9,4,32
* mtvsrd 32,9
* xxland 1,0,32
* xscvspdpn 1,1
*
* I.e., it converts the SFmode to the memory format (instead of the DFmode
* that is used within the register), converts the mask so that it is in the
* vector register in the upper 32-bits, and does a XXLAND (i.e. there is only
* one direct move from GPR to vector register). Then after doing this, it
* converts the upper 32-bits back to DFmode.
*
* If the XSCVSPDN instruction took the value in the normal 32-bit scalar in a
* vector register, we wouldn't have needed the SLDI of the mask.
*
* On power9/power10/power11 before the fix wa applied, GCC generated:
*
* xscvdpspn 0,1
* mfvsrwz 2,0
* and 2,2,4
* mtvsrws 1,2
* xscvspdpn 1,1
* blr
*
* I.e convert to SFmode representation, move the value to a GPR, do an AND
* operation, move the 32-bit value with a splat, and then convert it back to
* DFmode format.
*
* After the patch was applied, it now generates:
*
* xscvdpspn 0,1
* mtvsrwz 32,2
* xxland 32,0,32
* xxspltw 1,32,1
* xscvspdpn 1,1
* blr
*/
union u {
float f;
uint32_t u32;
};
float
math_foo (float x, unsigned int mask)
{
union u arg;
arg.f = x;
arg.u32 &= mask;
return arg.f;
}
/* { dg-final { scan-assembler {\mxxland\M} } } */
/* { dg-final { scan-assembler-not {\mmfvsr} } } */
/* { dg-final { scan-assembler-not {\mand\M} } } */