This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Widening multiplication limitations


I was playing with adding support of the various modes of widening
multiplies on my backend, and hit some restrictions in the expansion
code that I couldn't explain to myself. These restrictions only impact
the signed by unsigned version.

The first limitation was about the detection of widening multiplies
when one of the operands is a big constant of opposite signedness of
the other. It might very well be the case that nobody cared adding the
support for that. I used the following simple patch to overcome that:

@@ -2059,16 +2059,30 @@ is_widening_mult_p (gimple stmt,

   if (*type1_out == NULL)
     {
-      if (*type2_out == NULL || !int_fits_type_p (*rhs1_out, *type2_out))
-       return false;
-      *type1_out = *type2_out;
+      if (*type2_out == NULL)
+        return false;
+      if (!int_fits_type_p (*rhs1_out, *type2_out)) {
+        tree other_type = signed_or_unsigned_type_for (!TYPE_UNSIGNED
(*type2_out)
+                                                       *type2_out);
+        if (!int_fits_type_p (*rhs1_out, other_type))
+          return false;
+        *type1_out = other_type;
+      } else {
+        *type1_out = *type2_out;
+      }
     }

   if (*type2_out == NULL)
     {
-      if (!int_fits_type_p (*rhs2_out, *type1_out))
-       return false;
-      *type2_out = *type1_out;
+      if (!int_fits_type_p (*rhs2_out, *type1_out)) {
+        tree other_type = signed_or_unsigned_type_for (!TYPE_UNSIGNED
(*type1_out)
+                                                       *type1_out);
+        if (!int_fits_type_p (*rhs2_out, other_type))
+          return false;
+        *type2_out = other_type;
+      } else {
+        *type2_out = *type1_out;
+      }
     }

Is that extension of the logic correct?

After having done that modification and thus having the middle end
generate widening multiplies of this kind, I hit the second limitation
in expr.c:expand_expr_real_2 :

       /* First, check if we have a multiplication of one signed and one
         unsigned operand.  */
      if (TREE_CODE (treeop1) != INTEGER_CST
         && (TYPE_UNSIGNED (TREE_TYPE (treeop0))
              != TYPE_UNSIGNED (TREE_TYPE (treeop1))))

Here, the code trying to expand a signed by unsigned widening multiply
explicitly checks that the operand isn't a constant. Why is that? I
removed that condition to try to find the failing cases, but the few
million random multiplies that I threw at it didn't fail in any
visible way.

One difficulty I found was that the widening multiplies are expressed as eg:

(mult (zero_extend (operand 1)) (zero_extend (operand 2)))

and that simplify_rtx will ICE when trying to simplify a zero_extend
of a VOIDmode const_int. It forced me to carefully add different
patterns to handle the immediate versions of the operations. But that
doesn't seem like a good reason to limit the code expansion...

Can anyone explain this condition?

Many thanks,
Fred


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]