This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH, rs6000] Fix PR70963: Wrong code for V2DF/V2DI vec_cts with zero scale factor
- From: Bill Schmidt <wschmidt at linux dot vnet dot ibm dot com>
- To: gcc-patches at gcc dot gnu dot org
- Cc: David Edelsohn <dje dot gcc at gmail dot com>, Segher Boessenkool <segher at kernel dot crashing dot org>
- Date: Mon, 9 May 2016 22:00:31 -0500
- Subject: [PATCH, rs6000] Fix PR70963: Wrong code for V2DF/V2DI vec_cts with zero scale factor
- Authentication-results: sourceware.org; auth=none
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 <wschmidt@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 <wschmidt@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");
+}