This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix up go regressions caused by my recent switchconv changes (PR go/91617)
- From: Jakub Jelinek <jakub at redhat dot com>
- To: Richard Biener <rguenther at suse dot de>
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Sat, 31 Aug 2019 15:12:07 +0200
- Subject: [PATCH] Fix up go regressions caused by my recent switchconv changes (PR go/91617)
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
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 <jakub@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