public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Richard Sandiford <richard.sandiford@linaro.org>
To: Sameera Deshpande <sameera.deshpande@linaro.org>
Cc: Sudakshina Das <sudi.das@arm.com>,
	 Ramana Radhakrishnan <ramana.gcc@googlemail.com>,
	 James Greenhalgh <james.greenhalgh@arm.com>,
	 Marcus Shawcroft <marcus.shawcroft@arm.com>,
	 Richard Earnshaw <richard.earnshaw@arm.com>,
	 gcc-patches <gcc-patches@gcc.gnu.org>,  nd <nd@arm.com>
Subject: Re: [Aarch64] Fix conditional branches with target far away.
Date: Fri, 30 Mar 2018 11:24:00 -0000	[thread overview]
Message-ID: <87h8oxvmys.fsf@linaro.org> (raw)
In-Reply-To: <CAAdirjzKMcOM17X7WDxNWWWTf2fy3JAKb=Kf_EmKkqLWVGk23Q@mail.gmail.com>	(Sameera Deshpande's message of "Thu, 29 Mar 2018 16:14:11 +0530")

> 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.das@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.sandiford@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,

  parent reply	other threads:[~2018-03-30 11:09 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-02-14  8:30 Sameera Deshpande
2018-02-27 12:13 ` Sameera Deshpande
2018-02-27 12:55 ` Ramana Radhakrishnan
2018-02-28 10:48   ` Sameera Deshpande
2018-03-15 15:35     ` Sameera Deshpande
2018-03-15 16:56       ` Sudakshina Das
2018-03-22  2:10         ` Sameera Deshpande
2018-03-22 13:42           ` Sudakshina Das
2018-03-29 11:28             ` Sameera Deshpande
2018-03-29 15:33               ` Sudakshina Das
2018-03-29 15:35                 ` Sameera Deshpande
2018-03-29 15:54               ` Kyrill Tkachov
2018-03-30 11:24               ` Richard Sandiford [this message]
2018-03-30 11:31                 ` Sameera Deshpande
2018-03-30 12:18                   ` Sameera Deshpande
2018-04-09  8:36                     ` Sameera Deshpande
2018-07-31 11:50                       ` Sameera Deshpande

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87h8oxvmys.fsf@linaro.org \
    --to=richard.sandiford@linaro.org \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=james.greenhalgh@arm.com \
    --cc=marcus.shawcroft@arm.com \
    --cc=nd@arm.com \
    --cc=ramana.gcc@googlemail.com \
    --cc=richard.earnshaw@arm.com \
    --cc=sameera.deshpande@linaro.org \
    --cc=sudi.das@arm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).