http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56474
--- Comment #17 from Eric Botcazou <ebotcazou at gcc dot gnu.org> 2013-05-06 09:33:53 UTC --- > is the testcase when changed to 'Empty_Vector : Vector (-2);' valid? Yes, this is the superflat case. > In any case, in 0 .. Size, Size seems to be signed. Yes, Stream_Element_Offset is signed. > Also, there is the special-case > > /* Similarly, if one of the values overflows in sizetype and the > range is null, use 1..0 for the sizetype bounds. */ > else if (TREE_CODE (gnu_min) == INTEGER_CST > && TREE_CODE (gnu_max) == INTEGER_CST > && (TREE_OVERFLOW (gnu_min) || TREE_OVERFLOW (gnu_max)) > && tree_int_cst_lt (gnu_orig_max, gnu_orig_min)) > { > gnu_min = size_one_node; > gnu_max = size_zero_node; > gnu_high = gnu_max; > } > > that simply chooses [1, 0] as "empty" domain, regardless of the original > min or max. So both cases (of which you fix only one), > > /* Otherwise, if the high bound is constant but the low bound is > not, we use the expression (hb >= lb) ? lb : hb + 1 for the > lower bound. Note that the comparison must be done in the > original type to avoid any overflow during the conversion. > */ > else if (TREE_CODE (gnu_max) == INTEGER_CST > && TREE_CODE (gnu_min) != INTEGER_CST) > { > gnu_high = gnu_max; > gnu_min > = build_cond_expr (sizetype, > build_binary_op (GE_EXPR, > boolean_type_node, > gnu_orig_max, > gnu_orig_min), > gnu_min, > size_binop (PLUS_EXPR, gnu_max, > size_one_node)); > } > > /* Finally we use (hb >= lb) ? hb : lb - 1 for the upper bound > in all the other cases. Note that, here as well as above, > the condition used in the comparison must be equivalent to > the condition (length != 0). This is relied upon in order > to optimize array comparisons in compare_arrays. */ > else > gnu_high > = build_cond_expr (sizetype, > build_binary_op (GE_EXPR, > boolean_type_node, > gnu_orig_max, > gnu_orig_min), > gnu_max, > size_binop (MINUS_EXPR, gnu_min, > size_one_node)); > > could be combined to > > else > { > gnu_min > = build_cond_expr (sizetype, > build_binary_op (GE_EXPR, > boolean_type_node, > gnu_orig_max, > gnu_orig_min), > gnu_min, > size_one_node)); > gnu_high > = build_cond_expr (sizetype, > build_binary_op (GE_EXPR, > boolean_type_node, > gnu_orig_max, > gnu_orig_min), > gnu_max, > size_zero_node); > } > > which fixes the issue for me. Right, at the expense of pessimizing a lot the common case of constant low bound and variable high bound. Not acceptable I'm afraid. > I can also easily guard the existing size_binop (MINUS_EXPR, gnu_min, > size_one_node) for gnu_min being zero, or I can simply use > int_const_binop here instead, as you expect that operation to _never_ > set TREE_OVERFLOW if not gnu_min had TREE_OVERFLOW set. Adding a guard would also pessimize the common case, albeit less severely. But using int_const_binop looks workable, I'll give it a whirl. > Note that if gnu_max - 1 is not computable as compile-time constant here, > but is retained as tree expression and folded later overflow will not > be considered either (it doesn't go the size_* API way, which is supposed > to be the interface giving overflow hints to the FEs via means of > TREE_OVERFLOW which better should not appear later during optimization). Yes, but these expressions appear in bounds and size of integer and array types so they cannot be arbitrarily complex, otherwise things can quickly blow up.