On Mon, Oct 21, 2013 at 8:21 PM, Richard Biener
<richard.guent...@gmail.com> wrote:
> On Fri, Oct 18, 2013 at 5:48 PM, Bin.Cheng <amker.ch...@gmail.com> wrote:
>> Hi Richard,
>> Is the first patch OK?  Since there is a patch depending on it.
>> http://gcc.gnu.org/ml/gcc-patches/2013-09/msg01931.html
>
> Yes.
I committed the patch fixing strip_offset_1 as r204116.
Since the root cause of the second issue is POINTER_PLUS_EXPR requires
an unsigned offset operand and can't be fixed as in the second patch,
I will discard that patch.

Thanks.
bin

>> On Fri, Oct 18, 2013 at 7:18 PM, Richard Biener
>> <richard.guent...@gmail.com> wrote:
>>> On Thu, Oct 17, 2013 at 7:52 AM, bin.cheng <bin.ch...@arm.com> wrote:
>>>> Hi,
>>>> As noted in previous messages, GCC forces offset to unsigned in middle end.
>>>> It also gets offset value and stores it in HOST_WIDE_INT then uses it in
>>>> various computation.  In this scenario, It should use int_cst_value to do
>>>> additional sign extension against the type of tree node, otherwise we might
>>>> lose sign information.  Take function fold_plusminus_mult_expr as an
>>>> example, the sign information of arg01/arg11 might be lost because it uses
>>>> TREE_INT_CST_LOW directly.  I think this is the offender of the problem in
>>>> this thread.  I think we should fix the offender, rather the hacking
>>>> strip_offset as in the original patch, so I split original patch into two 
>>>> as
>>>> attached, with one fixing the offset of COMPONENT_REF in strip_offset_1, 
>>>> the
>>>> other fixing the mentioned sign extension problem.
>>>
>>> Index: gcc/fold-const.c
>>> ===================================================================
>>> --- gcc/fold-const.c (revision 203267)
>>> +++ gcc/fold-const.c (working copy)
>>> @@ -7270,8 +7270,8 @@ fold_plusminus_mult_expr (location_t loc, enum tre
>>>        HOST_WIDE_INT int01, int11, tmp;
>>>        bool swap = false;
>>>        tree maybe_same;
>>> -      int01 = TREE_INT_CST_LOW (arg01);
>>> -      int11 = TREE_INT_CST_LOW (arg11);
>>> +      int01 = int_cst_value (arg01);
>>> +      int11 = int_cst_value (arg11);
>>>
>>> this is not correct - it will mishandle all large unsigned numbers.
>>>
>>> The real issue is that we rely on twos-complement arithmetic to work
>>> when operating on pointer offsets (because we convert them all to
>>> unsigned sizetype).  That makes interpreting the offsets or expressions
>>> that compute offsets hard (or impossible in some cases), as you can
>>> see from the issues in IVOPTs.
>>>
>>> The above means that strip_offset_1 cannot reliably look through
>>> MULT_EXPRs as that can make an offset X * CST that is
>>> "effectively" signed "surely" unsigned in the process.  Think of
>>> this looking into X * CST as performing a division - whose result
>>> is dependent on the sign of X which we lost with our unsigned
>>> casting.  Now, removing the MULT_EXPR look-through might
>>> be too pessimizing ... but it may be worth trying to see if it fixes
>>> your issue?  In this context I also remember a new bug filed
>>> recently of us not folding x /[ex] 4 * 4 to x.
>>>
>>> In the past I was working multiple times on stopping doing that
>>> (make all offsets unsigned), but I never managed to finish ...
>>>
>>> Richard.
>>>
>>>> Bootstrap and test on x86/x86_64/arm.  Is it OK?
>>>>
>>>> Thanks.
>>>> bin
>>>>
>>>> Patch a:
>>>> 2013-10-17  Bin Cheng  <bin.ch...@arm.com>
>>>>
>>>>         * tree-ssa-loop-ivopts.c (strip_offset_1): Change parameter type.
>>>>         Count DECL_FIELD_BIT_OFFSET when computing offset for 
>>>> COMPONENT_REF.
>>>>
>>>> Patch b:
>>>> 2013-10-17  Bin Cheng  <bin.ch...@arm.com>
>>>>
>>>>         * fold-const.c (fold_plusminus_mult_expr): Use int_cst_value 
>>>> instead
>>>>         of TREE_INT_CST_LOW.
>>>>
>>>> gcc/testsuite/ChangeLog
>>>> 2013-10-17  Bin Cheng  <bin.ch...@arm.com>
>>>>
>>>>         * gcc.dg/tree-ssa/ivopts-outside-loop-use-1.c: New test.
>>>>
>>>>> -----Original Message-----
>>>>> From: Richard Biener [mailto:richard.guent...@gmail.com]
>>>>> Sent: Wednesday, October 02, 2013 4:32 PM
>>>>> To: Bin.Cheng
>>>>> Cc: Bin Cheng; GCC Patches
>>>>> Subject: Re: [PATCH]Fix computation of offset in ivopt
>>>>>
>>>>> On Tue, Oct 1, 2013 at 6:13 PM, Bin.Cheng <amker.ch...@gmail.com> wrote:
>>>>> > On Tue, Oct 1, 2013 at 6:50 PM, Richard Biener
>>>>> > <richard.guent...@gmail.com> wrote:
>>>>> >> On Mon, Sep 30, 2013 at 7:39 AM, bin.cheng <bin.ch...@arm.com>
>>>>> wrote:
>>>>> >>>
>>>>> >>>
>>>>> >>
>>>>> >> I don't think you need
>>>>> >>
>>>>> >> +  /* Sign extend off if expr is in type which has lower precision
>>>>> >> +     than HOST_WIDE_INT.  */
>>>>> >> +  if (TYPE_PRECISION (TREE_TYPE (expr)) <= HOST_BITS_PER_WIDE_INT)
>>>>> >> +    off = sext_hwi (off, TYPE_PRECISION (TREE_TYPE (expr)));
>>>>> >>
>>>>> >> at least it would be suspicious if you did ...
>>>>> > There is a problem for example of the first message.  The iv base if
>>>> like:
>>>>> > pretmp_184 + ((sizetype) KeyIndex_180 + 1073741823) * 4 I am not sure
>>>>> > why but it seems (-4/0xFFFFFFFC) is represented by (1073741823*4).
>>>>> > For each operand strip_offset_1 returns exactly the positive number
>>>>> > and result of multiplication never get its chance of sign extend.
>>>>> > That's why the sign extend is necessary to fix the problem. Or it
>>>>> > should be fixed elsewhere by representing iv base with:
>>>>> > "pretmp_184 + ((sizetype) KeyIndex_180 + 4294967295) * 4" in the first
>>>>> place.
>>>>>
>>>>> Yeah, that's why I said the whole issue with forcing all offsets to be
>>>> unsigned
>>>>> is a mess ...
>>>>>
>>>>> There is really no good answer besides not doing that I fear.
>>>>>
>>>>> Yes, in the above case we could fold the whole thing differently
>>>> (interpret
>>>>> the offset of a POINTER_PLUS_EXPR as signed).  You can try tracking down
>>>>> the offender, but it'll get non-trivial easily as you have to consider the
>>>> fact
>>>>> that GCC will treat signed operations as having undefined behavior on
>>>>> overflow.
>>>>>
>>>>> So I see why you want to do the extension above (re-interpret the result),
>>>> I
>>>>> suppose we can live with it but please make sure to add a big fat ???
>>>>> comment before it explaining why it is necessary.
>>>>>
>>>>> Richard.
>>>>>
>>>>> >>
>>>>> >> The only case that I can think of points to a bug in strip_offset_1
>>>>> >> again, namely if sizetype (the type of all offsets) is smaller than a
>>>>> >> HOST_WIDE_INT in which case
>>>>> >>
>>>>> >> +    boffset = int_cst_value (DECL_FIELD_BIT_OFFSET (field));
>>>>> >> +    *offset = off0 + int_cst_value (tmp) + boffset / BITS_PER_UNIT;
>>>>> >>
>>>>> >> is wrong as boffset / BITS_PER_UNIT does not do a signed division
>>>>> >> then (for negative boffset which AFAIK does not happen - but it would
>>>>> >> be technically allowed).  Thus, the predicates like
>>>>> >>
>>>>> >> +    && cst_and_fits_in_hwi (tmp)
>>>>> >>
>>>>> >> would need to be amended with a check that the MSB is not set.
>>>>> > So I can handle it like:
>>>>> >
>>>>> > +    abs_boffset = abs_hwi (boffset);
>>>>> > +    xxxxx = abs_boffset / BITS_PER_UNIT;
>>>>> > +    if (boffset < 0)
>>>>> > +      xxxxx = -xxxxx;
>>>>> > +    *offset = off0 + int_cst_value (tmp) + xxxxx;
>>>>> >
>>>>> > Right?
>>>>> >
>>>>> >>
>>>>> >> Btw, the cst_and_fits_in_hwi implementation is odd:
>>>>> >>
>>>>> >> bool
>>>>> >> cst_and_fits_in_hwi (const_tree x)
>>>>> >> {
>>>>> >>   if (TREE_CODE (x) != INTEGER_CST)
>>>>> >>     return false;
>>>>> >>
>>>>> >>   if (TYPE_PRECISION (TREE_TYPE (x)) > HOST_BITS_PER_WIDE_INT)
>>>>> >>     return false;
>>>>> >>
>>>>> >>   return (TREE_INT_CST_HIGH (x) == 0
>>>>> >>           || TREE_INT_CST_HIGH (x) == -1); }
>>>>> >>
>>>>> >> the precision check seems totally pointless and I wonder what's the
>>>>> >> point of this routine as there is host_integerp () already and
>>>>> >> tree_low_cst instead of int_cst_value - oh, I see, the latter
>>>>> >> forcefully sign-extends .... that should make the extension not
>>>>> >> necessary.
>>>>> > See above.
>>>>> >
>>>>> > Thanks.
>>>>> > bin
>>
>>
>>
>> --
>> Best Regards.



-- 
Best Regards.

Reply via email to