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.