From 421dc953cecf09193273827f272a0d185c936f91 Mon Sep 17 00:00:00 2001
From: Duan bo <duanbo3@huawei.com>
Date: Wed, 26 Aug 2020 03:53:32 -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 | 24 +++++++++++++++
 gcc/tree-vect-patterns.c                   | 34 ++++++++++++++++++++++
 2 files changed, 58 insertions(+)
 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..4bca0fa1680
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/pr96757.c
@@ -0,0 +1,24 @@
+/* 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 03d50ec5c90..00dfaa6b395 100644
--- a/gcc/tree-vect-patterns.c
+++ b/gcc/tree-vect-patterns.c
@@ -4395,6 +4395,40 @@ vect_recog_mask_conversion_pattern (vec_info *vinfo,
 	{
 	  tmp = vect_recog_temp_ssa_var (TREE_TYPE (rhs1), NULL);
 	  pattern_stmt = gimple_build_assign (tmp, rhs1);
+	  tree rhs1_op0 = TREE_OPERAND (rhs1, 0);
+	  tree rhs1_op1 = TREE_OPERAND (rhs1, 1);
+	  if (rhs1_op0 && rhs1_op1
+	      && (TREE_CODE (TREE_TYPE (rhs1_op0)) == BOOLEAN_TYPE)
+	      && (TREE_CODE (TREE_TYPE (rhs1_op1)) == BOOLEAN_TYPE))
+	    {
+	      tree rhs1_op0_type = integer_type_for_mask (rhs1_op0, vinfo);
+	      tree rhs1_op1_type = integer_type_for_mask (rhs1_op1, vinfo);
+	      enum tree_code rhs1_code = gimple_assign_rhs_code (pattern_stmt);
+	      if (rhs1_op0_type && rhs1_op1_type
+		  && (!(TYPE_PRECISION (rhs1_op0_type)
+			== TYPE_PRECISION (rhs1_op1_type))))
+		{
+		  if (TYPE_PRECISION (rhs1_op0_type)
+		      < TYPE_PRECISION (rhs1_op1_type))
+		    {
+		      vectype2
+			= get_mask_type_for_scalar_type (vinfo, rhs1_op0_type);
+		      if (vectype2)
+			rhs1_op1 = build_mask_conversion (vinfo, rhs1_op1,
+							  vectype2, stmt_vinfo);
+		    }
+		  else
+		    {
+		      vectype2
+			= get_mask_type_for_scalar_type (vinfo, rhs1_op1_type);
+		      if (vectype2)
+			rhs1_op0 = build_mask_conversion (vinfo, rhs1_op0,
+							  vectype2, stmt_vinfo);
+		    }
+		  pattern_stmt = gimple_build_assign (tmp, rhs1_code,
+				 		      rhs1_op0, rhs1_op1);
+		}
+	    }
 	  rhs1 = tmp;
 	  append_pattern_def_seq (vinfo, stmt_vinfo, pattern_stmt, vectype2,
 				  rhs1_type);
-- 
2.19.1

