[PATCH] RISC-V: Do fixup for local symbols while with "-mno-relax"

Palmer Dabbelt palmer@dabbelt.com
Wed Dec 13 02:47:05 GMT 2023


On Tue, 12 Dec 2023 17:26:03 PST (-0800), i@maskray.me wrote:
>> In the scenario of generating .ko files, the kernel does not relax the .ko
>> files. However, due to the large amount of relax and local relocation
>> information, this increases the size of the .ko files.
>>
>> In this patch, it will finish the fixup of the local relocations while with
>> "-mno-relax" option. This can reduce the size of the relocation table.
>
> Thanks for the patch.  I was initially confused by the description.
> Perhaps clarify it to: "... the Linux kernel uses -mno-relax but still
> gets a lot of relocations which can be eliminated" and "... resolve
> some fixups to constants and remove relocations"
>
> On Tue, Dec 12, 2023 at 4:31 PM Palmer Dabbelt <palmer@dabbelt.com> wrote:
>>
>> On Tue, 12 Dec 2023 02:44:07 PST (-0800), nelson@rivosinc.com wrote:
>> > There is another stuff, do we need to limit linkers that only can link the
>> > objects with -mno-relax if this optimization applied?  If so, then we
>> > probably need,
>> > 1. An assembler option for this optimization
>> > 2. Record the object is relaxable or not into the elf attribute?  or
>> > readelf header?  or ...
>> > 2.1 Maybe we can record the relaxation information with
>> > Tag_RISCV_x3_reg_usage?,
>> > https://sourceware.org/pipermail/binutils/2023-September/129500.html?
>> > 2.2 Once the object enables relaxation for some code, the object needs to
>> > be marked as "relaxable", even if it sets `.option norelax' later.
>> >
>> > On Tue, Dec 12, 2023 at 5:46 PM Nelson Chu <nelson@rivosinc.com> wrote:
>> >
>> >> The idea looks good to me.  Passed regressions of riscv-gnu-toolchain, so
>> >> committed with some minor changes and indent fixes.
>> >>
>> >> There are some TODOs, but no rush to do for now,
>> >> 1. The implementation is based on the code from bfd/elfnn-riscv.c.  We
>> >> probably can move the code to bfd/elfxx-riscv.c, so that can reduce
>> >> duplicate code, just like what we did for the architecture parser.
>> >> Before that, I renamed functions and variables from *reloc* to *fixup*, to
>> >> distinguish the code from bfd/elfnn-riscv.c, since they are still a little
>> >> bit different.
>> >> 2. Maybe not only pcrel_hi/lo12 relocation with local symbols can be resolved
>> >> at assembler time.  Other pc-relative relocation, like branch, may also
>> >> be able to perform related optimizations.
>
> Agree that GNU assembler can resolve more PC-relative instructions to
> a constant without a relocation.
> For example, LLVM integrated assembler resolves the following `j` to constants:
>
>     // clang --target=riscv64-linux-gnu -march=rv64i -mno-relax -c
>     j .Ltmp1
>     j .Ltmp1
>     .Ltmp1:
>
> (Though LLVM has its own problem that a `.option relax` anywhere in
> the assembly file will lose this optimization.)
>
>> Nelson and I were just talking about this.  I'd been leaning towards
>> adding another option along the lines of "-mno-relax-abi", which would
>> explicitly mean that users can depend on no objects being relaxed.  That
>> said, I'm not actually sure I can come up with a case where anything
>> breaks.
>>
>> I was specifically worried about things like the compiler doing label
>> subtraction, but IIUC that can only happen within a single translation
>> unit so we're safe to take advantage of on R_RISCV_RELAX relocations.
>>
>> There's also cases like misaligned globals, but we're already broken
>> there so I'm not sure it counts.
>>
>> So maybe this safe?
>
> I lean towards not providing an option.  Beside the previous paragraph
> that LLVM integrated assembler omits relocations in more cases,
> architectures not using linker relaxation do optimize out relocations
> in these cases as well.
> It's a missing size optimization for RISC-V in the -mno-relax configuration.
> Users relying on the relocation can switch to `.reloc ., R_RISCV_JAL, xx`.

Sorry for being confusing: I agree resolving local R_RISCV_CALL 
relocations at assembly time (or I guess, not having R_RISCV_CALL at 
all) is safe as long as the call does not cross a R_RISCV_RELAX (or any 
of the normal-smelling boundaries like sections and such).

Nelson and I were wondering if many other PC-relative relocations can be 
processed at assembly time whenever they don't cross a R_RISCV_RELAX 
boundary (and meet all the other rules the other ports need to deal 
with).  I think there's a bunch where we can, and it's possible just 
having no relaxations in an object is sufficient to enable any of these 
optimizations.

FWIW, I'd still lean towards providing some sort of option/ELF flag that 
just bans relaxation entirely -- we basically don't use it in modern 
Linux user binaries (unless I missed some PIE optimizations going in), 
so we might as well just properly forbid relaxation.


More information about the Binutils mailing list