Bug 96757

Summary: aarch64:ICE during GIMPLE pass: vect
Product: gcc Reporter: Duanbo <duanbo3>
Component: tree-optimizationAssignee: Not yet assigned to anyone <unassigned>
Status: RESOLVED FIXED    
Severity: normal CC: duanbo3, marxin, rsandifo
Priority: P3    
Version: 11.0   
Target Milestone: ---   
Host: Target: aarch64
Build: Known to work:
Known to fail: Last reconfirmed:
Bug Depends on:    
Bug Blocks: 53947    

Description Duanbo 2020-08-24 02:18:49 UTC
Hi, gcc-trunk ICEs when compiling the following testcase with -O3 on aarch64:
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);
  }
}

a.c: In function ‘fun’:
a.c:12:1: error: non-trivial conversion in unary operation
   12 | fun(int a, int b, int c)
      | ^~~
vector(4) <signed-boolean:16>
vector(4) <signed-boolean:32>
mask_patt_29.18_65 = ~mask__2.17_64;
during GIMPLE pass: vect
dump file: a.c.163t.vect
a.c:12:1: internal compiler error: verify_gimple failed
0xcc4767 verify_gimple_in_cfg(function*, bool)
        .././../gcc/tree-cfg.c:5491
0xb8af2b execute_function_todo
        .././../gcc/passes.c:1992
0xb8be2b do_per_function
        .././../gcc/passes.c:1640
0xb8be2b execute_todo
        .././../gcc/passes.c:2046
Please submit a full bug report,
with preprocessed source if appropriate.
Please include the complete backtrace with any bug report.
See <https://gcc.gnu.org/bugs/> for instructions.

Before vect pass, the main statements of this case will be optimized like:
	_1 = d_10(D) > 3;
	_2 = a_11(D) > m_12(D);
	_18 = _1 > _2 ? _26 : 0;
 
At the beginning of vectorization analysis,function vect_recog_mask_conversion_pattern processed the gimple  _18 = _1 > _2 ? _15 : 0,and produce such results:
	patt_17 = _1 > _2
	patt_3 = patt_17 ? _15 : 0
However, it didn't consider the situation that  _1, _2's vectype is different,  So vectorization analysis failed with most of vector mode when examining the statement patt_17 = _1 > _2. 
Due to  aarch64  support vectorizing with multiple vector sizes (https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=74166aabeb7f) , in some special  mode, like V4HImode  for this case, _1 = d_10(D) > 3 and _2 = a_11(D) > m_12(D) had same nunits but different vectype, which make vectorization analysis succeeded.

After that,the statement patt_29 = _1 > _2 was transformed like: 
	mask_patt_29.21_72 = ~mask__2.20_71;
	mask_patt_29.21_73 = mask__1.19_68 & mask_patt_29.21_72;
the vectype of mask__2.20_71  is vector(4)  <signed-boolean:32>,the vectype of mask_patt_29.21_72 is vector(4)  <signed-boolean:16>, which leading to the ICE.

I have prepared the following patch to fix this problem, this patch added the identification and handling for this situation in vect_recog_mask_conversion_pattern. With that _18 = _1 > _2 ? _15 : 0 will be transformed to such statements:
	patt_3 = (<signed-boolean:16>) _2;
	patt_17 = _1 > patt_3;
	patt_20 = patt_17 ? _26 : 0;
Bootstrap and tested on both aarch64 and x86 Linux platform, no new regression witnessed.

diff --git a/gcc/tree-vect-patterns.c b/gcc/tree-vect-patterns.c
index 03d50ec5c90..cfd6bfdede8 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);
Comment 1 CVS Commits 2020-10-12 11:33:21 UTC
The master branch has been updated by Richard Sandiford <rsandifo@gcc.gnu.org>:

https://gcc.gnu.org/g:91d80cf4bd2827dd9c40fe6a7c719c909d79083d

commit r11-3819-g91d80cf4bd2827dd9c40fe6a7c719c909d79083d
Author: Duan bo <duanbo3@huawei.com>
Date:   Mon Oct 12 12:32:57 2020 +0100

    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.
Comment 2 rsandifo@gcc.gnu.org 2020-10-12 16:37:30 UTC
Fixed on trunk.