Hi Haochen,
  The regression cases are caused by "targetm.scalar_mode_supported_p" I added
for scalar mode checking. XImode, OImode and TImode (with -m32) are not
enabled in ix86_scalar_mode_supported_p. So they're excluded from by pieces
operations on i386.

  The original code doesn't do a check for scalar modes. I think it might be
incorrect as not all scalar modes support move and compare optabs. (e.g.
TImode with -m32 on rs6000).

  I drafted a new patch to manually check optabs for scalar mode. Now both
vector and scalar modes are checked for optabs.

  I did a simple test. All former regression cases are back. Could you help do
a full regression test? I am worry about the coverage of my CI system.

Thanks
Gui Haochen

patch.diff
diff --git a/gcc/expr.cc b/gcc/expr.cc
index 7aac575eff8..2af9fcbed18 100644
--- a/gcc/expr.cc
+++ b/gcc/expr.cc
@@ -1000,18 +1000,21 @@ can_use_qi_vectors (by_pieces_operation op)
 /* Return true if optabs exists for the mode and certain by pieces
    operations.  */
 static bool
-qi_vector_mode_supported_p (fixed_size_mode mode, by_pieces_operation op)
+mode_supported_p (fixed_size_mode mode, by_pieces_operation op)
 {
+  if (optab_handler (mov_optab, mode) == CODE_FOR_nothing)
+    return false;
+
   if ((op == SET_BY_PIECES || op == CLEAR_BY_PIECES)
-      && optab_handler (vec_duplicate_optab, mode) != CODE_FOR_nothing)
-    return true;
+      && VECTOR_MODE_P (mode)
+      && optab_handler (vec_duplicate_optab, mode) == CODE_FOR_nothing)
+    return false;

   if (op == COMPARE_BY_PIECES
-      && optab_handler (mov_optab, mode) != CODE_FOR_nothing
-      && can_compare_p (EQ, mode, ccp_jump))
-    return true;
+      && !can_compare_p (EQ, mode, ccp_jump))
+    return false;

-  return false;
+  return true;
 }

 /* Return the widest mode that can be used to perform part of an
@@ -1035,7 +1038,7 @@ widest_fixed_size_mode_for_size (unsigned int size, 
by_pieces_operation op)
          {
            if (GET_MODE_SIZE (candidate) >= size)
              break;
-           if (qi_vector_mode_supported_p (candidate, op))
+           if (mode_supported_p (candidate, op))
              result = candidate;
          }

@@ -1049,7 +1052,7 @@ widest_fixed_size_mode_for_size (unsigned int size, 
by_pieces_operation op)
     {
       mode = tmode.require ();
       if (GET_MODE_SIZE (mode) < size
-         && targetm.scalar_mode_supported_p (mode))
+         && mode_supported_p (mode, op))
       result = mode;
     }

@@ -1454,7 +1457,7 @@ op_by_pieces_d::smallest_fixed_size_mode_for_size 
(unsigned int size)
              break;

            if (GET_MODE_SIZE (candidate) >= size
-               && qi_vector_mode_supported_p (candidate, m_op))
+               && mode_supported_p (candidate, m_op))
              return candidate;
          }
     }

Reply via email to