Thorn Vectors fails to compile using gcc 8.X on POWER9

Issue #2530 resolved
Roland Haas created an issue

Vectors provides SIMD instructions for doubles on POWER9 using the vec_st intrinsic for aligned stores. However that intrinsic seems to differ in gcc 8 and gcc 9.

This demo code:

#if 0
g++ -mcpu=power9 -mvsx $0
exit
#endif

#include <altivec.h>

#define CCTK_REAL8 double
typedef vector double CCTK_REAL8_VEC;

static inline void vec8_store(CCTK_REAL8 &p,
                              CCTK_REAL8_VEC x) {
  vec_st(x, 0 , &p);
}

int main(void)
{
  CCTK_REAL8 p[2];
  CCTK_REAL8_VEC x;
  vec8_store(p[0], x);
  return 0;
}

demonstrates the issue and fails to compile when using eg module load gcc/8.1.0 on summit but is fine with module load gcc/9.1.0:

$ bash vec.cc
vec.cc: In function 'void vec8_store(double&, CCTK_REAL8_VEC)':
vec.cc:13:19: error: invalid parameter combination for AltiVec intrinsic '__builtin_vec_st'
   vec_st(x, 0 , &p);

Replacing vec_st by vec_vsx_st compiles the code with gcc 8.1.0 and gcc 9.1.0 on Summit (which allows unaligned loads). Though no matter how much alignment I try to specify, vec_st never compiles for me:

#if 0
g++ -mcpu=power9 -mvsx $0
exit
#endif

#include <altivec.h>

int main(void)
{
  double p[8] __attribute__((aligned(16)));
  vector double x __attribute__((aligned(16)));
  vec_st(x, 0 , p);
  return 0;
}

This is not a very worrysome issue right now since gcc 9.X is usually available, however it would be nice to not fail in this manner but rather check something to detect this issue or find out a workaround.

Comments (6)

  1. Roland Haas reporter

    It turns out it wants a cast to vector double * (see http://openpowerfoundation.org/wp-content/uploads/resources/Intrinsics-Reference/Intrinsics-Reference-20200211.pdf which does list both vec_st(vector double x, long long int, double * ) and vec_st(vector double x, long long int, vector double * ) and apparently gcc 8 only supports the latter one). So this:

    #if 0
    g++ -c -g3 -mcpu=power9 -mvsx -O1 -Wall $@ $0
    exit
    #endif
    
    #include <altivec.h>
    
    void foo(vector double x, double &p, double &q, double &r, double &s)
    {
      const long long null = 0;
      *(vector double*)&p = x;
      vec_vsx_st(x, null, &q);
      vec_st(x, null, (vector double*)&r);
    }
    

    works and produces code:

    Disassembly of section .text:
    
    0000000000000000 <_Z3fooDv2_dRdS0_S0_S0_>:
    #include <altivec.h>
    
    void foo(vector double x, double &p, double &q, double &r, double &s)
    {
      const long long null = 0;
      *(vector double*)&p = x;
       0:   0d 00 45 f4     stxv    vs34,0(r5)
      vec_vsx_st(x, null, &q);
       4:   0d 00 46 f4     stxv    vs34,0(r6)
      vec_st(x, null, (vector double*)&r);
       8:   ce 39 40 7c     stvx    v2,0,r7
    }
       c:   20 00 80 4e     blr
      10:   00 00 00 00     .long 0x0
      14:   00 09 00 00     .long 0x900
      18:   00 00 00 00     .long 0x0
    

    where stvx is the regular altivec one and stxv is the ISA3 (POWER9) instruction.

  2. Log in to comment