blob: 4be2360a36e748291636aedc379b4ffa4279475d [file] [log] [blame]
/* Check calling convention in the vector ABI regarding vector like structs. */
/* { dg-do compile { target { s390*-*-* } } } */
/* { dg-options "-O3 -mzarch -march=z13" } */
/* addA */
/* { dg-final { scan-assembler-times "vfadb\t%v24,%v24,%v26" 1 } } */
/* addB and addE*/
/* { dg-final { scan-assembler-times "vah\t%v24,%v\[0-9\]*,%v\[0-9\]*" 2 } } */
/* addC */
/* { dg-final { scan-assembler-times "vag\t%v24,%v\[0-9\]*,%v\[0-9\]*" 1 } } */
/* addB and addC are expected to read the arguments via pointers in r2 and r3 */
/* { dg-final { scan-assembler-times "vl\t%v\[0-9\]*,0\\(%r2\\)" 2 } } */
/* { dg-final { scan-assembler-times "vl\t%v\[0-9\]*,0\\(%r3\\)" 2 } } */
/* addD */
/* { dg-final { scan-assembler-times "vaf\t%v24,%v24,%v26" 1 } } */
/* addE */
/* { dg-final { scan-assembler-times "vah\t%v24,%v24,%v26" 1 } } */
/* addF */
/* { dg-final { scan-assembler-times "vab\t%v24,%v\[0-9\]*,%v\[0-9\]*" 1 } } */
/* { dg-final { scan-assembler-times "srlg\t%r\[0-9\]*,%r2,32" 1 { target lp64 } } } */
/* { dg-final { scan-assembler-times "srlg\t%r\[0-9\]*,%r3,32" 1 { target lp64 } } } */
/* { dg-final { scan-assembler-times "llgfr\t%.*,%r2" 1 { target { ! lp64 } } } } */
/* { dg-final { scan-assembler-times "llgfr\t%.*,%r4" 1 { target { ! lp64 } } } } */
typedef double v2df __attribute__((vector_size(16)));
typedef long long v2di __attribute__((vector_size(16)));
typedef int v4si __attribute__((vector_size(16)));
typedef short v8hi __attribute__((vector_size(16)));
typedef short v2hi __attribute__((vector_size(4)));
typedef char v4qi __attribute__((vector_size(4)));
/* Vector like structs are passed in VRs. */
struct A { v2df a; };
v2df
addA (struct A a, struct A b)
{
return a.a + b.a;
}
/* Only single element vectors qualify as vector type parms. This one
is passed as a struct. Since it is bigger than 8 bytes it is passed
on the stack with the reference being put into r2/r3. */
struct B { v8hi a; char b;};
v8hi
addB (struct B a, struct B b)
{
return a.a + b.a;
}
/* The resulting struct is bigger than 16 bytes and therefore passed
on the stack with the references residing in r2/r3. */
struct C { v2di __attribute__((aligned(32))) a; };
v2di
addC (struct C a, struct C b)
{
return a.a + b.a;
}
/* The attribute here does not have any effect. So this struct stays
vector like and hence is passed in a VR. */
struct D { v4si __attribute__((aligned(16))) a; };
v4si
addD (struct D a, struct D b)
{
return a.a + b.a;
}
/* Smaller vectors are passed in vector registers. This also applies
for vector like structs. */
struct E { v2hi a; };
v2hi
addE (struct E a, struct E b)
{
return a.a + b.a;
}
/* This struct is not passed in VRs because of padding. But since it
fits in a GPR and has a power of two size. It is passed in
GPRs. */
struct F { v4qi __attribute__((aligned(8))) a; };
v4qi
addF (struct F a, struct F b)
{
return a.a + b.a;
}