Hi Richard,

The testcase is working with the patch you suggested, thanks for
pointing that out.

On 30 March 2018 at 16:54, Sameera Deshpande
<sameera.deshpa...@linaro.org> wrote:
> On 30 March 2018 at 16:39, Richard Sandiford
> <richard.sandif...@linaro.org> wrote:
>>> Hi Sudakshina,
>>>
>>> Thanks for pointing that out. Updated the conditions for attribute
>>> length to take care of boundary conditions for offset range.
>>>
>>> Please find attached the updated patch.
>>>
>>> I have tested it for gcc testsuite and the failing testcase. Ok for trunk?
>>>
>>> On 22 March 2018 at 19:06, Sudakshina Das <sudi....@arm.com> wrote:
>>>> Hi Sameera
>>>>
>>>> On 22/03/18 02:07, Sameera Deshpande wrote:
>>>>>
>>>>> Hi Sudakshina,
>>>>>
>>>>> As per the ARMv8 ARM, for the offset range (-1048576 ,1048572), the
>>>>> far branch instruction offset is inclusive of both the offsets. Hence,
>>>>> I am using <=||=> and not <||>= as it was in previous implementation.
>>>>
>>>>
>>>> I have to admit earlier I was only looking at the patch mechanically and
>>>> found a difference with the previous implementation in offset comparison.
>>>> After you pointed out, I looked up the ARMv8 ARM and I have a couple of
>>>> doubts:
>>>>
>>>> 1. My understanding is that any offset in [-1048576 ,1048572] both 
>>>> inclusive
>>>> qualifies as an 'in range' offset. However, the code for both attribute
>>>> length and far_branch has been using [-1048576 ,1048572), that is, ( >= && 
>>>> <
>>>> ). If the far_branch was incorrectly calculated, then maybe the length
>>>> calculations with similar magic numbers should also be corrected? Of 
>>>> course,
>>>> I am not an expert in this and maybe this was a conscience decision so I
>>>> would ask Ramana to maybe clarify if he remembers.
>>>>
>>>> 2. Now to come back to your patch, if my understanding is correct, I think 
>>>> a
>>>> far_branch would be anything outside of this range, that is,
>>>> (offset < -1048576 || offset > 1048572), anything that can not be
>>>> represented in the 21-bit range.
>>>>
>>>> Thanks
>>>> Sudi
>>
>> [...]
>>
>>> @@ -466,14 +459,9 @@
>>>    [(set_attr "type" "branch")
>>>     (set (attr "length")
>>>       (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int 
>>> -1048576))
>>> -                        (lt (minus (match_dup 2) (pc)) (const_int 
>>> 1048572)))
>>> +                        (le (minus (match_dup 2) (pc)) (const_int 
>>> 1048572)))
>>>                     (const_int 4)
>>> -                   (const_int 8)))
>>
>> Sorry for not replying earlier, but I think the use of "lt" rather than
>> "le" in the current length attribute is deliberate.  Distances measured
>> from (pc) in "length" are a bit special in that backward distances are
>> measured from the start of the instruction and forward distances are
>> measured from the end of the instruction:
>>
>>       /* The address of the current insn.  We implement this actually as the
>>          address of the current insn for backward branches, but the last
>>          address of the next insn for forward branches, and both with
>>          adjustments that account for the worst-case possible stretching of
>>          intervening alignments between this insn and its destination.  */
>>
>> This avoids the chicken-and-egg situation of the length of the branch
>> depending on the forward distance and the forward distance depending
>> on the length of the branch.
>>
>> In contrast, this code:
>>
>>> @@ -712,7 +695,11 @@
>>>    {
>>>      if (get_attr_length (insn) == 8)
>>>        {
>>> -     if (get_attr_far_branch (insn) == 1)
>>> +     long long int offset;
>>> +     offset = INSN_ADDRESSES (INSN_UID (XEXP (operands[2], 0)))
>>> +               - INSN_ADDRESSES (INSN_UID (insn));
>>> +
>>> +     if (offset < -1048576 || offset > 1048572)
>>>         return aarch64_gen_far_branch (operands, 2, "Ltb",
>>>                                        "<inv_tb>\\t%<w>0, %1, ");
>>>       else
>>
>> is reading the final computed addresses, so the code is right to use
>> the real instruction range.  (FWIW I agree with Kyrill that using
>> IN_RANGE with hex constants would be clearer.)
>>
>> That said... a possible problem comes from situations like:
>>
>>    address length insn
>>    ......c      8 A
>>                   ..align to 8 bytes...
>>    ......8        B
>>    ......c      4 C
>>                   ..align to 16 bytes...
>>    ......0        D, branch to B
>>
>> when D is at the maximum extent of the branch range and when GCC's length
>> for A is only a conservative estimate.  If the length of A turns out to
>> be 4 rather than 8 at assembly time, the alignment to 8 bytes will be
>> a no-op and the address of B and C will be 8 less than we calculated.
>> But the alignment to 16 bytes will then insert 8 bytes of padding rather
>> than none, and the address of D won't change.  The branch will then be
>> out of range even though the addresses calculated by GCC showed it as
>> being in range.  insn_current_reference_address accounts for this, and
>> so copes correctly with conservative lengths.
>>
>> The length can legitimately be conservative for things like asm
>> statements, so I guess using the far_branch attribute is best
>> after all.  Sorry for the wrong turn.
>>
>> On the face of it (without access to the testcase), the only problem
>> with using far_branch in the output template is that insn_last_address
>> is not set, but needs to be for insn_current_reference_address to do
>> the right thing for forward branches.  Does the patch below work for
>> your testcase?
>>
>> (As the documentation you mentioned in the original covering message
>> says, it wouldn't be correct to use far_branch in anything other
>> than final, since only the "length" attribute can respond to changes
>> in addresses while the lengths are being calculated.  But using it
>> in final should be fine.)
>>
>> Thanks,
>> Richard
>>
>>
>> 2018-03-31  Richard Sandiford  <richard.sandif...@linaro.org>
>>
>> gcc/
>>         * final.c (final_1): Set insn_last_address to the same value as
>>         insn_current_address.
>>
>> Index: gcc/final.c
>> ===================================================================
>> --- gcc/final.c 2018-03-30 11:54:02.058881968 +0100
>> +++ gcc/final.c 2018-03-30 11:54:02.228869184 +0100
>> @@ -2081,6 +2081,9 @@ final_1 (rtx_insn *first, FILE *file, in
>>             }
>>           else
>>             insn_current_address = INSN_ADDRESSES (INSN_UID (insn));
>> +         /* final can be seen as an iteration of shorten_branches that
>> +            does nothing (since a fixed point has already been reached).  */
>> +         insn_last_address = insn_current_address;
>>         }
>>
>>        dump_basic_block_info (file, insn, start_to_bb, end_to_bb,
>
> Hi Richard,
>
> Thanks for the explanation. The problem was indeed because correct
> insn_last_address was not set properly, because of which the attribute
> FAR_BRANCH didn't work appropriately. However, I am not sure if that
> was the only problem. Will check the testcase with the ToT sans my
> changes, and will revert.
>
> --
> - Thanks and regards,
>   Sameera D.



-- 
- Thanks and regards,
  Sameera D.

Reply via email to