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");                                        
+}                                                                              


Reply via email to