Hi, I missed a case in the vector API work for little endian. When VSX is enabled, the vec_mergeh and vec_mergel interfaces for 4x32 vectors are translated into xxmrghw and xxmrglw. The patterns for these were not adjusted for little endian. This patch fixes this and adds tests for V4SI and V4SF modes when VSX is available.
Bootstrapped and tested on 4.8, 4.9, and trunk for powerpc64le-unknown-linux-gnu with no regressions. Tests are still ongoing for powerpc64-unknown-linux-gnu. Provided those complete without regressions, is this fix ok for trunk, 4.9, and 4.8? Thanks, Bill [gcc] 2014-04-17 Bill Schmidt <wschm...@linux.vnet.ibm.com> * config/rs6000/vsx.md (vsx_xxmrghw_<mode>): Adjust for little-endian. (vsx_xxmrglw_<mode>): Likewise. [gcc/testsuite] 2014-04-17 Bill Schmidt <wschm...@linux.vnet.ibm.com> * gcc.dg/vmx/merge-vsx.c: Add V4SI and V4SF tests. * gcc.dg/vmx/merge-vsx-be-order.c: Likewise. Index: gcc/config/rs6000/vsx.md =================================================================== --- gcc/config/rs6000/vsx.md (revision 209513) +++ gcc/config/rs6000/vsx.md (working copy) @@ -1891,7 +1891,12 @@ (parallel [(const_int 0) (const_int 4) (const_int 1) (const_int 5)])))] "VECTOR_MEM_VSX_P (<MODE>mode)" - "xxmrghw %x0,%x1,%x2" +{ + if (BYTES_BIG_ENDIAN) + return "xxmrghw %x0,%x1,%x2"; + else + return "xxmrglw %x0,%x2,%x1"; +} [(set_attr "type" "vecperm")]) (define_insn "vsx_xxmrglw_<mode>" @@ -1903,7 +1908,12 @@ (parallel [(const_int 2) (const_int 6) (const_int 3) (const_int 7)])))] "VECTOR_MEM_VSX_P (<MODE>mode)" - "xxmrglw %x0,%x1,%x2" +{ + if (BYTES_BIG_ENDIAN) + return "xxmrglw %x0,%x1,%x2"; + else + return "xxmrghw %x0,%x2,%x1"; +} [(set_attr "type" "vecperm")]) ;; Shift left double by word immediate Index: gcc/testsuite/gcc.dg/vmx/merge-vsx-be-order.c =================================================================== --- gcc/testsuite/gcc.dg/vmx/merge-vsx-be-order.c (revision 209513) +++ gcc/testsuite/gcc.dg/vmx/merge-vsx-be-order.c (working copy) @@ -21,10 +21,19 @@ static void test() vector long long vlb = {0,1}; vector double vda = {-2.0,-1.0}; vector double vdb = {0.0,1.0}; + vector unsigned int vuia = {0,1,2,3}; + vector unsigned int vuib = {4,5,6,7}; + vector signed int vsia = {-4,-3,-2,-1}; + vector signed int vsib = {0,1,2,3}; + vector float vfa = {-4.0,-3.0,-2.0,-1.0}; + vector float vfb = {0.0,1.0,2.0,3.0}; /* Result vectors. */ vector long long vlh, vll; vector double vdh, vdl; + vector unsigned int vuih, vuil; + vector signed int vsih, vsil; + vector float vfh, vfl; /* Expected result vectors. */ #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ @@ -32,11 +41,23 @@ static void test() vector long long vlrl = {0,-2}; vector double vdrh = {1.0,-1.0}; vector double vdrl = {0.0,-2.0}; + vector unsigned int vuirh = {6,2,7,3}; + vector unsigned int vuirl = {4,0,5,1}; + vector signed int vsirh = {2,-2,3,-1}; + vector signed int vsirl = {0,-4,1,-3}; + vector float vfrh = {2.0,-2.0,3.0,-1.0}; + vector float vfrl = {0.0,-4.0,1.0,-3.0}; #else vector long long vlrh = {-2,0}; vector long long vlrl = {-1,1}; vector double vdrh = {-2.0,0.0}; vector double vdrl = {-1.0,1.0}; + vector unsigned int vuirh = {0,4,1,5}; + vector unsigned int vuirl = {2,6,3,7}; + vector signed int vsirh = {-4,0,-3,1}; + vector signed int vsirl = {-2,2,-1,3}; + vector float vfrh = {-4.0,0.0,-3.0,1.0}; + vector float vfrl = {-2.0,2.0,-1.0,3.0}; #endif vlh = vec_mergeh (vla, vlb); @@ -43,9 +64,21 @@ static void test() vll = vec_mergel (vla, vlb); vdh = vec_mergeh (vda, vdb); vdl = vec_mergel (vda, vdb); + vuih = vec_mergeh (vuia, vuib); + vuil = vec_mergel (vuia, vuib); + vsih = vec_mergeh (vsia, vsib); + vsil = vec_mergel (vsia, vsib); + vfh = vec_mergeh (vfa, vfb ); + vfl = vec_mergel (vfa, vfb ); check (vec_long_long_eq (vlh, vlrh), "vlh"); check (vec_long_long_eq (vll, vlrl), "vll"); check (vec_double_eq (vdh, vdrh), "vdh" ); check (vec_double_eq (vdl, vdrl), "vdl" ); + check (vec_all_eq (vuih, vuirh), "vuih"); + check (vec_all_eq (vuil, vuirl), "vuil"); + check (vec_all_eq (vsih, vsirh), "vsih"); + check (vec_all_eq (vsil, vsirl), "vsil"); + check (vec_all_eq (vfh, vfrh), "vfh"); + check (vec_all_eq (vfl, vfrl), "vfl"); } Index: gcc/testsuite/gcc.dg/vmx/merge-vsx.c =================================================================== --- gcc/testsuite/gcc.dg/vmx/merge-vsx.c (revision 209513) +++ gcc/testsuite/gcc.dg/vmx/merge-vsx.c (working copy) @@ -21,10 +21,19 @@ static void test() vector long long vlb = {0,1}; vector double vda = {-2.0,-1.0}; vector double vdb = {0.0,1.0}; + vector unsigned int vuia = {0,1,2,3}; + vector unsigned int vuib = {4,5,6,7}; + vector signed int vsia = {-4,-3,-2,-1}; + vector signed int vsib = {0,1,2,3}; + vector float vfa = {-4.0,-3.0,-2.0,-1.0}; + vector float vfb = {0.0,1.0,2.0,3.0}; /* Result vectors. */ vector long long vlh, vll; vector double vdh, vdl; + vector unsigned int vuih, vuil; + vector signed int vsih, vsil; + vector float vfh, vfl; /* Expected result vectors. */ vector long long vlrh = {-2,0}; @@ -31,14 +40,32 @@ static void test() vector long long vlrl = {-1,1}; vector double vdrh = {-2.0,0.0}; vector double vdrl = {-1.0,1.0}; + vector unsigned int vuirh = {0,4,1,5}; + vector unsigned int vuirl = {2,6,3,7}; + vector signed int vsirh = {-4,0,-3,1}; + vector signed int vsirl = {-2,2,-1,3}; + vector float vfrh = {-4.0,0.0,-3.0,1.0}; + vector float vfrl = {-2.0,2.0,-1.0,3.0}; vlh = vec_mergeh (vla, vlb); vll = vec_mergel (vla, vlb); vdh = vec_mergeh (vda, vdb); vdl = vec_mergel (vda, vdb); + vuih = vec_mergeh (vuia, vuib); + vuil = vec_mergel (vuia, vuib); + vsih = vec_mergeh (vsia, vsib); + vsil = vec_mergel (vsia, vsib); + vfh = vec_mergeh (vfa, vfb ); + vfl = vec_mergel (vfa, vfb ); check (vec_long_long_eq (vlh, vlrh), "vlh"); check (vec_long_long_eq (vll, vlrl), "vll"); check (vec_double_eq (vdh, vdrh), "vdh" ); check (vec_double_eq (vdl, vdrl), "vdl" ); + check (vec_all_eq (vuih, vuirh), "vuih"); + check (vec_all_eq (vuil, vuirl), "vuil"); + check (vec_all_eq (vsih, vsirh), "vsih"); + check (vec_all_eq (vsil, vsirl), "vsil"); + check (vec_all_eq (vfh, vfrh), "vfh"); + check (vec_all_eq (vfl, vfrl), "vfl"); }