On Sat, Aug 31, 2019 at 6:12 AM Jakub Jelinek <ja...@redhat.com> wrote:
>
> Hi!
>
> Apparently my recent tree-{cfg,switch-conversion}.c changes broke a bunch of
> go tests.
> The problem is that range_check_type actually doesn't guarantee an unsigned
> type; it forces integer type for enum/bool (that was what was really needed
> to fix the PR), and for integer types that don't wrap forces unsigned type
> (and then verifies the wrap-around).  Seems go uses -fwrapv by default
> and we got thus signed types from it.  That is fine if we emit the
> x >= low && x < high range tests as x - low >= 0 && x - low < high - low,
> but we actually don't emit the >= 0 check and so we do need an unsigned
> type.  The other uses of range_check_type also eventually also call
> unsigned_type_for, e.g.
>   etype = range_check_type (etype);
>   if (etype == NULL_TREE)
>     return NULL_TREE;
>
>   if (POINTER_TYPE_P (etype))
>     etype = unsigned_type_for (etype);
> and in the recursion then because low is 0:
>       if (! TYPE_UNSIGNED (etype))
>         {
>           etype = unsigned_type_for (etype);
>           high = fold_convert_loc (loc, etype, high);
>           exp = fold_convert_loc (loc, etype, exp);
>         }
> Similarly match.pd:
>         tree etype = range_check_type (TREE_TYPE (@0));
>         if (etype)
>           {
>             if (! TYPE_UNSIGNED (etype))
>               etype = unsigned_type_for (etype);
> ...
> So, the following patch calls unsigned_type_for on the range_check_type
> result.
>
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
>
> 2019-08-31  Jakub Jelinek  <ja...@redhat.com>
>
>         PR go/91617
>         * tree-cfg.c (generate_range_test): Call unsigned_type_for on
>         the range_check_type result.
>         * tree-switch-conversion.c (switch_conversion::build_one_array,
>         bit_test_cluster::emit): Likewise.
>
> --- gcc/tree-cfg.c.jj   2019-08-31 12:09:09.135153318 +0200
> +++ gcc/tree-cfg.c      2019-08-31 12:48:06.259939680 +0200
> @@ -9222,6 +9222,7 @@ generate_range_test (basic_block bb, tre
>  {
>    tree type = TREE_TYPE (index);
>    tree utype = range_check_type (type);
> +  utype = unsigned_type_for (utype);
>
>    low = fold_convert (utype, low);
>    high = fold_convert (utype, high);
> --- gcc/tree-switch-conversion.c.jj     2019-08-31 12:09:09.129153406 +0200
> +++ gcc/tree-switch-conversion.c        2019-08-31 12:48:28.340617487 +0200
> @@ -616,6 +616,7 @@ switch_conversion::build_one_array (int
>
>        /* We must use type of constructor values.  */
>        gimple_seq seq = NULL;
> +      type = unsigned_type_for (type);
>        tree tmp = gimple_convert (&seq, type, m_index_expr);
>        tree tmp2 = gimple_build (&seq, MULT_EXPR, type,
>                                 wide_int_to_tree (type, coeff_a), tmp);
> @@ -1486,6 +1487,7 @@ bit_test_cluster::emit (tree index_expr,
>    unsigned int count;
>
>    tree unsigned_index_type = range_check_type (index_type);
> +  unsigned_index_type = unsigned_type_for (unsigned_index_type);
>
>    gimple_stmt_iterator gsi;
>    gassign *shift_stmt;



Thanks for looking into this.

Ian

Reply via email to