Hi, PR70963 reports a problem with vec_cts when used to convert vector double to vector long long. This is due to a register with an undefined value that is generated only when the scale factor is zero. This patch adds logic to provide the correct value when the scale factor is zero.
The problem from the PR is in the define_expand for vsx_xvcvdpsxds_scale. The define_expand for vsx_xvcvdpuxds_scale clearly has the same problem, although it is not possible to reach this via a call to vec_cts. The raw builtin __builtin_vsx_xvcvdpuxds_scale can be used, however, and I’ve shown this in the test case. Bootstrapped and tested on powerpc64le-unknown-linux-gnu with no regressions. Is this ok for trunk, and eventual backport to 6 and 5? Thanks, Bill [gcc] 2016-05-09 Bill Schmidt <wschm...@linux.vnet.ibm.com> * config/rs6000/vsx.md (vsx_xvcvdpsxds_scale): Generate correct code for a zero scale factor. (vsx_xvcvdpuxds_scale): Likewise. [gcc/testsuite] 2016-05-09 Bill Schmidt <wschm...@linux.vnet.ibm.com> * gcc.target/powerpc/pr70963.c: New. Index: gcc/config/rs6000/vsx.md =================================================================== --- gcc/config/rs6000/vsx.md (revision 236051) +++ gcc/config/rs6000/vsx.md (working copy) @@ -1717,10 +1717,15 @@ { rtx op0 = operands[0]; rtx op1 = operands[1]; - rtx tmp = gen_reg_rtx (V2DFmode); + rtx tmp; int scale = INTVAL(operands[2]); - if (scale != 0) - rs6000_scale_v2df (tmp, op1, scale); + if (scale == 0) + tmp = op1; + else + { + tmp = gen_reg_rtx (V2DFmode); + rs6000_scale_v2df (tmp, op1, scale); + } emit_insn (gen_vsx_xvcvdpsxds (op0, tmp)); DONE; }) @@ -1741,10 +1746,15 @@ { rtx op0 = operands[0]; rtx op1 = operands[1]; - rtx tmp = gen_reg_rtx (V2DFmode); + rtx tmp; int scale = INTVAL(operands[2]); - if (scale != 0) - rs6000_scale_v2df (tmp, op1, scale); + if (scale == 0) + tmp = op1; + else + { + tmp = gen_reg_rtx (V2DFmode); + rs6000_scale_v2df (tmp, op1, scale); + } emit_insn (gen_vsx_xvcvdpuxds (op0, tmp)); DONE; }) Index: gcc/testsuite/gcc.target/powerpc/pr70963.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/pr70963.c (revision 0) +++ gcc/testsuite/gcc.target/powerpc/pr70963.c (working copy) @@ -0,0 +1,39 @@ +/* { dg-do run { target { powerpc64*-*-* && vsx_hw } } } */ +/* { dg-require-effective-target powerpc_vsx_ok } */ +/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */ +/* { dg-options "-maltivec" } */ + +#include <stdlib.h> +#include <stdio.h> +#include <altivec.h> + +static int failed; +static void test (void); + +static void check (int result, const char *name) +{ + if (!result) + { + failed++; + printf ("fail %s\n", name); + } +} + +int main (void) +{ + test (); + if (failed) + abort (); + return 0; +} + +vector double x = { 81.0, 76.0 }; +vector long long y = { 81, 76 }; + +static void test() +{ + vector long long a = vec_cts (x, 0); + vector double b = vec_ctf (a, 0); + check (vec_all_eq (a, y), "vec_cts"); + check (vec_all_eq (b, x), "vec_ctf"); +}