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