https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86731

            Bug ID: 86731
           Summary: [8 Regression] Miscompiles vec_sl at -O3 with -fwrapv
                    on ppc64el
           Product: gcc
           Version: 8.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: target
          Assignee: unassigned at gcc dot gnu.org
          Reporter: jcowgill+gcc at jcowgill dot uk
  Target Milestone: ---

FFmpeg was hit by a bug which causes strange results when the optimized altivec
routines are compiled with -O3 and -fwrapv (which is used when FFmpeg is
configured with --toolchain=hardened). This bug only occurs with GCC 8.

Simplified extract which shows the bug:

#include <altivec.h>

vector unsigned int splat(void)
{
        vector unsigned int mzero = vec_splat_u32(-1);
        return (vector unsigned int) vec_sl(mzero, mzero);
}

The goal is to create a constant vector with each element containing 0x80000000
(== -0.0f). If I am reading the altivec manual correctly, the above code is
valid because the second argument to vec_sl should interpreted modulo 32 (ie as
31 in this case).

With gcc-7 this generates this correct code:
0000000000000000 <splat>:
   0:   8c 03 5f 10     vspltisw v2,-1
   4:   84 11 42 10     vslw    v2,v2,v2
   8:   20 00 80 4e     blr

When compiled with "gcc-8 -O3 -fwrapv -c altivectest.c" this wrong code is
produced:
0000000000000000 <splat>:
   0:   8c 03 5f 10     vspltisw v2,-1
   4:   20 00 80 4e     blr

====

If I pass -fdump-tree-all, I can see that the vec_sl gets transformed into a
normal left shift. My guess (which may be wrong) is that gcc is treating this
shift as UB because it is trying to shift > 32 bits.

Reply via email to