On Mon, 3 Apr 2006, Roger Sayle wrote: > > On Mon, 3 Apr 2006, Richard Guenther wrote: > > negate_expr_p currently contains > > ... > > where it looks bogus to simply return true for signed types but > > unset flag_trapv. > > ... > > which is bogus as it should read || (!flag_trapv && flag_wrapv) - no? > > I hit this with a patch to fold A +- CST to A -+ CST for negative CST, > > which tells me it is ok to negate -INT_MAX. > > I suspect the problem is in the use of negate_expr_p. This predicate > is designed for integer constants to check whether it is reasonable to > evaluate NEG_EXPR at compile-time. > > Hence, fold will/can convert: > > int foo() > { > return -INT_MIN; > } > > into "return INT_MIN;" during tree-ssa, provided that we don't rely > on trapping math. i.e. we take advantage of the undefined behaviour > of signed types, with or without flag_wrapv.
Hmm, but then, we would be allowed to transform A - -INT_MIN to A + INT_MIN, correct? Now, I'm trying to teach fold_binary to transform i - -1 to i + 1 by adjusting /* A - B -> A + (-B) if B is easily negatable. */ if (negate_expr_p (arg1) && ((FLOAT_TYPE_P (type) /* Avoid this transformation if B is a positive REAL_CST. */ && (TREE_CODE (arg1) != REAL_CST || REAL_VALUE_NEGATIVE (TREE_REAL_CST (arg1)))) || (INTEGRAL_TYPE_P (type) && flag_wrapv && !flag_trapv))) return fold_build2 (PLUS_EXPR, type, fold_convert (type, arg0), fold_convert (type, negate_expr (arg1))); which at the moment does not do that if flag_wrapv is not set. If your reasoning is correct, we can simply replace the last line in the condition with || (TREE_CODE (type) == INTEGER_TYPE && (TREE_CODE (arg1) == INTEGER_CST || TYPE_UNSIGNED (type) || (flag_wrapv && !flag_trapv))) (only do it for INTEGER_TYPE to avoid negating pointer constants) Now for constants this is always valid due to your reasoning, for unsigned types anyway and else if flag_wrapv and no trapping v is in effect. Does this sound reasonable? Thanks, Richard.