[PATCH] RISC-V: Relax PCREL to GPREL while doing other relaxations is dangerous.

Nelson Chu nelson.chu@sifive.com
Fri Nov 20 01:45:43 GMT 2020


On Fri, Nov 20, 2020 at 7:13 AM Jim Wilson <jimw@sifive.com> wrote:
> My only worry is that we might miss some relaxation opportunities if they are in separate passes.  Suppose we have a call that is just slightly out of range, but that there is a relaxable pc-rel reloc in the middle that if relaxed would pull it back in range.  So doing the call relaxation first before pc-rel relaxation means we won't be able to relax the call.  Though I think this may be already a problem if it is a forward call, and this currently only works for backwards calls.

Agree with this, but I think the backward calls also can not work as
expected right now.  The relax_pc only changes the R_RISCV_PCREL_HI20
relocs to R_RISCV_DELETE, but waits for the next relax pass to
actually delete the code.  That means we will get the same symbols for
relax_call, no matter if the patterns are relaxed by the relax_pc or
not.  Therefore, we should set `again` to TRUE, and try to run the
relaxation round many times (I think one round means run relax pass 0
to 2 one time), to let the call case you mentioned above have a chance
to be relaxed.  However, the `again` might fail because of the
relax_align that you mentioned as follows...


> Anyways, normally you would expect a second call to _bfd_riscv_relax_section to catch what the first one missed, as the first one will set *again if anything was relaxed.  However, there is a complication with R_RISCV_ALIGN, in that it must be done in the very last _bfd_riscv_relax_section call.  Otherwise, the code won't get the right alignments.  Currently, _bfd_riscv_relax_align sets sec_flg0 to indicate that we did the alignment relaxation, and in _bfd_riscv_relax_section it refuses to do anything if this flag was set.  So if we have any R_RISCV_ALIGN relocs the second call to _bfd_riscv_relax_section won't do anything.

Yeah, thanks for pointing this out and describing the behavior in
detail.  It's really helpful and important.


> On second thought, this looks like a pre-existing problem, it is just that your patch makes it very slightly worse.

Umm when we are in the relax pass 1 originally, we won't actually
delete the code for relax_pc, just use R_RISCV_DELETE to record that
the code should be deleted later in the relax pass 2.  Therefore, just
moving the relax_pc to the later relax pass should be fine, and should
get the same result as before.

>I think we need to refuse to do the R_RISCV_ALIGN relaxation if *again is already set, so that the next call to _bfd_riscv_relax_section can relax again.  Eventually we will make it to pass 3 with *again false and then we can do the R_RISCV_ALIGN which does not set *again itself so relaxation will stop.  If we do this, we maybe don't need the sec_flg0 code anymore.  This can be a separate patch as it is a separate bug report.

It's a great idea, and we can use it to make `again` more effective.

> Also, fyi, I noticed the comment before the _bfd_riscv_relax_delete function is wrong.  It is the same comment for the _bfd_riscv_relax_pc function so it looks like it was copied and then someone forgot to edit it.  This has nothing to do with your patch, or my R_RISCV_ALIGN suggestion though.  So this can be a separate trivial fix.

OK, I will fix that in another patch.


Thanks
Nelson


More information about the Binutils mailing list