This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
RE: [PATCH]Fix computation of offset in ivopt
- From: "bin.cheng" <bin dot cheng at arm dot com>
- To: "'Richard Biener'" <richard dot guenther at gmail dot com>
- Cc: "GCC Patches" <gcc-patches at gcc dot gnu dot org>
- Date: Fri, 27 Sep 2013 13:07:15 +0800
- Subject: RE: [PATCH]Fix computation of offset in ivopt
- Authentication-results: sourceware.org; auth=none
- References: <001501ceb906$56da1c00$048e5400$ at arm dot com> <CAFiYyc0WO3M8x-0eyN4xpami9yemcX0cVy=awfOFYYmeo+OSyg at mail dot gmail dot com>
> -----Original Message-----
> From: Richard Biener [mailto:richard.guenther@gmail.com]
> Sent: Tuesday, September 24, 2013 6:31 PM
> To: Bin Cheng
> Cc: GCC Patches
> Subject: Re: [PATCH]Fix computation of offset in ivopt
>
> On Tue, Sep 24, 2013 at 11:13 AM, bin.cheng <bin.cheng@arm.com> wrote:
>
> + field = TREE_OPERAND (expr, 1);
> + if (DECL_FIELD_BIT_OFFSET (field)
> + && cst_and_fits_in_hwi (DECL_FIELD_BIT_OFFSET (field)))
> + boffset = int_cst_value (DECL_FIELD_BIT_OFFSET (field));
> +
> + tmp = component_ref_field_offset (expr);
> + if (top_compref
> + && cst_and_fits_in_hwi (tmp))
> + {
> + /* Strip the component reference completely. */
> + op0 = TREE_OPERAND (expr, 0);
> + op0 = strip_offset_1 (op0, inside_addr, top_compref, &off0);
> + *offset = off0 + int_cst_value (tmp) + boffset /
BITS_PER_UNIT;
> + return op0;
> + }
>
> the failure paths seem mangled, that is, if cst_and_fits_in_hwi is false
for
> either offset part you may end up doing half accounting and not stripping.
>
> Btw, DECL_FIELD_BIT_OFFSET is always non-NULL. I suggest to rewrite to
>
> if (!inside_addr)
> return orig_expr;
>
> tmp = component_ref_field_offset (expr);
> field = TREE_OPERAND (expr, 1);
> if (top_compref
> && cst_and_fits_in_hwi (tmp)
> && cst_and_fits_in_hwi (DECL_FIELD_BIT_OFFSET (field)))
> {
> ...
> }
Will be refined.
>
> note that this doesn't really handle overflows correctly as
>
> + *offset = off0 + int_cst_value (tmp) + boffset /
> + BITS_PER_UNIT;
>
> may still overflow.
Since it's "unsigned + signed + signed", according to implicit conversion,
the signed operand will be converted to unsigned, so the overflow would only
happen when off0 is huge number and tmp/boffset is large positive number,
right? Do I need to check whether off0 is larger than the overflowed
result? Also there is signed->unsigned problem here, see below.
>
> @@ -4133,6 +4142,9 @@ get_computation_cost_at (struct ivopts_data *data,
> bitmap_clear (*depends_on);
> }
>
> + /* Sign-extend offset if utype has lower precision than
> + HOST_WIDE_INT. */ offset = sext_hwi (offset, TYPE_PRECISION
> + (utype));
> +
>
> offset is computed elsewhere in difference_cost and the bug to me seems
> that it is unsigned. sign-extending it here is odd at least (and the
extension
> should probably happen at sizetype precision, not that of utype).
I agree, The root cause is in split_offset_1, in which offset is computed.
Every time offset is computed in this function with a signed operand (like
"int_cst_value (tmp)" above), we need to take care the possible negative
number problem. Take this case as an example, we need to do below change:
case INTEGER_CST:
//.......
*offset = int_cst_value (expr);
change to
case INTEGER_CST:
//.......
*offset = sext_hwi (int_cst_value (expr), type);
and
case MULT_EXPR:
//.......
*offset = sext_hwi (int_cst_value (expr), type);
to
case MULT_EXPR:
//.......
HOST_WIDE_INT xxx = (HOST_WIDE_INT)off0 * int_cst_value (op1);
*offset = sext_hwi (xxx, type);
Any comments?
Thanks.
bin