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. The real question is whether your new transformation is using negate_expr_p correctly. It sounds as though you may be introducing an overflow that wasn't there before, in which case you need to be testing flag_wrapv && !flag_trapv in the calling clause. negate_expr_p (t) is simply an efficient version of temp = fold_build1 (NEGATE_EXPR, type, t); return TREE_CODE (temp) != NEGATE_EXPR; and its logic precisely mirrors the equivalent code in negate_expr. Perhaps some of the logic in fold_negate_const is more appropriate: temp = fold_negate_const (arg0, type); return !TREE_OVERFLOW (temp); I hope this helps. Roger --