Hello,

On 08/10/26 4:51 am, Michael Meissner wrote:
> On Wed, Oct 07, 2026 at 05:08:11PM +0530, Surya Kumari Jangala wrote:
>> Hi,
>>
>> On 06/10/26 3:04 AM, Kishan Parmar wrote:
>>> Hello All,
>>>
>>> Changes from v1:
>>>     - Dropped pr123055.c testcase from previsous patch. The
>>>       existing pr116030.c already carries scan-assembler-not
>>>       "stxvd2x" assertion that matches the regression, making a
>>>       separate pr123055.c redundant.
>>>
>>> Below patch is regtested and bootstrapped on power64le-linux-gnu.
>>>
>>> Thank You,
>>> Kishan
>>>
>>> PR123055 reports a regression on power little-endian systems,
>>> where gcc.target/powerpc/pr116030.c began emitting stxvd2x starting
>>> from r16-5947-ga6c50ec2c6ebcb.
>>>
>>> Commit r16-5947 introduced -ffuse-ops-with-volatile-access (enabled by
>>> default), which relaxes general_operand to accept volatile memory
>>> references.  As a side effect, the vsx_stxvd2x4_le_const_<mode> pattern
>>> whose destination was the "memory_operand" predicate started
>>> matching aligned volatile destinations such as the 16-byte-aligned
>>> volatile union U128 in pr116030.c.
>> Why is it incorrect if the vsx_stxvd2x4_le_const_<mode> pattern starts
>> matching now?
>>
>> vsx_stxvd2x4_le_const_<mode> ends up generating stxvd2x but stxvd2x
>> is not worse than stvx. stxvd2x could require a swap instruction to get 
>> the correct element order, but in vsx_stxvd2x4_le_const_<mode>, we ensure
>> that operand 1 is a splat constant (a vector constant with a duplicated 
>> element value).
>> So we don't require a swap instruction.
>>
>> The fix to PR123055 would be to just modify the failing testcase.
> Let me try to give a context for what is going on.
>
> In the original Altivec additions to the PowerPC architure for the G5
> and later power6, there was a separate Altivec register bank with 32
> 128-bit vector registers.  The Altivec load vector instruction (LVX)
> and store vector instruction (STVX) that was defined for either endian
> setup and it would swap bytes on a little endian system.
>
> However LVX and STVX have a serious flaw in that these instructions
> would ignore the bottom 4 bits of the address.  If you know the address
> is aligned properly you could use these instructions, but you couldn't
> use these instructions if the address was potentially unaligned.
>
> When power7 came out with the new VSX instruction set, the VSX register
> set included both the traditional floating point registers (VSX
> registers 0..31) and Altivec registers (VSX registers 32..63) as a
> combined register set.  However the initial VSX instruction set did not
> do the byte swapping on the entire 128 bits for the VSX load register
> instructions (LXVD2X and LXVW4X) and VSX store register instructions
> (STXVD2X and STXW4K).  At the time the power7 came out, it was only
> used on big endian systems.  LXVD2K/STXVD2K would swap the bytes within
> each 64-bit half of the register, and LXVW4K/STXVW4K would swap the
> bytes within each of the 4 32-bit elements in the register.
>
> After the power8 was designed, it was decided to switch the Linux
> operating system from big endian to little endian and restrict the base
> processor for little endian Linux to be the power8.
>
> Given that the vector load/store instructions used in the power7 and
> power8 did not properly swap all 16 bytes (128 bits), the compiler had
> to do a LXVD2K instruction followed by a XXPERMDI instruction to
> properly swap all of the bytes (i.w. LXVD2K would swap the 8 bytes in
> each 64-bit segment, and then XXPERMDI would swap the two 64-bit
> elements).  Similarly before the vector store could be done, the
> compiler would have to generate a XXPERMDI instruction to swap the 2
> 64-bit elements before the STXVD2K would be done.
>
> GCC added a pass controlled by the -moptimize-swaps option that would
> detect when it was safe to omit the XXPERMI swaps.  I.e. if the code
> was doing 2 loads, and add, and a store, you could eliminate the
> XXPERMDI's since the add instruction care that the individual elements
> were out of order.  I.e. without -moptimize-swaps the code:
>
>       void foo (vector float *p, vector float *q, vector float *r)
>       {
>         *p = *q + *r;
>       }
>
> would generate:
>
>         rldicr 4,4,0,59
>         rldicr 5,5,0,59
>         lxvd2x 0,0,4
>         lxvd2x 12,0,5
>         xxpermdi 0,0,0,2
>         xxpermdi 12,12,12,2
>         xvaddsp 0,0,12
>         xxpermdi 0,0,0,2
>         stxvd2x 0,0,3
>
> and with -moptimize-swaps, it would generate:
>
>         lxvd2x 0,0,4
>         lxvd2x 12,0,5
>         xvaddsp 0,0,12
>         stxvd2x 0,0,3
>
> When the power9 came out, new vector load instructions (LXV and LXVX)
> and new vector store instructions (STXV and STXVX) were added that
> properly byte swapped all 16 bytes.  Thus the optimize-swap pass was
> disabled.
>
> As noted, the special case where a vector constant that is duplicated
> (splat'ed), you don't have to do the element swapping.
>
Thank you for the context. Since |vsx_stxvd2x4_le_const_<mode>|is guarded by 
|const_vec_duplicate_p|, the source is always a splat constant with all 
elements identical. As you noted, for such a constant the element swapping is 
not required, so |stxvd2x|stores the correct value. I will send patch v3 
with|testcase pr116030.c fix. - Kishan|

Reply via email to