This is the mail archive of the gcc-bugs@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]

[Bug middle-end/23522] [3.4/4.0/4.1 Regression] fold_widened_comparison bug


------- Additional Comments From alexey dot starovoytov at sun dot com  2005-08-23 23:35 -------
Actually I think 3.x versions are fine.
Here is the snipper from 3.4.3:
      else if (TREE_CODE (TREE_TYPE (arg0)) == INTEGER_TYPE
               && TREE_CODE (arg0) == NOP_EXPR
               && (tem = get_unwidened (arg0, NULL_TREE)) != arg0
               && (code == EQ_EXPR || code == NE_EXPR
                   || TREE_UNSIGNED (TREE_TYPE (arg0))
                      == TREE_UNSIGNED (TREE_TYPE (tem)))
               && (t1 = get_unwidened (arg1, TREE_TYPE (tem))) != 0
               && (TREE_TYPE (t1) == TREE_TYPE (tem)
                   || (TREE_CODE (t1) == INTEGER_CST
                       && int_fits_type_p (t1, TREE_TYPE (tem)))))
        return fold (build (code, type, tem,
                            fold_convert (TREE_TYPE (tem), t1)));

the (t1 = get_unwidened (arg1, TREE_TYPE (tem))) != 0 line
may look suspicious, but it's actually just redundant.
If it's changed to t1 != arg1, then probably int_fits_type_p() condition
will never be called.

The real problem is in 4.0 and 4.1.
The snipper from 4.0.1:
  if (TREE_CODE (arg1_unw) != INTEGER_CST)
    return NULL_TREE;
  
  /* If we are comparing with the integer that does not fit into the range
     of the shorter type, the result is known.  */
  outer_type = TREE_TYPE (arg1_unw);
  min = lower_bound_in_type (outer_type, shorter_type);
  max = upper_bound_in_type (outer_type, shorter_type);
  
  above = integer_nonzerop (fold_relational_const (LT_EXPR, type,
                                                   max, arg1_unw));
  below = integer_nonzerop (fold_relational_const (LT_EXPR, type,
                                                   arg1_unw, min));
  
  switch (code)
    {
    case EQ_EXPR:
      if (above || below)
        return omit_one_operand (type, integer_zero_node, arg0);
      break;

This optimization is incorrect if unwidening of arg1 didn't happen.
So I think the proper new fix would be to remove lines 6104,6105
and add the check that unwidening happened to line 6115:

------- fold-const.c -------
*** /tmp/geta16407      Tue Aug 23 16:21:18 2005
--- /tmp/getb16407      Tue Aug 23 16:21:18 2005
***************
*** 6101,6108 ****
      return NULL_TREE;

    arg1_unw = get_unwidened (arg1, shorter_type);
-   if (!arg1_unw)
-     return NULL_TREE;

    /* If possible, express the comparison in the shorter mode.  */
    if ((code == EQ_EXPR || code == NE_EXPR
--- 6101,6106 ----
***************
*** 6114,6120 ****
      return fold (build (code, type, arg0_unw,
                        fold_convert (shorter_type, arg1_unw)));

!   if (TREE_CODE (arg1_unw) != INTEGER_CST)
      return NULL_TREE;

    /* If we are comparing with the integer that does not fit into the range
--- 6112,6118 ----
      return fold (build (code, type, arg0_unw,
                        fold_convert (shorter_type, arg1_unw)));

!   if (arg1_unw == arg1 || TREE_CODE (arg1_unw) != INTEGER_CST)
      return NULL_TREE;

    /* If we are comparing with the integer that does not fit into the range


My previous suggested fix accidentally disabled vectorization in
gcc.dg/vect/vect-87.c and gcc.dg/vect/vect-88.c on 64-bit targets.
New fix seems to be fine.

Alex.

-- 


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


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