MaskRay added a comment.

In D97446#3241416 <https://reviews.llvm.org/D97446#3241416>, @JonChesterfield 
wrote:

> It looks deeply wrong to be marking globals as either llvm.used or 
> llvm.compiler.used based on the output file format. It should be based on the 
> (purpose of) the global.
>
> In D97446#3241142 <https://reviews.llvm.org/D97446#3241142>, @rnk wrote:
>
>> This change was implemented so that llvm.used could prevent section GC on 
>> ELF, to make its semantics consistent with llvm.used on COFF and MachO. 
>> Essentially, llvm.used behaves differently on ELF now so to prevent behavior 
>> changes for users of `__attribute__((used))`, it was migrated to 
>> `llvm.compiler.used` on ELF targets. This is consistent with GCC's behavior.
>
> Is this sentence inverted? llvm.used should prevent sections from being 
> discarded. If it doesn't at present, that's a bug in the linker.

I agree with rnk.
The bug can be on the compiler side which does not give enough information to 
the linker.
Before `retain` was added to GCC and binutils supported SHF_GNU_RETAIN, the ELF 
world was in that state.

> llvm.compiler.used should generally be discarded by whatever part of the 
> compiler wanted the variable

The compiler cannot discard it per LangRef 
https://llvm.org/docs/LangRef.html#the-llvm-compiler-used-global-variable

> but if it makes it to the linker, the linker should throw it away. Because it 
> was only used by the compiler. It's possible some users marked things as 
> 'used' but wanted them thrown away, but it seems more likely that users 
> weren't using gc-sections if it broke their application by throwing away 
> things they asked to keep.

Correct.

>> This should only change behavior for you if you depend on the details of the 
>> LLVM IR being emitted, or perhaps if you use LTO, where GlobalOpt will 
>> behave differently. I don't think these use cases are as important as 
>> consistent ELF section GC behavior.
>>
>> So, apologies for changing the LLVM IR emitted for this attribute, but I 
>> think it's unlikely we will change our minds and revert this a year later.
>
> I'm hopeful I can change your minds now. The current modelling in the 
> compiler doesn't match the stated intent.
>
> In D97446#3241195 <https://reviews.llvm.org/D97446#3241195>, @MaskRay wrote:
>
>> llvm.compiler.used hasn't been changed.
>
> True, but attribute((used)) has. I only noticed this patch because it broke 
> some test cases in rocm, but it'll break some of my own code too. Moving a 
> variable from llvm.used to llvm.compiler.used changes whether internalise 
> skips the variable.

Modulo optimizer bugs, `__attribute__((used))` hasn't changed semantics.
If your downstream project does not handle llvm.compiler.used, maybe handle it 
now :)

I apologize that previous Clang probably very rarely emitted llvm.compiler.used 
and it started to do it more often now.

>> The text focuses on the semantics, and for practical reasons refers to the 
>> toolchain support.
>> Before GCC 11/binutils 2.36 there was just no portable way making a 
>> definition not discarded by ld --gc-sections.
>
> Sure there was. Don't pass gc-sections to the linker, or don't compile with 
> ffunction-sections to get a close approximation.
>
>>> edit: Would making attribute((used)) imply attribute((retain)) on elf 
>>> targets achieve the objective of this patch without breaking code that 
>>> expects 'used' to mean "don't throw this away"?
>>
>> This would make semantics less orthogonal and incompatible with GCC.
>> On COFF and Mach-O, there have been Clang-specific (not GCC) use cases 
>> relying on attribute((used)) implying GC roots.
>> On ELF, there was none before the toolchain support.
>>
>> Every llvm.used usage I can find in the wild does intend to have the GC 
>> semantics, and not having it on ELF was actually a bug and has been fixed by 
>> the patch series.
>
> I'm absolutely sure that people mark things as attribute((used)) to stop the 
> toolchain discarding them. I think we're in agreement there, but differ in 
> our assessment of popularity of gc-sections.
>
> Are we missing a category here?
>
> llvm.compiler.used <- the compiler uses the global, and may discard it. If it 
> doesn't, the linker should discard it
> llvm.linker.used <- the linker uses this global, and may discard it. The 
> compiler should leave it alone aside from passing it to the linker
> llvm.used <- some unspecified thing uses the global, the compiler and linker 
> should leave it alone aside from embedding it in the linked output

I think the llvm.compiler.used interpretation diverges from LangRef and how we 
teach optimizers to respect llvm.compiler.used.
Then llvm.linker.used shall not be needed.

> If we have to map 'attribute((used))' onto the new llvm.linker.used and 
> 'attribute((retain))' onto llvm.used that's a shame, but at least it keeps 
> the naming weirdness localised to the language front end.

I have checked the documentation of many GCC releases (including very ancient 
ones).
Its `__attribute__((used))` never suggests that it has the linker GC semantics.
In LLVM/Clang, Mach-O somehow chose to overload `used` with the additional 
linker dead stripping semantics.

The ideal semantics is that COFF/Mach-O uses llvm.compiler.used for 
`__attribute__((used))` as well.
But downgrading llvm.used to llvm.compiler.used may be regression for some 
code, so I chose not to do that.

I agree that there is unfortunate binary format inconsistency, but the ELF 
semantics as implemented in the patch series are ideal.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D97446/new/

https://reviews.llvm.org/D97446

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to