https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96757

            Bug ID: 96757
           Summary: aarch64:ICE during GIMPLE pass: vect
           Product: gcc
           Version: 11.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: tree-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: duanbo3 at huawei dot com
  Target Milestone: ---

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);

Reply via email to