diff mbox

Fix up vectorization of multiplication with bool cast to integer (PR tree-optimization/69820)

Message ID 20160215210704.GH3017@tucnak.redhat.com
State New
Headers show

Commit Message

Jakub Jelinek Feb. 15, 2016, 9:07 p.m. UTC
Hi!

The following testcase is miscompiled, because we first
create a pattern stmt for _5 = (int) _3; where _3 is bool,
but then recognize the following multiply as widening multiply, ignore
there the previous pattern stmt and thus instead of expanding the
cast as cond ? 1 : 0 we actually end up expanding it as cond (i.e.
cond ? -1 : 0).  In the widen mult pattern recognizer it perhaps would be
possible to handle that case, unless both arguments are cast from
bool, but there are lots of other places which call type_conversion_p and
most of them would need to either give up in those cases or add special
handling for it.  So, it seems like the easiest fix at least for GCC6 is
to punt in type_conversion_p on casts from bool/unsigned :1 (or should
I instead check STMT_VINFO_IN_PATTERN_P on the cast stmt and give up
if true?).

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2016-02-15  Jakub Jelinek  <jakub@redhat.com>

	PR tree-optimization/69820
	* tree-vect-patterns.c (type_conversion_p): Return false if
	*orig_type is unsigned single precision or boolean.
	(vect_recog_dot_prod_pattern, vect_recog_widen_mult_pattern):
	Formatting fix.

	* gcc.dg/vect/pr69820.c: New test.


	Jakub
diff mbox

Patch

--- gcc/tree-vect-patterns.c.jj	2016-01-12 14:14:56.000000000 +0100
+++ gcc/tree-vect-patterns.c	2016-02-15 18:52:52.695249972 +0100
@@ -184,6 +184,13 @@  type_conversion_p (tree name, gimple *us
       || ((TYPE_UNSIGNED (type) != TYPE_UNSIGNED (*orig_type)) && check_sign))
     return false;
 
+  /* Conversion from bool or unsigned single bit precision bitfields
+     should have been recognized by vect_recog_bool_pattern, callers
+     of this function are generally unprepared to handle those.  */
+  if ((TYPE_PRECISION (*orig_type) == 1 && TYPE_UNSIGNED (*orig_type))
+      || TREE_CODE (*orig_type) == BOOLEAN_TYPE)
+    return false;
+
   if (TYPE_PRECISION (type) >= (TYPE_PRECISION (*orig_type) * 2))
     *promotion = true;
   else
@@ -334,8 +341,8 @@  vect_recog_dot_prod_pattern (vec<gimple
       stmt = last_stmt;
 
       if (type_conversion_p (oprnd0, stmt, true, &half_type, &def_stmt,
-                               &promotion)
-         && promotion)
+			     &promotion)
+	  && promotion)
         {
           stmt = def_stmt;
           oprnd0 = gimple_assign_rhs1 (stmt);
@@ -395,13 +402,13 @@  vect_recog_dot_prod_pattern (vec<gimple
           || !types_compatible_p (TREE_TYPE (oprnd1), prod_type))
         return NULL;
       if (!type_conversion_p (oprnd0, stmt, true, &half_type0, &def_stmt,
-                                &promotion)
-          || !promotion)
+			      &promotion)
+	  || !promotion)
         return NULL;
       oprnd00 = gimple_assign_rhs1 (def_stmt);
       if (!type_conversion_p (oprnd1, stmt, true, &half_type1, &def_stmt,
-                                &promotion)
-          || !promotion)
+			      &promotion)
+	  || !promotion)
         return NULL;
       oprnd01 = gimple_assign_rhs1 (def_stmt);
       if (!types_compatible_p (half_type0, half_type1))
@@ -891,10 +898,10 @@  vect_recog_widen_mult_pattern (vec<gimpl
 	  oprnd = &oprnd1;
 	}
 
-        tree old_oprnd = gimple_assign_rhs1 (def_stmt);
-	tree new_oprnd = make_ssa_name (half_type0);
-	new_stmt = gimple_build_assign (new_oprnd, NOP_EXPR, old_oprnd);
-        *oprnd = new_oprnd;
+      tree old_oprnd = gimple_assign_rhs1 (def_stmt);
+      tree new_oprnd = make_ssa_name (half_type0);
+      new_stmt = gimple_build_assign (new_oprnd, NOP_EXPR, old_oprnd);
+      *oprnd = new_oprnd;
     }
 
   /* Handle unsigned case.  Look for
--- gcc/testsuite/gcc.dg/vect/pr69820.c.jj	2016-02-15 18:54:15.333122283 +0100
+++ gcc/testsuite/gcc.dg/vect/pr69820.c	2016-02-15 18:55:45.529891445 +0100
@@ -0,0 +1,35 @@ 
+/* PR tree-optimization/69820 */
+
+#include "tree-vect.h"
+
+unsigned int a[100];
+long long int b[100];
+unsigned short c[100];
+
+__attribute__((noinline, noclone)) void
+foo (void)
+{
+  int i;
+  for (i = 0; i < 100; ++i)
+    b[i] = a[i] * (c[i] * (_Bool) c[i]);
+}
+
+int
+main ()
+{
+  int i;
+  if (__SIZEOF_INT__ * __CHAR_BIT__ != 32)
+    return 0;
+  check_vect ();
+  for (i = 0; i < 100; ++i)
+    {
+      a[i] = 3489456818U;
+      b[i] = 0x1eadbeefbeefdeadLL;
+      c[i] = 38364;
+    }
+  foo ();
+  for (i = 0; i < 100; ++i)
+    if (b[i] != 0xed446af8U)
+      __builtin_abort ();
+  return 0;
+}