From 4db92f4164b134e86dc03a90dc14e670efa119f2 Mon Sep 17 00:00:00 2001
From: Duan bo <duanbo3@huawei.com>
Date: Fri, 18 Sep 2020 22:38:49 -0400
Subject: [PATCH] vect: Fix an ICE in vect_recog_mask_conversion_pattern

When processing the cond expression, vect_recog_mask_conversion_pattern
doesn't consider the situation that two operands of rhs1 are different
vectypes, leading to a vect ICE. This patch adds the identification and
handling of the situation to fix the problem.

gcc/ChangeLog:

	PR target/96757
	* tree-vect-patterns.c (vect_recog_mask_conversion_pattern): Add
	the identification and handling of the dropped situation in the
	cond expression processing phase.

gcc/testsuite/ChangeLog:

	PR target/96757
	* gcc.target/aarch64/pr96757.c: New test.
---
 gcc/testsuite/gcc.target/aarch64/pr96757.c | 23 ++++++
 gcc/tree-vect-patterns.c                   | 91 ++++++++++++++++++++--
 2 files changed, 107 insertions(+), 7 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/aarch64/pr96757.c

diff --git a/gcc/testsuite/gcc.target/aarch64/pr96757.c b/gcc/testsuite/gcc.target/aarch64/pr96757.c
new file mode 100644
index 00000000000..122e39dca0e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/pr96757.c
@@ -0,0 +1,23 @@
+/* PR target/96757 */
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+
+short 
+fun1(short i, short j)
+{ 
+  return i * j; 
+}
+
+int 
+fun(int a, int b, int c) 
+{
+  int *v, z, k, m;
+  short f, d;
+  for (int i=0; i<c; i++) 
+  {
+    f= 4 <= d;
+    k= a > m;
+    z = f > k;
+    *v += fun1(z,b);
+  }
+}
diff --git a/gcc/tree-vect-patterns.c b/gcc/tree-vect-patterns.c
index db45740da3c..b7c6593087c 100644
--- a/gcc/tree-vect-patterns.c
+++ b/gcc/tree-vect-patterns.c
@@ -4241,6 +4241,7 @@ vect_recog_mask_conversion_pattern (vec_info *vinfo,
   tree lhs = NULL_TREE, rhs1, rhs2, tmp, rhs1_type, rhs2_type;
   tree vectype1, vectype2;
   stmt_vec_info pattern_stmt_info;
+  tree rhs1_op0, rhs1_op1, rhs1_op0_type, rhs1_op1_type;
 
   /* Check for MASK_LOAD ans MASK_STORE calls requiring mask conversion.  */
   if (is_gimple_call (last_stmt)
@@ -4317,7 +4318,8 @@ vect_recog_mask_conversion_pattern (vec_info *vinfo,
   if (rhs_code == COND_EXPR)
     {
       vectype1 = get_vectype_for_scalar_type (vinfo, TREE_TYPE (lhs));
-
+      if (!vectype1)
+	return NULL;
       if (TREE_CODE (rhs1) == SSA_NAME)
 	{
 	  rhs1_type = integer_type_for_mask (rhs1, vinfo);
@@ -4340,16 +4342,91 @@ vect_recog_mask_conversion_pattern (vec_info *vinfo,
 
 	     it is better for b1 and b2 to use the mask type associated
 	     with int elements rather bool (byte) elements.  */
-	  rhs1_type = integer_type_for_mask (TREE_OPERAND (rhs1, 0), vinfo);
-	  if (!rhs1_type)
-	    rhs1_type = TREE_TYPE (TREE_OPERAND (rhs1, 0));
+	  rhs1_op0 = TREE_OPERAND (rhs1, 0);
+	  rhs1_op1 = TREE_OPERAND (rhs1, 1);
+	  if (!rhs1_op0 || !rhs1_op1)
+	    return NULL;
+	  rhs1_op0_type = integer_type_for_mask (rhs1_op0, vinfo);
+	  rhs1_op1_type = integer_type_for_mask (rhs1_op1, vinfo);
+
+	  if (!rhs1_op0_type && !rhs1_op1_type)
+	    {
+	      rhs1_type = TREE_TYPE (rhs1_op0);
+	      vectype2 = get_mask_type_for_scalar_type (vinfo, rhs1_type);
+	    }
+	  else if (!rhs1_op0_type && rhs1_op1_type)
+	    {
+	      rhs1_type = TREE_TYPE (rhs1_op0);
+	      vectype2 = get_mask_type_for_scalar_type (vinfo, rhs1_type);
+	      if (!vectype2)
+		return NULL;
+	      rhs1_op1 = build_mask_conversion (vinfo, rhs1_op1,
+						vectype2, stmt_vinfo);
+	    }
+	  else if (rhs1_op0_type && !rhs1_op1_type)
+	    {
+	      rhs1_type = TREE_TYPE (rhs1_op1);
+	      vectype2 = get_mask_type_for_scalar_type (vinfo, rhs1_type);
+	      if (!vectype2)
+		return NULL;
+	      rhs1_op0 = build_mask_conversion (vinfo, rhs1_op0,
+						vectype2, stmt_vinfo);
+	    }
+	  else if (TYPE_PRECISION (rhs1_op0_type)
+		   != TYPE_PRECISION (rhs1_op1_type))
+	    {
+	      int tmp1 = (int)TYPE_PRECISION (rhs1_op0_type)
+			 - (int)TYPE_PRECISION (TREE_TYPE (lhs));
+	      int tmp2 = (int)TYPE_PRECISION (rhs1_op1_type)
+			 - (int)TYPE_PRECISION (TREE_TYPE (lhs));
+	      if ((tmp1 > 0 && tmp2 > 0)||(tmp1 < 0 && tmp2 < 0))
+		{
+		  if (abs (tmp1) > abs (tmp2))
+		    {
+		      vectype2 = get_mask_type_for_scalar_type (vinfo,
+								rhs1_op1_type);
+		      if (!vectype2)
+			return NULL;
+		      rhs1_op0 = build_mask_conversion (vinfo, rhs1_op0,
+							vectype2, stmt_vinfo);
+		    }
+		  else
+		    {
+		      vectype2 = get_mask_type_for_scalar_type (vinfo,
+								rhs1_op0_type);
+		      if (!vectype2)
+			return NULL;
+		      rhs1_op1 = build_mask_conversion (vinfo, rhs1_op1,
+							vectype2, stmt_vinfo);
+		    }
+		  rhs1_type = integer_type_for_mask (rhs1_op0, vinfo);
+		}
+	      else
+		{
+		  rhs1_op0 = build_mask_conversion (vinfo, rhs1_op0,
+						    vectype1, stmt_vinfo);
+		  rhs1_op1 = build_mask_conversion (vinfo, rhs1_op1,
+						    vectype1, stmt_vinfo);
+		  rhs1_type = integer_type_for_mask (rhs1_op0, vinfo);
+		  if (!rhs1_type)
+		    return NULL;
+		  vectype2 = get_mask_type_for_scalar_type (vinfo, rhs1_type);
+		}
+	    }
+	  else
+	    {
+	      rhs1_type = integer_type_for_mask (rhs1_op0, vinfo);
+	      if (!rhs1_type)
+		return NULL;
+	      vectype2 = get_mask_type_for_scalar_type (vinfo, rhs1_type);
+	    }
+	  tmp = build2 (TREE_CODE (rhs1), TREE_TYPE (rhs1), rhs1_op0, rhs1_op1);
+	  rhs1 = tmp;
 	}
       else
 	return NULL;
 
-      vectype2 = get_mask_type_for_scalar_type (vinfo, rhs1_type);
-
-      if (!vectype1 || !vectype2)
+      if (!vectype2)
 	return NULL;
 
       /* Continue if a conversion is needed.  Also continue if we have
-- 
2.19.1

