From: Richard Sandiford Date: Mon, 29 Jul 2019 18:50:25 +0000 (+0000) Subject: Fix inchash handling of wide_ints (PR91242) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=5d5bb9bc26bbd714ef81a7eb91e77e312582ccdc;p=gcc.git Fix inchash handling of wide_ints (PR91242) inchash::hash::add_wide_int operated directly on the raw encoding of the wide_int, including any redundant upper bits. The problem with that is that the upper bits are only defined for some wide-int storage types (including wide_int itself). wi::to_wide(tree) instead returns a value that is extended according to the signedness of the type (so that wi::to_widest can use the same encoding) while rtxes have the awkward special case of BI, which can be zero-extended rather than sign-extended. In the PR, we computed a hash for a "normal" sign-extended wide_int while the existing entries hashed wi::to_wide(tree). This gives different results for unsigned types that have the top bit set. The patch fixes that by hashing the canonical sign-extended form even if the raw encoding happens to be different. 2019-07-29 Richard Sandiford gcc/ * wide-int.h (generic_wide_int::sext_elt): New function. * inchash.h (hash::add_wide_int): Use it instead of elt. From-SVN: r273881 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2d981f61fd8..7f3dfa7a3b4 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2019-07-29 Richard Sandiford + + * wide-int.h (generic_wide_int::sext_elt): New function. + * inchash.h (hash::add_wide_int): Use it instead of elt. + 2019-07-29 Kyrylo Tkachov * config/arm/arm-builtins.c (acle_builtin_data): Expand VAR1 to diff --git a/gcc/inchash.h b/gcc/inchash.h index f61e631ca3b..56588d27daf 100644 --- a/gcc/inchash.h +++ b/gcc/inchash.h @@ -85,7 +85,7 @@ class hash { add_int (x.get_len ()); for (unsigned i = 0; i < x.get_len (); i++) - add_hwi (x.elt (i)); + add_hwi (x.sext_elt (i)); } /* Hash in pointer PTR. */ diff --git a/gcc/wide-int.h b/gcc/wide-int.h index 6c816cc260b..862079a8549 100644 --- a/gcc/wide-int.h +++ b/gcc/wide-int.h @@ -730,6 +730,7 @@ public: /* Public accessors for the interior of a wide int. */ HOST_WIDE_INT sign_mask () const; HOST_WIDE_INT elt (unsigned int) const; + HOST_WIDE_INT sext_elt (unsigned int) const; unsigned HOST_WIDE_INT ulow () const; unsigned HOST_WIDE_INT uhigh () const; HOST_WIDE_INT slow () const; @@ -909,6 +910,23 @@ generic_wide_int ::elt (unsigned int i) const return this->get_val ()[i]; } +/* Like elt, but sign-extend beyond the upper bit, instead of returning + the raw encoding. */ +template +inline HOST_WIDE_INT +generic_wide_int ::sext_elt (unsigned int i) const +{ + HOST_WIDE_INT elt_i = elt (i); + if (!is_sign_extended) + { + unsigned int precision = this->get_precision (); + unsigned int lsb = i * HOST_BITS_PER_WIDE_INT; + if (precision - lsb < HOST_BITS_PER_WIDE_INT) + elt_i = sext_hwi (elt_i, precision - lsb); + } + return elt_i; +} + template template inline generic_wide_int &