On August 31, 2019 3:12:07 PM GMT+02:00, 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?

Hmm, couldn't we make range_check_type_for take an argument whether signed or 
unsigned type is required? That is, what do we do if the caller wants a signed 
type? Leaving it unspecified what the function returns is odd. 

Richard. 

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

Reply via email to