Page MenuHomePhabricator

[RISCV] -mno-relax: emit .option norelax
Needs ReviewPublic

Authored by MaskRay on May 14 2021, 2:28 PM.

Details

Summary

GNU as defaults to -mrelax. Emit .option norelax so that the emitted
assembly file can be assembled back correctly in -mno-relax mode.
This matches GCC.

Diff Detail

Event Timeline

MaskRay created this revision.May 14 2021, 2:28 PM
MaskRay requested review of this revision.May 14 2021, 2:28 PM
Herald added a project: Restricted Project. · View Herald TranscriptMay 14 2021, 2:28 PM
MaskRay updated this revision to Diff 345566.May 14 2021, 2:29 PM

improve test

I view this as a bug in whatever calls the assembler; it should be passing -mno-relax, just as it needs to pass -fPIC as appropriate.

jrtc27 added a comment.EditedMay 14 2021, 2:32 PM

I assume GCC's behaviour dates from before GNU as supported -mno-relax? Which isn't interesting to us, we require a pretty new binutils so %got_pcrel_hi works.

I view this as a bug in whatever calls the assembler; it should be passing -mno-relax, just as it needs to pass -fPIC as appropriate.

I'll use the -g analogy. clang -S -g emits debug info and leaves a .debug_line marker so that the assembler knows it needs to synthesize debug info and should not synthesize .debug_info from ELF symbols.
The assembler doesn't need -g to function.

For .option nopic, I agree it is not useful.

I view this as a bug in whatever calls the assembler; it should be passing -mno-relax, just as it needs to pass -fPIC as appropriate.

I'll use the -g analogy. clang -S -g emits debug info and leaves a .debug_line marker so that the assembler knows it needs to synthesize debug info and should not synthesize .debug_info from ELF symbols.
The assembler doesn't need -g to function.

For .option nopic, I agree it is not useful.

The two aren't comparable. Relaxation affects assembling and not code generation. Debug info affects code generation to emit all the information that's otherwise lost (the assembly doesn't have a copy of your source code...). Even PIC is more useful than .option norelax, as it affects what instructions get used to lower global addresses etc.

I view this as a bug in whatever calls the assembler; it should be passing -mno-relax, just as it needs to pass -fPIC as appropriate.

I'll use the -g analogy. clang -S -g emits debug info and leaves a .debug_line marker so that the assembler knows it needs to synthesize debug info and should not synthesize .debug_info from ELF symbols.
The assembler doesn't need -g to function.

For .option nopic, I agree it is not useful.

The two aren't comparable. Relaxation affects assembling and not code generation. Debug info affects code generation to emit all the information that's otherwise lost (the assembly doesn't have a copy of your source code...). Even PIC is more useful than .option norelax, as it affects what instructions get used to lower global addresses etc.

I think the -Wa,-mno-relax argument is justified if code generation cannot affect relaxation (which I am unsure).

Can GCC base assembly emission decisions on -mno-relax?

I view this as a bug in whatever calls the assembler; it should be passing -mno-relax, just as it needs to pass -fPIC as appropriate.

I'll use the -g analogy. clang -S -g emits debug info and leaves a .debug_line marker so that the assembler knows it needs to synthesize debug info and should not synthesize .debug_info from ELF symbols.
The assembler doesn't need -g to function.

For .option nopic, I agree it is not useful.

The two aren't comparable. Relaxation affects assembling and not code generation. Debug info affects code generation to emit all the information that's otherwise lost (the assembly doesn't have a copy of your source code...). Even PIC is more useful than .option norelax, as it affects what instructions get used to lower global addresses etc.

I think the -Wa,-mno-relax argument is justified if code generation cannot affect relaxation (which I am unsure).

Can GCC base assembly emission decisions on -mno-relax?

It can if it wants to, but as far as I know the option exists solely for the driver to pass to the assembler, and I don't know what you'd do with the information that's meaningful.

I view this as a bug in whatever calls the assembler; it should be passing -mno-relax, just as it needs to pass -fPIC as appropriate.

I'll use the -g analogy. clang -S -g emits debug info and leaves a .debug_line marker so that the assembler knows it needs to synthesize debug info and should not synthesize .debug_info from ELF symbols.
The assembler doesn't need -g to function.

For .option nopic, I agree it is not useful.

The two aren't comparable. Relaxation affects assembling and not code generation. Debug info affects code generation to emit all the information that's otherwise lost (the assembly doesn't have a copy of your source code...). Even PIC is more useful than .option norelax, as it affects what instructions get used to lower global addresses etc.

I think the -Wa,-mno-relax argument is justified if code generation cannot affect relaxation (which I am unsure).

Can GCC base assembly emission decisions on -mno-relax?

I think it will be better that clang driver passed the right argument to assembler ( provided it is external GNU assembler )

MaskRay added a comment.EditedMay 19 2021, 1:36 PM

This is to make clang -S -mno-relax a.c; clang -S a.s use no-relax.

I feel that if -mno-relax is really an assembler only option, -Wa,-mno-relax would be more appropriate. And -mno-relax should be warned with -S.

However, if the compiler (either Clang or GCC) reserves rights to change code generation (likely (as I feel), as it may do something special to aid assemblers), I'll actually prefer .option norelax in the emitted assembly output.
(With this patch, we don't need to pass -mno-relax to GNU as for the -fno-integrated-as code path.)

I found a random issue discussing relaxation (https://github.com/riscv/riscv-elf-psabi-doc/issues/34) and asked the code generation question to GCC contributors there.

If the user is passing along -mno-relax encoding that in the object file isn't expensive, and it doesn't harm anything. In fact, the user _could_ at a later point pass in -mrelax to the assembler to override the beahviour (with a warning). But what @raj.khem states about the non-IAS case should hold - -mno-relax should get passed along to the assembler along with the hint in the object file.

If the user is passing along -mno-relax encoding that in the object file isn't expensive, and it doesn't harm anything. In fact, the user _could_ at a later point pass in -mrelax to the assembler to override the beahviour (with a warning). But what @raj.khem states about the non-IAS case should hold - -mno-relax should get passed along to the assembler along with the hint in the object file.

.option norelax overrides -mrelax, just like any other assembler directive.

Hmm, actually looking at gcc, it appears that this is actually matching semantics with gcc:
https://github.com/riscv/riscv-gcc/blob/03cb20e5433cd8e65af6a1a6baaf3fe4c72785f6/gcc/config/riscv/riscv.c#L4590-L4593

If the user is passing along -mno-relax encoding that in the object file isn't expensive, and it doesn't harm anything. In fact, the user _could_ at a later point pass in -mrelax to the assembler to override the beahviour (with a warning). But what @raj.khem states about the non-IAS case should hold - -mno-relax should get passed along to the assembler along with the hint in the object file.

.option norelax overrides -mrelax, just like any other assembler directive.

Ah right, the attributes are processed late in ELF.

@asb @craig.topper @luismarques opinions on .option norelax and https://github.com/riscv/riscv-elf-psabi-doc/issues/34#issuecomment-844548202 ?

(From that comment it seems that https://github.com/riscv/riscv-c-api-doc is the place to discuss the option but that repo doesn't have many watchers.)

Personally I prefer keep compatible with GNU toolchain behavior on this, so this patch is LGTM.

But I would like to let @asb and @luismarques to do the final judge.

After discussion with Jim W, we think it's OK to pass -mno-relax to as for GCC, and we could sent patch recently, but keep emitting .option norelax for this moment to make sure the compatibility, and remove that later after 1 or 2 GCC version (that's means 1~2 years in generally)

I think an assembler only option should be spelled as -Wa,*. The driver option isn't useful and should just be avoided.

For -mno-relax, I think there can be arguments that the assembler generation may be affected (to appease assembler, for example) so a driver option is needed.

If the driver option -mno-relax is still preferred over -Wa,-mno-relax, I can abandon this and submit another one passing -mno-relax to GNU as for -fno-integrated-as.

I think an assembler only option should be spelled as -Wa,*. The driver option isn't useful and should just be avoided.

For -mno-relax, I think there can be arguments that the assembler generation may be affected (to appease assembler, for example) so a driver option is needed.

If the driver option -mno-relax is still preferred over -Wa,-mno-relax, I can abandon this and submit another one passing -mno-relax to GNU as for -fno-integrated-as.

Jim W and me don't have strong opinion here, but we don't want to break backward compatible/behavior change on GNU toolchain, so we using both for now.

The reason why we did't pass -mno-relax to assembler...is because we already using .option norelax scheme there, so we thought it's enough (long times ago I don't even remember when).

For clang/LLVM, I think there is freedom to choose implement both or just pass -mno-relax.

MaskRay added a comment.EditedMay 26 2021, 12:58 PM

If .option norelax is the agreed-upon choice (is it?), can I get a stamp?

I did not participate in the meetings you have ... and I am confused about the state now.

If .option norelax is the agreed-upon choice (is it?), can I get a stamp?

I did not participate in the meetings you have ... and I am confused about the state now.

Oh, sorry for confusing, I should ask that in LLVM sync up meeting before I said it's free to choose, we can discuss this at today's LLVM sync up meeting,
But again, I would prefer to let @asb and @luismarques to do the final judge :)

Oh, sorry for confusing, I should ask that in LLVM sync up meeting before I said it's free to choose, we can discuss this at today's LLVM sync up meeting,
But again, I would prefer to let @asb and @luismarques to do the final judge :)

@evandro had some good points about this issue that we didn't have time to fully discuss during the call. Evandro, when you find the time please chime in with your points here. Thank you!

@evandro had some good points about this issue that we didn't have time to fully discuss during the call. Evandro, when you find the time please chime in with your points here. Thank you!

ping @evandro. IIRC correctly the main argument was that this was an optional optimization option, so it should be chosen explicitly (or not) when driving the assembler.

Methinks that the choice of whether to relax or not should be decided outside of the assembler code. This directive sets the choice in stone and counters any choice done at build time, when optimizations are specified. For instance, when building a debug version, the optimizations may be different from when building a release version. This directive blocks such common practices and may create confusion and non expected results.

Methinks that the choice of whether to relax or not should be decided outside of the assembler code. This directive sets the choice in stone and counters any choice done at build time, when optimizations are specified. For instance, when building a debug version, the optimizations may be different from when building a release version. This directive blocks such common practices and may create confusion and non expected results.

I thought I understood your point initially, but now I'm not sure. Can you clarify what flexibility you're losing? Doesn't the emission of this directive reflect exactly the build settings you specify at compilation time? Why is it important to override this later?

I thought I understood your point initially, but now I'm not sure. Can you clarify what flexibility you're losing? Doesn't the emission of this directive reflect exactly the build settings you specify at compilation time? Why is it important to override this later?

If consistency is desired from clang to as, then -Wa,-mno-relax is preferred. This way, the same assembly source can be assembled with or without relaxation without changing the source code. Moreover, in the case of an assembly source file, the choice to relax its code or not can be made at build time, or, more specifically, at link time.