http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55142



--- Comment #8 from H.J. Lu <hjl.tools at gmail dot com> 2012-10-31 12:19:56 
UTC ---

Does this make any senses?



diff --git a/gcc/fold-const.c b/gcc/fold-const.c

index 5ea5110..50879d6 100644

--- a/gcc/fold-const.c

+++ b/gcc/fold-const.c

@@ -7038,6 +7038,24 @@ fold_to_nonsharp_ineq_using_bound (location_t loc, tree

ineq, tree bound)

   return fold_build2_loc (loc, GE_EXPR, type, a, y);

 }



+static unsigned int

+unsigned_expr_operands (tree op)

+{

+  switch (TREE_CODE (op))

+    {

+    case MULT_EXPR:

+      if (!unsigned_expr_operands (TREE_OPERAND (op, 0)))

+    return 0;

+      return unsigned_expr_operands (TREE_OPERAND (op, 1));

+

+    case NOP_EXPR:

+      return unsigned_expr_operands (TREE_OPERAND (op, 0));

+

+    default:

+      return TYPE_UNSIGNED (TREE_TYPE (op));

+    }

+}

+

 /* Fold a sum or difference of at least one multiplication.

    Returns the folded tree or NULL if no simplification could be made.  */



@@ -7048,6 +7066,17 @@ fold_plusminus_mult_expr (location_t loc, enum tree_code

code, tree type,

   tree arg00, arg01, arg10, arg11;

   tree alt0 = NULL_TREE, alt1 = NULL_TREE, same;



+  /* Make sure the type is not saturating and has the signedness of

+     the stripped operands, as fold_plusminus_mult_expr will re-associate.

+     ??? The latter condition should use TYPE_OVERFLOW_* flags instead.  */

+  if (!((TREE_CODE (arg0) == MULT_EXPR

+       || TREE_CODE (arg1) == MULT_EXPR)

+      && !TYPE_SATURATING (type)

+      && TYPE_UNSIGNED (type) == unsigned_expr_operands (arg0)

+      && TYPE_UNSIGNED (type) == unsigned_expr_operands (arg1)

+      && (!FLOAT_TYPE_P (type) || flag_associative_math)))

+    return NULL_TREE;

+

   /* (A * C) +- (B * C) -> (A+-B) * C.

      (A * C) +- A -> A * (C+-1).

      We are most concerned about the case where C is a constant,

@@ -10042,17 +10071,7 @@ fold_binary_loc (location_t loc,

         }

     }



-      /* Handle (A1 * C1) + (A2 * C2) with A1, A2 or C1, C2 being the same or

-     one.  Make sure the type is not saturating and has the signedness of

-     the stripped operands, as fold_plusminus_mult_expr will re-associate.

-     ??? The latter condition should use TYPE_OVERFLOW_* flags instead.  */

-      if ((TREE_CODE (arg0) == MULT_EXPR

-       || TREE_CODE (arg1) == MULT_EXPR)

-      && !TYPE_SATURATING (type)

-      && TYPE_UNSIGNED (type) == TYPE_UNSIGNED (TREE_TYPE (arg0))

-      && TYPE_UNSIGNED (type) == TYPE_UNSIGNED (TREE_TYPE (arg1))

-      && (!FLOAT_TYPE_P (type) || flag_associative_math))

-        {

+    {

       tree tem = fold_plusminus_mult_expr (loc, code, type, arg0, arg1);

       if (tem)

         return tem;

@@ -10668,17 +10687,7 @@ fold_binary_loc (location_t loc,

       && (tem = distribute_real_division (loc, code, type, arg0, arg1)))

     return tem;



-      /* Handle (A1 * C1) - (A2 * C2) with A1, A2 or C1, C2 being the same or

-     one.  Make sure the type is not saturating and has the signedness of

-     the stripped operands, as fold_plusminus_mult_expr will re-associate.

-     ??? The latter condition should use TYPE_OVERFLOW_* flags instead.  */

-      if ((TREE_CODE (arg0) == MULT_EXPR

-       || TREE_CODE (arg1) == MULT_EXPR)

-      && !TYPE_SATURATING (type)

-      && TYPE_UNSIGNED (type) == TYPE_UNSIGNED (TREE_TYPE (arg0))

-      && TYPE_UNSIGNED (type) == TYPE_UNSIGNED (TREE_TYPE (arg1))

-      && (!FLOAT_TYPE_P (type) || flag_associative_math))

-        {

+    {

       tree tem = fold_plusminus_mult_expr (loc, code, type, arg0, arg1);

       if (tem)

         return tem;

Reply via email to