Hi Jeff,
Can you take a look at the patch? It fixes a bootstrap failure on
LoongArch. And in this month 3 related bugzilla tickets have been
created (110939, 111124, 111171).
On Thu, 2023-08-10 at 15:04 +0200, Stefan Schulze Frielinghaus via Gcc-
patches wrote:
> In the former fix in commit 41ef5a34161356817807be3a2e51fbdbe575ae85 I
> completely missed the fact that the normal form of a generated constant for a
> mode with fewer bits than in HOST_WIDE_INT is a sign extended version of the
> actual constant. This even holds true for unsigned constants.
>
> Fixed by masking out the upper bits for the incoming constant and sign
> extending the resulting unsigned constant.
>
> Bootstrapped and regtested on x64 and s390x. Ok for mainline?
>
> While reading existing optimizations in combine I stumbled across two
> optimizations where either my intuition about the representation of
> unsigned integers via a const_int rtx is wrong, which then in turn would
> probably also mean that this patch is wrong, or that the optimizations
> are missed sometimes. In other words in the following I would assume
> that the upper bits are masked out:
/* removed the inlined patch to avoid confusion */
> For example, while bootstrapping on x64 the optimization is missed since
> a LTU comparison in QImode is done and the constant equals
> 0xffffffffffffff80.
>
> Sorry for inlining another patch, but I would really like to make sure
> that my understanding is correct, now, before I come up with another
> patch. Thus it would be great if someone could shed some light on this.
>
> gcc/ChangeLog:
>
> * combine.cc (simplify_compare_const): Properly handle unsigned
> constants while narrowing comparison of memory and constants.
> ---
> gcc/combine.cc | 19 ++++++++++---------
> 1 file changed, 10 insertions(+), 9 deletions(-)
>
> diff --git a/gcc/combine.cc b/gcc/combine.cc
> index e46d202d0a7..468b7fde911 100644
> --- a/gcc/combine.cc
> +++ b/gcc/combine.cc
> @@ -12003,14 +12003,15 @@ simplify_compare_const (enum rtx_code code,
> machine_mode mode,
> && !MEM_VOLATILE_P (op0)
> /* The optimization makes only sense for constants which are big enough
> so that we have a chance to chop off something at all. */
> - && (unsigned HOST_WIDE_INT) const_op > 0xff
> - /* Bail out, if the constant does not fit into INT_MODE. */
> - && (unsigned HOST_WIDE_INT) const_op
> - < ((HOST_WIDE_INT_1U << (GET_MODE_PRECISION (int_mode) - 1) << 1) -
> 1)
> + && ((unsigned HOST_WIDE_INT) const_op & GET_MODE_MASK (int_mode)) >
> 0xff
> /* Ensure that we do not overflow during normalization. */
> - && (code != GTU || (unsigned HOST_WIDE_INT) const_op <
> HOST_WIDE_INT_M1U))
> + && (code != GTU
> + || ((unsigned HOST_WIDE_INT) const_op & GET_MODE_MASK (int_mode))
> + < HOST_WIDE_INT_M1U)
> + && trunc_int_for_mode (const_op, int_mode) == const_op)
> {
> - unsigned HOST_WIDE_INT n = (unsigned HOST_WIDE_INT) const_op;
> + unsigned HOST_WIDE_INT n
> + = (unsigned HOST_WIDE_INT) const_op & GET_MODE_MASK (int_mode);
> enum rtx_code adjusted_code;
>
> /* Normalize code to either LEU or GEU. */
> @@ -12051,15 +12052,15 @@ simplify_compare_const (enum rtx_code code,
> machine_mode mode,
> HOST_WIDE_INT_PRINT_HEX ") to (MEM %s "
> HOST_WIDE_INT_PRINT_HEX ").\n", GET_MODE_NAME (int_mode),
> GET_MODE_NAME (narrow_mode_iter), GET_RTX_NAME (code),
> - (unsigned HOST_WIDE_INT)const_op, GET_RTX_NAME
> (adjusted_code),
> - n);
> + (unsigned HOST_WIDE_INT) const_op & GET_MODE_MASK (int_mode),
> + GET_RTX_NAME (adjusted_code), n);
> }
> poly_int64 offset = (BYTES_BIG_ENDIAN
> ? 0
> : (GET_MODE_SIZE (int_mode)
> - GET_MODE_SIZE (narrow_mode_iter)));
> *pop0 = adjust_address_nv (op0, narrow_mode_iter, offset);
> - *pop1 = GEN_INT (n);
> + *pop1 = gen_int_mode (n, narrow_mode_iter);
> return adjusted_code;
> }
> }
--
Xi Ruoyao <[email protected]>
School of Aerospace Science and Technology, Xidian University